[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v2 4/6] dwc-hsotg USB host controller emulation
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [PATCH v2 4/6] dwc-hsotg USB host controller emulation |
Date: |
Mon, 20 Apr 2020 09:16:26 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 |
Hi Paul,
On 3/29/20 1:17 AM, Paul Zimmerman wrote:
> Add the dwc-hsotg (dwc2) USB host controller emulation code.
> Based on hw/usb/hcd-ehci.c and hw/usb/hcd-ohci.c.
>
> Note that to use this with the dwc-otg driver in the Raspbian
> kernel, you must pass the option "dwc_otg.fiq_fsm_enable=0" on
> the kernel command line.
>
> Emulation of slave mode and of descriptor-DMA mode has not been
> implemented yet. These modes are seldom used.
>
> I have used some on-line sources of information while developing
> this emulation, including:
>
> http://www.capital-micro.com/PDF/CME-M7_Family_User_Guide_EN.pdf
> has a pretty complete description of the controller starting on
> page 370.
>
> https://sourceforge.net/p/wive-ng/wive-ng-mt/ci/master/tree/docs/DataSheets/RT3050_5x_V2.0_081408_0902.pdf
> has a description of the controller registers starting on page
> 130.
>
> Signed-off-by: Paul Zimmerman <address@hidden>
> ---
> hw/usb/hcd-dwc2.c | 1301 +++++++++++++++++++++++++++++++++++++++++++
> hw/usb/trace-events | 47 ++
> 2 files changed, 1348 insertions(+)
> create mode 100644 hw/usb/hcd-dwc2.c
>
> diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c
[...]
> +static void dwc2_init(DWC2State *s, DeviceState *dev)
> +{
> + s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */
> + if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) {
> + s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */
> + } else {
> + s->usb_bit_time = 1;
> + }
> +
> + s->fi = 11999;
What is this magic number?
> +
> + memory_region_init(&s->mem, OBJECT(dev), "dwc2", DWC2_MMIO_SIZE);
> + memory_region_init_io(&s->mem_glbreg, OBJECT(dev),
> &dwc2_mmio_glbreg_ops, s,
> + "global", 0x70);
> + memory_region_init_io(&s->mem_fszreg, OBJECT(dev),
> &dwc2_mmio_fszreg_ops, s,
> + "hptxfsiz", 0x4);
> + memory_region_init_io(&s->mem_hreg0, OBJECT(dev), &dwc2_mmio_hreg0_ops,
> s,
> + "host", 0x44);
> + memory_region_init_io(&s->mem_hreg1, OBJECT(dev), &dwc2_mmio_hreg1_ops,
> s,
> + "host channels", 0x20 * NB_CHAN);
> + memory_region_init_io(&s->mem_pcgreg, OBJECT(dev),
> &dwc2_mmio_pcgreg_ops, s,
> + "power/clock", 0x8);
> + memory_region_init_io(&s->mem_hreg2, OBJECT(dev), &dwc2_mmio_hreg2_ops,
> s,
> + "host fifos", NB_CHAN * 0x1000);
> +
> + memory_region_add_subregion(&s->mem, s->glbregbase, &s->mem_glbreg);
> + memory_region_add_subregion(&s->mem, s->fszregbase, &s->mem_fszreg);
> + memory_region_add_subregion(&s->mem, s->hreg0base, &s->mem_hreg0);
> + memory_region_add_subregion(&s->mem, s->hreg1base, &s->mem_hreg1);
> + memory_region_add_subregion(&s->mem, s->pcgregbase, &s->mem_pcgreg);
> + memory_region_add_subregion(&s->mem, s->hreg2base, &s->mem_hreg2);
> +
> + s->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
> + dwc2_frame_boundary, s);
> +}
> +
> +static void dwc2_sysbus_reset(DeviceState *dev)
> +{
> + SysBusDevice *d = SYS_BUS_DEVICE(dev);
> + DWC2State *s = DWC2_USB(d);
> +
> + dwc2_reset(s);
> +}
> +
> +static void dwc2_sysbus_realize(DeviceState *dev, Error **errp)
> +{
> + SysBusDevice *d = SYS_BUS_DEVICE(dev);
> + DWC2State *s = DWC2_USB(dev);
> +
> + s->glbregbase = 0;
> + s->fszregbase = 0x0100;
> + s->hreg0base = 0x0400;
> + s->hreg1base = 0x0500;
> + s->pcgregbase = 0x0e00;
> + s->hreg2base = 0x1000;
No need to use variable for the constant base addresses, use them
directly in as argument to memory_region_add_subregion().
Since you don't reuse each block, and blocks cover very few registers,
have you considered using a pair of MRs instead? One of 4KB and the
other 64KB. hreg2 is the only one particularly different.
> + s->portnr = NB_PORTS;
> + s->as = &address_space_memory;
> +
> + dwc2_realize(s, dev, errp);
> + dwc2_init(s, dev);
> + sysbus_init_irq(d, &s->irq);
> + sysbus_init_mmio(d, &s->mem);
> +}
[...]