blob: 8a949bfe61d01a38df2dba611e772578ea6f0452 [file] [log] [blame]
Subbaraman Narayanamurthy95450d62017-01-18 20:10:51 -08001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "FG: %s: " fmt, __func__
14
15#include "fg-core.h"
16#include "fg-reg.h"
17
18/* Generic definitions */
19#define RETRY_COUNT 3
20#define BYTES_PER_SRAM_WORD 4
21
22enum {
23 FG_READ = 0,
24 FG_WRITE,
25};
26
27static int fg_set_address(struct fg_chip *chip, u16 address)
28{
29 u8 buffer[2];
30 int rc;
31
32 buffer[0] = address & 0xFF;
33 /* MSB has to be written zero */
34 buffer[1] = 0;
35
36 rc = fg_write(chip, MEM_IF_ADDR_LSB(chip), buffer, 2);
37 if (rc < 0) {
38 pr_err("failed to write to 0x%04X, rc=%d\n",
39 MEM_IF_ADDR_LSB(chip), rc);
40 return rc;
41 }
42
43 return rc;
44}
45
46static int fg_config_access_mode(struct fg_chip *chip, bool access, bool burst)
47{
48 int rc;
49 u8 intf_ctl = 0;
50
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -070051 fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "access: %d burst: %d\n",
52 access, burst);
53
54 WARN_ON(burst && chip->use_ima_single_mode);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070055 intf_ctl = ((access == FG_WRITE) ? IMA_WR_EN_BIT : 0) |
56 (burst ? MEM_ACS_BURST_BIT : 0);
57
58 rc = fg_masked_write(chip, MEM_IF_IMA_CTL(chip), IMA_CTL_MASK,
59 intf_ctl);
60 if (rc < 0) {
61 pr_err("failed to write to 0x%04x, rc=%d\n",
62 MEM_IF_IMA_CTL(chip), rc);
63 return -EIO;
64 }
65
66 return rc;
67}
68
69static int fg_run_iacs_clear_sequence(struct fg_chip *chip)
70{
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -070071 u8 val, hw_sts, exp_sts;
72 int rc, tries = 250;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070073
74 /*
75 * Values to write for running IACS clear sequence comes from
76 * hardware documentation.
77 */
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -070078 rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip),
79 IACS_CLR_BIT | STATIC_CLK_EN_BIT,
80 IACS_CLR_BIT | STATIC_CLK_EN_BIT);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070081 if (rc < 0) {
82 pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_IMA_CFG(chip),
83 rc);
84 return rc;
85 }
86
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -070087 rc = fg_config_access_mode(chip, FG_READ, false);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070088 if (rc < 0) {
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -070089 pr_err("failed to write to 0x%04x, rc=%d\n",
90 MEM_IF_IMA_CTL(chip), rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070091 return rc;
92 }
93
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -070094 rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
95 MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT,
96 MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070097 if (rc < 0) {
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -070098 pr_err("failed to set ima_req_access bit rc=%d\n", rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -070099 return rc;
100 }
101
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700102 /* Delay for the clock to reach FG */
103 usleep_range(35, 40);
104
105 while (1) {
106 val = 0;
107 rc = fg_write(chip, MEM_IF_ADDR_MSB(chip), &val, 1);
108 if (rc < 0) {
109 pr_err("failed to write 0x%04x, rc=%d\n",
110 MEM_IF_ADDR_MSB(chip), rc);
111 return rc;
112 }
113
114 val = 0;
115 rc = fg_write(chip, MEM_IF_WR_DATA3(chip), &val, 1);
116 if (rc < 0) {
117 pr_err("failed to write 0x%04x, rc=%d\n",
118 MEM_IF_WR_DATA3(chip), rc);
119 return rc;
120 }
121
122 rc = fg_read(chip, MEM_IF_RD_DATA3(chip), &val, 1);
123 if (rc < 0) {
124 pr_err("failed to read 0x%04x, rc=%d\n",
125 MEM_IF_RD_DATA3(chip), rc);
126 return rc;
127 }
128
129 /* Delay for IMA hardware to clear */
130 usleep_range(35, 40);
131
132 rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1);
133 if (rc < 0) {
134 pr_err("failed to read ima_hw_sts rc=%d\n", rc);
135 return rc;
136 }
137
138 if (hw_sts != 0)
139 continue;
140
141 rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1);
142 if (rc < 0) {
143 pr_err("failed to read ima_exp_sts rc=%d\n", rc);
144 return rc;
145 }
146
147 if (exp_sts == 0 || !(--tries))
148 break;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700149 }
150
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700151 if (!tries)
152 pr_err("Failed to clear the error? hw_sts: %x exp_sts: %d\n",
153 hw_sts, exp_sts);
154
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700155 rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), IACS_CLR_BIT, 0);
156 if (rc < 0) {
157 pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_IMA_CFG(chip),
158 rc);
159 return rc;
160 }
161
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700162 udelay(5);
163
164 rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
165 MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
166 if (rc < 0) {
167 pr_err("failed to write to 0x%04x, rc=%d\n",
168 MEM_IF_MEM_INTF_CFG(chip), rc);
169 return rc;
170 }
171
172 /* Delay before next transaction is attempted */
173 usleep_range(35, 40);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700174 fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "IACS clear sequence complete\n");
175 return rc;
176}
177
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700178int fg_clear_dma_errors_if_any(struct fg_chip *chip)
179{
180 int rc;
181 u8 dma_sts;
Subbaraman Narayanamurthy3f3040a2017-03-14 20:30:47 -0700182 bool error_present;
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700183
184 rc = fg_read(chip, MEM_IF_DMA_STS(chip), &dma_sts, 1);
185 if (rc < 0) {
186 pr_err("failed to read addr=0x%04x, rc=%d\n",
187 MEM_IF_DMA_STS(chip), rc);
188 return rc;
189 }
190 fg_dbg(chip, FG_STATUS, "dma_sts: %x\n", dma_sts);
191
Subbaraman Narayanamurthy3f3040a2017-03-14 20:30:47 -0700192 error_present = dma_sts & (DMA_WRITE_ERROR_BIT | DMA_READ_ERROR_BIT);
193 rc = fg_masked_write(chip, MEM_IF_DMA_CTL(chip), DMA_CLEAR_LOG_BIT,
194 error_present ? DMA_CLEAR_LOG_BIT : 0);
195 if (rc < 0) {
196 pr_err("failed to write addr=0x%04x, rc=%d\n",
197 MEM_IF_DMA_CTL(chip), rc);
198 return rc;
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700199 }
200
201 return 0;
202}
203
204int fg_clear_ima_errors_if_any(struct fg_chip *chip, bool check_hw_sts)
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700205{
206 int rc = 0;
207 u8 err_sts, exp_sts = 0, hw_sts = 0;
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700208 bool run_err_clr_seq = false;
209
210 rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1);
211 if (rc < 0) {
212 pr_err("failed to read ima_exp_sts rc=%d\n", rc);
213 return rc;
214 }
215
216 rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1);
217 if (rc < 0) {
218 pr_err("failed to read ima_hw_sts rc=%d\n", rc);
219 return rc;
220 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700221
222 rc = fg_read(chip, MEM_IF_IMA_ERR_STS(chip), &err_sts, 1);
223 if (rc < 0) {
224 pr_err("failed to read ima_err_sts rc=%d\n", rc);
225 return rc;
226 }
227
Subbaraman Narayanamurthy03e6c612016-11-09 16:40:27 -0800228 fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n",
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700229 err_sts, exp_sts, hw_sts);
230
231 if (check_hw_sts) {
232 /*
233 * Lower nibble should be equal to upper nibble before SRAM
234 * transactions begins from SW side. If they are unequal, then
235 * the error clear sequence should be run irrespective of IMA
236 * exception errors.
237 */
238 if ((hw_sts & 0x0F) != hw_sts >> 4) {
239 pr_err("IMA HW not in correct state, hw_sts=%x\n",
240 hw_sts);
241 run_err_clr_seq = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700242 }
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700243 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700244
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700245 if (exp_sts & (IACS_ERR_BIT | XCT_TYPE_ERR_BIT | DATA_RD_ERR_BIT |
246 DATA_WR_ERR_BIT | ADDR_BURST_WRAP_BIT | ADDR_STABLE_ERR_BIT)) {
247 pr_err("IMA exception bit set, exp_sts=%x\n", exp_sts);
248 run_err_clr_seq = true;
249 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700250
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700251 if (run_err_clr_seq) {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700252 /* clear the error */
253 rc = fg_run_iacs_clear_sequence(chip);
254 if (rc < 0) {
255 pr_err("failed to run iacs clear sequence rc=%d\n", rc);
256 return rc;
257 }
258
259 /* Retry again as there was an error in the transaction */
260 return -EAGAIN;
261 }
262
263 return rc;
264}
265
266static int fg_check_iacs_ready(struct fg_chip *chip)
267{
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700268 int rc = 0, tries = 250;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700269 u8 ima_opr_sts = 0;
270
271 /*
272 * Additional delay to make sure IACS ready bit is set after
273 * Read/Write operation.
274 */
275
276 usleep_range(30, 35);
277 while (1) {
278 rc = fg_read(chip, MEM_IF_IMA_OPR_STS(chip), &ima_opr_sts, 1);
279 if (rc < 0) {
280 pr_err("failed to read 0x%04x, rc=%d\n",
281 MEM_IF_IMA_OPR_STS(chip), rc);
282 return rc;
283 }
284
285 if (ima_opr_sts & IACS_RDY_BIT)
286 break;
287
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700288 if (!(--tries))
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700289 break;
290
291 /* delay for iacs_ready to be asserted */
292 usleep_range(5000, 7000);
293 }
294
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700295 if (!tries) {
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800296 pr_err("IACS_RDY not set, opr_sts: %d\n", ima_opr_sts);
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700297 /* check for error condition */
298 rc = fg_clear_ima_errors_if_any(chip, false);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700299 if (rc < 0) {
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700300 if (rc != -EAGAIN)
301 pr_err("Failed to check for ima errors rc=%d\n",
302 rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700303 return rc;
304 }
305
306 return -EBUSY;
307 }
308
309 return 0;
310}
311
312static int __fg_interleaved_mem_write(struct fg_chip *chip, u16 address,
313 int offset, u8 *val, int len)
314{
315 int rc = 0, i;
316 u8 *ptr = val, byte_enable = 0, num_bytes = 0;
317
318 fg_dbg(chip, FG_SRAM_WRITE, "length %d addr=%02X offset=%d\n", len,
319 address, offset);
320
321 while (len > 0) {
322 num_bytes = (offset + len) > BYTES_PER_SRAM_WORD ?
323 (BYTES_PER_SRAM_WORD - offset) : len;
324
325 /* write to byte_enable */
326 for (i = offset; i < (offset + num_bytes); i++)
327 byte_enable |= BIT(i);
328
329 rc = fg_write(chip, MEM_IF_IMA_BYTE_EN(chip), &byte_enable, 1);
330 if (rc < 0) {
331 pr_err("Unable to write to byte_en_reg rc=%d\n",
332 rc);
333 return rc;
334 }
335
336 /* write data */
337 rc = fg_write(chip, MEM_IF_WR_DATA0(chip) + offset, ptr,
338 num_bytes);
339 if (rc < 0) {
340 pr_err("failed to write to 0x%04x, rc=%d\n",
341 MEM_IF_WR_DATA0(chip) + offset, rc);
342 return rc;
343 }
344
345 /*
346 * The last-byte WR_DATA3 starts the write transaction.
347 * Write a dummy value to WR_DATA3 if it does not have
348 * valid data. This dummy data is not written to the
349 * SRAM as byte_en for WR_DATA3 is not set.
350 */
351 if (!(byte_enable & BIT(3))) {
352 u8 dummy_byte = 0x0;
353
354 rc = fg_write(chip, MEM_IF_WR_DATA3(chip), &dummy_byte,
355 1);
356 if (rc < 0) {
357 pr_err("failed to write dummy-data to WR_DATA3 rc=%d\n",
358 rc);
359 return rc;
360 }
361 }
362
363 /* check for error condition */
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700364 rc = fg_clear_ima_errors_if_any(chip, false);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700365 if (rc < 0) {
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700366 if (rc == -EAGAIN)
367 pr_err("IMA error cleared, address [%d %d] len %d\n",
368 address, offset, len);
369 else
370 pr_err("Failed to check for ima errors rc=%d\n",
371 rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700372 return rc;
373 }
374
375 ptr += num_bytes;
376 len -= num_bytes;
377 offset = byte_enable = 0;
378
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700379 if (chip->use_ima_single_mode && len) {
380 address++;
381 rc = fg_set_address(chip, address);
382 if (rc < 0) {
383 pr_err("failed to set address rc = %d\n", rc);
384 return rc;
385 }
386 }
387
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700388 rc = fg_check_iacs_ready(chip);
389 if (rc < 0) {
390 pr_debug("IACS_RDY failed rc=%d\n", rc);
391 return rc;
392 }
393 }
394
395 return rc;
396}
397
398static int __fg_interleaved_mem_read(struct fg_chip *chip, u16 address,
399 int offset, u8 *val, int len)
400{
401 int rc = 0, total_len;
402 u8 *rd_data = val, num_bytes;
403 char str[DEBUG_PRINT_BUFFER_SIZE];
404
405 fg_dbg(chip, FG_SRAM_READ, "length %d addr=%02X\n", len, address);
406
407 total_len = len;
408 while (len > 0) {
409 num_bytes = (offset + len) > BYTES_PER_SRAM_WORD ?
410 (BYTES_PER_SRAM_WORD - offset) : len;
411 rc = fg_read(chip, MEM_IF_RD_DATA0(chip) + offset, rd_data,
412 num_bytes);
413 if (rc < 0) {
414 pr_err("failed to read 0x%04x, rc=%d\n",
415 MEM_IF_RD_DATA0(chip) + offset, rc);
416 return rc;
417 }
418
419 rd_data += num_bytes;
420 len -= num_bytes;
421 offset = 0;
422
423 /* check for error condition */
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700424 rc = fg_clear_ima_errors_if_any(chip, false);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700425 if (rc < 0) {
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700426 if (rc == -EAGAIN)
427 pr_err("IMA error cleared, address [%d %d] len %d\n",
428 address, offset, len);
429 else
430 pr_err("Failed to check for ima errors rc=%d\n",
431 rc);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700432 return rc;
433 }
434
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700435 if (chip->use_ima_single_mode) {
436 if (len) {
437 address++;
438 rc = fg_set_address(chip, address);
439 if (rc < 0) {
440 pr_err("failed to set address rc = %d\n",
441 rc);
442 return rc;
443 }
444 }
445 } else {
446 if (len && len < BYTES_PER_SRAM_WORD) {
447 /*
448 * Move to single mode. Changing address is not
449 * required here as it must be in burst mode.
450 * Address will get incremented internally by FG
451 * HW once the MSB of RD_DATA is read.
452 */
453 rc = fg_config_access_mode(chip, FG_READ,
454 false);
455 if (rc < 0) {
456 pr_err("failed to move to single mode rc=%d\n",
457 rc);
458 return -EIO;
459 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700460 }
461 }
462
463 rc = fg_check_iacs_ready(chip);
464 if (rc < 0) {
465 pr_debug("IACS_RDY failed rc=%d\n", rc);
466 return rc;
467 }
468 }
469
470 if (*chip->debug_mask & FG_SRAM_READ) {
471 fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, total_len);
472 pr_info("data read: %s\n", str);
473 }
474
475 return rc;
476}
477
478static int fg_get_mem_access_status(struct fg_chip *chip, bool *status)
479{
480 int rc;
481 u8 mem_if_sts;
482
483 rc = fg_read(chip, MEM_IF_MEM_INTF_CFG(chip), &mem_if_sts, 1);
484 if (rc < 0) {
485 pr_err("failed to read rif_mem status rc=%d\n", rc);
486 return rc;
487 }
488
489 *status = mem_if_sts & MEM_ACCESS_REQ_BIT;
490 return 0;
491}
492
493static bool is_mem_access_available(struct fg_chip *chip, int access)
494{
495 bool rif_mem_sts = true;
496 int rc, time_count = 0;
497
498 while (1) {
499 rc = fg_get_mem_access_status(chip, &rif_mem_sts);
500 if (rc < 0)
501 return rc;
502
503 /* This is an inverting logic */
504 if (!rif_mem_sts)
505 break;
506
507 fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "MEM_ACCESS_REQ is not clear yet for IMA_%s\n",
508 access ? "write" : "read");
509
510 /*
511 * Try this no more than 4 times. If MEM_ACCESS_REQ is not
512 * clear, then return an error instead of waiting for it again.
513 */
514 if (time_count > 4) {
515 pr_err("Tried 4 times(~16ms) polling MEM_ACCESS_REQ\n");
516 return false;
517 }
518
519 /* Wait for 4ms before reading MEM_ACCESS_REQ again */
520 usleep_range(4000, 4100);
521 time_count++;
522 }
523 return true;
524}
525
526static int fg_interleaved_mem_config(struct fg_chip *chip, u8 *val,
527 u16 address, int offset, int len, bool access)
528{
529 int rc = 0;
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700530 bool burst_mode = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700531
532 if (!is_mem_access_available(chip, access))
533 return -EBUSY;
534
535 /* configure for IMA access */
536 rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
537 MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT,
538 MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT);
539 if (rc < 0) {
540 pr_err("failed to set ima_req_access bit rc=%d\n", rc);
541 return rc;
542 }
543
544 /* configure for the read/write, single/burst mode */
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700545 burst_mode = chip->use_ima_single_mode ? false : ((offset + len) > 4);
546 rc = fg_config_access_mode(chip, access, burst_mode);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700547 if (rc < 0) {
548 pr_err("failed to set memory access rc = %d\n", rc);
549 return rc;
550 }
551
552 rc = fg_check_iacs_ready(chip);
553 if (rc < 0) {
554 pr_err_ratelimited("IACS_RDY failed rc=%d\n", rc);
555 return rc;
556 }
557
558 rc = fg_set_address(chip, address);
559 if (rc < 0) {
560 pr_err("failed to set address rc = %d\n", rc);
561 return rc;
562 }
563
564 if (access == FG_READ) {
565 rc = fg_check_iacs_ready(chip);
566 if (rc < 0) {
567 pr_debug("IACS_RDY failed rc=%d\n", rc);
568 return rc;
569 }
570 }
571
572 return rc;
573}
574
575static int fg_get_beat_count(struct fg_chip *chip, u8 *count)
576{
577 int rc;
578
579 rc = fg_read(chip, MEM_IF_FG_BEAT_COUNT(chip), count, 1);
580 *count &= BEAT_COUNT_MASK;
581 return rc;
582}
583
584int fg_interleaved_mem_read(struct fg_chip *chip, u16 address, u8 offset,
585 u8 *val, int len)
586{
Subbaraman Narayanamurthy95450d62017-01-18 20:10:51 -0800587 int rc = 0, ret;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700588 u8 start_beat_count, end_beat_count, count = 0;
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800589 bool retry = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700590
591 if (offset > 3) {
592 pr_err("offset too large %d\n", offset);
593 return -EINVAL;
594 }
595
596retry:
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800597 if (count >= RETRY_COUNT) {
598 pr_err("Tried %d times\n", RETRY_COUNT);
599 retry = false;
600 goto out;
601 }
602
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700603 rc = fg_interleaved_mem_config(chip, val, address, offset, len,
604 FG_READ);
605 if (rc < 0) {
606 pr_err("failed to configure SRAM for IMA rc = %d\n", rc);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800607 count++;
608 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700609 goto out;
610 }
611
612 /* read the start beat count */
613 rc = fg_get_beat_count(chip, &start_beat_count);
614 if (rc < 0) {
615 pr_err("failed to read beat count rc=%d\n", rc);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800616 count++;
617 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700618 goto out;
619 }
620
621 /* read data */
622 rc = __fg_interleaved_mem_read(chip, address, offset, val, len);
623 if (rc < 0) {
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800624 count++;
625 if (rc == -EAGAIN) {
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700626 pr_err("IMA read failed retry_count = %d\n", count);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700627 goto retry;
628 }
629 pr_err("failed to read SRAM address rc = %d\n", rc);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800630 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700631 goto out;
632 }
633
634 /* read the end beat count */
635 rc = fg_get_beat_count(chip, &end_beat_count);
636 if (rc < 0) {
637 pr_err("failed to read beat count rc=%d\n", rc);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800638 count++;
639 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700640 goto out;
641 }
642
643 fg_dbg(chip, FG_SRAM_READ, "Start beat_count = %x End beat_count = %x\n",
644 start_beat_count, end_beat_count);
645
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800646 if (start_beat_count != end_beat_count) {
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700647 fg_dbg(chip, FG_SRAM_READ, "Beat count(%d/%d) do not match - retry transaction\n",
648 start_beat_count, end_beat_count);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800649 count++;
650 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700651 }
652out:
653 /* Release IMA access */
Subbaraman Narayanamurthy95450d62017-01-18 20:10:51 -0800654 ret = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700655 MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800656 if (rc < 0 && ret < 0) {
Subbaraman Narayanamurthy95450d62017-01-18 20:10:51 -0800657 pr_err("failed to reset IMA access bit ret = %d\n", ret);
658 return ret;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700659 }
660
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800661 if (retry) {
662 retry = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700663 goto retry;
Subbaraman Narayanamurthycd0a9b22016-09-14 19:20:24 -0700664 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700665
666 return rc;
667}
668
669int fg_interleaved_mem_write(struct fg_chip *chip, u16 address, u8 offset,
670 u8 *val, int len, bool atomic_access)
671{
Subbaraman Narayanamurthy95450d62017-01-18 20:10:51 -0800672 int rc = 0, ret;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700673 u8 start_beat_count, end_beat_count, count = 0;
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800674 bool retry = false;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700675
676 if (offset > 3) {
677 pr_err("offset too large %d\n", offset);
678 return -EINVAL;
679 }
680
681retry:
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800682 if (count >= RETRY_COUNT) {
683 pr_err("Tried %d times\n", RETRY_COUNT);
684 retry = false;
685 goto out;
686 }
687
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700688 rc = fg_interleaved_mem_config(chip, val, address, offset, len,
689 FG_WRITE);
690 if (rc < 0) {
691 pr_err("failed to configure SRAM for IMA rc = %d\n", rc);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800692 count++;
693 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700694 goto out;
695 }
696
697 /* read the start beat count */
698 rc = fg_get_beat_count(chip, &start_beat_count);
699 if (rc < 0) {
700 pr_err("failed to read beat count rc=%d\n", rc);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800701 count++;
702 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700703 goto out;
704 }
705
706 /* write data */
707 rc = __fg_interleaved_mem_write(chip, address, offset, val, len);
708 if (rc < 0) {
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800709 count++;
Subbaraman Narayanamurthy1dece462017-03-23 11:06:08 -0700710 if (rc == -EAGAIN) {
711 pr_err("IMA write failed retry_count = %d\n", count);
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700712 goto retry;
713 }
714 pr_err("failed to write SRAM address rc = %d\n", rc);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800715 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700716 goto out;
717 }
718
719 /* read the end beat count */
720 rc = fg_get_beat_count(chip, &end_beat_count);
721 if (rc < 0) {
722 pr_err("failed to read beat count rc=%d\n", rc);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800723 count++;
724 retry = true;
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700725 goto out;
726 }
727
728 if (atomic_access && start_beat_count != end_beat_count)
729 pr_err("Start beat_count = %x End beat_count = %x\n",
730 start_beat_count, end_beat_count);
731out:
732 /* Release IMA access */
Subbaraman Narayanamurthy95450d62017-01-18 20:10:51 -0800733 ret = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700734 MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800735 if (rc < 0 && ret < 0) {
Subbaraman Narayanamurthy95450d62017-01-18 20:10:51 -0800736 pr_err("failed to reset IMA access bit ret = %d\n", ret);
737 return ret;
738 }
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700739
Subbaraman Narayanamurthyae899e22017-01-20 18:26:25 -0800740 if (retry) {
741 retry = false;
742 goto retry;
743 }
744
Subbaraman Narayanamurthy95450d62017-01-18 20:10:51 -0800745 /* Return the error we got before releasing memory access */
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700746 return rc;
747}
748
749int fg_ima_init(struct fg_chip *chip)
750{
751 int rc;
752
753 /*
754 * Change the FG_MEM_INT interrupt to track IACS_READY
755 * condition instead of end-of-transaction. This makes sure
756 * that the next transaction starts only after the hw is ready.
757 */
758 rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), IACS_INTR_SRC_SLCT_BIT,
759 IACS_INTR_SRC_SLCT_BIT);
760 if (rc < 0) {
761 pr_err("failed to configure interrupt source %d\n", rc);
762 return rc;
763 }
764
Subbaraman Narayanamurthya71c9dd2016-10-14 19:38:05 -0700765 /* Clear DMA errors if any before clearing IMA errors */
766 rc = fg_clear_dma_errors_if_any(chip);
767 if (rc < 0) {
768 pr_err("Error in checking DMA errors rc:%d\n", rc);
769 return rc;
770 }
771
772 /* Clear IMA errors if any before SRAM transactions can begin */
773 rc = fg_clear_ima_errors_if_any(chip, true);
774 if (rc < 0 && rc != -EAGAIN) {
775 pr_err("Error in checking IMA errors rc:%d\n", rc);
776 return rc;
777 }
778
Subbaraman Narayanamurthy6accb262016-03-14 16:41:16 -0700779 return 0;
780}