From: SangeethaRao <sangeetha....@lsi.com> CONFIG_LSI_USB_SW_WORKAROUND Kconfig definition since AXM55xx doesn’t need EHCI controller workarounds that were required in older devices.
Signed-off-by: SangeethaRao <sangeetha....@lsi.com> --- arch/arm/boot/dts/axm55xx.dts | 9 +++++++ drivers/usb/host/ehci-ci13612.c | 59 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/axm55xx.dts b/arch/arm/boot/dts/axm55xx.dts index 1807727..d3cbf1c 100644 --- a/arch/arm/boot/dts/axm55xx.dts +++ b/arch/arm/boot/dts/axm55xx.dts @@ -246,6 +246,15 @@ mac-address = [00 00 00 00 00 00]; }; + USB0: usb@004a4000 { + device_type = "usb"; + compatible = "acp-usb"; + enabled = <0>; + reg = <0x20 0x10140000 0x0 0020000>, + <0x20 0x10094000 0x0 0002000>; + interrupts = <0 55 4>; + }; + amba { compatible = "arm,amba-bus"; #address-cells = <2>; diff --git a/drivers/usb/host/ehci-ci13612.c b/drivers/usb/host/ehci-ci13612.c index cf0b2e4..02a6d29 100644 --- a/drivers/usb/host/ehci-ci13612.c +++ b/drivers/usb/host/ehci-ci13612.c @@ -24,9 +24,15 @@ #include <linux/platform_device.h> #include <linux/irq.h> #include <linux/of_platform.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/uaccess.h> +#include <linux/io.h> #include "ehci-ci13612.h" +#ifdef CONFIG_LSI_USB_SW_WORKAROUND static void ci13612_usb_setup(struct usb_hcd *hcd) { int USB_TXFIFOTHRES, VUSB_HS_TX_BURST; @@ -64,16 +70,17 @@ static void ci13612_usb_setup(struct usb_hcd *hcd) "USB_TXFIFOTHRES = 0x%x\n", VUSB_HS_TX_BURST, USB_TXFIFOTHRES); return; } +#endif /* called after powerup, by probe or system-pm "wakeup" */ static int ehci_ci13612_reinit(struct ehci_hcd *ehci) { + #ifdef CONFIG_LSI_USB_SW_WORKAROUND /* S/W workarounds are not needed in AXM55xx */ ci13612_usb_setup(ehci_to_hcd(ehci)); -#endif ehci_port_power(ehci, 0); - +#endif return 0; } @@ -84,7 +91,6 @@ static int ci13612_ehci_init(struct usb_hcd *hcd) int retval = 0; int len; - /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 @@ -114,11 +120,13 @@ static int ci13612_ehci_init(struct usb_hcd *hcd) static int ehci_run_fix(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); +#ifdef CONFIG_LSI_USB_SW_WORKAROUND u32 port_status; +#endif unsigned burst_size; int retval; -#ifdef CONFIG_LSI_USB_SW_WORKAROUND +#ifdef CONFIG_LSI_USB_SW_WORKAROUND /* Fix HW errata 0003256: Do not enable USBCMD.RS for some time after * the USB reset has been completed (PORTSCx.PR=0). This ensures that * the host does not send the SOF until the ULPI post reset processing @@ -151,6 +159,25 @@ static int ehci_run_fix(struct usb_hcd *hcd) burst_size = (burst_size & 0xffff00ff) | 0x4000; /* TXPBURST */ ehci_writel(ehci, burst_size, &ehci->regs->reserved[1]); +#else +#if 1 + /* Fix for HW errata 9000373951: You can adjust the burst size and fill the + * level to minimize under-run possibilities. In the failing case, the + * transfer size was 96 bytes, the burst size was 16, and the fill + * threshold level was set to 2. Because of this, the Host core issued + * the Out token when it requested the second burst of data. If the + * burst size had been changed to 8, and the fill level set to 3, + * then the core would have pre-fetched the 96 bytes before issuing + * the OUT token. + */ + burst_size = ehci_readl(ehci, &ehci->regs->reserved[1]); + burst_size = (burst_size & 0xffff00ff) | 0x4000; /* TXPBURST */ + ehci_writel(ehci, burst_size, &ehci->regs->reserved[1]); + + retval = ehci_run(hcd); + if (retval) + return retval; +#endif #endif return 0; @@ -190,6 +217,8 @@ static int ci13612_ehci_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct resource *res; +#ifdef CONFIG_LSI_USB_SW_WORKAROUND + /* Check if device is enabled */ if (!of_device_is_available(np)) { printk(KERN_INFO "%s: Port disabled via device-tree\n", @@ -209,12 +238,29 @@ static int ci13612_ehci_probe(struct platform_device *pdev) goto fail_create_hcd; } + if (0 != irq_set_irq_type(87, IRQ_TYPE_LEVEL_HIGH)) { + dev_dbg(&pdev->dev, "set_irq_type() failed\n"); + retval = -EBUSY; + goto fail_create_hcd; + } +#else + + irq = irq_of_parse_and_map(np, 0); + if (NO_IRQ == irq) { + dev_dbg(&pdev->dev, "error getting irq number\n"); + retval = -EBUSY; + goto fail_create_hcd; + } + if (0 != irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH)) { dev_dbg(&pdev->dev, "set_irq_type() failed\n"); retval = -EBUSY; goto fail_create_hcd; } +#endif + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Error: resource addr %s setup!\n", @@ -239,6 +285,7 @@ static int ci13612_ehci_probe(struct platform_device *pdev) goto fail_put_hcd; } + gpreg_base = of_iomap(np, 1); if (!gpreg_base) { dev_warn(&pdev->dev, "of_iomap error can't map region 1\n"); @@ -247,6 +294,10 @@ static int ci13612_ehci_probe(struct platform_device *pdev) } else { /* Setup GPREG for USB to enable the 6-bit address line */ writel(0x0, gpreg_base + 0x8); +#ifndef CONFIG_LSI_USB_SW_WORKAROUND + /* setup hprot for uncached USB mode */ + writel(0x0, gpreg_base + 0x74); +#endif iounmap(gpreg_base); } -- 1.8.4.3 _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto