diff options
author | Doug Evans <dje@google.com> | 2021-02-18 13:24:52 -0800 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-03-05 15:17:34 +0000 |
commit | 7758643650f0229bd3ccd23112c255664445eabd (patch) | |
tree | 5c863779c7cbef028a47a3ca83634faee1e0feff | |
parent | 01c966b54f5effd7132da1a8d33ae1927944cfdf (diff) | |
download | qemu-7758643650f0229bd3ccd23112c255664445eabd.zip qemu-7758643650f0229bd3ccd23112c255664445eabd.tar.gz qemu-7758643650f0229bd3ccd23112c255664445eabd.tar.bz2 |
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>
-rw-r--r-- | docs/system/arm/nuvoton.rst | 3 | ||||
-rw-r--r-- | hw/arm/npcm7xx.c | 50 | ||||
-rw-r--r-- | include/hw/arm/npcm7xx.h | 2 |
3 files changed, 52 insertions, 3 deletions
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst index 34fc799..f9fb922 100644 --- a/docs/system/arm/nuvoton.rst +++ b/docs/system/arm/nuvoton.rst @@ -44,6 +44,7 @@ Supported devices * Analog to Digital Converter (ADC) * Pulse Width Modulation (PWM) * SMBus controller (SMBF) + * Ethernet controller (EMC) Missing devices --------------- @@ -57,7 +58,7 @@ Missing devices * Shared memory (SHM) * eSPI slave interface - * Ethernet controllers (GMAC and EMC) + * Ethernet controller (GMAC) * USB device (USBD) * Peripheral SPI controller (PSPI) * SD/MMC host diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c index f8950f9..9bd1e83 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); diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h index cea1bd1..d32849a 100644 --- a/include/hw/arm/npcm7xx.h +++ b/include/hw/arm/npcm7xx.h @@ -26,6 +26,7 @@ #include "hw/misc/npcm7xx_gcr.h" #include "hw/misc/npcm7xx_pwm.h" #include "hw/misc/npcm7xx_rng.h" +#include "hw/net/npcm7xx_emc.h" #include "hw/nvram/npcm7xx_otp.h" #include "hw/timer/npcm7xx_timer.h" #include "hw/ssi/npcm7xx_fiu.h" @@ -90,6 +91,7 @@ typedef struct NPCM7xxState { EHCISysBusState ehci; OHCISysBusState ohci; NPCM7xxFIUState fiu[2]; + NPCM7xxEMCState emc[2]; } NPCM7xxState; #define TYPE_NPCM7XX "npcm7xx" |