|
|
1.1 ! root 1: /* ! 2: * Toshiba TC6393XB I/O Controller. ! 3: * Found in Sharp Zaurus SL-6000 (tosa) or some ! 4: * Toshiba e-Series PDAs. ! 5: * ! 6: * Most features are currently unsupported!!! ! 7: * ! 8: * This code is licensed under the GNU GPL v2. ! 9: */ ! 10: #include "hw.h" ! 11: #include "pxa.h" ! 12: #include "devices.h" ! 13: #include "flash.h" ! 14: #include "console.h" ! 15: #include "pixel_ops.h" ! 16: ! 17: #define IRQ_TC6393_NAND 0 ! 18: #define IRQ_TC6393_MMC 1 ! 19: #define IRQ_TC6393_OHCI 2 ! 20: #define IRQ_TC6393_SERIAL 3 ! 21: #define IRQ_TC6393_FB 4 ! 22: ! 23: #define TC6393XB_NR_IRQS 8 ! 24: ! 25: #define TC6393XB_GPIOS 16 ! 26: ! 27: #define SCR_REVID 0x08 /* b Revision ID */ ! 28: #define SCR_ISR 0x50 /* b Interrupt Status */ ! 29: #define SCR_IMR 0x52 /* b Interrupt Mask */ ! 30: #define SCR_IRR 0x54 /* b Interrupt Routing */ ! 31: #define SCR_GPER 0x60 /* w GP Enable */ ! 32: #define SCR_GPI_SR(i) (0x64 + (i)) /* b3 GPI Status */ ! 33: #define SCR_GPI_IMR(i) (0x68 + (i)) /* b3 GPI INT Mask */ ! 34: #define SCR_GPI_EDER(i) (0x6c + (i)) /* b3 GPI Edge Detect Enable */ ! 35: #define SCR_GPI_LIR(i) (0x70 + (i)) /* b3 GPI Level Invert */ ! 36: #define SCR_GPO_DSR(i) (0x78 + (i)) /* b3 GPO Data Set */ ! 37: #define SCR_GPO_DOECR(i) (0x7c + (i)) /* b3 GPO Data OE Control */ ! 38: #define SCR_GP_IARCR(i) (0x80 + (i)) /* b3 GP Internal Active Register Control */ ! 39: #define SCR_GP_IARLCR(i) (0x84 + (i)) /* b3 GP INTERNAL Active Register Level Control */ ! 40: #define SCR_GPI_BCR(i) (0x88 + (i)) /* b3 GPI Buffer Control */ ! 41: #define SCR_GPA_IARCR 0x8c /* w GPa Internal Active Register Control */ ! 42: #define SCR_GPA_IARLCR 0x90 /* w GPa Internal Active Register Level Control */ ! 43: #define SCR_GPA_BCR 0x94 /* w GPa Buffer Control */ ! 44: #define SCR_CCR 0x98 /* w Clock Control */ ! 45: #define SCR_PLL2CR 0x9a /* w PLL2 Control */ ! 46: #define SCR_PLL1CR 0x9c /* l PLL1 Control */ ! 47: #define SCR_DIARCR 0xa0 /* b Device Internal Active Register Control */ ! 48: #define SCR_DBOCR 0xa1 /* b Device Buffer Off Control */ ! 49: #define SCR_FER 0xe0 /* b Function Enable */ ! 50: #define SCR_MCR 0xe4 /* w Mode Control */ ! 51: #define SCR_CONFIG 0xfc /* b Configuration Control */ ! 52: #define SCR_DEBUG 0xff /* b Debug */ ! 53: ! 54: #define NAND_CFG_COMMAND 0x04 /* w Command */ ! 55: #define NAND_CFG_BASE 0x10 /* l Control Base Address */ ! 56: #define NAND_CFG_INTP 0x3d /* b Interrupt Pin */ ! 57: #define NAND_CFG_INTE 0x48 /* b Int Enable */ ! 58: #define NAND_CFG_EC 0x4a /* b Event Control */ ! 59: #define NAND_CFG_ICC 0x4c /* b Internal Clock Control */ ! 60: #define NAND_CFG_ECCC 0x5b /* b ECC Control */ ! 61: #define NAND_CFG_NFTC 0x60 /* b NAND Flash Transaction Control */ ! 62: #define NAND_CFG_NFM 0x61 /* b NAND Flash Monitor */ ! 63: #define NAND_CFG_NFPSC 0x62 /* b NAND Flash Power Supply Control */ ! 64: #define NAND_CFG_NFDC 0x63 /* b NAND Flash Detect Control */ ! 65: ! 66: #define NAND_DATA 0x00 /* l Data */ ! 67: #define NAND_MODE 0x04 /* b Mode */ ! 68: #define NAND_STATUS 0x05 /* b Status */ ! 69: #define NAND_ISR 0x06 /* b Interrupt Status */ ! 70: #define NAND_IMR 0x07 /* b Interrupt Mask */ ! 71: ! 72: #define NAND_MODE_WP 0x80 ! 73: #define NAND_MODE_CE 0x10 ! 74: #define NAND_MODE_ALE 0x02 ! 75: #define NAND_MODE_CLE 0x01 ! 76: #define NAND_MODE_ECC_MASK 0x60 ! 77: #define NAND_MODE_ECC_EN 0x20 ! 78: #define NAND_MODE_ECC_READ 0x40 ! 79: #define NAND_MODE_ECC_RST 0x60 ! 80: ! 81: struct tc6393xb_s { ! 82: qemu_irq irq; ! 83: qemu_irq *sub_irqs; ! 84: struct { ! 85: uint8_t ISR; ! 86: uint8_t IMR; ! 87: uint8_t IRR; ! 88: uint16_t GPER; ! 89: uint8_t GPI_SR[3]; ! 90: uint8_t GPI_IMR[3]; ! 91: uint8_t GPI_EDER[3]; ! 92: uint8_t GPI_LIR[3]; ! 93: uint8_t GP_IARCR[3]; ! 94: uint8_t GP_IARLCR[3]; ! 95: uint8_t GPI_BCR[3]; ! 96: uint16_t GPA_IARCR; ! 97: uint16_t GPA_IARLCR; ! 98: uint16_t CCR; ! 99: uint16_t PLL2CR; ! 100: uint32_t PLL1CR; ! 101: uint8_t DIARCR; ! 102: uint8_t DBOCR; ! 103: uint8_t FER; ! 104: uint16_t MCR; ! 105: uint8_t CONFIG; ! 106: uint8_t DEBUG; ! 107: } scr; ! 108: uint32_t gpio_dir; ! 109: uint32_t gpio_level; ! 110: uint32_t prev_level; ! 111: qemu_irq handler[TC6393XB_GPIOS]; ! 112: qemu_irq *gpio_in; ! 113: ! 114: struct { ! 115: uint8_t mode; ! 116: uint8_t isr; ! 117: uint8_t imr; ! 118: } nand; ! 119: int nand_enable; ! 120: uint32_t nand_phys; ! 121: struct nand_flash_s *flash; ! 122: struct ecc_state_s ecc; ! 123: ! 124: DisplayState *ds; ! 125: ram_addr_t vram_addr; ! 126: uint32_t scr_width, scr_height; /* in pixels */ ! 127: qemu_irq l3v; ! 128: unsigned blank : 1, ! 129: blanked : 1; ! 130: }; ! 131: ! 132: qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s) ! 133: { ! 134: return s->gpio_in; ! 135: } ! 136: ! 137: static void tc6393xb_gpio_set(void *opaque, int line, int level) ! 138: { ! 139: // struct tc6393xb_s *s = opaque; ! 140: ! 141: if (line > TC6393XB_GPIOS) { ! 142: printf("%s: No GPIO pin %i\n", __FUNCTION__, line); ! 143: return; ! 144: } ! 145: ! 146: // FIXME: how does the chip reflect the GPIO input level change? ! 147: } ! 148: ! 149: void tc6393xb_gpio_out_set(struct tc6393xb_s *s, int line, ! 150: qemu_irq handler) ! 151: { ! 152: if (line >= TC6393XB_GPIOS) { ! 153: fprintf(stderr, "TC6393xb: no GPIO pin %d\n", line); ! 154: return; ! 155: } ! 156: ! 157: s->handler[line] = handler; ! 158: } ! 159: ! 160: static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s) ! 161: { ! 162: uint32_t level, diff; ! 163: int bit; ! 164: ! 165: level = s->gpio_level & s->gpio_dir; ! 166: ! 167: for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { ! 168: bit = ffs(diff) - 1; ! 169: qemu_set_irq(s->handler[bit], (level >> bit) & 1); ! 170: } ! 171: ! 172: s->prev_level = level; ! 173: } ! 174: ! 175: qemu_irq tc6393xb_l3v_get(struct tc6393xb_s *s) ! 176: { ! 177: return s->l3v; ! 178: } ! 179: ! 180: static void tc6393xb_l3v(void *opaque, int line, int level) ! 181: { ! 182: struct tc6393xb_s *s = opaque; ! 183: s->blank = !level; ! 184: fprintf(stderr, "L3V: %d\n", level); ! 185: } ! 186: ! 187: static void tc6393xb_sub_irq(void *opaque, int line, int level) { ! 188: struct tc6393xb_s *s = opaque; ! 189: uint8_t isr = s->scr.ISR; ! 190: if (level) ! 191: isr |= 1 << line; ! 192: else ! 193: isr &= ~(1 << line); ! 194: s->scr.ISR = isr; ! 195: qemu_set_irq(s->irq, isr & s->scr.IMR); ! 196: } ! 197: ! 198: #define SCR_REG_B(N) \ ! 199: case SCR_ ##N: return s->scr.N ! 200: #define SCR_REG_W(N) \ ! 201: case SCR_ ##N: return s->scr.N; \ ! 202: case SCR_ ##N + 1: return s->scr.N >> 8; ! 203: #define SCR_REG_L(N) \ ! 204: case SCR_ ##N: return s->scr.N; \ ! 205: case SCR_ ##N + 1: return s->scr.N >> 8; \ ! 206: case SCR_ ##N + 2: return s->scr.N >> 16; \ ! 207: case SCR_ ##N + 3: return s->scr.N >> 24; ! 208: #define SCR_REG_A(N) \ ! 209: case SCR_ ##N(0): return s->scr.N[0]; \ ! 210: case SCR_ ##N(1): return s->scr.N[1]; \ ! 211: case SCR_ ##N(2): return s->scr.N[2] ! 212: ! 213: static uint32_t tc6393xb_scr_readb(struct tc6393xb_s *s, target_phys_addr_t addr) ! 214: { ! 215: switch (addr) { ! 216: case SCR_REVID: ! 217: return 3; ! 218: case SCR_REVID+1: ! 219: return 0; ! 220: SCR_REG_B(ISR); ! 221: SCR_REG_B(IMR); ! 222: SCR_REG_B(IRR); ! 223: SCR_REG_W(GPER); ! 224: SCR_REG_A(GPI_SR); ! 225: SCR_REG_A(GPI_IMR); ! 226: SCR_REG_A(GPI_EDER); ! 227: SCR_REG_A(GPI_LIR); ! 228: case SCR_GPO_DSR(0): ! 229: case SCR_GPO_DSR(1): ! 230: case SCR_GPO_DSR(2): ! 231: return (s->gpio_level >> ((addr - SCR_GPO_DSR(0)) * 8)) & 0xff; ! 232: case SCR_GPO_DOECR(0): ! 233: case SCR_GPO_DOECR(1): ! 234: case SCR_GPO_DOECR(2): ! 235: return (s->gpio_dir >> ((addr - SCR_GPO_DOECR(0)) * 8)) & 0xff; ! 236: SCR_REG_A(GP_IARCR); ! 237: SCR_REG_A(GP_IARLCR); ! 238: SCR_REG_A(GPI_BCR); ! 239: SCR_REG_W(GPA_IARCR); ! 240: SCR_REG_W(GPA_IARLCR); ! 241: SCR_REG_W(CCR); ! 242: SCR_REG_W(PLL2CR); ! 243: SCR_REG_L(PLL1CR); ! 244: SCR_REG_B(DIARCR); ! 245: SCR_REG_B(DBOCR); ! 246: SCR_REG_B(FER); ! 247: SCR_REG_W(MCR); ! 248: SCR_REG_B(CONFIG); ! 249: SCR_REG_B(DEBUG); ! 250: } ! 251: fprintf(stderr, "tc6393xb_scr: unhandled read at %08x\n", (uint32_t) addr); ! 252: return 0; ! 253: } ! 254: #undef SCR_REG_B ! 255: #undef SCR_REG_W ! 256: #undef SCR_REG_L ! 257: #undef SCR_REG_A ! 258: ! 259: #define SCR_REG_B(N) \ ! 260: case SCR_ ##N: s->scr.N = value; return; ! 261: #define SCR_REG_W(N) \ ! 262: case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \ ! 263: case SCR_ ##N + 1: s->scr.N = (s->scr.N & 0xff) | (value << 8); return ! 264: #define SCR_REG_L(N) \ ! 265: case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \ ! 266: case SCR_ ##N + 1: s->scr.N = (s->scr.N & ~(0xff << 8)) | (value & (0xff << 8)); return; \ ! 267: case SCR_ ##N + 2: s->scr.N = (s->scr.N & ~(0xff << 16)) | (value & (0xff << 16)); return; \ ! 268: case SCR_ ##N + 3: s->scr.N = (s->scr.N & ~(0xff << 24)) | (value & (0xff << 24)); return; ! 269: #define SCR_REG_A(N) \ ! 270: case SCR_ ##N(0): s->scr.N[0] = value; return; \ ! 271: case SCR_ ##N(1): s->scr.N[1] = value; return; \ ! 272: case SCR_ ##N(2): s->scr.N[2] = value; return ! 273: ! 274: static void tc6393xb_scr_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) ! 275: { ! 276: switch (addr) { ! 277: SCR_REG_B(ISR); ! 278: SCR_REG_B(IMR); ! 279: SCR_REG_B(IRR); ! 280: SCR_REG_W(GPER); ! 281: SCR_REG_A(GPI_SR); ! 282: SCR_REG_A(GPI_IMR); ! 283: SCR_REG_A(GPI_EDER); ! 284: SCR_REG_A(GPI_LIR); ! 285: case SCR_GPO_DSR(0): ! 286: case SCR_GPO_DSR(1): ! 287: case SCR_GPO_DSR(2): ! 288: s->gpio_level = (s->gpio_level & ~(0xff << ((addr - SCR_GPO_DSR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DSR(0))*8)); ! 289: tc6393xb_gpio_handler_update(s); ! 290: return; ! 291: case SCR_GPO_DOECR(0): ! 292: case SCR_GPO_DOECR(1): ! 293: case SCR_GPO_DOECR(2): ! 294: s->gpio_dir = (s->gpio_dir & ~(0xff << ((addr - SCR_GPO_DOECR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DOECR(0))*8)); ! 295: tc6393xb_gpio_handler_update(s); ! 296: return; ! 297: SCR_REG_A(GP_IARCR); ! 298: SCR_REG_A(GP_IARLCR); ! 299: SCR_REG_A(GPI_BCR); ! 300: SCR_REG_W(GPA_IARCR); ! 301: SCR_REG_W(GPA_IARLCR); ! 302: SCR_REG_W(CCR); ! 303: SCR_REG_W(PLL2CR); ! 304: SCR_REG_L(PLL1CR); ! 305: SCR_REG_B(DIARCR); ! 306: SCR_REG_B(DBOCR); ! 307: SCR_REG_B(FER); ! 308: SCR_REG_W(MCR); ! 309: SCR_REG_B(CONFIG); ! 310: SCR_REG_B(DEBUG); ! 311: } ! 312: fprintf(stderr, "tc6393xb_scr: unhandled write at %08x: %02x\n", ! 313: (uint32_t) addr, value & 0xff); ! 314: } ! 315: #undef SCR_REG_B ! 316: #undef SCR_REG_W ! 317: #undef SCR_REG_L ! 318: #undef SCR_REG_A ! 319: ! 320: static void tc6393xb_nand_irq(struct tc6393xb_s *s) { ! 321: qemu_set_irq(s->sub_irqs[IRQ_TC6393_NAND], ! 322: (s->nand.imr & 0x80) && (s->nand.imr & s->nand.isr)); ! 323: } ! 324: ! 325: static uint32_t tc6393xb_nand_cfg_readb(struct tc6393xb_s *s, target_phys_addr_t addr) { ! 326: switch (addr) { ! 327: case NAND_CFG_COMMAND: ! 328: return s->nand_enable ? 2 : 0; ! 329: case NAND_CFG_BASE: ! 330: case NAND_CFG_BASE + 1: ! 331: case NAND_CFG_BASE + 2: ! 332: case NAND_CFG_BASE + 3: ! 333: return s->nand_phys >> (addr - NAND_CFG_BASE); ! 334: } ! 335: fprintf(stderr, "tc6393xb_nand_cfg: unhandled read at %08x\n", (uint32_t) addr); ! 336: return 0; ! 337: } ! 338: static void tc6393xb_nand_cfg_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) { ! 339: switch (addr) { ! 340: case NAND_CFG_COMMAND: ! 341: s->nand_enable = (value & 0x2); ! 342: return; ! 343: case NAND_CFG_BASE: ! 344: case NAND_CFG_BASE + 1: ! 345: case NAND_CFG_BASE + 2: ! 346: case NAND_CFG_BASE + 3: ! 347: s->nand_phys &= ~(0xff << ((addr - NAND_CFG_BASE) * 8)); ! 348: s->nand_phys |= (value & 0xff) << ((addr - NAND_CFG_BASE) * 8); ! 349: return; ! 350: } ! 351: fprintf(stderr, "tc6393xb_nand_cfg: unhandled write at %08x: %02x\n", ! 352: (uint32_t) addr, value & 0xff); ! 353: } ! 354: ! 355: static uint32_t tc6393xb_nand_readb(struct tc6393xb_s *s, target_phys_addr_t addr) { ! 356: switch (addr) { ! 357: case NAND_DATA + 0: ! 358: case NAND_DATA + 1: ! 359: case NAND_DATA + 2: ! 360: case NAND_DATA + 3: ! 361: return nand_getio(s->flash); ! 362: case NAND_MODE: ! 363: return s->nand.mode; ! 364: case NAND_STATUS: ! 365: return 0x14; ! 366: case NAND_ISR: ! 367: return s->nand.isr; ! 368: case NAND_IMR: ! 369: return s->nand.imr; ! 370: } ! 371: fprintf(stderr, "tc6393xb_nand: unhandled read at %08x\n", (uint32_t) addr); ! 372: return 0; ! 373: } ! 374: static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) { ! 375: // fprintf(stderr, "tc6393xb_nand: write at %08x: %02x\n", ! 376: // (uint32_t) addr, value & 0xff); ! 377: switch (addr) { ! 378: case NAND_DATA + 0: ! 379: case NAND_DATA + 1: ! 380: case NAND_DATA + 2: ! 381: case NAND_DATA + 3: ! 382: nand_setio(s->flash, value); ! 383: s->nand.isr &= 1; ! 384: tc6393xb_nand_irq(s); ! 385: return; ! 386: case NAND_MODE: ! 387: s->nand.mode = value; ! 388: nand_setpins(s->flash, ! 389: value & NAND_MODE_CLE, ! 390: value & NAND_MODE_ALE, ! 391: !(value & NAND_MODE_CE), ! 392: value & NAND_MODE_WP, ! 393: 0); // FIXME: gnd ! 394: switch (value & NAND_MODE_ECC_MASK) { ! 395: case NAND_MODE_ECC_RST: ! 396: ecc_reset(&s->ecc); ! 397: break; ! 398: case NAND_MODE_ECC_READ: ! 399: // FIXME ! 400: break; ! 401: case NAND_MODE_ECC_EN: ! 402: ecc_reset(&s->ecc); ! 403: } ! 404: return; ! 405: case NAND_ISR: ! 406: s->nand.isr = value; ! 407: tc6393xb_nand_irq(s); ! 408: return; ! 409: case NAND_IMR: ! 410: s->nand.imr = value; ! 411: tc6393xb_nand_irq(s); ! 412: return; ! 413: } ! 414: fprintf(stderr, "tc6393xb_nand: unhandled write at %08x: %02x\n", ! 415: (uint32_t) addr, value & 0xff); ! 416: } ! 417: ! 418: #define BITS 8 ! 419: #include "tc6393xb_template.h" ! 420: #define BITS 15 ! 421: #include "tc6393xb_template.h" ! 422: #define BITS 16 ! 423: #include "tc6393xb_template.h" ! 424: #define BITS 24 ! 425: #include "tc6393xb_template.h" ! 426: #define BITS 32 ! 427: #include "tc6393xb_template.h" ! 428: ! 429: static void tc6393xb_draw_graphic(struct tc6393xb_s *s, int full_update) ! 430: { ! 431: switch (ds_get_bits_per_pixel(s->ds)) { ! 432: case 8: ! 433: tc6393xb_draw_graphic8(s); ! 434: break; ! 435: case 15: ! 436: tc6393xb_draw_graphic15(s); ! 437: break; ! 438: case 16: ! 439: tc6393xb_draw_graphic16(s); ! 440: break; ! 441: case 24: ! 442: tc6393xb_draw_graphic24(s); ! 443: break; ! 444: case 32: ! 445: tc6393xb_draw_graphic32(s); ! 446: break; ! 447: default: ! 448: printf("tc6393xb: unknown depth %d\n", ds_get_bits_per_pixel(s->ds)); ! 449: return; ! 450: } ! 451: ! 452: dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); ! 453: } ! 454: ! 455: static void tc6393xb_draw_blank(struct tc6393xb_s *s, int full_update) ! 456: { ! 457: int i, w; ! 458: uint8_t *d; ! 459: ! 460: if (!full_update) ! 461: return; ! 462: ! 463: w = s->scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); ! 464: d = ds_get_data(s->ds); ! 465: for(i = 0; i < s->scr_height; i++) { ! 466: memset(d, 0, w); ! 467: d += ds_get_linesize(s->ds); ! 468: } ! 469: ! 470: dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); ! 471: } ! 472: ! 473: static void tc6393xb_update_display(void *opaque) ! 474: { ! 475: struct tc6393xb_s *s = opaque; ! 476: int full_update; ! 477: ! 478: if (s->scr_width == 0 || s->scr_height == 0) ! 479: return; ! 480: ! 481: full_update = 0; ! 482: if (s->blanked != s->blank) { ! 483: s->blanked = s->blank; ! 484: full_update = 1; ! 485: } ! 486: if (s->scr_width != ds_get_width(s->ds) || s->scr_height != ds_get_height(s->ds)) { ! 487: qemu_console_resize(s->ds, s->scr_width, s->scr_height); ! 488: full_update = 1; ! 489: } ! 490: if (s->blanked) ! 491: tc6393xb_draw_blank(s, full_update); ! 492: else ! 493: tc6393xb_draw_graphic(s, full_update); ! 494: } ! 495: ! 496: ! 497: static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) { ! 498: struct tc6393xb_s *s = opaque; ! 499: ! 500: switch (addr >> 8) { ! 501: case 0: ! 502: return tc6393xb_scr_readb(s, addr & 0xff); ! 503: case 1: ! 504: return tc6393xb_nand_cfg_readb(s, addr & 0xff); ! 505: }; ! 506: ! 507: if ((addr &~0xff) == s->nand_phys && s->nand_enable) { ! 508: // return tc6393xb_nand_readb(s, addr & 0xff); ! 509: uint8_t d = tc6393xb_nand_readb(s, addr & 0xff); ! 510: // fprintf(stderr, "tc6393xb_nand: read at %08x: %02hhx\n", (uint32_t) addr, d); ! 511: return d; ! 512: } ! 513: ! 514: // fprintf(stderr, "tc6393xb: unhandled read at %08x\n", (uint32_t) addr); ! 515: return 0; ! 516: } ! 517: ! 518: static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) { ! 519: struct tc6393xb_s *s = opaque; ! 520: ! 521: switch (addr >> 8) { ! 522: case 0: ! 523: tc6393xb_scr_writeb(s, addr & 0xff, value); ! 524: return; ! 525: case 1: ! 526: tc6393xb_nand_cfg_writeb(s, addr & 0xff, value); ! 527: return; ! 528: }; ! 529: ! 530: if ((addr &~0xff) == s->nand_phys && s->nand_enable) ! 531: tc6393xb_nand_writeb(s, addr & 0xff, value); ! 532: else ! 533: fprintf(stderr, "tc6393xb: unhandled write at %08x: %02x\n", ! 534: (uint32_t) addr, value & 0xff); ! 535: } ! 536: ! 537: static uint32_t tc6393xb_readw(void *opaque, target_phys_addr_t addr) ! 538: { ! 539: return (tc6393xb_readb(opaque, addr) & 0xff) | ! 540: (tc6393xb_readb(opaque, addr + 1) << 8); ! 541: } ! 542: ! 543: static uint32_t tc6393xb_readl(void *opaque, target_phys_addr_t addr) ! 544: { ! 545: return (tc6393xb_readb(opaque, addr) & 0xff) | ! 546: ((tc6393xb_readb(opaque, addr + 1) & 0xff) << 8) | ! 547: ((tc6393xb_readb(opaque, addr + 2) & 0xff) << 16) | ! 548: ((tc6393xb_readb(opaque, addr + 3) & 0xff) << 24); ! 549: } ! 550: ! 551: static void tc6393xb_writew(void *opaque, target_phys_addr_t addr, uint32_t value) ! 552: { ! 553: tc6393xb_writeb(opaque, addr, value); ! 554: tc6393xb_writeb(opaque, addr + 1, value >> 8); ! 555: } ! 556: ! 557: static void tc6393xb_writel(void *opaque, target_phys_addr_t addr, uint32_t value) ! 558: { ! 559: tc6393xb_writeb(opaque, addr, value); ! 560: tc6393xb_writeb(opaque, addr + 1, value >> 8); ! 561: tc6393xb_writeb(opaque, addr + 2, value >> 16); ! 562: tc6393xb_writeb(opaque, addr + 3, value >> 24); ! 563: } ! 564: ! 565: struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq) ! 566: { ! 567: int iomemtype; ! 568: struct tc6393xb_s *s; ! 569: CPUReadMemoryFunc *tc6393xb_readfn[] = { ! 570: tc6393xb_readb, ! 571: tc6393xb_readw, ! 572: tc6393xb_readl, ! 573: }; ! 574: CPUWriteMemoryFunc *tc6393xb_writefn[] = { ! 575: tc6393xb_writeb, ! 576: tc6393xb_writew, ! 577: tc6393xb_writel, ! 578: }; ! 579: ! 580: s = (struct tc6393xb_s *) qemu_mallocz(sizeof(struct tc6393xb_s)); ! 581: s->irq = irq; ! 582: s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS); ! 583: ! 584: s->l3v = *qemu_allocate_irqs(tc6393xb_l3v, s, 1); ! 585: s->blanked = 1; ! 586: ! 587: s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS); ! 588: ! 589: s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76); ! 590: ! 591: iomemtype = cpu_register_io_memory(0, tc6393xb_readfn, ! 592: tc6393xb_writefn, s); ! 593: cpu_register_physical_memory(base, 0x10000, iomemtype); ! 594: ! 595: s->vram_addr = qemu_ram_alloc(0x100000); ! 596: cpu_register_physical_memory(base + 0x100000, 0x100000, s->vram_addr); ! 597: s->scr_width = 480; ! 598: s->scr_height = 640; ! 599: s->ds = graphic_console_init(tc6393xb_update_display, ! 600: NULL, /* invalidate */ ! 601: NULL, /* screen_dump */ ! 602: NULL, /* text_update */ ! 603: s); ! 604: ! 605: return s; ! 606: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.