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)
{
}
}
+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,
CPUReadMemoryFunc *sl_readfn[] = {
sl_readb,
sl_readb,
- sl_readb,
+ sl_readl,
};
CPUWriteMemoryFunc *sl_writefn[] = {
sl_writeb,
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 */
{ 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 },
};
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 */
#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;
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 */
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;
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;
}
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;
bl_intensity = 0x20;
bl_power = 0;
+
+ register_savevm("spitz_ssp", 0, 0, spitz_ssp_save, spitz_ssp_load, cpu);
}
/* CF Microdrive */
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)
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);
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 */