On Mon, Feb 23, 2015 at 4:21 AM, Jan Kiszka <jan.kis...@siemens.com> wrote: > This allows to use the SD card emulation of the board: Forward the > signals from the pl181 top the CP control register emulation, report the > current state via CP_INTREG, deliver CARDIN IRQ to the secondary > interrupt controller and also support clearing that line via CP_INTREG. > > Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com> > --- > hw/arm/integratorcp.c | 62 > ++++++++++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 56 insertions(+), 6 deletions(-) > > diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c > index 2d62275..59658d3 100644 > --- a/hw/arm/integratorcp.c > +++ b/hw/arm/integratorcp.c > @@ -416,18 +416,29 @@ typedef struct ICPCtrlRegsState { > /*< public >*/ > > MemoryRegion iomem; > + > + qemu_irq mmc_irq; > + uint32_t intreg_state; > } ICPCtrlRegsState; > > +#define ICP_GPIO_MMC_WPROT "mmc-wprot" > +#define ICP_GPIO_MMC_CARDIN "mmc-cardin" > + > +#define ICP_INTREG_WPROT (1 << 0) > +#define ICP_INTREG_CARDIN (1 << 3) > + > static uint64_t icp_control_read(void *opaque, hwaddr offset, > unsigned size) > { > + ICPCtrlRegsState *s = opaque; > + > switch (offset >> 2) { > case 0: /* CP_IDFIELD */ > return 0x41034003; > case 1: /* CP_FLASHPROG */ > return 0; > case 2: /* CP_INTREG */ > - return 0; > + return s->intreg_state; > case 3: /* CP_DECODE */ > return 0x11; > default: > @@ -439,9 +450,14 @@ static uint64_t icp_control_read(void *opaque, hwaddr > offset, > static void icp_control_write(void *opaque, hwaddr offset, > uint64_t value, unsigned size) > { > + ICPCtrlRegsState *s = opaque; > + > switch (offset >> 2) { > - case 1: /* CP_FLASHPROG */ > case 2: /* CP_INTREG */ > + s->intreg_state &= ~(value & ICP_INTREG_CARDIN); > + qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN)); > + break; > + case 1: /* CP_FLASHPROG */ > case 3: /* CP_DECODE */ > /* Nothing interesting implemented yet. */ > break; > @@ -456,14 +472,41 @@ static const MemoryRegionOps icp_control_ops = { > .endianness = DEVICE_NATIVE_ENDIAN, > }; > > +static void icp_control_mmc_wprot(void *opaque, int line, int level) > +{ > + ICPCtrlRegsState *s = opaque; > + > + s->intreg_state &= ~ICP_INTREG_WPROT; > + if (level) { > + s->intreg_state |= ICP_INTREG_WPROT; > + } > +} > + > +static void icp_control_mmc_cardin(void *opaque, int line, int level) > +{ > + ICPCtrlRegsState *s = opaque; > + > + /* line is released by writing to CP_INTREG */ > + if (level) { > + s->intreg_state |= ICP_INTREG_CARDIN; > + qemu_set_irq(s->mmc_irq, 1); > + } > +} > + > static void icp_control_init(Object *obj) > { > SysBusDevice *sbd = SYS_BUS_DEVICE(obj); > ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj); > + DeviceState *dev = DEVICE(obj); > > memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s, > "icp_ctrl_regs", 0x00800000); > sysbus_init_mmio(sbd, &s->iomem); > + > + qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, > 1); > + qdev_init_gpio_in_named(dev, icp_control_mmc_cardin, > + ICP_GPIO_MMC_CARDIN, 1); > + sysbus_init_irq(sbd, &s->mmc_irq); > } > > > @@ -488,7 +531,7 @@ static void integratorcp_init(MachineState *machine) > MemoryRegion *ram = g_new(MemoryRegion, 1); > MemoryRegion *ram_alias = g_new(MemoryRegion, 1); > qemu_irq pic[32]; > - DeviceState *dev; > + DeviceState *dev, *sic, *icp; > int i; > Error *err = NULL; > > @@ -546,17 +589,24 @@ static void integratorcp_init(MachineState *machine) > for (i = 0; i < 32; i++) { > pic[i] = qdev_get_gpio_in(dev, i); > } > - sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]); > + sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]); > sysbus_create_varargs("integrator_pit", 0x13000000, > pic[5], pic[6], pic[7], NULL); > sysbus_create_simple("pl031", 0x15000000, pic[8]); > sysbus_create_simple("pl011", 0x16000000, pic[1]); > sysbus_create_simple("pl011", 0x17000000, pic[2]); > - sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000, NULL); > + icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000, > + qdev_get_gpio_in(sic, 3)); > sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]); > sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]); > sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0); > - sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL); > + > + dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL); > + qdev_connect_gpio_out(dev, 0, > + qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, > 0)); > + qdev_connect_gpio_out(dev, 1, > + qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, > 0)); > + > if (nd_table[0].used) > smc91c111_init(&nd_table[0], 0xc8000000, pic[27]); > > -- > 2.1.4 > >