Message ID | 20200408033532.26973-1-rayagonda.kokatanur@broadcom.com |
---|---|
State | Superseded |
Headers | show |
Series | [v3,1/1] drivers: usb: host: Add BRCM xHCI driver | expand |
On 4/8/20 5:35 AM, Rayagonda Kokatanur wrote: [...] > +struct brcm_xhci_platdata { > + unsigned int arcache; > + unsigned int awcache; > + uintptr_t hc_base; This could be struct xhci_hccr * instead , and then you can remove the cast ... > +}; > + > +static int xhci_brcm_probe(struct udevice *dev) > +{ > + struct brcm_xhci_platdata *plat = dev_get_platdata(dev); > + struct xhci_hcor *hcor; > + struct xhci_hccr *hcd; > + int len, ret = 0; > + > + if (!plat) { > + dev_err(dev, "Can't get xHCI Plat data\n"); > + return -ENOMEM; > + } > + > + hcd = dev_read_addr_ptr(dev); > + if (!hcd) { > + dev_err(dev, "Can't get the xHCI register base address\n"); > + return -ENXIO; > + } > + > + plat->hc_base = (uintptr_t)hcd; ... here. > + len = HC_LENGTH(xhci_readl(&hcd->cr_capbase)); > + hcor = (struct xhci_hcor *)(plat->hc_base + len); [...]
On Wed, Apr 8, 2020 at 9:56 AM Marek Vasut <marex at denx.de> wrote: > > On 4/8/20 5:35 AM, Rayagonda Kokatanur wrote: > [...] > > +struct brcm_xhci_platdata { > > + unsigned int arcache; > > + unsigned int awcache; > > + uintptr_t hc_base; > > This could be struct xhci_hccr * instead , and then you can remove the > cast ... If we make it struct xhci_hccr * then I think we need to type cast in readl and writel function. Please let me know ? > > > +}; > > + > > +static int xhci_brcm_probe(struct udevice *dev) > > +{ > > + struct brcm_xhci_platdata *plat = dev_get_platdata(dev); > > + struct xhci_hcor *hcor; > > + struct xhci_hccr *hcd; > > + int len, ret = 0; > > + > > + if (!plat) { > > + dev_err(dev, "Can't get xHCI Plat data\n"); > > + return -ENOMEM; > > + } > > + > > + hcd = dev_read_addr_ptr(dev); > > + if (!hcd) { > > + dev_err(dev, "Can't get the xHCI register base address\n"); > > + return -ENXIO; > > + } > > + > > + plat->hc_base = (uintptr_t)hcd; > > ... here. > > > + len = HC_LENGTH(xhci_readl(&hcd->cr_capbase)); > > + hcor = (struct xhci_hcor *)(plat->hc_base + len); > [...]
On Wed, Apr 8, 2020 at 11:18 AM Rayagonda Kokatanur <rayagonda.kokatanur at broadcom.com> wrote: > > On Wed, Apr 8, 2020 at 9:56 AM Marek Vasut <marex at denx.de> wrote: > > > > On 4/8/20 5:35 AM, Rayagonda Kokatanur wrote: > > [...] > > > +struct brcm_xhci_platdata { > > > + unsigned int arcache; > > > + unsigned int awcache; > > > + uintptr_t hc_base; > > > > This could be struct xhci_hccr * instead , and then you can remove the > > cast ... Hi Marek, uintptr_t is "unsigned long int" , its not pointer. If we make hc_base as a pointer "struct xhci_hccr *" it won't work because of pointer arithmetic during readl and writel. Please let me know if I am missing anything ? > > If we make it struct xhci_hccr * then I think we need to type cast in > readl and writel function. > Please let me know ? > > > > > +}; > > > + > > > +static int xhci_brcm_probe(struct udevice *dev) > > > +{ > > > + struct brcm_xhci_platdata *plat = dev_get_platdata(dev); > > > + struct xhci_hcor *hcor; > > > + struct xhci_hccr *hcd; > > > + int len, ret = 0; > > > + > > > + if (!plat) { > > > + dev_err(dev, "Can't get xHCI Plat data\n"); > > > + return -ENOMEM; > > > + } > > > + > > > + hcd = dev_read_addr_ptr(dev); > > > + if (!hcd) { > > > + dev_err(dev, "Can't get the xHCI register base address\n"); > > > + return -ENXIO; > > > + } > > > + > > > + plat->hc_base = (uintptr_t)hcd; > > > > ... here. > > > > > + len = HC_LENGTH(xhci_readl(&hcd->cr_capbase)); > > > + hcor = (struct xhci_hcor *)(plat->hc_base + len); > > [...]
On 4/8/20 7:48 AM, Rayagonda Kokatanur wrote: > On Wed, Apr 8, 2020 at 9:56 AM Marek Vasut <marex at denx.de> wrote: >> >> On 4/8/20 5:35 AM, Rayagonda Kokatanur wrote: >> [...] >>> +struct brcm_xhci_platdata { >>> + unsigned int arcache; >>> + unsigned int awcache; >>> + uintptr_t hc_base; >> >> This could be struct xhci_hccr * instead , and then you can remove the >> cast ... > > If we make it struct xhci_hccr * then I think we need to type cast in > readl and writel function. > Please let me know ? Ah yes, that's right, then I think you want void __iomem * ?
On Wed, Apr 8, 2020 at 7:16 PM Marek Vasut <marex at denx.de> wrote: > > On 4/8/20 7:48 AM, Rayagonda Kokatanur wrote: > > On Wed, Apr 8, 2020 at 9:56 AM Marek Vasut <marex at denx.de> wrote: > >> > >> On 4/8/20 5:35 AM, Rayagonda Kokatanur wrote: > >> [...] > >>> +struct brcm_xhci_platdata { > >>> + unsigned int arcache; > >>> + unsigned int awcache; > >>> + uintptr_t hc_base; > >> > >> This could be struct xhci_hccr * instead , and then you can remove the > >> cast ... > > > > If we make it struct xhci_hccr * then I think we need to type cast in > > readl and writel function. > > Please let me know ? > > Ah yes, that's right, then I think you want void __iomem * ? Done, declared as void __iomem * , thank you.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0987ff25b1..94ac969058 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -88,6 +88,14 @@ config USB_XHCI_FSL depends on !SPL_NO_USB help Enables support for the on-chip xHCI controller on NXP Layerscape SoCs. + +config USB_XHCI_BRCM + bool "Broadcom USB3 Host XHCI controller" + depends on DM_USB + help + USB controller based on the Broadcom USB3 IP Core. + Supports USB2/3 functionality. + endif # USB_XHCI_HCD config USB_EHCI_HCD diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 7feeff679c..b62f346094 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_USB_EHCI_RMOBILE) += ehci-rmobile.o obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o # xhci +obj-$(CONFIG_USB_XHCI_BRCM) += xhci-brcm.o obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o obj-$(CONFIG_USB_XHCI_DWC3) += xhci-dwc3.o obj-$(CONFIG_USB_XHCI_DWC3_OF_SIMPLE) += dwc3-of-simple.o diff --git a/drivers/usb/host/xhci-brcm.c b/drivers/usb/host/xhci-brcm.c new file mode 100644 index 0000000000..7192305dba --- /dev/null +++ b/drivers/usb/host/xhci-brcm.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Broadcom. + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <usb.h> +#include <asm/io.h> +#include <usb/xhci.h> + +#define DRD2U3H_XHC_REGS_AXIWRA 0xC08 +#define DRD2U3H_XHC_REGS_AXIRDA 0xC0C + +#define USBAXI_CACHE 0xF +#define USBAXI_PROT 0x8 +#define USBAXI_SA_MASK 0x1FF +#define USBAXI_UA_MASK (0x1FF << 16) +#define USBAXI_SA_VAL ((USBAXI_CACHE << 4) | USBAXI_PROT) +#define USBAXI_UA_VAL (USBAXI_SA_VAL << 16) +#define USBAXI_SA_UA_MASK (USBAXI_UA_MASK | USBAXI_SA_MASK) +#define USBAXI_SA_UA_VAL (USBAXI_UA_VAL | USBAXI_SA_VAL) + +struct brcm_xhci_platdata { + unsigned int arcache; + unsigned int awcache; + uintptr_t hc_base; +}; + +static int xhci_brcm_probe(struct udevice *dev) +{ + struct brcm_xhci_platdata *plat = dev_get_platdata(dev); + struct xhci_hcor *hcor; + struct xhci_hccr *hcd; + int len, ret = 0; + + if (!plat) { + dev_err(dev, "Can't get xHCI Plat data\n"); + return -ENOMEM; + } + + hcd = dev_read_addr_ptr(dev); + if (!hcd) { + dev_err(dev, "Can't get the xHCI register base address\n"); + return -ENXIO; + } + + plat->hc_base = (uintptr_t)hcd; + len = HC_LENGTH(xhci_readl(&hcd->cr_capbase)); + hcor = (struct xhci_hcor *)(plat->hc_base + len); + + /* Save the default values of AXI read and write attributes */ + plat->awcache = readl(plat->hc_base + DRD2U3H_XHC_REGS_AXIWRA); + plat->arcache = readl(plat->hc_base + DRD2U3H_XHC_REGS_AXIRDA); + + /* Enable AXI write attributes */ + clrsetbits_le32(plat->hc_base + DRD2U3H_XHC_REGS_AXIWRA, + USBAXI_SA_UA_MASK, USBAXI_SA_UA_VAL); + + /* Enable AXI read attributes */ + clrsetbits_le32(plat->hc_base + DRD2U3H_XHC_REGS_AXIRDA, + USBAXI_SA_UA_MASK, USBAXI_SA_UA_VAL); + + ret = xhci_register(dev, hcd, hcor); + if (ret) + dev_err(dev, "Failed to register xHCI\n"); + + return ret; +} + +static int xhci_brcm_deregister(struct udevice *dev) +{ + struct brcm_xhci_platdata *plat = dev_get_platdata(dev); + + /* Restore the default values for AXI read and write attributes */ + writel(plat->awcache, plat->hc_base + DRD2U3H_XHC_REGS_AXIWRA); + writel(plat->arcache, plat->hc_base + DRD2U3H_XHC_REGS_AXIRDA); + + return xhci_deregister(dev); +} + +static const struct udevice_id xhci_brcm_ids[] = { + { .compatible = "brcm,generic-xhci" }, + { } +}; + +U_BOOT_DRIVER(usb_xhci) = { + .name = "xhci_brcm", + .id = UCLASS_USB, + .probe = xhci_brcm_probe, + .remove = xhci_brcm_deregister, + .ops = &xhci_usb_ops, + .of_match = xhci_brcm_ids, + .platdata_auto_alloc_size = sizeof(struct brcm_xhci_platdata), + .priv_auto_alloc_size = sizeof(struct xhci_ctrl), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};