1 /* $NetBSD: cuda.c,v 1.7 2008/04/29 06:53:02 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 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: cuda.c,v 1.7 2008/04/29 06:53:02 martin Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/device.h> 36 #include <sys/proc.h> 37 38 #include <machine/bus.h> 39 #include <machine/autoconf.h> 40 #include <machine/pio.h> 41 #include <dev/clock_subr.h> 42 #include <dev/i2c/i2cvar.h> 43 44 #include <macppc/dev/viareg.h> 45 #include <macppc/dev/cudavar.h> 46 47 #include <dev/ofw/openfirm.h> 48 #include <dev/adb/adbvar.h> 49 #include "opt_cuda.h" 50 51 #ifdef CUDA_DEBUG 52 #define DPRINTF printf 53 #else 54 #define DPRINTF while (0) printf 55 #endif 56 57 #define CUDA_NOTREADY 0x1 /* has not been initialized yet */ 58 #define CUDA_IDLE 0x2 /* the bus is currently idle */ 59 #define CUDA_OUT 0x3 /* sending out a command */ 60 #define CUDA_IN 0x4 /* receiving data */ 61 #define CUDA_POLLING 0x5 /* polling - II only */ 62 63 static void cuda_attach(struct device *, struct device *, void *); 64 static int cuda_match(struct device *, struct cfdata *, void *); 65 static void cuda_autopoll(void *, int); 66 67 static int cuda_intr(void *); 68 69 typedef struct _cuda_handler { 70 int (*handler)(void *, int, uint8_t *); 71 void *cookie; 72 } CudaHandler; 73 74 struct cuda_softc { 75 struct device sc_dev; 76 void *sc_ih; 77 CudaHandler sc_handlers[16]; 78 struct todr_chip_handle sc_todr; 79 struct adb_bus_accessops sc_adbops; 80 struct i2c_controller sc_i2c; 81 bus_space_tag_t sc_memt; 82 bus_space_handle_t sc_memh; 83 int sc_node; 84 int sc_state; 85 int sc_waiting; 86 int sc_polling; 87 int sc_sent; 88 int sc_out_length; 89 int sc_received; 90 int sc_iic_done; 91 int sc_error; 92 /* time */ 93 uint32_t sc_tod; 94 uint32_t sc_autopoll; 95 uint32_t sc_todev; 96 /* ADB */ 97 void (*sc_adb_handler)(void *, int, uint8_t *); 98 void *sc_adb_cookie; 99 uint32_t sc_i2c_read_len; 100 /* internal buffers */ 101 uint8_t sc_in[256]; 102 uint8_t sc_out[256]; 103 }; 104 105 CFATTACH_DECL(cuda, sizeof(struct cuda_softc), 106 cuda_match, cuda_attach, NULL, NULL); 107 108 static inline void cuda_write_reg(struct cuda_softc *, int, uint8_t); 109 static inline uint8_t cuda_read_reg(struct cuda_softc *, int); 110 static void cuda_idle(struct cuda_softc *); 111 static void cuda_tip(struct cuda_softc *); 112 static void cuda_clear_tip(struct cuda_softc *); 113 static void cuda_in(struct cuda_softc *); 114 static void cuda_out(struct cuda_softc *); 115 static void cuda_toggle_ack(struct cuda_softc *); 116 static void cuda_ack_off(struct cuda_softc *); 117 static int cuda_intr_state(struct cuda_softc *); 118 119 static void cuda_init(struct cuda_softc *); 120 121 /* 122 * send a message to Cuda. 123 */ 124 /* cookie, flags, length, data */ 125 static int cuda_send(void *, int, int, uint8_t *); 126 static void cuda_poll(void *); 127 static void cuda_adb_poll(void *); 128 static int cuda_set_handler(void *, int, int (*)(void *, int, uint8_t *), void *); 129 130 static int cuda_error_handler(void *, int, uint8_t *); 131 132 static int cuda_todr_handler(void *, int, uint8_t *); 133 static int cuda_todr_set(todr_chip_handle_t, volatile struct timeval *); 134 static int cuda_todr_get(todr_chip_handle_t, volatile struct timeval *); 135 136 static int cuda_adb_handler(void *, int, uint8_t *); 137 static void cuda_final(struct device *); 138 139 static struct cuda_attach_args *cuda0 = NULL; 140 141 /* ADB bus attachment stuff */ 142 static int cuda_adb_send(void *, int, int, int, uint8_t *); 143 static int cuda_adb_set_handler(void *, void (*)(void *, int, uint8_t *), void *); 144 145 /* i2c stuff */ 146 static int cuda_i2c_acquire_bus(void *, int); 147 static void cuda_i2c_release_bus(void *, int); 148 static int cuda_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 149 void *, size_t, int); 150 151 static int 152 cuda_match(struct device *parent, struct cfdata *cf, void *aux) 153 { 154 struct confargs *ca = aux; 155 156 if (ca->ca_nreg < 8) 157 return 0; 158 159 if (ca->ca_nintr < 4) 160 return 0; 161 162 if (strcmp(ca->ca_name, "via-cuda") == 0) { 163 return 10; /* beat adb* at obio? */ 164 } 165 166 return 0; 167 } 168 169 static void 170 cuda_attach(struct device *parent, struct device *dev, void *aux) 171 { 172 struct confargs *ca = aux; 173 struct cuda_softc *sc = (struct cuda_softc *)dev; 174 struct i2cbus_attach_args iba; 175 static struct cuda_attach_args caa; 176 int irq = ca->ca_intr[0]; 177 int node, i, child; 178 char name[32]; 179 180 node = of_getnode_byname(OF_parent(ca->ca_node), "extint-gpio1"); 181 if (node) 182 OF_getprop(node, "interrupts", &irq, 4); 183 184 printf(" irq %d: ", irq); 185 186 sc->sc_node = ca->ca_node; 187 sc->sc_memt = ca->ca_tag; 188 189 sc->sc_sent = 0; 190 sc->sc_received = 0; 191 sc->sc_waiting = 0; 192 sc->sc_polling = 0; 193 sc->sc_state = CUDA_NOTREADY; 194 sc->sc_error = 0; 195 sc->sc_i2c_read_len = 0; 196 197 if (bus_space_map(sc->sc_memt, ca->ca_reg[0] + ca->ca_baseaddr, 198 ca->ca_reg[1], 0, &sc->sc_memh) != 0) { 199 200 printf("%s: unable to map registers\n", dev->dv_xname); 201 return; 202 } 203 sc->sc_ih = intr_establish(irq, IST_EDGE, IPL_TTY, cuda_intr, sc); 204 printf("\n"); 205 206 for (i = 0; i < 16; i++) { 207 sc->sc_handlers[i].handler = NULL; 208 sc->sc_handlers[i].cookie = NULL; 209 } 210 211 cuda_init(sc); 212 213 /* now attach children */ 214 config_interrupts(dev, cuda_final); 215 cuda_set_handler(sc, CUDA_ERROR, cuda_error_handler, sc); 216 cuda_set_handler(sc, CUDA_PSEUDO, cuda_todr_handler, sc); 217 218 child = OF_child(ca->ca_node); 219 while (child != 0) { 220 221 if (OF_getprop(child, "name", name, 32) == 0) 222 continue; 223 if (strncmp(name, "adb", 4) == 0) { 224 225 cuda_set_handler(sc, CUDA_ADB, cuda_adb_handler, sc); 226 sc->sc_adbops.cookie = sc; 227 sc->sc_adbops.send = cuda_adb_send; 228 sc->sc_adbops.poll = cuda_adb_poll; 229 sc->sc_adbops.autopoll = cuda_autopoll; 230 sc->sc_adbops.set_handler = cuda_adb_set_handler; 231 config_found_ia(dev, "adb_bus", &sc->sc_adbops, 232 nadb_print); 233 } else if (strncmp(name, "rtc", 4) == 0) { 234 235 sc->sc_todr.todr_gettime = cuda_todr_get; 236 sc->sc_todr.todr_settime = cuda_todr_set; 237 sc->sc_todr.cookie = sc; 238 todr_attach(&sc->sc_todr); 239 } 240 child = OF_peer(child); 241 } 242 243 caa.cookie = sc; 244 caa.set_handler = cuda_set_handler; 245 caa.send = cuda_send; 246 caa.poll = cuda_poll; 247 #if notyet 248 config_found(dev, &caa, cuda_print); 249 #endif 250 251 iba.iba_tag = &sc->sc_i2c; 252 sc->sc_i2c.ic_cookie = sc; 253 sc->sc_i2c.ic_acquire_bus = cuda_i2c_acquire_bus; 254 sc->sc_i2c.ic_release_bus = cuda_i2c_release_bus; 255 sc->sc_i2c.ic_send_start = NULL; 256 sc->sc_i2c.ic_send_stop = NULL; 257 sc->sc_i2c.ic_initiate_xfer = NULL; 258 sc->sc_i2c.ic_read_byte = NULL; 259 sc->sc_i2c.ic_write_byte = NULL; 260 sc->sc_i2c.ic_exec = cuda_i2c_exec; 261 config_found_ia(&sc->sc_dev, "i2cbus", &iba, iicbus_print); 262 263 if (cuda0 == NULL) 264 cuda0 = &caa; 265 } 266 267 static void 268 cuda_init(struct cuda_softc *sc) 269 { 270 volatile int i; 271 uint8_t reg; 272 273 reg = cuda_read_reg(sc, vDirB); 274 reg |= 0x30; /* register B bits 4 and 5: outputs */ 275 cuda_write_reg(sc, vDirB, reg); 276 277 reg = cuda_read_reg(sc, vDirB); 278 reg &= 0xf7; /* register B bit 3: input */ 279 cuda_write_reg(sc, vDirB, reg); 280 281 reg = cuda_read_reg(sc, vACR); 282 reg &= ~vSR_OUT; /* make sure SR is set to IN */ 283 cuda_write_reg(sc, vACR, reg); 284 285 cuda_write_reg(sc, vACR, (cuda_read_reg(sc, vACR) | 0x0c) & ~0x10); 286 287 sc->sc_state = CUDA_IDLE; /* used by all types of hardware */ 288 289 cuda_write_reg(sc, vIER, 0x84); /* make sure VIA interrupts are on */ 290 cuda_idle(sc); /* set ADB bus state to idle */ 291 292 /* sort of a device reset */ 293 i = cuda_read_reg(sc, vSR); /* clear interrupt */ 294 cuda_write_reg(sc, vIER, 0x04); /* no interrupts while clearing */ 295 cuda_idle(sc); /* reset state to idle */ 296 delay(150); 297 cuda_tip(sc); /* signal start of frame */ 298 delay(150); 299 cuda_toggle_ack(sc); 300 delay(150); 301 cuda_clear_tip(sc); 302 delay(150); 303 cuda_idle(sc); /* back to idle state */ 304 i = cuda_read_reg(sc, vSR); /* clear interrupt */ 305 cuda_write_reg(sc, vIER, 0x84); /* ints ok now */ 306 } 307 308 static void 309 cuda_final(struct device *dev) 310 { 311 struct cuda_softc *sc = (struct cuda_softc *)dev; 312 313 sc->sc_polling = 0; 314 #if 0 315 { 316 int err; 317 uint8_t buffer[2], buf2[2]; 318 319 /* trying to read */ 320 printf("reading\n"); 321 buffer[0] = 0; 322 buffer[1] = 1; 323 buf2[0] = 0; 324 err = cuda_i2c_exec(sc, I2C_OP_WRITE, 0x8a, buffer, 2, buf2, 0, 0); 325 buf2[0] = 0; 326 err = cuda_i2c_exec(sc, I2C_OP_WRITE | I2C_OP_READ, 0x8a, buffer, 1, buf2, 2, 0); 327 printf("buf2: %02x\n", buf2[0]); 328 } 329 #endif 330 } 331 332 static inline void 333 cuda_write_reg(struct cuda_softc *sc, int offset, uint8_t value) 334 { 335 336 bus_space_write_1(sc->sc_memt, sc->sc_memh, offset, value); 337 } 338 339 static inline uint8_t 340 cuda_read_reg(struct cuda_softc *sc, int offset) 341 { 342 343 return bus_space_read_1(sc->sc_memt, sc->sc_memh, offset); 344 } 345 346 static int 347 cuda_set_handler(void *cookie, int type, 348 int (*handler)(void *, int, uint8_t *), void *hcookie) 349 { 350 struct cuda_softc *sc = cookie; 351 CudaHandler *me; 352 353 if ((type >= 0) && (type < 16)) { 354 me = &sc->sc_handlers[type]; 355 me->handler = handler; 356 me->cookie = hcookie; 357 return 0; 358 } 359 return -1; 360 } 361 362 static int 363 cuda_send(void *cookie, int poll, int length, uint8_t *msg) 364 { 365 struct cuda_softc *sc = cookie; 366 int s; 367 368 DPRINTF("cuda_send %08x\n", (uint32_t)cookie); 369 if (sc->sc_state == CUDA_NOTREADY) 370 return -1; 371 372 s = splhigh(); 373 374 if ((sc->sc_state == CUDA_IDLE) /*&& 375 ((cuda_read_reg(sc, vBufB) & vPB3) == vPB3)*/) { 376 /* fine */ 377 DPRINTF("chip is idle\n"); 378 } else { 379 DPRINTF("cuda state is %d\n", sc->sc_state); 380 if (sc->sc_waiting == 0) { 381 sc->sc_waiting = 1; 382 } else { 383 splx(s); 384 return -1; 385 } 386 } 387 388 sc->sc_error = 0; 389 memcpy(sc->sc_out, msg, length); 390 sc->sc_out_length = length; 391 sc->sc_sent = 0; 392 393 if (sc->sc_waiting != 1) { 394 395 delay(150); 396 sc->sc_state = CUDA_OUT; 397 cuda_out(sc); 398 cuda_write_reg(sc, vSR, sc->sc_out[0]); 399 cuda_ack_off(sc); 400 cuda_tip(sc); 401 } 402 sc->sc_waiting = 1; 403 404 if (sc->sc_polling || poll || cold) { 405 cuda_poll(sc); 406 } 407 408 splx(s); 409 410 return 0; 411 } 412 413 static void 414 cuda_poll(void *cookie) 415 { 416 struct cuda_softc *sc = cookie; 417 int s; 418 419 DPRINTF("polling\n"); 420 while ((sc->sc_state != CUDA_IDLE) || 421 (cuda_intr_state(sc)) || 422 (sc->sc_waiting == 1)) { 423 if ((cuda_read_reg(sc, vIFR) & vSR_INT) == vSR_INT) { 424 s = splhigh(); 425 cuda_intr(sc); 426 splx(s); 427 } 428 } 429 } 430 431 static void 432 cuda_adb_poll(void *cookie) 433 { 434 struct cuda_softc *sc = cookie; 435 int s; 436 437 s = splhigh(); 438 cuda_intr(sc); 439 splx(s); 440 } 441 442 static void 443 cuda_idle(struct cuda_softc *sc) 444 { 445 uint8_t reg; 446 447 reg = cuda_read_reg(sc, vBufB); 448 reg |= (vPB4 | vPB5); 449 cuda_write_reg(sc, vBufB, reg); 450 } 451 452 static void 453 cuda_tip(struct cuda_softc *sc) 454 { 455 uint8_t reg; 456 457 reg = cuda_read_reg(sc, vBufB); 458 reg &= ~vPB5; 459 cuda_write_reg(sc, vBufB, reg); 460 } 461 462 static void 463 cuda_clear_tip(struct cuda_softc *sc) 464 { 465 uint8_t reg; 466 467 reg = cuda_read_reg(sc, vBufB); 468 reg |= vPB5; 469 cuda_write_reg(sc, vBufB, reg); 470 } 471 472 static void 473 cuda_in(struct cuda_softc *sc) 474 { 475 uint8_t reg; 476 477 reg = cuda_read_reg(sc, vACR); 478 reg &= ~vSR_OUT; 479 cuda_write_reg(sc, vACR, reg); 480 } 481 482 static void 483 cuda_out(struct cuda_softc *sc) 484 { 485 uint8_t reg; 486 487 reg = cuda_read_reg(sc, vACR); 488 reg |= vSR_OUT; 489 cuda_write_reg(sc, vACR, reg); 490 } 491 492 static void 493 cuda_toggle_ack(struct cuda_softc *sc) 494 { 495 uint8_t reg; 496 497 reg = cuda_read_reg(sc, vBufB); 498 reg ^= vPB4; 499 cuda_write_reg(sc, vBufB, reg); 500 } 501 502 static void 503 cuda_ack_off(struct cuda_softc *sc) 504 { 505 uint8_t reg; 506 507 reg = cuda_read_reg(sc, vBufB); 508 reg |= vPB4; 509 cuda_write_reg(sc, vBufB, reg); 510 } 511 512 static int 513 cuda_intr_state(struct cuda_softc *sc) 514 { 515 return ((cuda_read_reg(sc, vBufB) & vPB3) == 0); 516 } 517 518 static int 519 cuda_intr(void *arg) 520 { 521 struct cuda_softc *sc = arg; 522 int i, ending, type; 523 uint8_t reg; 524 525 reg = cuda_read_reg(sc, vIFR); /* Read the interrupts */ 526 DPRINTF("["); 527 if ((reg & 0x80) == 0) { 528 DPRINTF("irq %02x]", reg); 529 return 0; /* No interrupts to process */ 530 } 531 DPRINTF(":"); 532 533 cuda_write_reg(sc, vIFR, 0x7f); /* Clear 'em */ 534 535 switch_start: 536 switch (sc->sc_state) { 537 case CUDA_IDLE: 538 /* 539 * This is an unexpected packet, so grab the first (dummy) 540 * byte, set up the proper vars, and tell the chip we are 541 * starting to receive the packet by setting the TIP bit. 542 */ 543 sc->sc_in[1] = cuda_read_reg(sc, vSR); 544 DPRINTF("start: %02x", sc->sc_in[1]); 545 if (cuda_intr_state(sc) == 0) { 546 /* must have been a fake start */ 547 DPRINTF(" ... fake start\n"); 548 if (sc->sc_waiting) { 549 /* start over */ 550 delay(150); 551 sc->sc_state = CUDA_OUT; 552 sc->sc_sent = 0; 553 cuda_out(sc); 554 cuda_write_reg(sc, vSR, sc->sc_out[1]); 555 cuda_ack_off(sc); 556 cuda_tip(sc); 557 } 558 break; 559 } 560 561 cuda_in(sc); 562 cuda_tip(sc); 563 564 sc->sc_received = 1; 565 sc->sc_state = CUDA_IN; 566 DPRINTF(" CUDA_IN"); 567 break; 568 569 case CUDA_IN: 570 sc->sc_in[sc->sc_received] = cuda_read_reg(sc, vSR); 571 DPRINTF(" %02x", sc->sc_in[sc->sc_received]); 572 ending = 0; 573 if (sc->sc_received > 255) { 574 /* bitch only once */ 575 if (sc->sc_received == 256) { 576 printf("%s: input overflow\n", 577 sc->sc_dev.dv_xname); 578 ending = 1; 579 } 580 } else 581 sc->sc_received++; 582 if (sc->sc_received > 3) { 583 if ((sc->sc_in[3] == CMD_IIC) && 584 (sc->sc_received > (sc->sc_i2c_read_len + 4))) { 585 ending = 1; 586 } 587 } 588 589 /* intr off means this is the last byte (end of frame) */ 590 if (cuda_intr_state(sc) == 0) { 591 ending = 1; 592 DPRINTF(".\n"); 593 } else { 594 cuda_toggle_ack(sc); 595 } 596 597 if (ending == 1) { /* end of message? */ 598 599 sc->sc_in[0] = sc->sc_received - 1; 600 601 /* reset vars and signal the end of this frame */ 602 cuda_idle(sc); 603 604 /* check if we have a handler for this message */ 605 type = sc->sc_in[1]; 606 if ((type >= 0) && (type < 16)) { 607 CudaHandler *me = &sc->sc_handlers[type]; 608 609 if (me->handler != NULL) { 610 me->handler(me->cookie, 611 sc->sc_received - 1, &sc->sc_in[1]); 612 } else { 613 printf("no handler for type %02x\n", type); 614 panic("barf"); 615 } 616 } 617 618 DPRINTF("CUDA_IDLE"); 619 sc->sc_state = CUDA_IDLE; 620 621 sc->sc_received = 0; 622 623 /* 624 * If there is something waiting to be sent out, 625 * set everything up and send the first byte. 626 */ 627 if (sc->sc_waiting == 1) { 628 629 DPRINTF("pending write\n"); 630 delay(1500); /* required */ 631 sc->sc_sent = 0; 632 sc->sc_state = CUDA_OUT; 633 634 /* 635 * If the interrupt is on, we were too slow 636 * and the chip has already started to send 637 * something to us, so back out of the write 638 * and start a read cycle. 639 */ 640 if (cuda_intr_state(sc)) { 641 cuda_in(sc); 642 cuda_idle(sc); 643 sc->sc_sent = 0; 644 sc->sc_state = CUDA_IDLE; 645 sc->sc_received = 0; 646 delay(150); 647 DPRINTF("too slow - incoming message\n"); 648 goto switch_start; 649 } 650 /* 651 * If we got here, it's ok to start sending 652 * so load the first byte and tell the chip 653 * we want to send. 654 */ 655 DPRINTF("sending "); 656 657 cuda_out(sc); 658 cuda_write_reg(sc, vSR, 659 sc->sc_out[sc->sc_sent]); 660 cuda_ack_off(sc); 661 cuda_tip(sc); 662 } 663 } 664 break; 665 666 case CUDA_OUT: 667 i = cuda_read_reg(sc, vSR); /* reset SR-intr in IFR */ 668 669 sc->sc_sent++; 670 if (cuda_intr_state(sc)) { /* ADB intr low during write */ 671 672 DPRINTF("incoming msg during send\n"); 673 cuda_in(sc); /* make sure SR is set to IN */ 674 cuda_idle(sc); 675 sc->sc_sent = 0; /* must start all over */ 676 sc->sc_state = CUDA_IDLE; /* new state */ 677 sc->sc_received = 0; 678 sc->sc_waiting = 1; /* must retry when done with 679 * read */ 680 delay(150); 681 goto switch_start; /* process next state right 682 * now */ 683 break; 684 } 685 if (sc->sc_out_length == sc->sc_sent) { /* check for done */ 686 687 sc->sc_waiting = 0; /* done writing */ 688 sc->sc_state = CUDA_IDLE; /* signal bus is idle */ 689 cuda_in(sc); 690 cuda_idle(sc); 691 DPRINTF("done sending\n"); 692 } else { 693 /* send next byte */ 694 cuda_write_reg(sc, vSR, sc->sc_out[sc->sc_sent]); 695 cuda_toggle_ack(sc); /* signal byte ready to 696 * shift */ 697 } 698 break; 699 700 case CUDA_NOTREADY: 701 DPRINTF("adb: not yet initialized\n"); 702 break; 703 704 default: 705 DPRINTF("intr: unknown ADB state\n"); 706 break; 707 } 708 709 DPRINTF("]"); 710 return 1; 711 } 712 713 static int 714 cuda_error_handler(void *cookie, int len, uint8_t *data) 715 { 716 struct cuda_softc *sc = cookie; 717 718 /* 719 * something went wrong 720 * byte 3 seems to be the failed command 721 */ 722 sc->sc_error = 1; 723 wakeup(&sc->sc_todev); 724 return 0; 725 } 726 727 728 /* real time clock */ 729 730 static int 731 cuda_todr_handler(void *cookie, int len, uint8_t *data) 732 { 733 struct cuda_softc *sc = cookie; 734 735 #ifdef CUDA_DEBUG 736 int i; 737 printf("msg: %02x", data[0]); 738 for (i = 1; i < len; i++) { 739 printf(" %02x", data[i]); 740 } 741 printf("\n"); 742 #endif 743 744 switch(data[2]) { 745 case CMD_READ_RTC: 746 memcpy(&sc->sc_tod, &data[3], 4); 747 break; 748 case CMD_WRITE_RTC: 749 sc->sc_tod = 0xffffffff; 750 break; 751 case CMD_AUTOPOLL: 752 sc->sc_autopoll = 1; 753 break; 754 case CMD_IIC: 755 sc->sc_iic_done = len; 756 break; 757 } 758 wakeup(&sc->sc_todev); 759 return 0; 760 } 761 762 #define DIFF19041970 2082844800 763 764 static int 765 cuda_todr_get(todr_chip_handle_t tch, volatile struct timeval *tvp) 766 { 767 struct cuda_softc *sc = tch->cookie; 768 int cnt = 0; 769 uint8_t cmd[] = { CUDA_PSEUDO, CMD_READ_RTC}; 770 771 sc->sc_tod = 0; 772 cuda_send(sc, 0, 2, cmd); 773 774 while ((sc->sc_tod == 0) && (cnt < 10)) { 775 tsleep(&sc->sc_todev, 0, "todr", 10); 776 cnt++; 777 } 778 779 if (sc->sc_tod == 0) 780 return EIO; 781 782 tvp->tv_sec = sc->sc_tod - DIFF19041970; 783 DPRINTF("tod: %ld\n", tvp->tv_sec); 784 tvp->tv_usec = 0; 785 return 0; 786 } 787 788 static int 789 cuda_todr_set(todr_chip_handle_t tch, volatile struct timeval *tvp) 790 { 791 struct cuda_softc *sc = tch->cookie; 792 uint32_t sec; 793 uint8_t cmd[] = {CUDA_PSEUDO, CMD_WRITE_RTC, 0, 0, 0, 0}; 794 795 sec = tvp->tv_sec + DIFF19041970; 796 memcpy(&cmd[2], &sec, 4); 797 sc->sc_tod = 0; 798 if (cuda_send(sc, 0, 6, cmd) == 0) { 799 while (sc->sc_tod == 0) { 800 tsleep(&sc->sc_todev, 0, "todr", 10); 801 } 802 return 0; 803 } 804 return -1; 805 806 } 807 808 /* poweroff and reboot */ 809 810 void 811 cuda_poweroff() 812 { 813 struct cuda_softc *sc; 814 uint8_t cmd[] = {CUDA_PSEUDO, CMD_POWEROFF}; 815 816 if (cuda0 == NULL) 817 return; 818 sc = cuda0->cookie; 819 sc->sc_polling = 1; 820 cuda0->poll(sc); 821 if (cuda0->send(sc, 1, 2, cmd) == 0) 822 while (1); 823 } 824 825 void 826 cuda_restart() 827 { 828 struct cuda_softc *sc; 829 uint8_t cmd[] = {CUDA_PSEUDO, CMD_RESET}; 830 831 if (cuda0 == NULL) 832 return; 833 sc = cuda0->cookie; 834 sc->sc_polling = 1; 835 cuda0->poll(sc); 836 if (cuda0->send(sc, 1, 2, cmd) == 0) 837 while (1); 838 } 839 840 /* ADB message handling */ 841 842 static void 843 cuda_autopoll(void *cookie, int flag) 844 { 845 struct cuda_softc *sc = cookie; 846 uint8_t cmd[] = {CUDA_PSEUDO, CMD_AUTOPOLL, (flag != 0)}; 847 848 if (cmd[2] == sc->sc_autopoll) 849 return; 850 851 sc->sc_autopoll = -1; 852 cuda_send(sc, 0, 3, cmd); 853 while(sc->sc_autopoll == -1) { 854 if (sc->sc_polling || cold) { 855 cuda_poll(sc); 856 } else 857 tsleep(&sc->sc_todev, 0, "autopoll", 100); 858 } 859 } 860 861 static int 862 cuda_adb_handler(void *cookie, int len, uint8_t *data) 863 { 864 struct cuda_softc *sc = cookie; 865 866 if (sc->sc_adb_handler != NULL) { 867 sc->sc_adb_handler(sc->sc_adb_cookie, len - 1, 868 &data[1]); 869 return 0; 870 } 871 return -1; 872 } 873 874 static int 875 cuda_adb_send(void *cookie, int poll, int command, int len, uint8_t *data) 876 { 877 struct cuda_softc *sc = cookie; 878 int i, s = 0; 879 uint8_t packet[16]; 880 881 /* construct an ADB command packet and send it */ 882 packet[0] = CUDA_ADB; 883 packet[1] = command; 884 for (i = 0; i < len; i++) 885 packet[i + 2] = data[i]; 886 if (poll || cold) { 887 s = splhigh(); 888 cuda_poll(sc); 889 } 890 cuda_send(sc, poll, len + 2, packet); 891 if (poll || cold) { 892 cuda_poll(sc); 893 splx(s); 894 } 895 return 0; 896 } 897 898 static int 899 cuda_adb_set_handler(void *cookie, void (*handler)(void *, int, uint8_t *), 900 void *hcookie) 901 { 902 struct cuda_softc *sc = cookie; 903 904 /* register a callback for incoming ADB messages */ 905 sc->sc_adb_handler = handler; 906 sc->sc_adb_cookie = hcookie; 907 return 0; 908 } 909 910 /* i2c message handling */ 911 912 static int 913 cuda_i2c_acquire_bus(void *cookie, int flags) 914 { 915 /* nothing yet */ 916 return 0; 917 } 918 919 static void 920 cuda_i2c_release_bus(void *cookie, int flags) 921 { 922 /* nothing here either */ 923 } 924 925 static int 926 cuda_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *_send, 927 size_t send_len, void *_recv, size_t recv_len, int flags) 928 { 929 struct cuda_softc *sc = cookie; 930 const uint8_t *send = _send; 931 uint8_t *recv = _recv; 932 uint8_t command[16] = {CUDA_PSEUDO, CMD_IIC}; 933 934 DPRINTF("cuda_i2c_exec(%02x)\n", addr); 935 command[2] = addr; 936 937 memcpy(&command[3], send, min((int)send_len, 12)); 938 939 sc->sc_iic_done = 0; 940 cuda_send(sc, sc->sc_polling, send_len + 3, command); 941 942 while ((sc->sc_iic_done == 0) && (sc->sc_error == 0)) { 943 if (sc->sc_polling || cold) { 944 cuda_poll(sc); 945 } else 946 tsleep(&sc->sc_todev, 0, "i2c", 1000); 947 } 948 949 if (sc->sc_error) { 950 sc->sc_error = 0; 951 return -1; 952 } 953 954 /* see if we're supposed to do a read */ 955 if (recv_len > 0) { 956 sc->sc_iic_done = 0; 957 command[2] |= 1; 958 command[3] = 0; 959 960 /* 961 * XXX we need to do something to limit the size of the answer 962 * - apparently the chip keeps sending until we tell it to stop 963 */ 964 sc->sc_i2c_read_len = recv_len; 965 DPRINTF("rcv_len: %d\n", recv_len); 966 cuda_send(sc, sc->sc_polling, 3, command); 967 while ((sc->sc_iic_done == 0) && (sc->sc_error == 0)) { 968 if (sc->sc_polling || cold) { 969 cuda_poll(sc); 970 } else 971 tsleep(&sc->sc_todev, 0, "i2c", 1000); 972 } 973 974 if (sc->sc_error) { 975 printf("error trying to read\n"); 976 sc->sc_error = 0; 977 return -1; 978 } 979 } 980 981 DPRINTF("received: %d\n", sc->sc_iic_done); 982 if ((sc->sc_iic_done > 3) && (recv_len > 0)) { 983 int rlen; 984 985 /* we got an answer */ 986 rlen = min(sc->sc_iic_done - 3, recv_len); 987 memcpy(recv, &sc->sc_in[4], rlen); 988 #ifdef CUDA_DEBUG 989 { 990 int i; 991 printf("ret:"); 992 for (i = 0; i < rlen; i++) 993 printf(" %02x", recv[i]); 994 printf("\n"); 995 } 996 #endif 997 return rlen; 998 } 999 return 0; 1000 } 1001