2013/1/29 Andreas Färber <afaer...@suse.de>

> Am 29.01.2013 06:43, schrieb Kuo-Jung Su:
> > From: Kuo-Jung Su <dant...@faraday-tech.com>
> >
> > Add Faraday FUSBH200 support, which is slightly different from EHCI spec.
> > (Or maybe simply a bad/wrong implementation...)
> >
> > Signed-off-by: Kuo-Jung Su <dant...@faraday-tech.com>
> > Cc: Gerd Hoffmann <kra...@redhat.com>
> > Cc: Andreas <afaer...@suse.de>
> > Cc: Peter Crosthwaite <peter.crosthwa...@xilinx.com>
> > ---
> >  hw/usb/hcd-ehci-sysbus.c |   66
> ++++++++++++++++++++++++++++++++++++++++++++++
> >  hw/usb/hcd-ehci.h        |    5 ++++
> >  2 files changed, 71 insertions(+)
> >
> > diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
> > index ae2db1a..404a227 100644
> > --- a/hw/usb/hcd-ehci-sysbus.c
> > +++ b/hw/usb/hcd-ehci-sysbus.c
> > @@ -17,6 +17,49 @@
> >
> >  #include "hw/usb/hcd-ehci.h"
> >
> > +/*
> > + * Faraday FUSBH200 USB 2.0 EHCI
> > + */
> > +
> > +static uint64_t
> > +ehci_fusbh200_read(void *ptr, hwaddr addr, unsigned size)
> > +{
> > +    hwaddr off = 0x34 + addr;
> > +
> > +    switch (off) {
> > +    case 0x34:  /* fusbh200: EOF/Async. Sleep Timer Register */
> > +        return 0x00000041;
> > +    case 0x40:  /* fusbh200: Bus Monitor Control/Status Register */
> > +        /* High-Speed, VBUS valid, interrupt level-high active */
> > +        return (2 << 9) | (1 << 8) | (1 << 3);
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static void
> > +ehci_fusbh200_write(void *ptr, hwaddr addr, uint64_t val, unsigned size)
> > +{
> > +}
> > +
> > +static const MemoryRegionOps ehci_mmio_fusbh200_ops = {
> > +    .read = ehci_fusbh200_read,
> > +    .write = ehci_fusbh200_write,
> > +    .valid.min_access_size = 4,
> > +    .valid.max_access_size = 4,
> > +    .endianness = DEVICE_LITTLE_ENDIAN,
> > +};
>
> This part looks okay now, except that I'd suggest to name the ops
> ehci_fusbh200_mmio_ops (ehci_fusbh200_ being a consistent prefix).
>
>
Sure, consider it done.


> > +
> > +static void
> > +usb_ehci_fusbh200_initfn(EHCIState *s, DeviceState *dev)
>
> Bad naming, the inconsistent use of "initfn" is what my patch tried to
> clean up for you.
> And this signature is only necessary in common EHCI code because it
> needs to access EHCIState from both PCIDevice and SysBusDevice. This
> change is in SysBus-only code though, so you can access EHCIState
> through the device state.
>
>
My bad, because I didn't know what's the difference between realizefn and
initfn,
so I did it in a wrong way.


> > +{
> > +    memory_region_init_io(&s->mem_vendor, &ehci_mmio_fusbh200_ops, s,
> > +                          "fusbh200", 0x4c);
>
> This has no dependencies on other fields, so it should go into a
> void ehci_fusbh200_initfn(Object *obj) hooked to your .instance_init.
>
> > +    memory_region_add_subregion(&s->mem,
> > +                                s->opregbase + s->portscbase + 4 *
> s->portnr,
> > +                                &s->mem_vendor);
> > +}
> > +
> >  static const VMStateDescription vmstate_ehci_sysbus = {
> >      .name        = "ehci-sysbus",
> >      .version_id  = 2,
> > @@ -46,6 +89,9 @@ static void usb_ehci_sysbus_realizefn(DeviceState
> *dev, Error **errp)
> >      s->dma = &dma_context_memory;
> >
> >      usb_ehci_initfn(s, dev);
>
> FWIW I notice that I should've renamed this in my patch, too (outside
> the scope of your patch).
>
> > +    if (sec->vendor_init) {
> > +        sec->vendor_init(s, DEVICE(dev));
> > +    }
> >      sysbus_init_irq(d, &s->irq);
> >      sysbus_init_mmio(d, &s->mem);
> >  }
>
> This is not what I had in mind. For one thing your initialization does
> not need to go before sysbus_init_{irq,mmio}.
>
> What I am not too sure about without digging out SysBus and PCI EHCI
> sources is at which point the fields may get modified. In 1/2 your new
> fields are only ever initialized in class_init and then transferred to
> instance state in the realizefn.
>
> There's two better options:
>
> 1) Change 1/2 to set the default values s->... in an instance_init
> initfn directly, then your instance_init can execute "on top" (with QOM
> infrastructure taking care of calling the parent's initfn before yours)
> and overwrite its values.
> You won't need sec->portscbase and sec->portnr then and we avoid
> duplicating "sec->portscbase = 0x44; sec->portnr = NB_PORTS;".
>
> 2) Keep 1/2 as is and override the realizefn in 2/2 via dc->realize =
> your_realizefn. This involves saving the parent's realizefn in a new
> FUSHBH200SysBusEHCIClass::parent_realize and explicitly invoking that
> parent_realize function before adding your MemoryRegion as subregion.
>
> The big underlying question is whether other future devices may want to
> override the values via qdev static properties. Then the assignment
> needs to remain in realizefn, otherwise initfn makes our life easier.
>

