blob: f06989b8af76f2e0e61649faef5e6d57825d537c [file] [log] [blame]
Angel Pons5f249e62020-04-04 18:51:01 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Angel Pons5f249e62020-04-04 18:51:01 +02002
David Hendricks8cbd5692017-12-01 20:49:48 -08003/*
David Hendricks8cbd5692017-12-01 20:49:48 -08004 * Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0.
5 */
Angel Pons5f249e62020-04-04 18:51:01 +02006
David Hendricks8cbd5692017-12-01 20:49:48 -08007#include <console/console.h>
8#include <soc/twsi.h>
9#include <soc/clock.h>
10#include <device/i2c.h>
11#include <device/i2c_simple.h>
David Hendricks8cbd5692017-12-01 20:49:48 -080012#include <delay.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020013#include <device/mmio.h>
David Hendricks8cbd5692017-12-01 20:49:48 -080014#include <soc/addressmap.h>
Jes Klinke19baa9d2022-02-22 16:00:09 -080015#include <timer.h>
David Hendricks8cbd5692017-12-01 20:49:48 -080016
17#define TWSI_THP 24
18
19#define TWSI_SW_TWSI 0x1000
20#define TWSI_TWSI_SW 0x1008
21#define TWSI_INT 0x1010
22#define TWSI_SW_TWSI_EXT 0x1018
23
24union twsx_sw_twsi {
25 u64 u;
26 struct {
27 u64 data:32;
28 u64 eop_ia:3;
29 u64 ia:5;
30 u64 addr:10;
31 u64 scr:2;
32 u64 size:3;
33 u64 sovr:1;
34 u64 r:1;
35 u64 op:4;
36 u64 eia:1;
37 u64 slonly:1;
38 u64 v:1;
39 } s;
40};
41
42union twsx_sw_twsi_ext {
43 u64 u;
44 struct {
45 u64 data:32;
46 u64 ia:8;
47 u64 :24;
48 } s;
49};
50
51union twsx_int {
52 u64 u;
53 struct {
54 u64 st_int:1; /** TWSX_SW_TWSI register update int */
55 u64 ts_int:1; /** TWSX_TWSI_SW register update int */
56 u64 core_int:1; /** TWSI core interrupt, ignored for HLC */
57 u64 :5; /** Reserved */
58 u64 sda_ovr:1; /** SDA testing override */
59 u64 scl_ovr:1; /** SCL testing override */
60 u64 sda:1; /** SDA signal */
61 u64 scl:1; /** SCL signal */
62 u64 :52; /** Reserved */
63 } s;
64};
65
66enum {
67 TWSI_OP_WRITE = 0,
68 TWSI_OP_READ = 1,
69};
70
71enum {
72 TWSI_EOP_SLAVE_ADDR = 0,
73 TWSI_EOP_CLK_CTL = 3,
74 TWSI_SW_EOP_IA = 6,
75};
76
77enum {
78 TWSI_SLAVEADD = 0,
79 TWSI_DATA = 1,
80 TWSI_CTL = 2,
81 TWSI_CLKCTL = 3,
82 TWSI_STAT = 3,
83 TWSI_SLAVEADD_EXT = 4,
84 TWSI_RST = 7,
85};
86
87enum {
88 TWSI_CTL_AAK = (1 << 2),
89 TWSI_CTL_IFLG = (1 << 3),
90 TWSI_CTL_STP = (1 << 4),
91 TWSI_CTL_STA = (1 << 5),
92 TWSI_CTL_ENAB = (1 << 6),
93 TWSI_CTL_CE = (1 << 7),
94};
95
96enum {
97 /** Bus error */
98 TWSI_STAT_BUS_ERROR = 0x00,
99 /** Start condition transmitted */
100 TWSI_STAT_START = 0x08,
101 /** Repeat start condition transmitted */
102 TWSI_STAT_RSTART = 0x10,
103 /** Address + write bit transmitted, ACK received */
104 TWSI_STAT_TXADDR_ACK = 0x18,
105 /** Address + write bit transmitted, /ACK received */
106 TWSI_STAT_TXADDR_NAK = 0x20,
107 /** Data byte transmitted in master mode, ACK received */
108 TWSI_STAT_TXDATA_ACK = 0x28,
109 /** Data byte transmitted in master mode, ACK received */
110 TWSI_STAT_TXDATA_NAK = 0x30,
111 /** Arbitration lost in address or data byte */
112 TWSI_STAT_TX_ARB_LOST = 0x38,
113 /** Address + read bit transmitted, ACK received */
114 TWSI_STAT_RXADDR_ACK = 0x40,
115 /** Address + read bit transmitted, /ACK received */
116 TWSI_STAT_RXADDR_NAK = 0x48,
117 /** Data byte received in master mode, ACK transmitted */
118 TWSI_STAT_RXDATA_ACK_SENT = 0x50,
119 /** Data byte received, NACK transmitted */
120 TWSI_STAT_RXDATA_NAK_SENT = 0x58,
121 /** Slave address received, sent ACK */
122 TWSI_STAT_SLAVE_RXADDR_ACK = 0x60,
123 /**
124 * Arbitration lost in address as master, slave address + write bit
125 * received, ACK transmitted
126 */
127 TWSI_STAT_TX_ACK_ARB_LOST = 0x68,
128 /** General call address received, ACK transmitted */
129 TWSI_STAT_RX_GEN_ADDR_ACK = 0x70,
130 /**
131 * Arbitration lost in address as master, general call address
132 * received, ACK transmitted
133 */
134 TWSI_STAT_RX_GEN_ADDR_ARB_LOST = 0x78,
135 /** Data byte received after slave address received, ACK transmitted */
136 TWSI_STAT_SLAVE_RXDATA_ACK = 0x80,
137 /** Data byte received after slave address received, /ACK transmitted */
138 TWSI_STAT_SLAVE_RXDATA_NAK = 0x88,
139 /**
140 * Data byte received after general call address received, ACK
141 * transmitted
142 */
143 TWSI_STAT_GEN_RXADDR_ACK = 0x90,
144 /**
145 * Data byte received after general call address received, /ACK
146 * transmitted
147 */
148 TWSI_STAT_GEN_RXADDR_NAK = 0x98,
149 /** STOP or repeated START condition received in slave mode */
150 TWSI_STAT_STOP_MULTI_START = 0xA0,
151 /** Slave address + read bit received, ACK transmitted */
152 TWSI_STAT_SLAVE_RXADDR2_ACK = 0xA8,
153 /**
154 * Arbitration lost in address as master, slave address + read bit
155 * received, ACK transmitted
156 */
157 TWSI_STAT_RXDATA_ACK_ARB_LOST = 0xB0,
158 /** Data byte transmitted in slave mode, ACK received */
159 TWSI_STAT_SLAVE_TXDATA_ACK = 0xB8,
160 /** Data byte transmitted in slave mode, /ACK received */
161 TWSI_STAT_SLAVE_TXDATA_NAK = 0xC0,
162 /** Last byte transmitted in slave mode, ACK received */
163 TWSI_STAT_SLAVE_TXDATA_END_ACK = 0xC8,
164 /** Second address byte + write bit transmitted, ACK received */
165 TWSI_STAT_TXADDR2DATA_ACK = 0xD0,
166 /** Second address byte + write bit transmitted, /ACK received */
167 TWSI_STAT_TXADDR2DATA_NAK = 0xD8,
168 /** No relevant status information */
169 TWSI_STAT_IDLE = 0xF8
170};
171
172/**
173 * Returns true if we lost arbitration
174 *
175 * @param code status code
176 * @param final_read true if this is the final read operation
177 *
178 * @return true if arbitration has been lost, false if it hasn't been lost.
179 */
180static int twsi_i2c_lost_arb(u8 code, int final_read)
181{
182 switch (code) {
183 /* Arbitration lost */
184 case TWSI_STAT_TX_ARB_LOST:
185 case TWSI_STAT_TX_ACK_ARB_LOST:
186 case TWSI_STAT_RX_GEN_ADDR_ARB_LOST:
187 case TWSI_STAT_RXDATA_ACK_ARB_LOST:
188 return -1;
189
190 /* Being addressed as slave, should back off and listen */
191 case TWSI_STAT_SLAVE_RXADDR_ACK:
192 case TWSI_STAT_RX_GEN_ADDR_ACK:
193 case TWSI_STAT_GEN_RXADDR_ACK:
194 case TWSI_STAT_GEN_RXADDR_NAK:
195 return -1;
196
197 /* Core busy as slave */
198 case TWSI_STAT_SLAVE_RXDATA_ACK:
199 case TWSI_STAT_SLAVE_RXDATA_NAK:
200 case TWSI_STAT_STOP_MULTI_START:
201 case TWSI_STAT_SLAVE_RXADDR2_ACK:
202 case TWSI_STAT_SLAVE_TXDATA_ACK:
203 case TWSI_STAT_SLAVE_TXDATA_NAK:
204 case TWSI_STAT_SLAVE_TXDATA_END_ACK:
205 return -1;
206
207 /* Ack allowed on pre-terminal bytes only */
208 case TWSI_STAT_RXDATA_ACK_SENT:
209 if (!final_read)
210 return 0;
211 return -1;
212
213 /* NAK allowed on terminal byte only */
214 case TWSI_STAT_RXDATA_NAK_SENT:
215 if (!final_read)
216 return 0;
217 return -1;
218
219 case TWSI_STAT_TXDATA_NAK:
220 case TWSI_STAT_TXADDR_NAK:
221 case TWSI_STAT_RXADDR_NAK:
222 case TWSI_STAT_TXADDR2DATA_NAK:
223 return -1;
224 }
225 return 0;
226}
227
228#define RST_BOOT_PNR_MUL(Val) ((Val >> 33) & 0x1F)
229
230/**
231 * Writes to the MIO_TWS(0..5)_SW_TWSI register
232 *
233 * @param baseaddr Base address of i2c registers
234 * @param sw_twsi value to write
235 *
236 * @return 0 for success, otherwise error
237 */
238static u64 twsi_write_sw(void *baseaddr, union twsx_sw_twsi sw_twsi)
239{
240 unsigned long timeout = 500000;
241
242 sw_twsi.s.r = 0;
243 sw_twsi.s.v = 1;
244
245 printk(BIOS_SPEW, "%s(%p, 0x%llx)\n", __func__, baseaddr, sw_twsi.u);
246 write64(baseaddr + TWSI_SW_TWSI, sw_twsi.u);
247 do {
248 sw_twsi.u = read64(baseaddr + TWSI_SW_TWSI);
249 timeout--;
250 } while (sw_twsi.s.v != 0 && timeout > 0);
251
252 if (sw_twsi.s.v)
253 printk(BIOS_ERR, "%s: timed out\n", __func__);
254 return sw_twsi.u;
255}
256
257/**
258 * Reads the MIO_TWS(0..5)_SW_TWSI register
259 *
260 * @param baseaddr Base address of i2c registers
261 * @param sw_twsi value for eia and op, etc. to read
262 *
263 * @return value of the register
264 */
265static u64 twsi_read_sw(void *baseaddr, union twsx_sw_twsi sw_twsi)
266{
267 unsigned long timeout = 500000;
268 sw_twsi.s.r = 1;
269 sw_twsi.s.v = 1;
270
271 printk(BIOS_SPEW, "%s(%p, 0x%llx)\n", __func__, baseaddr, sw_twsi.u);
272 write64(baseaddr + TWSI_SW_TWSI, sw_twsi.u);
273
274 do {
275 sw_twsi.u = read64(baseaddr + TWSI_SW_TWSI);
276 timeout--;
277 } while (sw_twsi.s.v != 0 && timeout > 0);
278
279 if (sw_twsi.s.v)
280 printk(BIOS_ERR, "%s: Error writing 0x%llx\n", __func__,
281 sw_twsi.u);
282
283 printk(BIOS_SPEW, "%s: Returning 0x%llx\n", __func__, sw_twsi.u);
284 return sw_twsi.u;
285}
286
287/**
288 * Write control register
289 *
290 * @param baseaddr Base address for i2c registers
291 * @param data data to write
292 */
293static void twsi_write_ctl(void *baseaddr, const u8 data)
294{
295 union twsx_sw_twsi twsi_sw;
296
297 printk(BIOS_SPEW, "%s(%p, 0x%x)\n", __func__, baseaddr, data);
298 twsi_sw.u = 0;
299
300 twsi_sw.s.op = TWSI_SW_EOP_IA;
301 twsi_sw.s.eop_ia = TWSI_CTL;
302 twsi_sw.s.data = data;
303
304 twsi_write_sw(baseaddr, twsi_sw);
305}
306
307/**
308 * Reads the TWSI Control Register
309 *
310 * @param[in] baseaddr Base address for i2c
311 *
312 * @return 8-bit TWSI control register
313 */
314static u32 twsi_read_ctl(void *baseaddr)
315{
316 union twsx_sw_twsi sw_twsi;
317
318 sw_twsi.u = 0;
319 sw_twsi.s.op = TWSI_SW_EOP_IA;
320 sw_twsi.s.eop_ia = TWSI_CTL;
321
322 sw_twsi.u = twsi_read_sw(baseaddr, sw_twsi);
323 printk(BIOS_SPEW, "%s(%p): 0x%x\n", __func__, baseaddr, sw_twsi.s.data);
324 return sw_twsi.s.data;
325}
326
327/**
328 * Read i2c status register
329 *
330 * @param baseaddr Base address of i2c registers
331 *
332 * @return value of status register
333 */
334static u8 twsi_read_status(void *baseaddr)
335{
336 union twsx_sw_twsi twsi_sw;
337
338 twsi_sw.u = 0;
339 twsi_sw.s.op = TWSI_SW_EOP_IA;
340 twsi_sw.s.eop_ia = TWSI_STAT;
341
342 return twsi_read_sw(baseaddr, twsi_sw);
343}
344
345/**
346 * Waits for an i2c operation to complete
347 *
348 * @param baseaddr Base address of registers
349 *
350 * @return 0 for success, 1 if timeout
351 */
Jes Klinke19baa9d2022-02-22 16:00:09 -0800352static int twsi_wait(void *baseaddr, struct stopwatch *timeout)
David Hendricks8cbd5692017-12-01 20:49:48 -0800353{
David Hendricks8cbd5692017-12-01 20:49:48 -0800354 u8 twsi_ctl;
355
356 printk(BIOS_SPEW, "%s(%p)\n", __func__, baseaddr);
357 do {
358 twsi_ctl = twsi_read_ctl(baseaddr);
359 twsi_ctl &= TWSI_CTL_IFLG;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800360 } while (!twsi_ctl && !stopwatch_expired(timeout));
David Hendricks8cbd5692017-12-01 20:49:48 -0800361
362 printk(BIOS_SPEW, " return: %u\n", !twsi_ctl);
363 return !twsi_ctl;
364}
365
366/**
367 * Sends an i2c stop condition
368 *
369 * @param baseaddr register base address
370 *
371 * @return 0 for success, -1 if error
372 */
373static int twsi_stop(void *baseaddr)
374{
375 u8 stat;
376 twsi_write_ctl(baseaddr, TWSI_CTL_STP | TWSI_CTL_ENAB);
377
378 stat = twsi_read_status(baseaddr);
379 if (stat != TWSI_STAT_IDLE) {
380 printk(BIOS_ERR, "%s: Bad status on bus@%p\n", __func__,
381 baseaddr);
382 return -1;
383 }
384 return 0;
385}
386
387/**
388 * Manually clear the I2C bus and send a stop
389 */
390static void twsi_unblock(void *baseaddr)
391{
392 int i;
393 union twsx_int int_reg;
394
395 int_reg.u = 0;
396 for (i = 0; i < 9; i++) {
397 int_reg.s.scl_ovr = 0;
398 write64(baseaddr + TWSI_INT, int_reg.u);
399 udelay(5);
400 int_reg.s.scl_ovr = 1;
401 write64(baseaddr + TWSI_INT, int_reg.u);
402 udelay(5);
403 }
404 int_reg.s.sda_ovr = 1;
405 write64(baseaddr + TWSI_INT, int_reg.u);
406 udelay(5);
407 int_reg.s.scl_ovr = 0;
408 write64(baseaddr + TWSI_INT, int_reg.u);
409 udelay(5);
410 int_reg.u = 0;
411 write64(baseaddr + TWSI_INT, int_reg.u);
412 udelay(5);
413}
414
415/**
416 * Unsticks the i2c bus
417 *
418 * @param baseaddr base address of registers
419 */
420static int twsi_start_unstick(void *baseaddr)
421{
422 twsi_stop(baseaddr);
423
424 twsi_unblock(baseaddr);
425
426 return 0;
427}
428
429/**
430 * Sends an i2c start condition
431 *
432 * @param baseaddr base address of registers
433 *
434 * @return 0 for success, otherwise error
435 */
436static int twsi_start(void *baseaddr)
437{
438 int result;
439 u8 stat;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800440 struct stopwatch timeout;
David Hendricks8cbd5692017-12-01 20:49:48 -0800441
442 printk(BIOS_SPEW, "%s(%p)\n", __func__, baseaddr);
Jes Klinke19baa9d2022-02-22 16:00:09 -0800443 stopwatch_init_usecs_expire(&timeout, CONFIG_I2C_TRANSFER_TIMEOUT_US);
David Hendricks8cbd5692017-12-01 20:49:48 -0800444 twsi_write_ctl(baseaddr, TWSI_CTL_STA | TWSI_CTL_ENAB);
Jes Klinke19baa9d2022-02-22 16:00:09 -0800445 result = twsi_wait(baseaddr, &timeout);
David Hendricks8cbd5692017-12-01 20:49:48 -0800446 if (result) {
447 stat = twsi_read_status(baseaddr);
448 printk(BIOS_SPEW, "%s: result: 0x%x, status: 0x%x\n", __func__,
449 result, stat);
450 switch (stat) {
451 case TWSI_STAT_START:
452 case TWSI_STAT_RSTART:
453 return 0;
454 case TWSI_STAT_RXADDR_ACK:
455 default:
456 return twsi_start_unstick(baseaddr);
457 }
458 }
459 printk(BIOS_SPEW, "%s: success\n", __func__);
460 return 0;
461}
462
463/**
464 * Writes data to the i2c bus
465 *
466 * @param baseraddr register base address
467 * @param slave_addr address of slave to write to
468 * @param buffer Pointer to buffer to write
469 * @param length Number of bytes in buffer to write
470 *
471 * @return 0 for success, otherwise error
472 */
473static int twsi_write_data(void *baseaddr, const u8 slave_addr,
474 const u8 *buffer, const unsigned int length)
475{
476 union twsx_sw_twsi twsi_sw;
477 unsigned int curr = 0;
478 int result;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800479 struct stopwatch timeout;
David Hendricks8cbd5692017-12-01 20:49:48 -0800480
481 printk(BIOS_SPEW, "%s(%p, 0x%x, %p, 0x%x)\n", __func__, baseaddr,
482 slave_addr, buffer, length);
Jes Klinke19baa9d2022-02-22 16:00:09 -0800483 stopwatch_init_usecs_expire(&timeout, CONFIG_I2C_TRANSFER_TIMEOUT_US);
David Hendricks8cbd5692017-12-01 20:49:48 -0800484 result = twsi_start(baseaddr);
485 if (result) {
486 printk(BIOS_ERR, "%s: Could not start BUS transaction\n",
487 __func__);
488 return -1;
489 }
490
Jes Klinke19baa9d2022-02-22 16:00:09 -0800491 result = twsi_wait(baseaddr, &timeout);
David Hendricks8cbd5692017-12-01 20:49:48 -0800492 if (result) {
493 printk(BIOS_ERR, "%s: wait failed\n", __func__);
494 return result;
495 }
496
497 twsi_sw.u = 0;
498 twsi_sw.s.op = TWSI_SW_EOP_IA;
499 twsi_sw.s.eop_ia = TWSI_DATA;
Elyes Haouasa51d9b02022-11-18 15:10:03 +0100500 twsi_sw.s.data = (u32)(slave_addr << 1) | TWSI_OP_WRITE;
David Hendricks8cbd5692017-12-01 20:49:48 -0800501
502 twsi_write_sw(baseaddr, twsi_sw);
503 twsi_write_ctl(baseaddr, TWSI_CTL_ENAB);
504
505 printk(BIOS_SPEW, "%s: Waiting\n", __func__);
Jes Klinke19baa9d2022-02-22 16:00:09 -0800506 result = twsi_wait(baseaddr, &timeout);
David Hendricks8cbd5692017-12-01 20:49:48 -0800507 if (result) {
508 printk(BIOS_ERR, "%s: Timed out writing slave address 0x%x\n",
509 __func__, slave_addr);
510 return result;
511 }
512 result = twsi_read_status(baseaddr);
513 if ((result = twsi_read_status(baseaddr)) != TWSI_STAT_TXADDR_ACK) {
514 twsi_stop(baseaddr);
515 return twsi_i2c_lost_arb(result, 0);
516 }
517
518 while (curr < length) {
519 twsi_sw.u = 0;
520 twsi_sw.s.op = TWSI_SW_EOP_IA;
521 twsi_sw.s.eop_ia = TWSI_DATA;
522 twsi_sw.s.data = buffer[curr++];
523
524 twsi_write_sw(baseaddr, twsi_sw);
525 twsi_write_ctl(baseaddr, TWSI_CTL_ENAB);
526
Jes Klinke19baa9d2022-02-22 16:00:09 -0800527 result = twsi_wait(baseaddr, &timeout);
David Hendricks8cbd5692017-12-01 20:49:48 -0800528 if (result) {
529 printk(BIOS_ERR, "%s: Timed out writing data to 0x%x\n",
530 __func__, slave_addr);
531 return result;
532 }
533 }
534
535 printk(BIOS_SPEW, "%s: Stopping\n", __func__);
536 return twsi_stop(baseaddr);
537}
538
539/**
540 * Performs a read transaction on the i2c bus
541 *
542 * @param baseaddr Base address of twsi registers
543 * @param slave_addr i2c bus address to read from
544 * @param buffer buffer to read into
545 * @param length number of bytes to read
546 *
547 * @return 0 for success, otherwise error
548 */
549static int twsi_read_data(void *baseaddr, const u8 slave_addr,
550 u8 *buffer, const unsigned int length)
551{
552 union twsx_sw_twsi twsi_sw;
553 unsigned int curr = 0;
554 int result;
Jes Klinke19baa9d2022-02-22 16:00:09 -0800555 struct stopwatch timeout;
David Hendricks8cbd5692017-12-01 20:49:48 -0800556
557 printk(BIOS_SPEW, "%s(%p, 0x%x, %p, %u)\n", __func__, baseaddr,
558 slave_addr, buffer, length);
Jes Klinke19baa9d2022-02-22 16:00:09 -0800559 stopwatch_init_usecs_expire(&timeout, CONFIG_I2C_TRANSFER_TIMEOUT_US);
David Hendricks8cbd5692017-12-01 20:49:48 -0800560 result = twsi_start(baseaddr);
561 if (result) {
562 printk(BIOS_ERR, "%s: start failed\n", __func__);
563 return result;
564 }
565
Jes Klinke19baa9d2022-02-22 16:00:09 -0800566 result = twsi_wait(baseaddr, &timeout);
David Hendricks8cbd5692017-12-01 20:49:48 -0800567 if (result) {
568 printk(BIOS_ERR, "%s: wait failed\n", __func__);
569 return result;
570 }
571
572 twsi_sw.u = 0;
573
574 twsi_sw.s.op = TWSI_SW_EOP_IA;
575 twsi_sw.s.eop_ia = TWSI_DATA;
576
Elyes Haouasa51d9b02022-11-18 15:10:03 +0100577 twsi_sw.s.data = (u32)(slave_addr << 1) | TWSI_OP_READ;
David Hendricks8cbd5692017-12-01 20:49:48 -0800578
579 twsi_write_sw(baseaddr, twsi_sw);
580 twsi_write_ctl(baseaddr, TWSI_CTL_ENAB);
581
Jes Klinke19baa9d2022-02-22 16:00:09 -0800582 result = twsi_wait(baseaddr, &timeout);
David Hendricks8cbd5692017-12-01 20:49:48 -0800583 if (result) {
584 printk(BIOS_ERR, "%s: waiting for sending addr failed\n", __func__);
585 return result;
586 }
587
588 result = twsi_read_status(baseaddr);
589 if (result != TWSI_STAT_RXADDR_ACK) {
590 twsi_stop(baseaddr);
591 return twsi_i2c_lost_arb(result, 0);
592 }
593
594 while (curr < length) {
595 twsi_write_ctl(baseaddr, TWSI_CTL_ENAB |
596 ((curr < length - 1) ? TWSI_CTL_AAK : 0));
597
Jes Klinke19baa9d2022-02-22 16:00:09 -0800598 result = twsi_wait(baseaddr, &timeout);
David Hendricks8cbd5692017-12-01 20:49:48 -0800599 if (result) {
600 printk(BIOS_ERR, "%s: waiting for data failed\n",
601 __func__);
602 return result;
603 }
604
605 twsi_sw.u = twsi_read_sw(baseaddr, twsi_sw);
606 buffer[curr++] = twsi_sw.s.data;
607 }
608
609 twsi_stop(baseaddr);
610
611 return 0;
612}
613
614static int twsi_set_speed(void *baseaddr, const unsigned int speed)
615{
616 u64 io_clock_hz;
617 int n_div;
618 int m_div;
619 union twsx_sw_twsi sw_twsi;
620
621 io_clock_hz = thunderx_get_io_clock();
622
623 /* Set the TWSI clock to a conservative TWSI_BUS_FREQ. Compute the
624 * clocks M divider based on the SCLK.
625 * TWSI freq = (core freq) / (20 x (M+1) x (thp+1) x 2^N)
626 * M = ((core freq) / (20 x (TWSI freq) x (thp+1) x 2^N)) - 1
627 */
628 for (n_div = 0; n_div < 8; n_div++) {
629 m_div = io_clock_hz / (20 * speed * (TWSI_THP + 1));
630 m_div /= 1 << n_div;
631 m_div -= 1;
632 if (m_div < 16)
633 break;
634 }
635 if (m_div >= 16)
636 return -1;
637
638 sw_twsi.u = 0;
639 sw_twsi.s.v = 1;
640 sw_twsi.s.op = 0x6; /* See EOP field */
641 sw_twsi.s.r = 0; /* Select CLKCTL when R = 0 */
642 sw_twsi.s.eop_ia = 3; /* R=0 selects CLKCTL, R=1 selects STAT */
643 sw_twsi.s.data = ((m_div & 0xf) << 3) | ((n_div & 0x7) << 0);
644
645 twsi_write_sw(baseaddr, sw_twsi);
646 return 0;
647}
648
649int twsi_init(unsigned int bus, enum i2c_speed hz)
650{
651 void *baseaddr = (void *)MIO_TWSx_PF_BAR0(bus);
652 if (!baseaddr)
653 return -1;
654
655 if (twsi_set_speed(baseaddr, hz) < 0)
656 return -1;
657
658 /* Enable TWSI, HLC disable, STOP, NAK */
659 twsi_write_ctl(baseaddr, TWSI_CTL_ENAB);
660
661 return 0;
662}
663
Martin Roth57e89092019-10-23 21:45:23 -0600664int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
David Hendricks8cbd5692017-12-01 20:49:48 -0800665 int seg_count)
666{
667 int result;
668 void *baseaddr = (void *)MIO_TWSx_PF_BAR0(bus);
669 if (!baseaddr)
670 return -1;
671
672 printk(BIOS_SPEW, "%s: %d messages\n", __func__, seg_count);
673 for (; seg_count > 0; seg_count--, segments++) {
674 if (segments->flags & I2C_M_RD) {
675 result = twsi_read_data(baseaddr, segments->slave,
676 segments->buf, segments->len);
677 } else {
678 result = twsi_write_data(baseaddr, segments->slave,
679 segments->buf, segments->len);
680 }
681 if (result) {
682 printk(BIOS_ERR, "%s: error transmitting data\n",
683 __func__);
684 return -1;
685 }
686 }
687
688 return 0;
689}