jziic.c revision 1.10 1 /* $NetBSD: jziic.c,v 1.10 2025/09/15 13:23:02 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2015 Michael Lorenz
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: jziic.c,v 1.10 2025/09/15 13:23:02 thorpej Exp $");
31
32 /*
33 * a preliminary driver for JZ4780's on-chip SMBus controllers
34 * - needs more error handling and interrupt support
35 * - transfers can't be more than the chip's FIFO, supposedly 16 bytes per
36 * direction
37 * so, good enough for RTCs but not much else yet
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
44 #include <sys/mutex.h>
45 #include <sys/bus.h>
46 #include <sys/mutex.h>
47 #include <sys/condvar.h>
48
49 #include <mips/ingenic/ingenic_var.h>
50 #include <mips/ingenic/ingenic_regs.h>
51
52 #include <dev/i2c/i2cvar.h>
53
54 #include "opt_ingenic.h"
55
56 #ifdef JZIIC_DEBUG
57 #define DPRINTF aprint_error
58 #define STATIC /* */
59 #else
60 #define DPRINTF while (0) printf
61 #define STATIC static
62 #endif
63
64 STATIC int jziic_match(device_t, struct cfdata *, void *);
65 STATIC void jziic_attach(device_t, device_t, void *);
66
67 struct jziic_softc {
68 device_t sc_dev;
69 bus_space_tag_t sc_memt;
70 bus_space_handle_t sc_memh;
71 struct i2c_controller sc_i2c;
72 kmutex_t sc_cvlock;
73 uint32_t sc_pclk;
74 /* stuff used for interrupt-driven transfers */
75 const uint8_t *sc_cmd;
76 uint8_t *sc_buf;
77 uint32_t sc_cmdlen, sc_buflen;
78 uint32_t sc_cmdptr, sc_bufptr, sc_rds;
79 uint32_t sc_abort;
80 kcondvar_t sc_ping;
81 uint8_t sc_txbuf[256];
82 boolean_t sc_reading;
83 };
84
85 CFATTACH_DECL_NEW(jziic, sizeof(struct jziic_softc),
86 jziic_match, jziic_attach, NULL, NULL);
87
88 STATIC int jziic_enable(struct jziic_softc *);
89 STATIC void jziic_disable(struct jziic_softc *);
90 STATIC int jziic_wait(struct jziic_softc *);
91 STATIC void jziic_set_speed(struct jziic_softc *);
92 STATIC int jziic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
93 void *, size_t, int);
94 STATIC int jziic_i2c_exec_poll(struct jziic_softc *, i2c_op_t, i2c_addr_t,
95 const void *, size_t, void *, size_t, int);
96 STATIC int jziic_i2c_exec_intr(struct jziic_softc *, i2c_op_t, i2c_addr_t,
97 const void *, size_t, void *, size_t, int);
98
99 STATIC int jziic_intr(void *);
100
101
102 /* ARGSUSED */
103 STATIC int
104 jziic_match(device_t parent, struct cfdata *match, void *aux)
105 {
106 struct apbus_attach_args *aa = aux;
107
108 if (strcmp(aa->aa_name, "jziic") != 0)
109 return 0;
110
111 return 1;
112 }
113
114 /* ARGSUSED */
115 STATIC void
116 jziic_attach(device_t parent, device_t self, void *aux)
117 {
118 struct jziic_softc *sc = device_private(self);
119 struct apbus_attach_args *aa = aux;
120 int error;
121 void *ih;
122 #ifdef JZIIC_DEBUG
123 int i;
124 uint8_t in[1] = {0}, out[16];
125 #endif
126
127 sc->sc_dev = self;
128 sc->sc_pclk = aa->aa_pclk;
129 sc->sc_memt = aa->aa_bst;
130
131 error = bus_space_map(aa->aa_bst, aa->aa_addr, 0x100, 0, &sc->sc_memh);
132 if (error) {
133 aprint_error_dev(self,
134 "can't map registers for %s: %d\n", aa->aa_name, error);
135 return;
136 }
137
138 mutex_init(&sc->sc_cvlock, MUTEX_DEFAULT, IPL_NONE);
139 cv_init(&sc->sc_ping, device_xname(self));
140
141 aprint_naive(": SMBus controller\n");
142 aprint_normal(": SMBus controller\n");
143
144 ih = evbmips_intr_establish(aa->aa_irq, jziic_intr, sc);
145
146 if (ih == NULL) {
147 aprint_error_dev(self, "failed to establish interrupt %d\n",
148 aa->aa_irq);
149 goto fail;
150 }
151
152 #ifdef JZIIC_DEBUG
153 if (jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 0x51, in, 1, out, 9, 0)
154 >= 0) {
155 for (i = 0; i < 9; i++)
156 printf(" %02x", out[i]);
157 printf("\n");
158 delay(1000000);
159 jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP,
160 0x51, in, 1, out, 9, 0);
161 for (i = 0; i < 9; i++)
162 printf(" %02x", out[i]);
163 printf("\n");
164 delay(1000000);
165 jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP,
166 0x51, in, 1, out, 9, 0);
167 for (i = 0; i < 9; i++)
168 printf(" %02x", out[i]);
169 printf("\n");
170 }
171 #endif
172
173 /* fill in the i2c tag */
174 iic_tag_init(&sc->sc_i2c);
175 sc->sc_i2c.ic_cookie = sc;
176 sc->sc_i2c.ic_exec = jziic_i2c_exec;
177
178 iicbus_attach(sc->sc_dev, &sc->sc_i2c);
179
180 return;
181
182 fail:
183 if (ih) {
184 evbmips_intr_disestablish(ih);
185 }
186 bus_space_unmap(sc->sc_memt, sc->sc_memh, 0x100);
187 }
188
189 STATIC int
190 jziic_enable(struct jziic_softc *sc)
191 {
192 int bail = 100000;
193 uint32_t reg;
194
195 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBENB, JZ_ENABLE);
196 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST);
197 DPRINTF("status: %02x\n", reg);
198 while ((bail > 0) && (reg == 0)) {
199 bail--;
200 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST);
201 }
202 DPRINTF("bail: %d\n", bail);
203 return (reg != 0);
204 }
205
206 STATIC void
207 jziic_disable(struct jziic_softc *sc)
208 {
209 int bail = 100000;
210 uint32_t reg;
211
212 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBENB, 0);
213 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST);
214 DPRINTF("status: %02x\n", reg);
215 while ((bail > 0) && (reg != 0)) {
216 bail--;
217 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST);
218 }
219 DPRINTF("bail: %d\n", bail);
220 }
221
222 STATIC int
223 jziic_wait(struct jziic_softc *sc)
224 {
225 uint32_t reg;
226 int bail = 10000;
227 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST);
228 while ((reg & JZ_MSTACT) && (bail > 0)) {
229 delay(100);
230 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST);
231 bail--;
232 }
233 return ((reg & JZ_MSTACT) == 0);
234 }
235
236 STATIC void
237 jziic_set_speed(struct jziic_softc *sc)
238 {
239 int ticks, hcnt, lcnt, hold, setup;
240
241 /* PCLK ticks per SMBus cycle */
242 ticks = sc->sc_pclk / 100; /* assuming 100kHz for now */
243 hcnt = (ticks * 40 / (40 + 47)) - 8;
244 lcnt = (ticks * 47 / (40 + 47)) - 1;
245 hold = sc->sc_pclk * 4 / 10000 - 1; /* ... * 400 / 1000000 ... */
246 hold = uimax(1, hold);
247 hold |= JZ_HDENB;
248 setup = sc->sc_pclk * 3 / 10000 + 1; /* ... * 300 / 1000000 ... */
249 DPRINTF("hcnt %d lcnt %d hold %d\n", hcnt, lcnt, hold);
250 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSHCNT, hcnt);
251 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSLCNT, lcnt);
252 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSDAHD, hold);
253 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSDASU, setup);
254 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON,
255 JZ_SLVDIS | JZ_STPHLD | JZ_REST | JZ_SPD_100KB | JZ_MD);
256 (void)bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT);
257 }
258
259 STATIC int
260 jziic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *vcmd,
261 size_t cmdlen, void *vbuf, size_t buflen, int flags)
262 {
263 struct jziic_softc *sc = cookie;
264
265 if (flags & I2C_F_POLL) {
266 return jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf,
267 buflen, flags);
268 } else {
269 #ifdef JZIIC_DEBUG
270 uint8_t *b = vbuf;
271 int i, ret;
272
273 memset(vbuf, 0, buflen);
274 jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf,
275 buflen, flags);
276 for (i = 0; i < buflen; i++) {
277 printf(" %02x", b[i]);
278 }
279 printf("\n");
280 ret = jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf,
281 buflen, flags);
282 for (i = 0; i < buflen; i++) {
283 printf(" %02x", b[i]);
284 }
285 printf("\n");
286 return ret;
287 #else
288 return jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf,
289 buflen, flags);
290 #endif
291 }
292 }
293
294 STATIC int
295 jziic_i2c_exec_poll(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr,
296 const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags)
297 {
298 int i, bail = 10000, ret = 0;
299 uint32_t abort;
300 uint8_t *rx, data;
301 const uint8_t *tx;
302
303 tx = vcmd;
304 rx = vbuf;
305
306 DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen);
307
308 jziic_disable(sc);
309
310 /* we're polling, so disable interrupts */
311 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
312
313 jziic_set_speed(sc);
314 jziic_wait(sc);
315 /* try to talk... */
316
317 if (!jziic_enable(sc)) {
318 ret = -1;
319 goto bork;
320 }
321 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
322
323 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr);
324 jziic_wait(sc);
325 DPRINTF("st: %02x\n",
326 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST));
327 DPRINTF("wr int: %02x\n",
328 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST));
329 abort = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBABTSRC);
330 DPRINTF("abort: %02x\n", abort);
331 if ((abort != 0)) {
332 ret = -1;
333 goto bork;
334 }
335
336 do {
337 bail--;
338 delay(100);
339 } while (((bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST) &
340 JZ_TFE) == 0) && (bail > 0));
341
342 if (cmdlen != 0) {
343 for (i = 0; i < cmdlen; i++) {
344 bus_space_write_4(sc->sc_memt, sc->sc_memh,
345 JZ_SMBDC, *tx);
346 tx++;
347 }
348 }
349
350 if (I2C_OP_READ_P(op)) {
351 /* now read */
352 for (i = 0; i < (buflen + 1); i++) {
353 bus_space_write_4(sc->sc_memt, sc->sc_memh,
354 JZ_SMBDC, JZ_CMD);
355 }
356 wbflush();
357 DPRINTF("rd st: %02x\n",
358 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST));
359 DPRINTF("rd int: %02x\n",
360 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST));
361 DPRINTF("abort: %02x\n",
362 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBABTSRC));
363 for (i = 0; i < buflen; i++) {
364 bail = 10000;
365 while (((bus_space_read_4(sc->sc_memt, sc->sc_memh,
366 JZ_SMBST) & JZ_RFNE) == 0) && (bail > 0)) {
367 bail--;
368 delay(100);
369 }
370 if (bail == 0) {
371 ret = -1;
372 goto bork;
373 }
374 data = bus_space_read_4(sc->sc_memt, sc->sc_memh,
375 JZ_SMBDC);
376 DPRINTF("rd st: %02x %d\n",
377 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST),
378 bail);
379 DPRINTF("rd int: %02x\n",
380 bus_space_read_4(sc->sc_memt, sc->sc_memh,
381 JZ_SMBINTST));
382 DPRINTF("abort: %02x\n", abort);
383 DPRINTF("rd data: %02x\n", data);
384 *rx = data;
385 rx++;
386 }
387 } else {
388 tx = vbuf;
389 for (i = 0; i < buflen; i++) {
390 DPRINTF("wr data: %02x\n", *tx);
391 bus_space_write_4(sc->sc_memt, sc->sc_memh,
392 JZ_SMBDC, *tx);
393 wbflush();
394 tx++;
395 }
396 jziic_wait(sc);
397 abort = bus_space_read_4(sc->sc_memt, sc->sc_memh,
398 JZ_SMBABTSRC);
399 DPRINTF("abort: %02x\n", abort);
400 if ((abort != 0)) {
401 ret = -1;
402 goto bork;
403 }
404
405 DPRINTF("st: %02x %d\n",
406 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST), bail);
407 DPRINTF("wr int: %02x\n",
408 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST));
409 }
410 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON,
411 JZ_SLVDIS | JZ_REST | JZ_SPD_100KB | JZ_MD);
412 bork:
413 jziic_disable(sc);
414 return ret;
415 }
416
417 STATIC int
418 jziic_i2c_exec_intr(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr,
419 const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags)
420 {
421 int i, ret = 0, bail;
422
423 DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen);
424
425 jziic_disable(sc);
426 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
427
428 mutex_enter(&sc->sc_cvlock);
429
430 sc->sc_reading = FALSE;
431
432 if (I2C_OP_READ_P(op)) {
433 sc->sc_cmd = vcmd;
434 sc->sc_cmdlen = cmdlen;
435 sc->sc_buf = vbuf;
436 sc->sc_buflen = buflen;
437 memset(vbuf, 0, buflen);
438 } else {
439 if ((cmdlen + buflen) > 256)
440 return -1;
441 memcpy(sc->sc_txbuf, vcmd, cmdlen);
442 memcpy(sc->sc_txbuf + cmdlen, vbuf, buflen);
443 sc->sc_cmd = sc->sc_txbuf;
444 sc->sc_cmdlen = cmdlen + buflen;
445 sc->sc_buf = NULL;
446 sc->sc_buflen = 0;
447 }
448 sc->sc_cmdptr = 0;
449 sc->sc_bufptr = 0;
450 sc->sc_rds = 0;
451 sc->sc_abort = 0;
452
453 jziic_set_speed(sc);
454 jziic_wait(sc);
455
456 /* set FIFO levels */
457 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTXTL, 4);
458 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBRXTL, 0
459 /*min(7, max(0, buflen - 2 ))*/);
460
461 /* try to talk... */
462
463 if (!jziic_enable(sc)) {
464 ret = -1;
465 goto bork;
466 }
467 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
468
469 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr);
470 jziic_wait(sc);
471 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT, JZ_CLEARALL);
472 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM,
473 JZ_TXABT | JZ_TXEMP);
474
475 bail = 100 * sc->sc_cmdlen;
476 while ((sc->sc_cmdptr < sc->sc_cmdlen) && (bail > 0)) {
477 cv_timedwait(&sc->sc_ping, &sc->sc_cvlock, 1);
478 if (sc->sc_abort) {
479 /* we received an abort interrupt -> bailout */
480 DPRINTF("abort: %x\n", sc->sc_abort);
481 ret = -1;
482 goto bork;
483 }
484 bail--;
485 }
486
487 if (sc->sc_cmdptr < sc->sc_cmdlen) {
488 /* we didn't send everything? */
489 DPRINTF("sent %d of %d\n", sc->sc_cmdptr, sc->sc_cmdlen);
490 ret = -1;
491 goto bork;
492 }
493
494 if (I2C_OP_READ_P(op)) {
495 /* now read */
496 sc->sc_reading = TRUE;
497 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM,
498 JZ_TXABT | JZ_RXFL | JZ_TXEMP);
499
500 for (i = 0; i < uimin((buflen + 1), 4); i++) {
501 bus_space_write_4(sc->sc_memt, sc->sc_memh,
502 JZ_SMBDC, JZ_CMD);
503 wbflush();
504 }
505 sc->sc_rds = i;
506
507 bail = 10 * sc->sc_buflen; /* 10 ticks per byte should be ok */
508 while ((sc->sc_bufptr < sc->sc_buflen) && (bail > 0)) {
509 cv_timedwait(&sc->sc_ping, &sc->sc_cvlock, 1);
510 if (sc->sc_abort) {
511 /* we received an abort interrupt -> bailout */
512 DPRINTF("rx abort: %x\n", sc->sc_abort);
513 ret = -1;
514 goto bork;
515 }
516 bail--;
517 }
518
519 if (sc->sc_bufptr < sc->sc_buflen) {
520 /* we didn't get everything? */
521 DPRINTF("rcvd %d of %d\n", sc->sc_bufptr, sc->sc_buflen);
522 ret = -1;
523 goto bork;
524 }
525 }
526 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON,
527 JZ_SLVDIS | JZ_REST | JZ_SPD_100KB | JZ_MD);
528 bork:
529 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
530 jziic_disable(sc);
531 mutex_exit(&sc->sc_cvlock);
532 return ret;
533 }
534
535 STATIC int
536 jziic_intr(void *cookie)
537 {
538 struct jziic_softc *sc = cookie;
539 uint32_t stat, data, rstat;
540 int i;
541
542 stat = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST);
543 if (stat & JZ_TXEMP) {
544 if (sc->sc_reading) {
545 if (sc->sc_rds < (sc->sc_buflen + 1)) {
546 for (i = 0;
547 i < uimin(4, (sc->sc_buflen + 1) -
548 sc->sc_rds);
549 i++) {
550 bus_space_write_4( sc->sc_memt,
551 sc->sc_memh,
552 JZ_SMBDC, JZ_CMD);
553 wbflush();
554 }
555 sc->sc_rds += i;
556 } else {
557 /* we're done, so turn TX FIFO interrupt off */
558 bus_space_write_4(sc->sc_memt, sc->sc_memh,
559 JZ_SMBINTM,
560 JZ_TXABT | JZ_RXFL);
561 }
562 } else {
563 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh,
564 JZ_SMBST);
565 while ((rstat & JZ_TFNF) &&
566 (sc->sc_cmdptr < sc->sc_cmdlen)) {
567 data = *sc->sc_cmd;
568 sc->sc_cmd++;
569 sc->sc_cmdptr++;
570 bus_space_write_4(sc->sc_memt, sc->sc_memh,
571 JZ_SMBDC, data & 0xff);
572 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh,
573 JZ_SMBST);
574 };
575 /* no need to clear this one */
576 if (sc->sc_cmdptr >= sc->sc_cmdlen) {
577 cv_signal(&sc->sc_ping);
578 bus_space_write_4(sc->sc_memt, sc->sc_memh,
579 JZ_SMBINTM, JZ_TXABT);
580 }
581 }
582 }
583 if (stat & JZ_RXFL) {
584 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST);
585 while ((rstat & JZ_RFNE) && (sc->sc_bufptr < sc->sc_buflen)) {
586 data = bus_space_read_4(sc->sc_memt, sc->sc_memh,
587 JZ_SMBDC);
588 *sc->sc_buf = (uint8_t)(data & 0xff);
589 sc->sc_buf++;
590 sc->sc_bufptr++;
591 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh,
592 JZ_SMBST);
593 }
594 if (sc->sc_bufptr >= sc->sc_buflen)
595 cv_signal(&sc->sc_ping);
596 }
597 if (stat & JZ_TXABT) {
598 sc->sc_abort = bus_space_read_4(sc->sc_memt, sc->sc_memh,
599 JZ_SMBABTSRC);
600 cv_signal(&sc->sc_ping);
601 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT,
602 JZ_CLEARALL);
603 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
604 }
605 return 0;
606 }
607