1 /* $NetBSD: jziic.c,v 1.9 2021/08/07 16:18:59 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.9 2021/08/07 16:18:59 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
jziic_match(device_t parent,struct cfdata * match,void * aux)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
jziic_attach(device_t parent,device_t self,void * aux)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 struct i2cbus_attach_args iba;
121 int error;
122 void *ih;
123 #ifdef JZIIC_DEBUG
124 int i;
125 uint8_t in[1] = {0}, out[16];
126 #endif
127
128 sc->sc_dev = self;
129 sc->sc_pclk = aa->aa_pclk;
130 sc->sc_memt = aa->aa_bst;
131
132 error = bus_space_map(aa->aa_bst, aa->aa_addr, 0x100, 0, &sc->sc_memh);
133 if (error) {
134 aprint_error_dev(self,
135 "can't map registers for %s: %d\n", aa->aa_name, error);
136 return;
137 }
138
139 mutex_init(&sc->sc_cvlock, MUTEX_DEFAULT, IPL_NONE);
140 cv_init(&sc->sc_ping, device_xname(self));
141
142 aprint_naive(": SMBus controller\n");
143 aprint_normal(": SMBus controller\n");
144
145 ih = evbmips_intr_establish(aa->aa_irq, jziic_intr, sc);
146
147 if (ih == NULL) {
148 aprint_error_dev(self, "failed to establish interrupt %d\n",
149 aa->aa_irq);
150 goto fail;
151 }
152
153 #ifdef JZIIC_DEBUG
154 if (jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP, 0x51, in, 1, out, 9, 0)
155 >= 0) {
156 for (i = 0; i < 9; i++)
157 printf(" %02x", out[i]);
158 printf("\n");
159 delay(1000000);
160 jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP,
161 0x51, in, 1, out, 9, 0);
162 for (i = 0; i < 9; i++)
163 printf(" %02x", out[i]);
164 printf("\n");
165 delay(1000000);
166 jziic_i2c_exec(sc, I2C_OP_READ_WITH_STOP,
167 0x51, in, 1, out, 9, 0);
168 for (i = 0; i < 9; i++)
169 printf(" %02x", out[i]);
170 printf("\n");
171 }
172 #endif
173
174 /* fill in the i2c tag */
175 iic_tag_init(&sc->sc_i2c);
176 sc->sc_i2c.ic_cookie = sc;
177 sc->sc_i2c.ic_exec = jziic_i2c_exec;
178
179 memset(&iba, 0, sizeof(iba));
180 iba.iba_tag = &sc->sc_i2c;
181 config_found(sc->sc_dev, &iba, iicbus_print, CFARGS_NONE);
182
183
184 return;
185
186 fail:
187 if (ih) {
188 evbmips_intr_disestablish(ih);
189 }
190 bus_space_unmap(sc->sc_memt, sc->sc_memh, 0x100);
191 }
192
193 STATIC int
jziic_enable(struct jziic_softc * sc)194 jziic_enable(struct jziic_softc *sc)
195 {
196 int bail = 100000;
197 uint32_t reg;
198
199 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBENB, JZ_ENABLE);
200 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST);
201 DPRINTF("status: %02x\n", reg);
202 while ((bail > 0) && (reg == 0)) {
203 bail--;
204 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST);
205 }
206 DPRINTF("bail: %d\n", bail);
207 return (reg != 0);
208 }
209
210 STATIC void
jziic_disable(struct jziic_softc * sc)211 jziic_disable(struct jziic_softc *sc)
212 {
213 int bail = 100000;
214 uint32_t reg;
215
216 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBENB, 0);
217 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST);
218 DPRINTF("status: %02x\n", reg);
219 while ((bail > 0) && (reg != 0)) {
220 bail--;
221 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBENBST);
222 }
223 DPRINTF("bail: %d\n", bail);
224 }
225
226 STATIC int
jziic_wait(struct jziic_softc * sc)227 jziic_wait(struct jziic_softc *sc)
228 {
229 uint32_t reg;
230 int bail = 10000;
231 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST);
232 while ((reg & JZ_MSTACT) && (bail > 0)) {
233 delay(100);
234 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST);
235 bail--;
236 }
237 return ((reg & JZ_MSTACT) == 0);
238 }
239
240 STATIC void
jziic_set_speed(struct jziic_softc * sc)241 jziic_set_speed(struct jziic_softc *sc)
242 {
243 int ticks, hcnt, lcnt, hold, setup;
244
245 /* PCLK ticks per SMBus cycle */
246 ticks = sc->sc_pclk / 100; /* assuming 100kHz for now */
247 hcnt = (ticks * 40 / (40 + 47)) - 8;
248 lcnt = (ticks * 47 / (40 + 47)) - 1;
249 hold = sc->sc_pclk * 4 / 10000 - 1; /* ... * 400 / 1000000 ... */
250 hold = uimax(1, hold);
251 hold |= JZ_HDENB;
252 setup = sc->sc_pclk * 3 / 10000 + 1; /* ... * 300 / 1000000 ... */
253 DPRINTF("hcnt %d lcnt %d hold %d\n", hcnt, lcnt, hold);
254 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSHCNT, hcnt);
255 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSLCNT, lcnt);
256 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSDAHD, hold);
257 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBSDASU, setup);
258 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON,
259 JZ_SLVDIS | JZ_STPHLD | JZ_REST | JZ_SPD_100KB | JZ_MD);
260 (void)bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT);
261 }
262
263 STATIC int
jziic_i2c_exec(void * cookie,i2c_op_t op,i2c_addr_t addr,const void * vcmd,size_t cmdlen,void * vbuf,size_t buflen,int flags)264 jziic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *vcmd,
265 size_t cmdlen, void *vbuf, size_t buflen, int flags)
266 {
267 struct jziic_softc *sc = cookie;
268
269 if (flags & I2C_F_POLL) {
270 return jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf,
271 buflen, flags);
272 } else {
273 #ifdef JZIIC_DEBUG
274 uint8_t *b = vbuf;
275 int i, ret;
276
277 memset(vbuf, 0, buflen);
278 jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf,
279 buflen, flags);
280 for (i = 0; i < buflen; i++) {
281 printf(" %02x", b[i]);
282 }
283 printf("\n");
284 ret = jziic_i2c_exec_poll(sc, op, addr, vcmd, cmdlen, vbuf,
285 buflen, flags);
286 for (i = 0; i < buflen; i++) {
287 printf(" %02x", b[i]);
288 }
289 printf("\n");
290 return ret;
291 #else
292 return jziic_i2c_exec_intr(sc, op, addr, vcmd, cmdlen, vbuf,
293 buflen, flags);
294 #endif
295 }
296 }
297
298 STATIC int
jziic_i2c_exec_poll(struct jziic_softc * sc,i2c_op_t op,i2c_addr_t addr,const void * vcmd,size_t cmdlen,void * vbuf,size_t buflen,int flags)299 jziic_i2c_exec_poll(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr,
300 const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags)
301 {
302 int i, bail = 10000, ret = 0;
303 uint32_t abort;
304 uint8_t *rx, data;
305 const uint8_t *tx;
306
307 tx = vcmd;
308 rx = vbuf;
309
310 DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen);
311
312 jziic_disable(sc);
313
314 /* we're polling, so disable interrupts */
315 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
316
317 jziic_set_speed(sc);
318 jziic_wait(sc);
319 /* try to talk... */
320
321 if (!jziic_enable(sc)) {
322 ret = -1;
323 goto bork;
324 }
325 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
326
327 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr);
328 jziic_wait(sc);
329 DPRINTF("st: %02x\n",
330 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST));
331 DPRINTF("wr int: %02x\n",
332 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST));
333 abort = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBABTSRC);
334 DPRINTF("abort: %02x\n", abort);
335 if ((abort != 0)) {
336 ret = -1;
337 goto bork;
338 }
339
340 do {
341 bail--;
342 delay(100);
343 } while (((bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST) &
344 JZ_TFE) == 0) && (bail > 0));
345
346 if (cmdlen != 0) {
347 for (i = 0; i < cmdlen; i++) {
348 bus_space_write_4(sc->sc_memt, sc->sc_memh,
349 JZ_SMBDC, *tx);
350 tx++;
351 }
352 }
353
354 if (I2C_OP_READ_P(op)) {
355 /* now read */
356 for (i = 0; i < (buflen + 1); i++) {
357 bus_space_write_4(sc->sc_memt, sc->sc_memh,
358 JZ_SMBDC, JZ_CMD);
359 }
360 wbflush();
361 DPRINTF("rd st: %02x\n",
362 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST));
363 DPRINTF("rd int: %02x\n",
364 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST));
365 DPRINTF("abort: %02x\n",
366 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBABTSRC));
367 for (i = 0; i < buflen; i++) {
368 bail = 10000;
369 while (((bus_space_read_4(sc->sc_memt, sc->sc_memh,
370 JZ_SMBST) & JZ_RFNE) == 0) && (bail > 0)) {
371 bail--;
372 delay(100);
373 }
374 if (bail == 0) {
375 ret = -1;
376 goto bork;
377 }
378 data = bus_space_read_4(sc->sc_memt, sc->sc_memh,
379 JZ_SMBDC);
380 DPRINTF("rd st: %02x %d\n",
381 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST),
382 bail);
383 DPRINTF("rd int: %02x\n",
384 bus_space_read_4(sc->sc_memt, sc->sc_memh,
385 JZ_SMBINTST));
386 DPRINTF("abort: %02x\n", abort);
387 DPRINTF("rd data: %02x\n", data);
388 *rx = data;
389 rx++;
390 }
391 } else {
392 tx = vbuf;
393 for (i = 0; i < buflen; i++) {
394 DPRINTF("wr data: %02x\n", *tx);
395 bus_space_write_4(sc->sc_memt, sc->sc_memh,
396 JZ_SMBDC, *tx);
397 wbflush();
398 tx++;
399 }
400 jziic_wait(sc);
401 abort = bus_space_read_4(sc->sc_memt, sc->sc_memh,
402 JZ_SMBABTSRC);
403 DPRINTF("abort: %02x\n", abort);
404 if ((abort != 0)) {
405 ret = -1;
406 goto bork;
407 }
408
409 DPRINTF("st: %02x %d\n",
410 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST), bail);
411 DPRINTF("wr int: %02x\n",
412 bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST));
413 }
414 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON,
415 JZ_SLVDIS | JZ_REST | JZ_SPD_100KB | JZ_MD);
416 bork:
417 jziic_disable(sc);
418 return ret;
419 }
420
421 STATIC int
jziic_i2c_exec_intr(struct jziic_softc * sc,i2c_op_t op,i2c_addr_t addr,const void * vcmd,size_t cmdlen,void * vbuf,size_t buflen,int flags)422 jziic_i2c_exec_intr(struct jziic_softc *sc, i2c_op_t op, i2c_addr_t addr,
423 const void *vcmd, size_t cmdlen, void *vbuf, size_t buflen, int flags)
424 {
425 int i, ret = 0, bail;
426
427 DPRINTF("%s: 0x%02x %d %d\n", __func__, addr, cmdlen, buflen);
428
429 jziic_disable(sc);
430 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
431
432 mutex_enter(&sc->sc_cvlock);
433
434 sc->sc_reading = FALSE;
435
436 if (I2C_OP_READ_P(op)) {
437 sc->sc_cmd = vcmd;
438 sc->sc_cmdlen = cmdlen;
439 sc->sc_buf = vbuf;
440 sc->sc_buflen = buflen;
441 memset(vbuf, 0, buflen);
442 } else {
443 if ((cmdlen + buflen) > 256)
444 return -1;
445 memcpy(sc->sc_txbuf, vcmd, cmdlen);
446 memcpy(sc->sc_txbuf + cmdlen, vbuf, buflen);
447 sc->sc_cmd = sc->sc_txbuf;
448 sc->sc_cmdlen = cmdlen + buflen;
449 sc->sc_buf = NULL;
450 sc->sc_buflen = 0;
451 }
452 sc->sc_cmdptr = 0;
453 sc->sc_bufptr = 0;
454 sc->sc_rds = 0;
455 sc->sc_abort = 0;
456
457 jziic_set_speed(sc);
458 jziic_wait(sc);
459
460 /* set FIFO levels */
461 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTXTL, 4);
462 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBRXTL, 0
463 /*min(7, max(0, buflen - 2 ))*/);
464
465 /* try to talk... */
466
467 if (!jziic_enable(sc)) {
468 ret = -1;
469 goto bork;
470 }
471 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
472
473 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBTAR, addr);
474 jziic_wait(sc);
475 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT, JZ_CLEARALL);
476 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM,
477 JZ_TXABT | JZ_TXEMP);
478
479 bail = 100 * sc->sc_cmdlen;
480 while ((sc->sc_cmdptr < sc->sc_cmdlen) && (bail > 0)) {
481 cv_timedwait(&sc->sc_ping, &sc->sc_cvlock, 1);
482 if (sc->sc_abort) {
483 /* we received an abort interrupt -> bailout */
484 DPRINTF("abort: %x\n", sc->sc_abort);
485 ret = -1;
486 goto bork;
487 }
488 bail--;
489 }
490
491 if (sc->sc_cmdptr < sc->sc_cmdlen) {
492 /* we didn't send everything? */
493 DPRINTF("sent %d of %d\n", sc->sc_cmdptr, sc->sc_cmdlen);
494 ret = -1;
495 goto bork;
496 }
497
498 if (I2C_OP_READ_P(op)) {
499 /* now read */
500 sc->sc_reading = TRUE;
501 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM,
502 JZ_TXABT | JZ_RXFL | JZ_TXEMP);
503
504 for (i = 0; i < uimin((buflen + 1), 4); i++) {
505 bus_space_write_4(sc->sc_memt, sc->sc_memh,
506 JZ_SMBDC, JZ_CMD);
507 wbflush();
508 }
509 sc->sc_rds = i;
510
511 bail = 10 * sc->sc_buflen; /* 10 ticks per byte should be ok */
512 while ((sc->sc_bufptr < sc->sc_buflen) && (bail > 0)) {
513 cv_timedwait(&sc->sc_ping, &sc->sc_cvlock, 1);
514 if (sc->sc_abort) {
515 /* we received an abort interrupt -> bailout */
516 DPRINTF("rx abort: %x\n", sc->sc_abort);
517 ret = -1;
518 goto bork;
519 }
520 bail--;
521 }
522
523 if (sc->sc_bufptr < sc->sc_buflen) {
524 /* we didn't get everything? */
525 DPRINTF("rcvd %d of %d\n", sc->sc_bufptr, sc->sc_buflen);
526 ret = -1;
527 goto bork;
528 }
529 }
530 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCON,
531 JZ_SLVDIS | JZ_REST | JZ_SPD_100KB | JZ_MD);
532 bork:
533 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
534 jziic_disable(sc);
535 mutex_exit(&sc->sc_cvlock);
536 return ret;
537 }
538
539 STATIC int
jziic_intr(void * cookie)540 jziic_intr(void *cookie)
541 {
542 struct jziic_softc *sc = cookie;
543 uint32_t stat, data, rstat;
544 int i;
545
546 stat = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTST);
547 if (stat & JZ_TXEMP) {
548 if (sc->sc_reading) {
549 if (sc->sc_rds < (sc->sc_buflen + 1)) {
550 for (i = 0;
551 i < uimin(4, (sc->sc_buflen + 1) -
552 sc->sc_rds);
553 i++) {
554 bus_space_write_4( sc->sc_memt,
555 sc->sc_memh,
556 JZ_SMBDC, JZ_CMD);
557 wbflush();
558 }
559 sc->sc_rds += i;
560 } else {
561 /* we're done, so turn TX FIFO interrupt off */
562 bus_space_write_4(sc->sc_memt, sc->sc_memh,
563 JZ_SMBINTM,
564 JZ_TXABT | JZ_RXFL);
565 }
566 } else {
567 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh,
568 JZ_SMBST);
569 while ((rstat & JZ_TFNF) &&
570 (sc->sc_cmdptr < sc->sc_cmdlen)) {
571 data = *sc->sc_cmd;
572 sc->sc_cmd++;
573 sc->sc_cmdptr++;
574 bus_space_write_4(sc->sc_memt, sc->sc_memh,
575 JZ_SMBDC, data & 0xff);
576 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh,
577 JZ_SMBST);
578 };
579 /* no need to clear this one */
580 if (sc->sc_cmdptr >= sc->sc_cmdlen) {
581 cv_signal(&sc->sc_ping);
582 bus_space_write_4(sc->sc_memt, sc->sc_memh,
583 JZ_SMBINTM, JZ_TXABT);
584 }
585 }
586 }
587 if (stat & JZ_RXFL) {
588 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh, JZ_SMBST);
589 while ((rstat & JZ_RFNE) && (sc->sc_bufptr < sc->sc_buflen)) {
590 data = bus_space_read_4(sc->sc_memt, sc->sc_memh,
591 JZ_SMBDC);
592 *sc->sc_buf = (uint8_t)(data & 0xff);
593 sc->sc_buf++;
594 sc->sc_bufptr++;
595 rstat = bus_space_read_4(sc->sc_memt, sc->sc_memh,
596 JZ_SMBST);
597 }
598 if (sc->sc_bufptr >= sc->sc_buflen)
599 cv_signal(&sc->sc_ping);
600 }
601 if (stat & JZ_TXABT) {
602 sc->sc_abort = bus_space_read_4(sc->sc_memt, sc->sc_memh,
603 JZ_SMBABTSRC);
604 cv_signal(&sc->sc_ping);
605 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBCINT,
606 JZ_CLEARALL);
607 bus_space_write_4(sc->sc_memt, sc->sc_memh, JZ_SMBINTM, 0);
608 }
609 return 0;
610 }
611