blob: 618836ba5f6825edfc1ed269fe94736146412845 [file] [log] [blame]
Icenowy Zhengd9cb8952018-07-21 19:06:46 +08001/*
2 * Copyright (C) 2018 Marvell International Ltd.
3 * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 * https://spdx.org/licenses
7 */
8
9/*
10 * This driver is for Mentor Graphics Inventra MI2CV IP core, which is used
11 * for Marvell and Allwinner SoCs in ATF.
12 */
13
14#include <debug.h>
15#include <delay_timer.h>
16#include <errno.h>
17#include <mentor/mi2cv.h>
18#include <mmio.h>
19
20#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
21#define DEBUG_I2C
22#endif
23
24#define I2C_TIMEOUT_VALUE 0x500
25#define I2C_MAX_RETRY_CNT 1000
26#define I2C_CMD_WRITE 0x0
27#define I2C_CMD_READ 0x1
28
29#define I2C_DATA_ADDR_7BIT_OFFS 0x1
30#define I2C_DATA_ADDR_7BIT_MASK (0xFF << I2C_DATA_ADDR_7BIT_OFFS)
31
32#define I2C_CONTROL_ACK 0x00000004
33#define I2C_CONTROL_IFLG 0x00000008
34#define I2C_CONTROL_STOP 0x00000010
35#define I2C_CONTROL_START 0x00000020
36#define I2C_CONTROL_TWSIEN 0x00000040
37#define I2C_CONTROL_INTEN 0x00000080
38
39#define I2C_STATUS_START 0x08
40#define I2C_STATUS_REPEATED_START 0x10
41#define I2C_STATUS_ADDR_W_ACK 0x18
42#define I2C_STATUS_DATA_W_ACK 0x28
43#define I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER 0x38
44#define I2C_STATUS_ADDR_R_ACK 0x40
45#define I2C_STATUS_DATA_R_ACK 0x50
46#define I2C_STATUS_DATA_R_NAK 0x58
47#define I2C_STATUS_LOST_ARB_GENERAL_CALL 0x78
48#define I2C_STATUS_IDLE 0xF8
49
50#define I2C_UNSTUCK_TRIGGER 0x1
51#define I2C_UNSTUCK_ONGOING 0x2
52#define I2C_UNSTUCK_ERROR 0x4
53
54static struct mentor_i2c_regs *base;
55
56static int mentor_i2c_lost_arbitration(uint32_t *status)
57{
58 *status = mmio_read_32((uintptr_t)&base->status);
59 if ((*status == I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER) ||
60 (*status == I2C_STATUS_LOST_ARB_GENERAL_CALL))
61 return -EAGAIN;
62
63 return 0;
64}
65
66static void mentor_i2c_interrupt_clear(void)
67{
68 uint32_t reg;
69
70 reg = mmio_read_32((uintptr_t)&base->control);
71 reg &= ~(I2C_CONTROL_IFLG);
72 mmio_write_32((uintptr_t)&base->control, reg);
73 /* Wait for 1 us for the clear to take effect */
74 udelay(1);
75}
76
77static int mentor_i2c_interrupt_get(void)
78{
79 uint32_t reg;
80
81 /* get the interrupt flag bit */
82 reg = mmio_read_32((uintptr_t)&base->control);
83 reg &= I2C_CONTROL_IFLG;
84 return reg && I2C_CONTROL_IFLG;
85}
86
87static int mentor_i2c_wait_interrupt(void)
88{
89 uint32_t timeout = 0;
90
91 while (!mentor_i2c_interrupt_get() && (timeout++ < I2C_TIMEOUT_VALUE))
92 ;
93 if (timeout >= I2C_TIMEOUT_VALUE)
94 return -ETIMEDOUT;
95
96 return 0;
97}
98
99static int mentor_i2c_start_bit_set(void)
100{
101 int is_int_flag = 0;
102 uint32_t status;
103
104 if (mentor_i2c_interrupt_get())
105 is_int_flag = 1;
106
107 /* set start bit */
108 mmio_write_32((uintptr_t)&base->control,
109 mmio_read_32((uintptr_t)&base->control) |
110 I2C_CONTROL_START);
111
112 /* in case that the int flag was set before i.e. repeated start bit */
113 if (is_int_flag) {
114 VERBOSE("%s: repeated start Bit\n", __func__);
115 mentor_i2c_interrupt_clear();
116 }
117
118 if (mentor_i2c_wait_interrupt()) {
119 ERROR("Start clear bit timeout\n");
120 return -ETIMEDOUT;
121 }
122
123 /* check that start bit went down */
124 if ((mmio_read_32((uintptr_t)&base->control) &
125 I2C_CONTROL_START) != 0) {
126 ERROR("Start bit didn't went down\n");
127 return -EPERM;
128 }
129
130 /* check the status */
131 if (mentor_i2c_lost_arbitration(&status)) {
132 ERROR("%s - %d: Lost arbitration, got status %x\n",
133 __func__, __LINE__, status);
134 return -EAGAIN;
135 }
136 if ((status != I2C_STATUS_START) &&
137 (status != I2C_STATUS_REPEATED_START)) {
138 ERROR("Got status %x after enable start bit.\n", status);
139 return -EPERM;
140 }
141
142 return 0;
143}
144
145static int mentor_i2c_stop_bit_set(void)
146{
147 int timeout;
148 uint32_t status;
149
150 /* Generate stop bit */
151 mmio_write_32((uintptr_t)&base->control,
152 mmio_read_32((uintptr_t)&base->control) |
153 I2C_CONTROL_STOP);
154 mentor_i2c_interrupt_clear();
155
156 timeout = 0;
157 /* Read control register, check the control stop bit */
158 while ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) &&
159 (timeout++ < I2C_TIMEOUT_VALUE))
160 ;
161 if (timeout >= I2C_TIMEOUT_VALUE) {
162 ERROR("Stop bit didn't went down\n");
163 return -ETIMEDOUT;
164 }
165
166 /* check that stop bit went down */
167 if ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) != 0) {
168 ERROR("Stop bit didn't went down\n");
169 return -EPERM;
170 }
171
172 /* check the status */
173 if (mentor_i2c_lost_arbitration(&status)) {
174 ERROR("%s - %d: Lost arbitration, got status %x\n",
175 __func__, __LINE__, status);
176 return -EAGAIN;
177 }
178 if (status != I2C_STATUS_IDLE) {
179 ERROR("Got status %x after enable stop bit.\n", status);
180 return -EPERM;
181 }
182
183 return 0;
184}
185
186static int mentor_i2c_address_set(uint8_t chain, int command)
187{
188 uint32_t reg, status;
189
190 reg = (chain << I2C_DATA_ADDR_7BIT_OFFS) & I2C_DATA_ADDR_7BIT_MASK;
191 reg |= command;
192 mmio_write_32((uintptr_t)&base->data, reg);
193 udelay(1);
194
195 mentor_i2c_interrupt_clear();
196
197 if (mentor_i2c_wait_interrupt()) {
198 ERROR("Start clear bit timeout\n");
199 return -ETIMEDOUT;
200 }
201
202 /* check the status */
203 if (mentor_i2c_lost_arbitration(&status)) {
204 ERROR("%s - %d: Lost arbitration, got status %x\n",
205 __func__, __LINE__, status);
206 return -EAGAIN;
207 }
208 if (((status != I2C_STATUS_ADDR_R_ACK) && (command == I2C_CMD_READ)) ||
209 ((status != I2C_STATUS_ADDR_W_ACK) && (command == I2C_CMD_WRITE))) {
210 /* only in debug, since in boot we try to read the SPD
211 * of both DRAM, and we don't want error messages in cas
212 * DIMM doesn't exist.
213 */
214 INFO("%s: ERROR - status %x addr in %s mode.\n", __func__,
215 status, (command == I2C_CMD_WRITE) ? "Write" : "Read");
216 return -EPERM;
217 }
218
219 return 0;
220}
221
222/*
223 * The I2C module contains a clock divider to generate the SCL clock.
224 * This function calculates and sets the <N> and <M> fields in the I2C Baud
225 * Rate Register (t=01) to obtain given 'requested_speed'.
226 * The requested_speed will be equal to:
227 * CONFIG_SYS_TCLK / (10 * (M + 1) * (2 << N))
228 * Where M is the value represented by bits[6:3] and N is the value represented
229 * by bits[2:0] of "I2C Baud Rate Register".
230 * Therefore max M which can be set is 16 (2^4) and max N is 8 (2^3). So the
231 * lowest possible baudrate is:
232 * CONFIG_SYS_TCLK/(10 * (16 +1) * (2 << 8), which equals to:
233 * CONFIG_SYS_TCLK/87040. Assuming that CONFIG_SYS_TCLK=250MHz, the lowest
234 * possible frequency is ~2,872KHz.
235 */
236static unsigned int mentor_i2c_bus_speed_set(unsigned int requested_speed)
237{
238 unsigned int n, m, freq, margin, min_margin = 0xffffffff;
239 unsigned int actual_n = 0, actual_m = 0;
240 int val;
241
242 /* Calculate N and M for the TWSI clock baud rate */
243 for (n = 0; n < 8; n++) {
244 for (m = 0; m < 16; m++) {
245 freq = CONFIG_SYS_TCLK / (10 * (m + 1) * (2 << n));
246 val = requested_speed - freq;
247 margin = (val > 0) ? val : -val;
248
249 if ((freq <= requested_speed) &&
250 (margin < min_margin)) {
251 min_margin = margin;
252 actual_n = n;
253 actual_m = m;
254 }
255 }
256 }
257 VERBOSE("%s: actual_n = %u, actual_m = %u\n",
258 __func__, actual_n, actual_m);
259 /* Set the baud rate */
260 mmio_write_32((uintptr_t)&base->baudrate, (actual_m << 3) | actual_n);
261
262 return 0;
263}
264
265#ifdef DEBUG_I2C
266static int mentor_i2c_probe(uint8_t chip)
267{
268 int ret = 0;
269
270 ret = mentor_i2c_start_bit_set();
271 if (ret != 0) {
272 mentor_i2c_stop_bit_set();
273 ERROR("%s - %d: %s", __func__, __LINE__,
274 "mentor_i2c_start_bit_set failed\n");
275 return -EPERM;
276 }
277
278 ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE);
279 if (ret != 0) {
280 mentor_i2c_stop_bit_set();
281 ERROR("%s - %d: %s", __func__, __LINE__,
282 "mentor_i2c_address_set failed\n");
283 return -EPERM;
284 }
285
286 mentor_i2c_stop_bit_set();
287
288 VERBOSE("%s: successful I2C probe\n", __func__);
289
290 return ret;
291}
292#endif
293
294/* regular i2c transaction */
295static int mentor_i2c_data_receive(uint8_t *p_block, uint32_t block_size)
296{
297 uint32_t reg, status, block_size_read = block_size;
298
299 /* Wait for cause interrupt */
300 if (mentor_i2c_wait_interrupt()) {
301 ERROR("Start clear bit timeout\n");
302 return -ETIMEDOUT;
303 }
304 while (block_size_read) {
305 if (block_size_read == 1) {
306 reg = mmio_read_32((uintptr_t)&base->control);
307 reg &= ~(I2C_CONTROL_ACK);
308 mmio_write_32((uintptr_t)&base->control, reg);
309 }
310 mentor_i2c_interrupt_clear();
311
312 if (mentor_i2c_wait_interrupt()) {
313 ERROR("Start clear bit timeout\n");
314 return -ETIMEDOUT;
315 }
316 /* check the status */
317 if (mentor_i2c_lost_arbitration(&status)) {
318 ERROR("%s - %d: Lost arbitration, got status %x\n",
319 __func__, __LINE__, status);
320 return -EAGAIN;
321 }
322 if ((status != I2C_STATUS_DATA_R_ACK) &&
323 (block_size_read != 1)) {
324 ERROR("Status %x in read transaction\n", status);
325 return -EPERM;
326 }
327 if ((status != I2C_STATUS_DATA_R_NAK) &&
328 (block_size_read == 1)) {
329 ERROR("Status %x in Rd Terminate\n", status);
330 return -EPERM;
331 }
332
333 /* read the data */
334 *p_block = (uint8_t) mmio_read_32((uintptr_t)&base->data);
335 VERBOSE("%s: place %d read %x\n", __func__,
336 block_size - block_size_read, *p_block);
337 p_block++;
338 block_size_read--;
339 }
340
341 return 0;
342}
343
344static int mentor_i2c_data_transmit(uint8_t *p_block, uint32_t block_size)
345{
346 uint32_t status, block_size_write = block_size;
347
348 if (mentor_i2c_wait_interrupt()) {
349 ERROR("Start clear bit timeout\n");
350 return -ETIMEDOUT;
351 }
352
353 while (block_size_write) {
354 /* write the data */
355 mmio_write_32((uintptr_t)&base->data, (uint32_t) *p_block);
356 VERBOSE("%s: index = %d, data = %x\n", __func__,
357 block_size - block_size_write, *p_block);
358 p_block++;
359 block_size_write--;
360
361 mentor_i2c_interrupt_clear();
362
363 if (mentor_i2c_wait_interrupt()) {
364 ERROR("Start clear bit timeout\n");
365 return -ETIMEDOUT;
366 }
367
368 /* check the status */
369 if (mentor_i2c_lost_arbitration(&status)) {
370 ERROR("%s - %d: Lost arbitration, got status %x\n",
371 __func__, __LINE__, status);
372 return -EAGAIN;
373 }
374 if (status != I2C_STATUS_DATA_W_ACK) {
375 ERROR("Status %x in write transaction\n", status);
376 return -EPERM;
377 }
378 }
379
380 return 0;
381}
382
383static int mentor_i2c_target_offset_set(uint8_t chip, uint32_t addr, int alen)
384{
385 uint8_t off_block[2];
386 uint32_t off_size;
387
388 if (alen == 2) { /* 2-byte addresses support */
389 off_block[0] = (addr >> 8) & 0xff;
390 off_block[1] = addr & 0xff;
391 off_size = 2;
392 } else { /* 1-byte addresses support */
393 off_block[0] = addr & 0xff;
394 off_size = 1;
395 }
396 VERBOSE("%s: off_size = %x addr1 = %x addr2 = %x\n", __func__,
397 off_size, off_block[0], off_block[1]);
398 return mentor_i2c_data_transmit(off_block, off_size);
399}
400
401#ifdef I2C_CAN_UNSTUCK
402static int mentor_i2c_unstuck(int ret)
403{
404 uint32_t v;
405
406 if (ret != -ETIMEDOUT)
407 return ret;
408 VERBOSE("Trying to \"unstuck i2c\"... ");
409 i2c_init(base);
410 mmio_write_32((uintptr_t)&base->unstuck, I2C_UNSTUCK_TRIGGER);
411 do {
412 v = mmio_read_32((uintptr_t)&base->unstuck);
413 } while (v & I2C_UNSTUCK_ONGOING);
414
415 if (v & I2C_UNSTUCK_ERROR) {
416 VERBOSE("failed - soft reset i2c\n");
417 ret = -EPERM;
418 } else {
419 VERBOSE("ok\n");
420 i2c_init(base);
421 ret = -EAGAIN;
422 }
423 return ret;
424}
425#else
426static int mentor_i2c_unstuck(int ret)
427{
428 VERBOSE("Cannot \"unstuck i2c\" - soft reset i2c\n");
429 return -EPERM;
430}
431#endif
432
433/*
434 * API Functions
435 */
436void i2c_init(void *i2c_base)
437{
438 /* For I2C speed and slave address, now we do not set them since
439 * we just provide the working speed and slave address otherwhere
440 * for i2c_init
441 */
442 base = (struct mentor_i2c_regs *)i2c_base;
443
444 /* Reset the I2C logic */
445 mmio_write_32((uintptr_t)&base->soft_reset, 0);
446
447 udelay(200);
448
449 mentor_i2c_bus_speed_set(CONFIG_SYS_I2C_SPEED);
450
451 /* Enable the I2C and slave */
452 mmio_write_32((uintptr_t)&base->control,
453 I2C_CONTROL_TWSIEN | I2C_CONTROL_ACK);
454
455 /* set the I2C slave address */
456 mmio_write_32((uintptr_t)&base->xtnd_slave_addr, 0);
457 mmio_write_32((uintptr_t)&base->slave_address, CONFIG_SYS_I2C_SLAVE);
458
459 /* unmask I2C interrupt */
460 mmio_write_32((uintptr_t)&base->control,
461 mmio_read_32((uintptr_t)&base->control) |
462 I2C_CONTROL_INTEN);
463
464 udelay(10);
465}
466
467/*
468 * i2c_read: - Read multiple bytes from an i2c device
469 *
470 * The higher level routines take into account that this function is only
471 * called with len < page length of the device (see configuration file)
472 *
473 * @chip: address of the chip which is to be read
474 * @addr: i2c data address within the chip
475 * @alen: length of the i2c data address (1..2 bytes)
476 * @buffer: where to write the data
477 * @len: how much byte do we want to read
478 * @return: 0 in case of success
479 */
480int i2c_read(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len)
481{
482 int ret = 0;
483 uint32_t counter = 0;
484
485#ifdef DEBUG_I2C
486 mentor_i2c_probe(chip);
487#endif
488
489 do {
490 if (ret != -EAGAIN && ret) {
491 ERROR("i2c transaction failed, after %d retries\n",
492 counter);
493 mentor_i2c_stop_bit_set();
494 return ret;
495 }
496
497 /* wait for 1 us for the interrupt clear to take effect */
498 if (counter > 0)
499 udelay(1);
500 counter++;
501
502 ret = mentor_i2c_start_bit_set();
503 if (ret) {
504 ret = mentor_i2c_unstuck(ret);
505 continue;
506 }
507
508 /* if EEPROM device */
509 if (alen != 0) {
510 ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE);
511 if (ret)
512 continue;
513
514 ret = mentor_i2c_target_offset_set(chip, addr, alen);
515 if (ret)
516 continue;
517 ret = mentor_i2c_start_bit_set();
518 if (ret)
519 continue;
520 }
521
522 ret = mentor_i2c_address_set(chip, I2C_CMD_READ);
523 if (ret)
524 continue;
525
526 ret = mentor_i2c_data_receive(buffer, len);
527 if (ret)
528 continue;
529
530 ret = mentor_i2c_stop_bit_set();
531 } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT));
532
533 if (counter == I2C_MAX_RETRY_CNT) {
534 ERROR("I2C transactions failed, got EAGAIN %d times\n",
535 I2C_MAX_RETRY_CNT);
536 ret = -EPERM;
537 }
538 mmio_write_32((uintptr_t)&base->control,
539 mmio_read_32((uintptr_t)&base->control) |
540 I2C_CONTROL_ACK);
541
542 udelay(1);
543 return ret;
544}
545
546/*
547 * i2c_write: - Write multiple bytes to an i2c device
548 *
549 * The higher level routines take into account that this function is only
550 * called with len < page length of the device (see configuration file)
551 *
552 * @chip: address of the chip which is to be written
553 * @addr: i2c data address within the chip
554 * @alen: length of the i2c data address (1..2 bytes)
555 * @buffer: where to find the data to be written
556 * @len: how much byte do we want to read
557 * @return: 0 in case of success
558 */
559int i2c_write(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len)
560{
561 int ret = 0;
562 uint32_t counter = 0;
563
564 do {
565 if (ret != -EAGAIN && ret) {
566 ERROR("i2c transaction failed\n");
567 mentor_i2c_stop_bit_set();
568 return ret;
569 }
570 /* wait for 1 us for the interrupt clear to take effect */
571 if (counter > 0)
572 udelay(1);
573 counter++;
574
575 ret = mentor_i2c_start_bit_set();
576 if (ret) {
577 ret = mentor_i2c_unstuck(ret);
578 continue;
579 }
580
581 ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE);
582 if (ret)
583 continue;
584
585 /* if EEPROM device */
586 if (alen != 0) {
587 ret = mentor_i2c_target_offset_set(chip, addr, alen);
588 if (ret)
589 continue;
590 }
591
592 ret = mentor_i2c_data_transmit(buffer, len);
593 if (ret)
594 continue;
595
596 ret = mentor_i2c_stop_bit_set();
597 } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT));
598
599 if (counter == I2C_MAX_RETRY_CNT) {
600 ERROR("I2C transactions failed, got EAGAIN %d times\n",
601 I2C_MAX_RETRY_CNT);
602 ret = -EPERM;
603 }
604
605 udelay(1);
606 return ret;
607}