[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 04/10] arm: allwinner-h3: add USB host controller

From: Niek Linnenbank
Subject: Re: [PATCH 04/10] arm: allwinner-h3: add USB host controller
Date: Wed, 4 Dec 2019 21:20:33 +0100

On Wed, Dec 4, 2019 at 5:11 PM Aleksandar Markovic <address@hidden> wrote:

On Monday, December 2, 2019, Niek Linnenbank <address@hidden> wrote:
The Allwinner H3 System on Chip contains multiple USB 2.0 bus
connections which provide software access using the Enhanced
Host Controller Interface (EHCI) and Open Host Controller
Interface (OHCI) interfaces. This commit adds support for
both interfaces in the Allwinner H3 System on Chip.

Signed-off-by: Niek Linnenbank <address@hidden>

Niek, hi!

I would like to clarify a detail here:

The spec of the SoC enumerates (in USB Host Register List) a number of registers for reading various USB-related states, but also for setting some of USB features.
Does this series cover these registers, and interaction with them? If yes, how and where? If not, do you think it is not necessary at all? Or perhaps that it is a non-crucial limitation of this series?

Hello Aleksandar!

Very good question, I will try to explain what I did to support USB for the Allwinner H3 emulation.
EHCI and OHCI are both standardized interfaces to the USB bus and both provide their own standardized software interface.
Because they are standards, operatings system drivers can implement a generic driver which uses the defined interface and
re-use it in multiple boards/platforms. Things that can be different between boards are, for example the base address in
memory where the registers are provided.

In QEMU I found that both the OHCI and EHCI host controllers are already emulated and used by other boards as well. For example,
you can find the OHCI registers from implemented in the file hw/usb/hcd-ohci.c:1515 in ohci_mem_read(). So for the Allwinner
H3 I simply had to define the base address for both controllers and create the objects. At that point, the Linux kernel can access
the USB bus with the generic EHCI/OHCI platform drivers. In the Linux code, you can see in the file ./arch/arm/boot/dts/sunxi-h3-h5.dtsi:281
the definitions named ehci0-ehci3 and ohci0-ohci3 where it specifies in the device tree configuration to load the generic drivers.

Thanks in advance, and congrats for your, it seems, first submission!

Thank you Aleksandar! Indeed, it is my first submission. I will do my best to
update the patches to comply with the QEMU coding style and best practises.


 hw/arm/allwinner-h3.c    | 20 ++++++++++++++++++++
 hw/usb/hcd-ehci-sysbus.c | 17 +++++++++++++++++
 hw/usb/hcd-ehci.h        |  1 +
 3 files changed, 38 insertions(+)

diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
index 5566e979ec..afeb49c0ac 100644
--- a/hw/arm/allwinner-h3.c
+++ b/hw/arm/allwinner-h3.c
@@ -26,6 +26,7 @@
 #include "hw/sysbus.h"
 #include "hw/arm/allwinner-h3.h"
 #include "hw/misc/unimp.h"
+#include "hw/usb/hcd-ehci.h"
 #include "sysemu/sysemu.h"

 static void aw_h3_init(Object *obj)
@@ -183,6 +184,25 @@ static void aw_h3_realize(DeviceState *dev, Error **errp)
     sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, AW_H3_CCU_BASE);

+    /* Universal Serial Bus */
+    sysbus_create_simple(TYPE_AW_H3_EHCI, AW_H3_EHCI0_BASE,
+                         s->irq[AW_H3_GIC_SPI_EHCI0]);
+    sysbus_create_simple(TYPE_AW_H3_EHCI, AW_H3_EHCI1_BASE,
+                         s->irq[AW_H3_GIC_SPI_EHCI1]);
+    sysbus_create_simple(TYPE_AW_H3_EHCI, AW_H3_EHCI2_BASE,
+                         s->irq[AW_H3_GIC_SPI_EHCI2]);
+    sysbus_create_simple(TYPE_AW_H3_EHCI, AW_H3_EHCI3_BASE,
+                         s->irq[AW_H3_GIC_SPI_EHCI3]);
+    sysbus_create_simple("sysbus-ohci", AW_H3_OHCI0_BASE,
+                         s->irq[AW_H3_GIC_SPI_OHCI0]);
+    sysbus_create_simple("sysbus-ohci", AW_H3_OHCI1_BASE,
+                         s->irq[AW_H3_GIC_SPI_OHCI1]);
+    sysbus_create_simple("sysbus-ohci", AW_H3_OHCI2_BASE,
+                         s->irq[AW_H3_GIC_SPI_OHCI2]);
+    sysbus_create_simple("sysbus-ohci", AW_H3_OHCI3_BASE,
+                         s->irq[AW_H3_GIC_SPI_OHCI3]);
     /* UART */
     if (serial_hd(0)) {
         serial_mm_init(get_system_memory(), AW_H3_UART0_REG_BASE, 2,
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index 020211fd10..174c3446ef 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -145,6 +145,22 @@ static const TypeInfo ehci_exynos4210_type_info = {
     .class_init    = ehci_exynos4210_class_init,

+static void ehci_aw_h3_class_init(ObjectClass *oc, void *data)
+    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    sec->capsbase = 0x0;
+    sec->opregbase = 0x10;
+    set_bit(DEVICE_CATEGORY_USB, dc->categories);
+static const TypeInfo ehci_aw_h3_type_info = {
+    .name          = TYPE_AW_H3_EHCI,
+    .parent        = TYPE_SYS_BUS_EHCI,
+    .class_init    = ehci_aw_h3_class_init,
 static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
     SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
@@ -267,6 +283,7 @@ static void ehci_sysbus_register_types(void)
+    type_register_static(&ehci_aw_h3_type_info);
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index 0298238f0b..edb59311c4 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -342,6 +342,7 @@ typedef struct EHCIPCIState {
 #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
 #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_TEGRA2_EHCI "tegra2-ehci-usb"
 #define TYPE_PPC4xx_EHCI "ppc4xx-ehci-usb"
 #define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"

Niek Linnenbank

reply via email to

[Prev in Thread] Current Thread [Next in Thread]