[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 2/2] integrator/cp: Implement CARDIN and WPROT si
From: |
Jan Kiszka |
Subject: |
[Qemu-devel] [PATCH v2 2/2] integrator/cp: Implement CARDIN and WPROT signals |
Date: |
Thu, 19 Feb 2015 18:53:17 +0100 |
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 <address@hidden>
---
hw/arm/integratorcp.c | 58 +++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 52 insertions(+), 6 deletions(-)
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index c5aa1f6..39803a9 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 0
+#define ICP_GPIO_MMC_CARDIN 1
+
+#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,39 @@ static const MemoryRegionOps icp_control_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
+static void icp_control_gpio_set(void *opaque, int line, int level)
+{
+ ICPCtrlRegsState *s = opaque;
+
+ switch (line) {
+ case ICP_GPIO_MMC_WPROT:
+ s->intreg_state &= ~ICP_INTREG_WPROT;
+ if (level) {
+ s->intreg_state |= ICP_INTREG_WPROT;
+ }
+ break;
+ case ICP_GPIO_MMC_CARDIN:
+ /* line is released by writing to CP_INTREG */
+ if (level) {
+ s->intreg_state |= ICP_INTREG_CARDIN;
+ qemu_set_irq(s->mmc_irq, 1);
+ }
+ break;
+ }
+}
+
static int icp_control_init(SysBusDevice *sbd)
{
ICPCtrlRegsState *s = ICP_CONTROL_REGS(sbd);
+ DeviceState *dev = DEVICE(sbd);
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(dev, icp_control_gpio_set, 2);
+ sysbus_init_irq(sbd, &s->mmc_irq);
+
return 0;
}
@@ -489,7 +530,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;
@@ -547,17 +588,22 @@ 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(icp, ICP_GPIO_MMC_WPROT));
+ qdev_connect_gpio_out(dev, 1, qdev_get_gpio_in(icp, ICP_GPIO_MMC_CARDIN));
+
if (nd_table[0].used)
smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
--
2.1.4