summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
authorDoug Evans2021-02-18 22:24:52 +0100
committerPeter Maydell2021-03-05 16:17:34 +0100
commit7758643650f0229bd3ccd23112c255664445eabd (patch)
tree5c863779c7cbef028a47a3ca83634faee1e0feff /hw
parenthw/net: Add npcm7xx emc model (diff)
downloadqemu-7758643650f0229bd3ccd23112c255664445eabd.tar.gz
qemu-7758643650f0229bd3ccd23112c255664445eabd.tar.xz
qemu-7758643650f0229bd3ccd23112c255664445eabd.zip
hw/arm: Add npcm7xx emc model
This is a 10/100 ethernet device that has several features. Only the ones needed by the Linux driver have been implemented. See npcm7xx_emc.c for a list of unimplemented features. Reviewed-by: Hao Wu <wuhaotsh@google.com> Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Doug Evans <dje@google.com> Message-id: 20210218212453.831406-3-dje@google.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/npcm7xx.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index f8950f9470..9bd1e83f02 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -82,6 +82,8 @@ enum NPCM7xxInterrupt {
NPCM7XX_UART1_IRQ,
NPCM7XX_UART2_IRQ,
NPCM7XX_UART3_IRQ,
+ NPCM7XX_EMC1RX_IRQ = 15,
+ NPCM7XX_EMC1TX_IRQ,
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
NPCM7XX_TIMER1_IRQ,
NPCM7XX_TIMER2_IRQ,
@@ -120,6 +122,8 @@ enum NPCM7xxInterrupt {
NPCM7XX_SMBUS15_IRQ,
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
+ NPCM7XX_EMC2RX_IRQ = 114,
+ NPCM7XX_EMC2TX_IRQ,
NPCM7XX_GPIO0_IRQ = 116,
NPCM7XX_GPIO1_IRQ,
NPCM7XX_GPIO2_IRQ,
@@ -188,6 +192,12 @@ static const hwaddr npcm7xx_smbus_addr[] = {
0xf008f000,
};
+/* Register base address for each EMC Module */
+static const hwaddr npcm7xx_emc_addr[] = {
+ 0xf0825000,
+ 0xf0826000,
+};
+
static const struct {
hwaddr regs_addr;
uint32_t unconnected_pins;
@@ -406,6 +416,10 @@ static void npcm7xx_init(Object *obj)
for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
}
+
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
+ object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
+ }
}
static void npcm7xx_realize(DeviceState *dev, Error **errp)
@@ -590,6 +604,40 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
}
/*
+ * EMC Modules. Cannot fail.
+ * The mapping of the device to its netdev backend works as follows:
+ * emc[i] = nd_table[i]
+ * This works around the inability to specify the netdev property for the
+ * emc device: it's not pluggable and thus the -device option can't be
+ * used.
+ */
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
+ s->emc[i].emc_num = i;
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
+ if (nd_table[i].used) {
+ qemu_check_nic_model(&nd_table[i], TYPE_NPCM7XX_EMC);
+ qdev_set_nic_properties(DEVICE(sbd), &nd_table[i]);
+ }
+ /*
+ * The device exists regardless of whether it's connected to a QEMU
+ * netdev backend. So always instantiate it even if there is no
+ * backend.
+ */
+ sysbus_realize(sbd, &error_abort);
+ sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
+ int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
+ int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
+ /*
+ * N.B. The values for the second argument sysbus_connect_irq are
+ * chosen to match the registration order in npcm7xx_emc_realize.
+ */
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
+ sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
+ }
+
+ /*
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
* specified, but this is a programming error.
*/
@@ -649,8 +697,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
- create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
- create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);