X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hw%2Fspitz.c;h=aca244ee2f87381cb6e2f4f82d7574846d62ffd3;hb=cd346349b45ef056f138a184f660b8c34c3213cc;hp=aecace0073ee212ebb1feb76fd3d08cbf32d2ca4;hpb=d95b2f8d365a3ef431111e9188d219de1f577a90;p=qemu diff --git a/hw/spitz.c b/hw/spitz.c index aecace0..aca244e 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -78,6 +78,18 @@ static uint32_t sl_readb(void *opaque, target_phys_addr_t addr) return 0; } +static uint32_t sl_readl(void *opaque, target_phys_addr_t addr) +{ + struct sl_nand_s *s = (struct sl_nand_s *) opaque; + addr -= s->target_base; + + if (addr == FLASH_FLASHIO) + return ecc_digest(&s->ecc, nand_getio(s->nand)) | + (ecc_digest(&s->ecc, nand_getio(s->nand)) << 16); + + return sl_readb(opaque, addr); +} + static void sl_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) { @@ -109,6 +121,24 @@ static void sl_writeb(void *opaque, target_phys_addr_t addr, } } +static void sl_save(QEMUFile *f, void *opaque) +{ + struct sl_nand_s *s = (struct sl_nand_s *) opaque; + + qemu_put_8s(f, &s->ctl); + ecc_put(f, &s->ecc); +} + +static int sl_load(QEMUFile *f, void *opaque, int version_id) +{ + struct sl_nand_s *s = (struct sl_nand_s *) opaque; + + qemu_get_8s(f, &s->ctl); + ecc_get(f, &s->ecc); + + return 0; +} + enum { FLASH_128M, FLASH_1024M, @@ -121,7 +151,7 @@ static void sl_flash_register(struct pxa2xx_state_s *cpu, int size) CPUReadMemoryFunc *sl_readfn[] = { sl_readb, sl_readb, - sl_readb, + sl_readl, }; CPUWriteMemoryFunc *sl_writefn[] = { sl_writeb, @@ -140,6 +170,8 @@ static void sl_flash_register(struct pxa2xx_state_s *cpu, int size) iomemtype = cpu_register_io_memory(0, sl_readfn, sl_writefn, s); cpu_register_physical_memory(s->target_base, 0x40, iomemtype); + + register_savevm("sl_flash", 0, 0, sl_save, sl_load, s); } /* Spitz Keyboard */ @@ -162,8 +194,8 @@ static int spitz_keymap[SPITZ_KEY_SENSE_NUM + 1][SPITZ_KEY_STROBE_NUM] = { { 0x0f, 0x10, 0x12, 0x14, 0x22, 0x16, 0x24, 0x25, -1 , -1 , -1 }, { 0x3c, 0x11, 0x1f, 0x21, 0x2f, 0x23, 0x32, 0x26, -1 , 0x36, -1 }, { 0x3b, 0x1e, 0x20, 0x2e, 0x30, 0x31, 0x34, -1 , 0x1c, 0x2a, -1 }, - { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33, -1 , 0x48, -1 , -1 , 0x3d }, - { 0x37, 0x38, -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d, -1 , -1 }, + { 0x44, 0x2c, 0x2d, 0x0c, 0x39, 0x33, -1 , 0x48, -1 , -1 , 0x38 }, + { 0x37, 0x3d, -1 , 0x45, 0x57, 0x58, 0x4b, 0x50, 0x4d, -1 , -1 }, { 0x52, 0x43, 0x01, 0x47, 0x49, -1 , -1 , -1 , -1 , -1 , -1 }, }; @@ -383,13 +415,17 @@ static void spitz_keyboard_pre_map(struct spitz_keyboard_s *s) s->pre_map[0x0d | SHIFT ] = 0x13 | FN; /* plus */ s->pre_map[0x1a ] = 0x14 | FN; /* bracketleft */ s->pre_map[0x1b ] = 0x15 | FN; /* bracketright */ + s->pre_map[0x1a | SHIFT ] = 0x16 | FN; /* braceleft */ + s->pre_map[0x1b | SHIFT ] = 0x17 | FN; /* braceright */ s->pre_map[0x27 ] = 0x22 | FN; /* semicolon */ s->pre_map[0x27 | SHIFT ] = 0x23 | FN; /* colon */ s->pre_map[0x09 | SHIFT ] = 0x24 | FN; /* asterisk */ s->pre_map[0x2b ] = 0x25 | FN; /* backslash */ s->pre_map[0x2b | SHIFT ] = 0x26 | FN; /* bar */ s->pre_map[0x0c | SHIFT ] = 0x30 | FN; /* underscore */ + s->pre_map[0x33 | SHIFT ] = 0x33 | FN; /* less */ s->pre_map[0x35 ] = 0x33 | SHIFT; /* slash */ + s->pre_map[0x34 | SHIFT ] = 0x34 | FN; /* greater */ s->pre_map[0x35 | SHIFT ] = 0x34 | SHIFT; /* question */ s->pre_map[0x49 ] = 0x48 | FN; /* Page_Up */ s->pre_map[0x51 ] = 0x50 | FN; /* Page_Down */ @@ -406,6 +442,38 @@ static void spitz_keyboard_pre_map(struct spitz_keyboard_s *s) #undef CTRL #undef FN +static void spitz_keyboard_save(QEMUFile *f, void *opaque) +{ + struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque; + int i; + + qemu_put_be16s(f, &s->sense_state); + qemu_put_be16s(f, &s->strobe_state); + for (i = 0; i < 5; i ++) + qemu_put_byte(f, spitz_gpio_invert[i]); +} + +static int spitz_keyboard_load(QEMUFile *f, void *opaque, int version_id) +{ + struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque; + int i; + + qemu_get_be16s(f, &s->sense_state); + qemu_get_be16s(f, &s->strobe_state); + for (i = 0; i < 5; i ++) + spitz_gpio_invert[i] = qemu_get_byte(f); + + /* Release all pressed keys */ + memset(s->keyrow, 0, sizeof(s->keyrow)); + spitz_keyboard_sense_update(s); + s->modifiers = 0; + s->imodifiers = 0; + s->fifopos = 0; + s->fifolen = 0; + + return 0; +} + static void spitz_keyboard_register(struct pxa2xx_state_s *cpu) { int i, j; @@ -429,6 +497,9 @@ static void spitz_keyboard_register(struct pxa2xx_state_s *cpu) spitz_keyboard_pre_map(s); qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s); + + register_savevm("spitz_keyboard", 0, 0, + spitz_keyboard_save, spitz_keyboard_load, s); } /* SCOOP devices */ @@ -597,6 +668,42 @@ static inline void scoop_gpio_handler_set(struct scoop_info_s *s, int line, s->handler[line].opaque = opaque; } +static void scoop_save(QEMUFile *f, void *opaque) +{ + struct scoop_info_s *s = (struct scoop_info_s *) opaque; + qemu_put_be16s(f, &s->status); + qemu_put_be16s(f, &s->power); + qemu_put_be32s(f, &s->gpio_level); + qemu_put_be32s(f, &s->gpio_dir); + qemu_put_be32s(f, &s->prev_level); + qemu_put_be16s(f, &s->mcr); + qemu_put_be16s(f, &s->cdr); + qemu_put_be16s(f, &s->ccr); + qemu_put_be16s(f, &s->irr); + qemu_put_be16s(f, &s->imr); + qemu_put_be16s(f, &s->isr); + qemu_put_be16s(f, &s->gprr); +} + +static int scoop_load(QEMUFile *f, void *opaque, int version_id) +{ + struct scoop_info_s *s = (struct scoop_info_s *) opaque; + qemu_get_be16s(f, &s->status); + qemu_get_be16s(f, &s->power); + qemu_get_be32s(f, &s->gpio_level); + qemu_get_be32s(f, &s->gpio_dir); + qemu_get_be32s(f, &s->prev_level); + qemu_get_be16s(f, &s->mcr); + qemu_get_be16s(f, &s->cdr); + qemu_get_be16s(f, &s->ccr); + qemu_get_be16s(f, &s->irr); + qemu_get_be16s(f, &s->imr); + qemu_get_be16s(f, &s->isr); + qemu_get_be16s(f, &s->gprr); + + return 0; +} + static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu, int count) { int iomemtype; @@ -614,14 +721,16 @@ static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu, iomemtype = cpu_register_io_memory(0, scoop_readfn, scoop_writefn, &s[0]); - cpu_register_physical_memory(s[0].target_base, 0xfff, iomemtype); + cpu_register_physical_memory(s[0].target_base, 0x1000, iomemtype); + register_savevm("scoop", 0, 0, scoop_save, scoop_load, &s[0]); if (count < 2) return s; iomemtype = cpu_register_io_memory(0, scoop_readfn, scoop_writefn, &s[1]); - cpu_register_physical_memory(s[1].target_base, 0xfff, iomemtype); + cpu_register_physical_memory(s[1].target_base, 0x1000, iomemtype); + register_savevm("scoop", 1, 0, scoop_save, scoop_load, &s[1]); return s; } @@ -763,6 +872,26 @@ static void spitz_pendown_set(void *opaque, int line, int level) pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_TP_INT, level); } +static void spitz_ssp_save(QEMUFile *f, void *opaque) +{ + qemu_put_be32(f, lcd_en); + qemu_put_be32(f, ads_en); + qemu_put_be32(f, max_en); + qemu_put_be32(f, bl_intensity); + qemu_put_be32(f, bl_power); +} + +static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id) +{ + lcd_en = qemu_get_be32(f); + ads_en = qemu_get_be32(f); + max_en = qemu_get_be32(f); + bl_intensity = qemu_get_be32(f); + bl_power = qemu_get_be32(f); + + return 0; +} + static void spitz_ssp_attach(struct pxa2xx_state_s *cpu) { lcd_en = ads_en = max_en = 0; @@ -786,6 +915,8 @@ static void spitz_ssp_attach(struct pxa2xx_state_s *cpu) bl_intensity = 0x20; bl_power = 0; + + register_savevm("spitz_ssp", 0, 0, spitz_ssp_save, spitz_ssp_load, cpu); } /* CF Microdrive */ @@ -797,10 +928,61 @@ static void spitz_microdrive_attach(struct pxa2xx_state_s *cpu) if (bs && bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) { md = dscm1xxxx_init(bs); - pxa2xx_pcmcia_attach(cpu->pcmcia[0], md); + pxa2xx_pcmcia_attach(cpu->pcmcia[1], md); } } +/* Wm8750 and Max7310 on I2C */ + +#define AKITA_MAX_ADDR 0x18 +#define SPITZ_WM_ADDRL 0x1b +#define SPITZ_WM_ADDRH 0x1a + +#define SPITZ_GPIO_WM 5 + +#ifdef HAS_AUDIO +static void spitz_wm8750_addr(int line, int level, void *opaque) +{ + i2c_slave *wm = (i2c_slave *) opaque; + if (level) + i2c_set_slave_address(wm, SPITZ_WM_ADDRH); + else + i2c_set_slave_address(wm, SPITZ_WM_ADDRL); +} +#endif + +static void spitz_i2c_setup(struct pxa2xx_state_s *cpu) +{ + /* Attach the CPU on one end of our I2C bus. */ + i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]); + +#ifdef HAS_AUDIO + AudioState *audio; + i2c_slave *wm; + + audio = AUD_init(); + if (!audio) + return; + /* Attach a WM8750 to the bus */ + wm = wm8750_init(bus, audio); + + spitz_wm8750_addr(0, 0, wm); + pxa2xx_gpio_handler_set(cpu->gpio, SPITZ_GPIO_WM, spitz_wm8750_addr, wm); + /* .. and to the sound interface. */ + cpu->i2s->opaque = wm; + cpu->i2s->codec_out = wm8750_dac_dat; + cpu->i2s->codec_in = wm8750_adc_dat; + wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s); +#endif +} + +static void spitz_akita_i2c_setup(struct pxa2xx_state_s *cpu) +{ + /* Attach a Max7310 to Akita I2C bus. */ + i2c_set_slave_address(max7310_init(pxa2xx_i2c_bus(cpu->i2c[0])), + AKITA_MAX_ADDR); +} + /* Other peripherals */ static void spitz_charge_switch(int line, int level, void *opaque) @@ -1003,9 +1185,9 @@ static void spitz_common_init(int ram_size, int vga_ram_size, cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0"; /* Setup CPU & memory */ - if (ram_size < spitz_ram + spitz_rom) { + if (ram_size < spitz_ram + spitz_rom + PXA2XX_INTERNAL_SIZE) { fprintf(stderr, "This platform requires %i bytes of memory\n", - spitz_ram + spitz_rom); + spitz_ram + spitz_rom + PXA2XX_INTERNAL_SIZE); exit(1); } cpu = pxa270_init(spitz_ram, ds, cpu_model); @@ -1026,11 +1208,16 @@ static void spitz_common_init(int ram_size, int vga_ram_size, spitz_gpio_setup(cpu, (model == akita) ? 1 : 2); + spitz_i2c_setup(cpu); + + if (model == akita) + spitz_akita_i2c_setup(cpu); + if (model == terrier) - /* A 6.0 GB microdrive is permanently sitting in CF slot 0. */ + /* A 6.0 GB microdrive is permanently sitting in CF slot 1. */ spitz_microdrive_attach(cpu); else if (model != akita) - /* A 4.0 GB microdrive is permanently sitting in CF slot 0. */ + /* A 4.0 GB microdrive is permanently sitting in CF slot 1. */ spitz_microdrive_attach(cpu); /* Setup initial (reset) machine state */