hw/arm/npcm7xx: Add EHCI and OHCI controllers
The NPCM730 and NPCM750 chips have a single USB host port shared between a USB 2.0 EHCI host controller and a USB 1.1 OHCI host controller. This adds support for both of them. Testing notes: * With -device usb-kbd, qemu will automatically insert a full-speed hub, and the keyboard becomes controlled by the OHCI controller. * With -device usb-kbd,bus=usb-bus.0,port=1, the keyboard is directly attached to the port without any hubs, and the device becomes controlled by the EHCI controller since it's high speed capable. * With -device usb-kbd,bus=usb-bus.0,port=1,usb_version=1, the keyboard is directly attached to the port, but it only advertises itself as full-speed capable, so it becomes controlled by the OHCI controller. In all cases, the keyboard device enumerates correctly. Reviewed-by: Tyrone Ting <kfting@nuvoton.com> Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
326ccfe240
commit
e23e7b1259
@ -39,6 +39,7 @@ Supported devices
|
||||
* OTP controllers (no protection features)
|
||||
* Flash Interface Unit (FIU; no protection features)
|
||||
* Random Number Generator (RNG)
|
||||
* USB host (USBH)
|
||||
|
||||
Missing devices
|
||||
---------------
|
||||
@ -54,7 +55,6 @@ Missing devices
|
||||
* eSPI slave interface
|
||||
|
||||
* Ethernet controllers (GMAC and EMC)
|
||||
* USB host (USBH)
|
||||
* USB device (USBD)
|
||||
* SMBus controller (SMBF)
|
||||
* Peripheral SPI controller (PSPI)
|
||||
|
@ -46,6 +46,10 @@
|
||||
#define NPCM7XX_MC_BA (0xf0824000)
|
||||
#define NPCM7XX_RNG_BA (0xf000b000)
|
||||
|
||||
/* USB Host modules */
|
||||
#define NPCM7XX_EHCI_BA (0xf0806000)
|
||||
#define NPCM7XX_OHCI_BA (0xf0807000)
|
||||
|
||||
/* Internal AHB SRAM */
|
||||
#define NPCM7XX_RAM3_BA (0xc0008000)
|
||||
#define NPCM7XX_RAM3_SZ (4 * KiB)
|
||||
@ -90,6 +94,8 @@ enum NPCM7xxInterrupt {
|
||||
NPCM7XX_WDG0_IRQ = 47, /* Timer Module 0 Watchdog */
|
||||
NPCM7XX_WDG1_IRQ, /* Timer Module 1 Watchdog */
|
||||
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
|
||||
NPCM7XX_EHCI_IRQ = 61,
|
||||
NPCM7XX_OHCI_IRQ = 62,
|
||||
};
|
||||
|
||||
/* Total number of GIC interrupts, including internal Cortex-A9 interrupts. */
|
||||
@ -263,6 +269,9 @@ static void npcm7xx_init(Object *obj)
|
||||
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
|
||||
}
|
||||
|
||||
object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
|
||||
object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
|
||||
|
||||
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_fiu) != ARRAY_SIZE(s->fiu));
|
||||
for (i = 0; i < ARRAY_SIZE(s->fiu); i++) {
|
||||
object_initialize_child(obj, npcm7xx_fiu[i].name, &s->fiu[i],
|
||||
@ -380,6 +389,22 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->rng), &error_abort);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rng), 0, NPCM7XX_RNG_BA);
|
||||
|
||||
/* USB Host */
|
||||
object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
|
||||
&error_abort);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->ehci), &error_abort);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci), 0, NPCM7XX_EHCI_BA);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci), 0,
|
||||
npcm7xx_irq(s, NPCM7XX_EHCI_IRQ));
|
||||
|
||||
object_property_set_str(OBJECT(&s->ohci), "masterbus", "usb-bus.0",
|
||||
&error_abort);
|
||||
object_property_set_uint(OBJECT(&s->ohci), "num-ports", 1, &error_abort);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->ohci), &error_abort);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci), 0, NPCM7XX_OHCI_BA);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci), 0,
|
||||
npcm7xx_irq(s, NPCM7XX_OHCI_IRQ));
|
||||
|
||||
/*
|
||||
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
|
||||
* specified, but this is a programming error.
|
||||
@ -464,8 +489,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
create_unimplemented_device("npcm7xx.mcphy", 0xf05f0000, 64 * KiB);
|
||||
create_unimplemented_device("npcm7xx.gmac1", 0xf0802000, 8 * KiB);
|
||||
create_unimplemented_device("npcm7xx.gmac2", 0xf0804000, 8 * KiB);
|
||||
create_unimplemented_device("npcm7xx.ehci", 0xf0806000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.ohci", 0xf0807000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
|
||||
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
|
||||
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
|
||||
|
@ -147,6 +147,24 @@ static const TypeInfo ehci_aw_h3_type_info = {
|
||||
.class_init = ehci_aw_h3_class_init,
|
||||
};
|
||||
|
||||
static void ehci_npcm7xx_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
sec->capsbase = 0x0;
|
||||
sec->opregbase = 0x10;
|
||||
sec->portscbase = 0x44;
|
||||
sec->portnr = 1;
|
||||
set_bit(DEVICE_CATEGORY_USB, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo ehci_npcm7xx_type_info = {
|
||||
.name = TYPE_NPCM7XX_EHCI,
|
||||
.parent = TYPE_SYS_BUS_EHCI,
|
||||
.class_init = ehci_npcm7xx_class_init,
|
||||
};
|
||||
|
||||
static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
|
||||
@ -269,6 +287,7 @@ static void ehci_sysbus_register_types(void)
|
||||
type_register_static(&ehci_platform_type_info);
|
||||
type_register_static(&ehci_exynos4210_type_info);
|
||||
type_register_static(&ehci_aw_h3_type_info);
|
||||
type_register_static(&ehci_npcm7xx_type_info);
|
||||
type_register_static(&ehci_tegra2_type_info);
|
||||
type_register_static(&ehci_ppc4xx_type_info);
|
||||
type_register_static(&ehci_fusbh200_type_info);
|
||||
|
@ -344,6 +344,7 @@ struct EHCIPCIState {
|
||||
#define TYPE_PLATFORM_EHCI "platform-ehci-usb"
|
||||
#define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
|
||||
#define TYPE_AW_H3_EHCI "aw-h3-ehci-usb"
|
||||
#define TYPE_NPCM7XX_EHCI "npcm7xx-ehci-usb"
|
||||
#define TYPE_TEGRA2_EHCI "tegra2-ehci-usb"
|
||||
#define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
|
||||
#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "hw/nvram/npcm7xx_otp.h"
|
||||
#include "hw/timer/npcm7xx_timer.h"
|
||||
#include "hw/ssi/npcm7xx_fiu.h"
|
||||
#include "hw/usb/hcd-ehci.h"
|
||||
#include "hw/usb/hcd-ohci.h"
|
||||
#include "target/arm/cpu.h"
|
||||
|
||||
#define NPCM7XX_MAX_NUM_CPUS (2)
|
||||
@ -77,6 +79,8 @@ typedef struct NPCM7xxState {
|
||||
NPCM7xxOTPState fuse_array;
|
||||
NPCM7xxMCState mc;
|
||||
NPCM7xxRNGState rng;
|
||||
EHCISysBusState ehci;
|
||||
OHCISysBusState ohci;
|
||||
NPCM7xxFIUState fiu[2];
|
||||
} NPCM7xxState;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user