No problem,  consider it done.


> > @@ -76,6 +122,7 @@ static void ehci_xlnx_class_init(ObjectClass *oc,
> void *data)
> >      sec->opregbase = 0x140;
> >      sec->portscbase = 0x44;
> >      sec->portnr = NB_PORTS;
> > +    sec->vendor_init = NULL;
> >  }
> >
> >  static const TypeInfo ehci_xlnx_type_info = {
> > @@ -92,6 +139,7 @@ static void ehci_exynos4210_class_init(ObjectClass
> *oc, void *data)
> >      sec->opregbase = 0x10;
> >      sec->portscbase = 0x44;
> >      sec->portnr = NB_PORTS;
> > +    sec->vendor_init = NULL;
> >  }
> >
> >  static const TypeInfo ehci_exynos4210_type_info = {
>
> You don't need to zero-initialize fields in class_init or initfn.
>
>
got you, thanks


> > @@ -100,11 +148,29 @@ static const TypeInfo ehci_exynos4210_type_info = {
> >      .class_init    = ehci_exynos4210_class_init,
> >  };
> >
> > +static void ehci_fusbh200_class_init(ObjectClass *oc, void *data)
> > +{
> > +    SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
> > +
> > +    sec->capsbase = 0x0;
> > +    sec->opregbase = 0x10;
> > +    sec->portscbase = 0x20;
> > +    sec->portnr = 1;
> > +    sec->vendor_init = usb_ehci_fusbh200_initfn;
> > +}
> > +
> > +static const TypeInfo ehci_fusbh200_type_info = {
> > +    .name          = TYPE_FUSBH200_EHCI,
> > +    .parent        = TYPE_SYS_BUS_EHCI,
> > +    .class_init    = ehci_fusbh200_class_init,
> > +};
> > +
> >  static void ehci_sysbus_register_types(void)
> >  {
> >      type_register_static(&ehci_type_info);
> >      type_register_static(&ehci_xlnx_type_info);
> >      type_register_static(&ehci_exynos4210_type_info);
> > +    type_register_static(&ehci_fusbh200_type_info);
> >  }
> >
> >  type_init(ehci_sysbus_register_types)
> > diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
> > index e587b67..3ca9c8f 100644
> > --- a/hw/usb/hcd-ehci.h
> > +++ b/hw/usb/hcd-ehci.h
> > @@ -261,6 +261,7 @@ struct EHCIState {
> >      MemoryRegion mem_caps;
> >      MemoryRegion mem_opreg;
> >      MemoryRegion mem_ports;
> > +    MemoryRegion mem_vendor;
> >      int companion_count;
> >      uint16_t capsbase;
> >      uint16_t opregbase;
>
> Similar question here: Do we expect other models to expose a single
> vendor MemoryRegion as well?
>
> I would prefer to place this a) in the SysBus-specific state or if only
> for this device b) in a new FUSBH200-specific state derived from it.
>
>
ok, no problem


> > @@ -336,6 +337,7 @@ typedef struct EHCIPCIState {
> >
> >  #define TYPE_SYS_BUS_EHCI "sysbus-ehci-usb"
> >  #define TYPE_EXYNOS4210_EHCI "exynos4210-ehci-usb"
> > +#define TYPE_FUSBH200_EHCI "fusbh200-ehci-usb"
> >
> >  #define SYS_BUS_EHCI(obj) \
> >      OBJECT_CHECK(EHCISysBusState, (obj), TYPE_SYS_BUS_EHCI)
> > @@ -361,6 +363,9 @@ typedef struct SysBusEHCIClass {
> >      uint16_t opregbase;
> >      uint16_t portscbase;
> >      uint16_t portnr;
> > +
> > +    /* vendor specific init function */
> > +    void (*vendor_init)(EHCIState *s, DeviceState *dev);
> >  } SysBusEHCIClass;
> >
> >  #endif
>
> Gerd, what are your thoughts? If Kuo-Jung doesn't mind, I would offer to
> send a v2 implementing the changes I suggested in the way you prefer.
>

Don't worry about me, I'm O.K to any changes. It does not bother me at all,
what's really killing me is only the patch rules....


>
> Regards,
> Andreas
>
> --
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
>



-- 
Best wishes,
Kuo-Jung Su

Reply via email to