|
|
1.1 ! root 1: #include "config.h" ! 2: #include "libopenbios/bindings.h" ! 3: #include "drivers/drivers.h" ! 4: #include "libc/byteorder.h" ! 5: #include "libc/vsprintf.h" ! 6: ! 7: #include "macio.h" ! 8: #include "cuda.h" ! 9: ! 10: //#define DEBUG_CUDA ! 11: #ifdef DEBUG_CUDA ! 12: #define CUDA_DPRINTF(fmt, args...) \ ! 13: do { printk("CUDA - %s: " fmt, __func__ , ##args); } while (0) ! 14: #else ! 15: #define CUDA_DPRINTF(fmt, args...) do { } while (0) ! 16: #endif ! 17: ! 18: #define IO_CUDA_OFFSET 0x00016000 ! 19: #define IO_CUDA_SIZE 0x00002000 ! 20: ! 21: /* VIA registers - spaced 0x200 bytes apart */ ! 22: #define RS 0x200 /* skip between registers */ ! 23: #define B 0 /* B-side data */ ! 24: #define A RS /* A-side data */ ! 25: #define DIRB (2*RS) /* B-side direction (1=output) */ ! 26: #define DIRA (3*RS) /* A-side direction (1=output) */ ! 27: #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ ! 28: #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ ! 29: #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ ! 30: #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ ! 31: #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ ! 32: #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ ! 33: #define SR (10*RS) /* Shift register */ ! 34: #define ACR (11*RS) /* Auxiliary control register */ ! 35: #define PCR (12*RS) /* Peripheral control register */ ! 36: #define IFR (13*RS) /* Interrupt flag register */ ! 37: #define IER (14*RS) /* Interrupt enable register */ ! 38: #define ANH (15*RS) /* A-side data, no handshake */ ! 39: ! 40: /* Bits in B data register: all active low */ ! 41: #define TREQ 0x08 /* Transfer request (input) */ ! 42: #define TACK 0x10 /* Transfer acknowledge (output) */ ! 43: #define TIP 0x20 /* Transfer in progress (output) */ ! 44: ! 45: /* Bits in ACR */ ! 46: #define SR_CTRL 0x1c /* Shift register control bits */ ! 47: #define SR_EXT 0x0c /* Shift on external clock */ ! 48: #define SR_OUT 0x10 /* Shift out if 1 */ ! 49: ! 50: /* Bits in IFR and IER */ ! 51: #define IER_SET 0x80 /* set bits in IER */ ! 52: #define IER_CLR 0 /* clear bits in IER */ ! 53: #define SR_INT 0x04 /* Shift register full/empty */ ! 54: ! 55: #define CUDA_BUF_SIZE 16 ! 56: ! 57: #define ADB_PACKET 0 ! 58: #define CUDA_PACKET 1 ! 59: ! 60: /* CUDA commands (2nd byte) */ ! 61: #define CUDA_GET_TIME 0x03 ! 62: #define CUDA_SET_TIME 0x09 ! 63: #define CUDA_POWERDOWN 0x0a ! 64: #define CUDA_RESET_SYSTEM 0x11 ! 65: ! 66: static uint8_t cuda_readb (cuda_t *dev, int reg) ! 67: { ! 68: return *(volatile uint8_t *)(dev->base + reg); ! 69: } ! 70: ! 71: static void cuda_writeb (cuda_t *dev, int reg, uint8_t val) ! 72: { ! 73: *(volatile uint8_t *)(dev->base + reg) = val; ! 74: } ! 75: ! 76: static void cuda_wait_irq (cuda_t *dev) ! 77: { ! 78: int val; ! 79: ! 80: // CUDA_DPRINTF("\n"); ! 81: for(;;) { ! 82: val = cuda_readb(dev, IFR); ! 83: cuda_writeb(dev, IFR, val & 0x7f); ! 84: if (val & SR_INT) ! 85: break; ! 86: } ! 87: } ! 88: ! 89: ! 90: ! 91: static int cuda_request (cuda_t *dev, uint8_t pkt_type, const uint8_t *buf, ! 92: int buf_len, uint8_t *obuf) ! 93: { ! 94: int i, obuf_len, val; ! 95: ! 96: cuda_writeb(dev, ACR, cuda_readb(dev, ACR) | SR_OUT); ! 97: cuda_writeb(dev, SR, pkt_type); ! 98: cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP); ! 99: if (buf) { ! 100: //CUDA_DPRINTF("Send buf len: %d\n", buf_len); ! 101: /* send 'buf' */ ! 102: for(i = 0; i < buf_len; i++) { ! 103: cuda_wait_irq(dev); ! 104: cuda_writeb(dev, SR, buf[i]); ! 105: cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK); ! 106: } ! 107: } ! 108: cuda_wait_irq(dev); ! 109: cuda_writeb(dev, ACR, cuda_readb(dev, ACR) & ~SR_OUT); ! 110: cuda_readb(dev, SR); ! 111: cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK); ! 112: ! 113: obuf_len = 0; ! 114: if (obuf) { ! 115: cuda_wait_irq(dev); ! 116: cuda_readb(dev, SR); ! 117: cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP); ! 118: for(;;) { ! 119: cuda_wait_irq(dev); ! 120: val = cuda_readb(dev, SR); ! 121: if (obuf_len < CUDA_BUF_SIZE) ! 122: obuf[obuf_len++] = val; ! 123: if (cuda_readb(dev, B) & TREQ) ! 124: break; ! 125: cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK); ! 126: } ! 127: cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK); ! 128: ! 129: cuda_wait_irq(dev); ! 130: cuda_readb(dev, SR); ! 131: } ! 132: // CUDA_DPRINTF("Got len: %d\n", obuf_len); ! 133: ! 134: return obuf_len; ! 135: } ! 136: ! 137: ! 138: ! 139: static int cuda_adb_req (void *host, const uint8_t *snd_buf, int len, ! 140: uint8_t *rcv_buf) ! 141: { ! 142: uint8_t buffer[CUDA_BUF_SIZE], *pos; ! 143: ! 144: // CUDA_DPRINTF("len: %d %02x\n", len, snd_buf[0]); ! 145: len = cuda_request(host, ADB_PACKET, snd_buf, len, buffer); ! 146: if (len > 1 && buffer[0] == ADB_PACKET) { ! 147: pos = buffer + 2; ! 148: len -= 2; ! 149: } else { ! 150: pos = buffer + 1; ! 151: len = -1; ! 152: } ! 153: memcpy(rcv_buf, pos, len); ! 154: ! 155: return len; ! 156: } ! 157: ! 158: ! 159: DECLARE_UNNAMED_NODE(ob_cuda, INSTALL_OPEN, sizeof(int)); ! 160: ! 161: static cuda_t *main_cuda; ! 162: ! 163: static void ! 164: ppc32_reset_all(void) ! 165: { ! 166: uint8_t cmdbuf[2], obuf[64]; ! 167: ! 168: cmdbuf[0] = CUDA_RESET_SYSTEM; ! 169: cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf); ! 170: } ! 171: ! 172: static void ! 173: ppc32_poweroff(void) ! 174: { ! 175: uint8_t cmdbuf[2], obuf[64]; ! 176: ! 177: cmdbuf[0] = CUDA_POWERDOWN; ! 178: cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf); ! 179: } ! 180: ! 181: static void ! 182: ob_cuda_initialize (int *idx) ! 183: { ! 184: phandle_t ph=get_cur_dev(); ! 185: int props[2]; ! 186: ! 187: push_str("via-cuda"); ! 188: fword("device-type"); ! 189: ! 190: set_int_property(ph, "#address-cells", 1); ! 191: set_int_property(ph, "#size-cells", 0); ! 192: ! 193: set_property(ph, "compatible", "cuda", 5); ! 194: ! 195: props[0] = __cpu_to_be32(IO_CUDA_OFFSET); ! 196: props[1] = __cpu_to_be32(IO_CUDA_SIZE); ! 197: ! 198: set_property(ph, "reg", (char *)&props, sizeof(props)); ! 199: ! 200: /* on newworld machines the cuda is on interrupt 0x19 */ ! 201: ! 202: props[0] = 0x19; ! 203: props[1] = 0; ! 204: NEWWORLD(set_property(ph, "interrupts", (char *)props, sizeof(props))); ! 205: NEWWORLD(set_int_property(ph, "#interrupt-cells", 2)); ! 206: ! 207: /* we emulate an oldworld hardware, so we must use ! 208: * non-standard oldworld property (needed by linux 2.6.18) ! 209: */ ! 210: ! 211: OLDWORLD(set_int_property(ph, "AAPL,interrupts", 0x12)); ! 212: ! 213: bind_func("ppc32-reset-all", ppc32_reset_all); ! 214: push_str("' ppc32-reset-all to reset-all"); ! 215: fword("eval"); ! 216: } ! 217: ! 218: static void ! 219: ob_cuda_open(int *idx) ! 220: { ! 221: RET(-1); ! 222: } ! 223: ! 224: static void ! 225: ob_cuda_close(int *idx) ! 226: { ! 227: } ! 228: ! 229: NODE_METHODS(ob_cuda) = { ! 230: { NULL, ob_cuda_initialize }, ! 231: { "open", ob_cuda_open }, ! 232: { "close", ob_cuda_close }, ! 233: }; ! 234: ! 235: DECLARE_UNNAMED_NODE(rtc, INSTALL_OPEN, sizeof(int)); ! 236: ! 237: static void ! 238: rtc_open(int *idx) ! 239: { ! 240: RET(-1); ! 241: } ! 242: ! 243: /* ! 244: * get-time ( -- second minute hour day month year ) ! 245: * ! 246: */ ! 247: ! 248: static const int days_month[12] = ! 249: { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; ! 250: static const int days_month_leap[12] = ! 251: { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; ! 252: ! 253: static inline int is_leap(int year) ! 254: { ! 255: return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); ! 256: } ! 257: ! 258: static void ! 259: rtc_get_time(int *idx) ! 260: { ! 261: uint8_t cmdbuf[2], obuf[64]; ! 262: ucell second, minute, hour, day, month, year; ! 263: uint32_t now; ! 264: int current; ! 265: const int *days; ! 266: ! 267: cmdbuf[0] = CUDA_GET_TIME; ! 268: cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf); ! 269: ! 270: /* seconds since 01/01/1904 */ ! 271: ! 272: now = (obuf[3] << 24) + (obuf[4] << 16) + (obuf[5] << 8) + obuf[6]; ! 273: ! 274: second = now % 60; ! 275: now /= 60; ! 276: ! 277: minute = now % 60; ! 278: now /= 60; ! 279: ! 280: hour = now % 24; ! 281: now /= 24; ! 282: ! 283: year = now * 100 / 36525; ! 284: now -= year * 36525 / 100; ! 285: year += 1904; ! 286: ! 287: days = is_leap(year) ? days_month_leap : days_month; ! 288: ! 289: current = 0; ! 290: month = 0; ! 291: while (month < 12) { ! 292: if (now <= current + days[month]) { ! 293: break; ! 294: } ! 295: current += days[month]; ! 296: month++; ! 297: } ! 298: month++; ! 299: ! 300: day = now - current; ! 301: ! 302: PUSH(second); ! 303: PUSH(minute); ! 304: PUSH(hour); ! 305: PUSH(day); ! 306: PUSH(month); ! 307: PUSH(year); ! 308: } ! 309: ! 310: /* ! 311: * set-time ( second minute hour day month year -- ) ! 312: * ! 313: */ ! 314: ! 315: static void ! 316: rtc_set_time(int *idx) ! 317: { ! 318: uint8_t cmdbuf[5], obuf[3]; ! 319: ucell second, minute, hour, day, month, year; ! 320: const int *days; ! 321: uint32_t now; ! 322: unsigned int nb_days; ! 323: int i; ! 324: ! 325: year = POP(); ! 326: month = POP(); ! 327: day = POP(); ! 328: hour = POP(); ! 329: minute = POP(); ! 330: second = POP(); ! 331: ! 332: days = is_leap(year) ? days_month_leap : days_month; ! 333: nb_days = (year - 1904) * 36525 / 100 + day; ! 334: for (i = 0; i < month - 1; i++) ! 335: nb_days += days[i]; ! 336: ! 337: now = (((nb_days * 24) + hour) * 60 + minute) * 60 + second; ! 338: ! 339: cmdbuf[0] = CUDA_SET_TIME; ! 340: cmdbuf[1] = now >> 24; ! 341: cmdbuf[2] = now >> 16; ! 342: cmdbuf[3] = now >> 8; ! 343: cmdbuf[4] = now; ! 344: ! 345: cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf); ! 346: } ! 347: ! 348: NODE_METHODS(rtc) = { ! 349: { "open", rtc_open }, ! 350: { "get-time", rtc_get_time }, ! 351: { "set-time", rtc_set_time }, ! 352: }; ! 353: ! 354: static void ! 355: rtc_init(char *path) ! 356: { ! 357: phandle_t ph, aliases; ! 358: char buf[64]; ! 359: ! 360: snprintf(buf, sizeof(buf), "%s/rtc", path); ! 361: REGISTER_NAMED_NODE(rtc, buf); ! 362: ! 363: ph = find_dev(buf); ! 364: set_property(ph, "device_type", "rtc", 4); ! 365: set_property(ph, "compatible", "rtc", 4); ! 366: ! 367: aliases = find_dev("/aliases"); ! 368: set_property(aliases, "rtc", buf, strlen(buf) + 1); ! 369: ! 370: } ! 371: ! 372: cuda_t *cuda_init (const char *path, phys_addr_t base) ! 373: { ! 374: cuda_t *cuda; ! 375: char buf[64]; ! 376: phandle_t aliases; ! 377: ! 378: base += IO_CUDA_OFFSET; ! 379: CUDA_DPRINTF(" base=" FMT_plx "\n", base); ! 380: cuda = malloc(sizeof(cuda_t)); ! 381: if (cuda == NULL) ! 382: return NULL; ! 383: ! 384: snprintf(buf, sizeof(buf), "%s/via-cuda", path); ! 385: REGISTER_NAMED_NODE(ob_cuda, buf); ! 386: ! 387: aliases = find_dev("/aliases"); ! 388: set_property(aliases, "via-cuda", buf, strlen(buf) + 1); ! 389: ! 390: cuda->base = base; ! 391: cuda_writeb(cuda, B, cuda_readb(cuda, B) | TREQ | TIP); ! 392: #ifdef CONFIG_DRIVER_ADB ! 393: cuda->adb_bus = adb_bus_new(cuda, &cuda_adb_req); ! 394: if (cuda->adb_bus == NULL) { ! 395: free(cuda); ! 396: return NULL; ! 397: } ! 398: adb_bus_init(buf, cuda->adb_bus); ! 399: #endif ! 400: ! 401: rtc_init(buf); ! 402: ! 403: main_cuda = cuda; ! 404: ! 405: device_end(); ! 406: bind_func("poweroff", ppc32_poweroff); ! 407: ! 408: return cuda; ! 409: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.