1 /* $OpenBSD: dwiic.c,v 1.21 2024/08/17 02:35:00 deraadt Exp $ */
2 /*
3 * Synopsys DesignWare I2C controller
4 *
5 * Copyright (c) 2015-2017 joshua stein <jcs@openbsd.org>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/kernel.h>
23
24 #include <dev/i2c/i2cvar.h>
25
26 #include <dev/ic/dwiicvar.h>
27
28 struct cfdriver dwiic_cd = {
29 NULL, "dwiic", DV_DULL
30 };
31
32 int
dwiic_activate(struct device * self,int act)33 dwiic_activate(struct device *self, int act)
34 {
35 struct dwiic_softc *sc = (struct dwiic_softc *)self;
36 int rv;
37
38 switch (act) {
39 case DVACT_SUSPEND:
40 rv = config_activate_children(self, act);
41 /* disable controller */
42 dwiic_enable(sc, 0);
43
44 /* disable interrupts */
45 dwiic_write(sc, DW_IC_INTR_MASK, 0);
46 dwiic_read(sc, DW_IC_CLR_INTR);
47 break;
48 case DVACT_RESUME:
49 /* if it became enabled for some reason, force it down */
50 dwiic_enable(sc, 0);
51
52 dwiic_write(sc, DW_IC_INTR_MASK, 0);
53 dwiic_read(sc, DW_IC_CLR_INTR);
54
55 /* write standard-mode SCL timing parameters */
56 dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt);
57 dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt);
58
59 /* and fast-mode SCL timing parameters */
60 dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt);
61 dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt);
62
63 /* SDA hold time */
64 dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time);
65
66 dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2);
67 dwiic_write(sc, DW_IC_RX_TL, 0);
68
69 /* configure as i2c master with fast speed */
70 sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
71 DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
72 dwiic_write(sc, DW_IC_CON, sc->master_cfg);
73 rv = config_activate_children(self, act);
74 break;
75 default:
76 rv = config_activate_children(self, act);
77 break;
78 }
79 return rv;
80 }
81
82 int
dwiic_i2c_print(void * aux,const char * pnp)83 dwiic_i2c_print(void *aux, const char *pnp)
84 {
85 struct i2c_attach_args *ia = aux;
86
87 if (pnp != NULL)
88 printf("\"%s\" at %s", ia->ia_name, pnp);
89
90 printf(" addr 0x%x", ia->ia_addr);
91
92 return UNCONF;
93 }
94
95 uint32_t
dwiic_read(struct dwiic_softc * sc,int offset)96 dwiic_read(struct dwiic_softc *sc, int offset)
97 {
98 u_int32_t b = bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset);
99
100 DPRINTF(("%s: read at 0x%x = 0x%x\n", sc->sc_dev.dv_xname, offset, b));
101
102 return b;
103 }
104
105 void
dwiic_write(struct dwiic_softc * sc,int offset,uint32_t val)106 dwiic_write(struct dwiic_softc *sc, int offset, uint32_t val)
107 {
108 DPRINTF(("%s: write at 0x%x: 0x%x\n", sc->sc_dev.dv_xname, offset,
109 val));
110
111 bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val);
112 }
113
114 int
dwiic_i2c_acquire_bus(void * cookie,int flags)115 dwiic_i2c_acquire_bus(void *cookie, int flags)
116 {
117 struct dwiic_softc *sc = cookie;
118
119 if (cold || sc->sc_poll || (flags & I2C_F_POLL))
120 return (0);
121
122 return rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR);
123 }
124
125 void
dwiic_i2c_release_bus(void * cookie,int flags)126 dwiic_i2c_release_bus(void *cookie, int flags)
127 {
128 struct dwiic_softc *sc = cookie;
129
130 if (cold || sc->sc_poll || (flags & I2C_F_POLL))
131 return;
132
133 rw_exit(&sc->sc_i2c_lock);
134 }
135
136 int
dwiic_init(struct dwiic_softc * sc)137 dwiic_init(struct dwiic_softc *sc)
138 {
139 uint32_t reg;
140 uint8_t tx_fifo_depth;
141 uint8_t rx_fifo_depth;
142
143 /* make sure we're talking to a device we know */
144 reg = dwiic_read(sc, DW_IC_COMP_TYPE);
145 if (reg != DW_IC_COMP_TYPE_VALUE) {
146 DPRINTF(("%s: invalid component type 0x%x\n",
147 sc->sc_dev.dv_xname, reg));
148 return 1;
149 }
150
151 /* fetch default timing parameters if not already specified */
152 if (!sc->ss_hcnt)
153 sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT);
154 if (!sc->ss_lcnt)
155 sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT);
156 if (!sc->fs_hcnt)
157 sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT);
158 if (!sc->fs_lcnt)
159 sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT);
160 if (!sc->sda_hold_time)
161 sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD);
162
163 /* disable the adapter */
164 dwiic_enable(sc, 0);
165
166 /* write standard-mode SCL timing parameters */
167 dwiic_write(sc, DW_IC_SS_SCL_HCNT, sc->ss_hcnt);
168 dwiic_write(sc, DW_IC_SS_SCL_LCNT, sc->ss_lcnt);
169
170 /* and fast-mode SCL timing parameters */
171 dwiic_write(sc, DW_IC_FS_SCL_HCNT, sc->fs_hcnt);
172 dwiic_write(sc, DW_IC_FS_SCL_LCNT, sc->fs_lcnt);
173
174 /* SDA hold time */
175 reg = dwiic_read(sc, DW_IC_COMP_VERSION);
176 if (reg >= DW_IC_SDA_HOLD_MIN_VERS)
177 dwiic_write(sc, DW_IC_SDA_HOLD, sc->sda_hold_time);
178
179 /* FIFO threshold levels */
180 sc->tx_fifo_depth = 32;
181 sc->rx_fifo_depth = 32;
182 reg = dwiic_read(sc, DW_IC_COMP_PARAM_1);
183 tx_fifo_depth = DW_IC_TX_FIFO_DEPTH(reg);
184 rx_fifo_depth = DW_IC_RX_FIFO_DEPTH(reg);
185 if (tx_fifo_depth > 1 && tx_fifo_depth < sc->tx_fifo_depth)
186 sc->tx_fifo_depth = tx_fifo_depth;
187 if (rx_fifo_depth > 1 && rx_fifo_depth < sc->rx_fifo_depth)
188 sc->rx_fifo_depth = rx_fifo_depth;
189
190 dwiic_write(sc, DW_IC_TX_TL, sc->tx_fifo_depth / 2);
191 dwiic_write(sc, DW_IC_RX_TL, 0);
192
193 /* configure as i2c master with fast speed */
194 sc->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
195 DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
196 dwiic_write(sc, DW_IC_CON, sc->master_cfg);
197
198 return 0;
199 }
200
201 void
dwiic_enable(struct dwiic_softc * sc,int enable)202 dwiic_enable(struct dwiic_softc *sc, int enable)
203 {
204 int retries;
205
206 for (retries = 100; retries > 0; retries--) {
207 dwiic_write(sc, DW_IC_ENABLE, enable);
208 if ((dwiic_read(sc, DW_IC_ENABLE_STATUS) & 1) == enable)
209 return;
210
211 DELAY(25);
212 }
213
214 printf("%s: failed to %sable\n", sc->sc_dev.dv_xname,
215 (enable ? "en" : "dis"));
216 }
217
218 int
dwiic_i2c_exec(void * cookie,i2c_op_t op,i2c_addr_t addr,const void * cmdbuf,size_t cmdlen,void * buf,size_t len,int flags)219 dwiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf,
220 size_t cmdlen, void *buf, size_t len, int flags)
221 {
222 struct dwiic_softc *sc = cookie;
223 u_int32_t ic_con, st, cmd, resp;
224 int retries, tx_limit, rx_avail, x, readpos;
225 uint8_t *b;
226 int s;
227
228 if (sc->sc_busy)
229 return 1;
230
231 sc->sc_busy++;
232
233 DPRINTF(("%s: %s: op %d, addr 0x%02x, cmdlen %zu, len %zu, "
234 "flags 0x%02x\n", sc->sc_dev.dv_xname, __func__, op, addr, cmdlen,
235 len, flags));
236
237 /* setup transfer */
238 sc->sc_i2c_xfer.op = op;
239 sc->sc_i2c_xfer.buf = buf;
240 sc->sc_i2c_xfer.len = len;
241 sc->sc_i2c_xfer.flags = flags;
242 sc->sc_i2c_xfer.error = 0;
243
244 /* wait for bus to be idle */
245 for (retries = 100; retries > 0; retries--) {
246 st = dwiic_read(sc, DW_IC_STATUS);
247 if (!(st & DW_IC_STATUS_ACTIVITY))
248 break;
249 DELAY(1000);
250 }
251 DPRINTF(("%s: %s: status 0x%x\n", sc->sc_dev.dv_xname, __func__, st));
252 if (st & DW_IC_STATUS_ACTIVITY) {
253 sc->sc_busy = 0;
254 return (1);
255 }
256
257 if (cold || sc->sc_poll)
258 flags |= I2C_F_POLL;
259
260 /* disable controller */
261 dwiic_enable(sc, 0);
262
263 /* set slave address */
264 ic_con = dwiic_read(sc, DW_IC_CON);
265 ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
266 dwiic_write(sc, DW_IC_CON, ic_con);
267 dwiic_write(sc, DW_IC_TAR, addr);
268
269 /* disable interrupts */
270 dwiic_write(sc, DW_IC_INTR_MASK, 0);
271 dwiic_read(sc, DW_IC_CLR_INTR);
272
273 /* enable controller */
274 dwiic_enable(sc, 1);
275
276 /* wait until the controller is ready for commands */
277 if (flags & I2C_F_POLL)
278 DELAY(200);
279 else {
280 s = splbio();
281 dwiic_read(sc, DW_IC_CLR_INTR);
282 dwiic_write(sc, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY);
283
284 if (tsleep_nsec(&sc->sc_writewait, PRIBIO, "dwiic",
285 MSEC_TO_NSEC(500)) != 0)
286 printf("%s: timed out waiting for tx_empty intr\n",
287 sc->sc_dev.dv_xname);
288 splx(s);
289 }
290
291 /* send our command, one byte at a time */
292 if (cmdlen > 0) {
293 b = (void *)cmdbuf;
294
295 DPRINTF(("%s: %s: sending cmd (len %zu):", sc->sc_dev.dv_xname,
296 __func__, cmdlen));
297 for (x = 0; x < cmdlen; x++)
298 DPRINTF((" %02x", b[x]));
299 DPRINTF(("\n"));
300
301 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR);
302 if (cmdlen > tx_limit) {
303 /* TODO */
304 printf("%s: can't write %zu (> %d)\n",
305 sc->sc_dev.dv_xname, cmdlen, tx_limit);
306 sc->sc_i2c_xfer.error = 1;
307 sc->sc_busy = 0;
308 return (1);
309 }
310
311 for (x = 0; x < cmdlen; x++) {
312 cmd = b[x];
313 /*
314 * Generate STOP condition if this is the last
315 * byte of the transfer.
316 */
317 if (x == (cmdlen - 1) && len == 0 && I2C_OP_STOP_P(op))
318 cmd |= DW_IC_DATA_CMD_STOP;
319 dwiic_write(sc, DW_IC_DATA_CMD, cmd);
320 }
321 }
322
323 b = (void *)buf;
324 x = readpos = 0;
325 tx_limit = sc->tx_fifo_depth - dwiic_read(sc, DW_IC_TXFLR);
326
327 DPRINTF(("%s: %s: need to read %zu bytes, can send %d read reqs\n",
328 sc->sc_dev.dv_xname, __func__, len, tx_limit));
329
330 while (x < len) {
331 if (I2C_OP_WRITE_P(op))
332 cmd = b[x];
333 else
334 cmd = DW_IC_DATA_CMD_READ;
335
336 /*
337 * Generate RESTART condition if we're reversing
338 * direction.
339 */
340 if (x == 0 && cmdlen > 0 && I2C_OP_READ_P(op))
341 cmd |= DW_IC_DATA_CMD_RESTART;
342 /*
343 * Generate STOP condition on the last byte of the
344 * transfer.
345 */
346 if (x == (len - 1) && I2C_OP_STOP_P(op))
347 cmd |= DW_IC_DATA_CMD_STOP;
348
349 dwiic_write(sc, DW_IC_DATA_CMD, cmd);
350
351 /*
352 * For a block read, get the byte count before
353 * continuing to read the data bytes.
354 */
355 if (I2C_OP_READ_P(op) && I2C_OP_BLKMODE_P(op) && readpos == 0)
356 tx_limit = 1;
357
358 tx_limit--;
359 x++;
360
361 /*
362 * As TXFLR fills up, we need to clear it out by reading all
363 * available data.
364 */
365 while (I2C_OP_READ_P(op) && (tx_limit == 0 || x == len)) {
366 DPRINTF(("%s: %s: tx_limit %d, sent %d read reqs\n",
367 sc->sc_dev.dv_xname, __func__, tx_limit, x));
368
369 if (flags & I2C_F_POLL) {
370 for (retries = 1000; retries > 0; retries--) {
371 rx_avail = dwiic_read(sc, DW_IC_RXFLR);
372 if (rx_avail > 0)
373 break;
374 DELAY(50);
375 }
376 } else {
377 s = splbio();
378 dwiic_read(sc, DW_IC_CLR_INTR);
379 dwiic_write(sc, DW_IC_INTR_MASK,
380 DW_IC_INTR_RX_FULL);
381
382 if (tsleep_nsec(&sc->sc_readwait, PRIBIO,
383 "dwiic", MSEC_TO_NSEC(500)) != 0)
384 printf("%s: timed out waiting for "
385 "rx_full intr\n",
386 sc->sc_dev.dv_xname);
387 splx(s);
388
389 rx_avail = dwiic_read(sc, DW_IC_RXFLR);
390 }
391
392 if (rx_avail == 0) {
393 printf("%s: timed out reading remaining %d\n",
394 sc->sc_dev.dv_xname, (int)(len - readpos));
395 sc->sc_i2c_xfer.error = 1;
396 sc->sc_busy = 0;
397
398 return (1);
399 }
400
401 DPRINTF(("%s: %s: %d avail to read (%zu remaining)\n",
402 sc->sc_dev.dv_xname, __func__, rx_avail,
403 len - readpos));
404
405 while (rx_avail > 0) {
406 resp = dwiic_read(sc, DW_IC_DATA_CMD);
407 if (readpos < len) {
408 b[readpos] = resp;
409 readpos++;
410 }
411 rx_avail--;
412 }
413
414 /*
415 * Update the transfer length when doing a
416 * block read.
417 */
418 if (I2C_OP_BLKMODE_P(op) && readpos > 0 && len > b[0])
419 len = b[0] + 1;
420
421 if (readpos >= len)
422 break;
423
424 DPRINTF(("%s: still need to read %d bytes\n",
425 sc->sc_dev.dv_xname, (int)(len - readpos)));
426 tx_limit = sc->tx_fifo_depth -
427 dwiic_read(sc, DW_IC_TXFLR);
428 }
429
430 if (I2C_OP_WRITE_P(op) && tx_limit == 0 && x < len) {
431 if (flags & I2C_F_POLL) {
432 for (retries = 1000; retries > 0; retries--) {
433 tx_limit = sc->tx_fifo_depth -
434 dwiic_read(sc, DW_IC_TXFLR);
435 if (tx_limit > 0)
436 break;
437 DELAY(50);
438 }
439 } else {
440 s = splbio();
441 dwiic_read(sc, DW_IC_CLR_INTR);
442 dwiic_write(sc, DW_IC_INTR_MASK,
443 DW_IC_INTR_TX_EMPTY);
444
445 if (tsleep_nsec(&sc->sc_writewait, PRIBIO,
446 "dwiic", MSEC_TO_NSEC(500)) != 0)
447 printf("%s: timed out waiting for "
448 "tx_empty intr\n",
449 sc->sc_dev.dv_xname);
450 splx(s);
451
452 tx_limit = sc->tx_fifo_depth -
453 dwiic_read(sc, DW_IC_TXFLR);
454 }
455
456 if (tx_limit == 0) {
457 printf("%s: timed out writing remaining %d\n",
458 sc->sc_dev.dv_xname, (int)(len - x));
459 sc->sc_i2c_xfer.error = 1;
460 sc->sc_busy = 0;
461
462 return (1);
463 }
464 }
465 }
466
467 if (I2C_OP_STOP_P(op) && I2C_OP_WRITE_P(op)) {
468 if (flags & I2C_F_POLL) {
469 for (retries = 100; retries > 0; retries--) {
470 st = dwiic_read(sc, DW_IC_RAW_INTR_STAT);
471 if (st & DW_IC_INTR_STOP_DET)
472 break;
473 DELAY(1000);
474 }
475 if (!(st & DW_IC_INTR_STOP_DET))
476 printf("%s: timed out waiting for bus idle\n",
477 sc->sc_dev.dv_xname);
478 } else {
479 s = splbio();
480 while (sc->sc_busy) {
481 dwiic_write(sc, DW_IC_INTR_MASK,
482 DW_IC_INTR_STOP_DET);
483 if (tsleep_nsec(&sc->sc_busy, PRIBIO, "dwiic",
484 MSEC_TO_NSEC(500)) != 0)
485 printf("%s: timed out waiting for "
486 "stop intr\n",
487 sc->sc_dev.dv_xname);
488 }
489 splx(s);
490 }
491 }
492 sc->sc_busy = 0;
493
494 return 0;
495 }
496
497 uint32_t
dwiic_read_clear_intrbits(struct dwiic_softc * sc)498 dwiic_read_clear_intrbits(struct dwiic_softc *sc)
499 {
500 uint32_t stat;
501
502 stat = dwiic_read(sc, DW_IC_INTR_STAT);
503
504 if (stat & DW_IC_INTR_RX_UNDER)
505 dwiic_read(sc, DW_IC_CLR_RX_UNDER);
506 if (stat & DW_IC_INTR_RX_OVER)
507 dwiic_read(sc, DW_IC_CLR_RX_OVER);
508 if (stat & DW_IC_INTR_TX_OVER)
509 dwiic_read(sc, DW_IC_CLR_TX_OVER);
510 if (stat & DW_IC_INTR_RD_REQ)
511 dwiic_read(sc, DW_IC_CLR_RD_REQ);
512 if (stat & DW_IC_INTR_TX_ABRT)
513 dwiic_read(sc, DW_IC_CLR_TX_ABRT);
514 if (stat & DW_IC_INTR_RX_DONE)
515 dwiic_read(sc, DW_IC_CLR_RX_DONE);
516 if (stat & DW_IC_INTR_ACTIVITY)
517 dwiic_read(sc, DW_IC_CLR_ACTIVITY);
518 if (stat & DW_IC_INTR_STOP_DET)
519 dwiic_read(sc, DW_IC_CLR_STOP_DET);
520 if (stat & DW_IC_INTR_START_DET)
521 dwiic_read(sc, DW_IC_CLR_START_DET);
522 if (stat & DW_IC_INTR_GEN_CALL)
523 dwiic_read(sc, DW_IC_CLR_GEN_CALL);
524
525 return stat;
526 }
527
528 int
dwiic_intr(void * arg)529 dwiic_intr(void *arg)
530 {
531 struct dwiic_softc *sc = arg;
532 uint32_t en, stat;
533
534 en = dwiic_read(sc, DW_IC_ENABLE);
535 /* probably for the other controller */
536 if (!en)
537 return 0;
538
539 stat = dwiic_read_clear_intrbits(sc);
540 DPRINTF(("%s: %s: enabled=0x%x stat=0x%x\n", sc->sc_dev.dv_xname,
541 __func__, en, stat));
542 if (!(stat & ~DW_IC_INTR_ACTIVITY))
543 return 0;
544
545 if (stat & DW_IC_INTR_TX_ABRT)
546 sc->sc_i2c_xfer.error = 1;
547
548 if (sc->sc_i2c_xfer.flags & I2C_F_POLL)
549 DPRINTF(("%s: %s: intr in poll mode?\n", sc->sc_dev.dv_xname,
550 __func__));
551 else {
552 if (stat & DW_IC_INTR_RX_FULL) {
553 dwiic_write(sc, DW_IC_INTR_MASK, 0);
554 DPRINTF(("%s: %s: waking up reader\n",
555 sc->sc_dev.dv_xname, __func__));
556 wakeup(&sc->sc_readwait);
557 }
558 if (stat & DW_IC_INTR_TX_EMPTY) {
559 dwiic_write(sc, DW_IC_INTR_MASK, 0);
560 DPRINTF(("%s: %s: waking up writer\n",
561 sc->sc_dev.dv_xname, __func__));
562 wakeup(&sc->sc_writewait);
563 }
564 if (stat & DW_IC_INTR_STOP_DET) {
565 dwiic_write(sc, DW_IC_INTR_MASK, 0);
566 sc->sc_busy = 0;
567 wakeup(&sc->sc_busy);
568 }
569 }
570
571 return 1;
572 }
573