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