uint32_t rising[PXA2XX_GPIO_BANKS];
uint32_t falling[PXA2XX_GPIO_BANKS];
uint32_t status[PXA2XX_GPIO_BANKS];
+ uint32_t gpsr[PXA2XX_GPIO_BANKS];
uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
uint32_t prev_level[PXA2XX_GPIO_BANKS];
} pxa2xx_gpio_regs[0x200] = {
[0 ... 0x1ff] = { GPIO_NONE, 0 },
#define PXA2XX_REG(reg, a0, a1, a2, a3) \
- [a0] = { reg, 0 }, [a1] = { reg, 1 }, [a2] = { reg, 2 }, [a3] = { reg, 3 },
+ [a0] = { reg, 0 }, [a1] = { reg, 1 }, [a2] = { reg, 2 }, [a3] = { reg, 3 },
PXA2XX_REG(GPLR, 0x000, 0x004, 0x008, 0x100)
PXA2XX_REG(GPSR, 0x018, 0x01c, 0x020, 0x118)
case GPDR: /* GPIO Pin-Direction registers */
return s->dir[bank];
+ case GPSR: /* GPIO Pin-Output Set registers */
+ printf("%s: Read from a write-only register " REG_FMT "\n",
+ __FUNCTION__, offset);
+ return s->gpsr[bank]; /* Return last written value. */
+
case GRER: /* GPIO Rising-Edge Detect Enable registers */
return s->rising[bank];
case GPSR: /* GPIO Pin-Output Set registers */
s->olevel[bank] |= value;
pxa2xx_gpio_handler_update(s);
+ s->gpsr[bank] = value;
break;
case GPCR: /* GPIO Pin-Output Clear registers */
pxa2xx_gpio_write
};
+static void pxa2xx_gpio_save(QEMUFile *f, void *opaque)
+{
+ struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
+ int i;
+
+ qemu_put_be32(f, s->lines);
+
+ for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
+ qemu_put_be32s(f, &s->ilevel[i]);
+ qemu_put_be32s(f, &s->olevel[i]);
+ qemu_put_be32s(f, &s->dir[i]);
+ qemu_put_be32s(f, &s->rising[i]);
+ qemu_put_be32s(f, &s->falling[i]);
+ qemu_put_be32s(f, &s->status[i]);
+ qemu_put_be32s(f, &s->gafr[i * 2 + 0]);
+ qemu_put_be32s(f, &s->gafr[i * 2 + 1]);
+
+ qemu_put_be32s(f, &s->prev_level[i]);
+ }
+}
+
+static int pxa2xx_gpio_load(QEMUFile *f, void *opaque, int version_id)
+{
+ struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
+ int i;
+
+ if (qemu_get_be32(f) != s->lines)
+ return -EINVAL;
+
+ for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
+ qemu_get_be32s(f, &s->ilevel[i]);
+ qemu_get_be32s(f, &s->olevel[i]);
+ qemu_get_be32s(f, &s->dir[i]);
+ qemu_get_be32s(f, &s->rising[i]);
+ qemu_get_be32s(f, &s->falling[i]);
+ qemu_get_be32s(f, &s->status[i]);
+ qemu_get_be32s(f, &s->gafr[i * 2 + 0]);
+ qemu_get_be32s(f, &s->gafr[i * 2 + 1]);
+
+ qemu_get_be32s(f, &s->prev_level[i]);
+ }
+
+ return 0;
+}
+
struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base,
CPUState *env, qemu_irq *pic, int lines)
{
iomemtype = cpu_register_io_memory(0, pxa2xx_gpio_readfn,
pxa2xx_gpio_writefn, s);
- cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+ cpu_register_physical_memory(base, 0x00001000, iomemtype);
+
+ register_savevm("pxa2xx_gpio", 0, 0,
+ pxa2xx_gpio_save, pxa2xx_gpio_load, s);
return s;
}