]> git.sur5r.net Git - u-boot/commitdiff
Merge git://git.denx.de/u-boot-usb
authorTom Rini <trini@konsulko.com>
Wed, 19 Aug 2015 22:04:48 +0000 (18:04 -0400)
committerTom Rini <trini@konsulko.com>
Wed, 19 Aug 2015 22:04:48 +0000 (18:04 -0400)
arch/arm/cpu/arm926ejs/spear/cpu.c
arch/arm/include/asm/arch-spear/hardware.h
drivers/usb/gadget/ether.c
drivers/usb/host/Makefile
drivers/usb/host/dwc2.c
drivers/usb/host/ehci-mx6.c
drivers/usb/host/ehci-spear.c
drivers/usb/host/xhci-omap.c
drivers/usb/host/xhci.c

index 1ce9db7a7da54176e38bc6bb17c4951022eb770c..3037084b29bce7cdae69b31a65f25eb79bb7dba0 100644 (file)
@@ -47,8 +47,12 @@ int arch_cpu_init(void)
 #if defined(CONFIG_NAND_FSMC)
        periph1_clken |= MISC_FSMCENB;
 #endif
+#if defined(CONFIG_USB_EHCI_SPEAR)
+       periph1_clken |= PERIPH_USBH1 | PERIPH_USBH2;
+#endif
 
        writel(periph1_clken, &misc_p->periph1_clken);
+
        return 0;
 }
 
index c6da405cc07a6fafe346999321187837ee2eaf34..065360ab35a7254a2931ceedeb8caa4e0c11c78f 100644 (file)
@@ -11,6 +11,8 @@
 #define CONFIG_SYS_USBD_BASE                   0xE1100000
 #define CONFIG_SYS_PLUG_BASE                   0xE1200000
 #define CONFIG_SYS_FIFO_BASE                   0xE1000800
+#define CONFIG_SYS_UHC0_EHCI_BASE              0xE1800000
+#define CONFIG_SYS_UHC1_EHCI_BASE              0xE2000000
 #define CONFIG_SYS_SMI_BASE                    0xFC000000
 #define CONFIG_SPEAR_SYSCNTLBASE               0xFCA00000
 #define CONFIG_SPEAR_TIMERBASE                 0xFC800000
index 141ff8be59ab3c361ba79b2365d501e20fb13a54..53f4672291f3d83a32cae43f4bd99caedba6c502 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/gadget.h>
 #include <net.h>
+#include <usb.h>
 #include <malloc.h>
 #include <linux/ctype.h>
 
@@ -2312,6 +2313,8 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
                goto fail;
        }
 
+       board_usb_init(0, USB_INIT_DEVICE);
+
        /* Configure default mac-addresses for the USB ethernet device */
 #ifdef CONFIG_USBNET_DEV_ADDR
        strlcpy(dev_addr, CONFIG_USBNET_DEV_ADDR, sizeof(dev_addr));
@@ -2492,6 +2495,7 @@ void usb_eth_halt(struct eth_device *netdev)
        }
 
        usb_gadget_unregister_driver(&eth_driver);
+       board_usb_cleanup(0, USB_INIT_DEVICE);
 }
 
 static struct usb_gadget_driver eth_driver = {
@@ -2501,6 +2505,7 @@ static struct usb_gadget_driver eth_driver = {
        .unbind         = eth_unbind,
 
        .setup          = eth_setup,
+       .reset          = eth_disconnect,
        .disconnect     = eth_disconnect,
 
        .suspend        = eth_suspend,
index 7f07d7734a5ac1c0e749fad5ed6052b244f89dab..f70f38c9e8006e5d39e060c2eba40398fbb9936c 100644 (file)
@@ -37,6 +37,7 @@ obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
 obj-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o
 obj-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o
 obj-$(CONFIG_USB_EHCI_MX6) += ehci-mx6.o
+obj-$(CONFIG_USB_EHCI_MX7) += ehci-mx6.o
 obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o
 obj-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o
 obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o
index 09f91f190af3d07245b186d7765b3eac149d4b51..85236aeb2a48bc135248a46a12f4a9ae2d4c0a20 100644 (file)
@@ -1113,11 +1113,12 @@ struct dm_usb_ops dwc2_usb_ops = {
 
 static const struct udevice_id dwc2_usb_ids[] = {
        { .compatible = "brcm,bcm2835-usb" },
+       { .compatible = "snps,dwc2" },
        { }
 };
 
 U_BOOT_DRIVER(usb_dwc2) = {
-       .name   = "dwc2_exynos",
+       .name   = "dwc2_usb",
        .id     = UCLASS_USB,
        .of_match = dwc2_usb_ids,
        .ofdata_to_platdata = dwc2_usb_ofdata_to_platdata,
index 951dd3b25f2cf766df706a4fdbf86366dbff4e05..2666351391431e091a761fb92f7879777bde2625 100644 (file)
 #define ANADIG_USB2_PLL_480_CTRL_POWER         0x00001000
 #define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS   0x00000040
 
-
+#define USBNC_OFFSET           0x200
+#define USBNC_PHYSTATUS_ID_DIG (1 << 4) /* otg_id status */
+#define USBNC_PHYCFG2_ACAENB   (1 << 4) /* otg_id detection enable */
+#define UCTRL_PM                (1 << 9) /* OTG Power Mask */
 #define UCTRL_OVER_CUR_POL     (1 << 8) /* OTG Polarity of Overcurrent */
 #define UCTRL_OVER_CUR_DIS     (1 << 7) /* Disable OTG Overcurrent Detection */
 
@@ -53,6 +56,7 @@
 #define UCMD_RUN_STOP           (1 << 0) /* controller run/stop */
 #define UCMD_RESET             (1 << 1) /* controller reset */
 
+#if defined(CONFIG_MX6)
 static const unsigned phy_bases[] = {
        USB_PHY0_BASE_ADDR,
        USB_PHY1_BASE_ADDR,
@@ -67,7 +71,7 @@ static void usb_internal_phy_clock_gate(int index, int on)
 
        phy_reg = (void __iomem *)phy_bases[index];
        phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET;
-       __raw_writel(USBPHY_CTRL_CLKGATE, phy_reg);
+       writel(USBPHY_CTRL_CLKGATE, phy_reg);
 }
 
 static void usb_power_config(int index)
@@ -100,26 +104,52 @@ static void usb_power_config(int index)
         * is totally controlled by IC, so the Software only needs
         * to enable them at initializtion.
         */
-       __raw_writel(ANADIG_USB2_CHRG_DETECT_EN_B |
+       writel(ANADIG_USB2_CHRG_DETECT_EN_B |
                     ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
                     chrg_detect);
 
-       __raw_writel(ANADIG_USB2_PLL_480_CTRL_BYPASS,
+       writel(ANADIG_USB2_PLL_480_CTRL_BYPASS,
                     pll_480_ctrl_clr);
 
-       __raw_writel(ANADIG_USB2_PLL_480_CTRL_ENABLE |
+       writel(ANADIG_USB2_PLL_480_CTRL_ENABLE |
                     ANADIG_USB2_PLL_480_CTRL_POWER |
                     ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
                     pll_480_ctrl_set);
 }
 
+static int wait_for_bit(u32 *reg, const u32 mask, bool set)
+{
+       u32 val;
+       const unsigned int timeout = 10000;
+       unsigned long start = get_timer(0);
+
+       while(1) {
+               val = readl(reg);
+               if (!set)
+                       val = ~val;
+
+               if ((val & mask) == mask)
+                       return 0;
+
+               if (get_timer(start) > timeout)
+                       break;
+
+               udelay(1);
+       }
+
+       debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n",
+                       __func__, reg, mask, set);
+
+       return -ETIMEDOUT;
+}
+
 /* Return 0 : host node, <>0 : device mode */
 static int usb_phy_enable(int index, struct usb_ehci *ehci)
 {
        void __iomem *phy_reg;
        void __iomem *phy_ctrl;
        void __iomem *usb_cmd;
-       u32 val;
+       int ret;
 
        if (index >= ARRAY_SIZE(phy_bases))
                return 0;
@@ -129,40 +159,50 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci)
        usb_cmd = (void __iomem *)&ehci->usbcmd;
 
        /* Stop then Reset */
-       val = __raw_readl(usb_cmd);
-       val &= ~UCMD_RUN_STOP;
-       __raw_writel(val, usb_cmd);
-       while (__raw_readl(usb_cmd) & UCMD_RUN_STOP)
-               ;
-
-       val = __raw_readl(usb_cmd);
-       val |= UCMD_RESET;
-       __raw_writel(val, usb_cmd);
-       while (__raw_readl(usb_cmd) & UCMD_RESET)
-               ;
+       clrbits_le32(usb_cmd, UCMD_RUN_STOP);
+       ret = wait_for_bit(usb_cmd, UCMD_RUN_STOP, 0);
+       if (ret)
+               return ret;
+
+       setbits_le32(usb_cmd, UCMD_RESET);
+       ret = wait_for_bit(usb_cmd, UCMD_RESET, 0);
+       if (ret)
+               return ret;
 
        /* Reset USBPHY module */
-       val = __raw_readl(phy_ctrl);
-       val |= USBPHY_CTRL_SFTRST;
-       __raw_writel(val, phy_ctrl);
+       setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST);
        udelay(10);
 
        /* Remove CLKGATE and SFTRST */
-       val = __raw_readl(phy_ctrl);
-       val &= ~(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
-       __raw_writel(val, phy_ctrl);
+       clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
        udelay(10);
 
        /* Power up the PHY */
-       __raw_writel(0, phy_reg + USBPHY_PWD);
+       writel(0, phy_reg + USBPHY_PWD);
        /* enable FS/LS device */
-       val = __raw_readl(phy_ctrl);
-       val |= (USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3);
-       __raw_writel(val, phy_ctrl);
+       setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 |
+                       USBPHY_CTRL_ENUTMILEVEL3);
 
        return 0;
 }
 
+int usb_phy_mode(int port)
+{
+       void __iomem *phy_reg;
+       void __iomem *phy_ctrl;
+       u32 val;
+
+       phy_reg = (void __iomem *)phy_bases[port];
+       phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
+
+       val = readl(phy_ctrl);
+
+       if (val & USBPHY_CTRL_OTG_ID)
+               return USB_INIT_DEVICE;
+       else
+               return USB_INIT_HOST;
+}
+
 /* Base address for this IP block is 0x02184800 */
 struct usbnc_regs {
        u32     ctrl[4];        /* otg/host1-3 */
@@ -171,55 +211,113 @@ struct usbnc_regs {
        u32     otg_phy_ctrl_0;
        u32     uh1_phy_ctrl_0;
 };
+#elif defined(CONFIG_MX7)
+struct usbnc_regs {
+       u32 ctrl1;
+       u32 ctrl2;
+       u32 reserve1[10];
+       u32 phy_cfg1;
+       u32 phy_cfg2;
+       u32 phy_status;
+       u32 reserve2[4];
+       u32 adp_cfg1;
+       u32 adp_cfg2;
+       u32 adp_status;
+};
 
-static void usb_oc_config(int index)
+static void usb_power_config(int index)
 {
        struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
-                       USB_OTHERREGS_OFFSET);
-       void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]);
-       u32 val;
+                       (0x10000 * index) + USBNC_OFFSET);
+       void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2);
 
-       val = __raw_readl(ctrl);
-#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2
-       /* mx6qarm2 seems to required a different setting*/
-       val &= ~UCTRL_OVER_CUR_POL;
-#else
-       val |= UCTRL_OVER_CUR_POL;
-#endif
-       __raw_writel(val, ctrl);
-
-       val = __raw_readl(ctrl);
-       val |= UCTRL_OVER_CUR_DIS;
-       __raw_writel(val, ctrl);
+       /* Enable usb_otg_id detection */
+       setbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB);
 }
 
 int usb_phy_mode(int port)
 {
-       void __iomem *phy_reg;
-       void __iomem *phy_ctrl;
+       struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+                       (0x10000 * port) + USBNC_OFFSET);
+       void __iomem *status = (void __iomem *)(&usbnc->phy_status);
        u32 val;
 
-       phy_reg = (void __iomem *)phy_bases[port];
-       phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
-
-       val = __raw_readl(phy_ctrl);
+       val = readl(status);
 
-       if (val & USBPHY_CTRL_OTG_ID)
+       if (val & USBNC_PHYSTATUS_ID_DIG)
                return USB_INIT_DEVICE;
        else
                return USB_INIT_HOST;
 }
+#endif
 
+static void usb_oc_config(int index)
+{
+#if defined(CONFIG_MX6)
+       struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+                       USB_OTHERREGS_OFFSET);
+       void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]);
+#elif defined(CONFIG_MX7)
+       struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+                       (0x10000 * index) + USBNC_OFFSET);
+       void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1);
+#endif
+
+#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2
+       /* mx6qarm2 seems to required a different setting*/
+       clrbits_le32(ctrl, UCTRL_OVER_CUR_POL);
+#else
+       setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
+#endif
+
+#if defined(CONFIG_MX6)
+       setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
+#elif defined(CONFIG_MX7)
+       setbits_le32(ctrl, UCTRL_OVER_CUR_DIS | UCTRL_PM);
+#endif
+}
+
+/**
+ * board_ehci_hcd_init - override usb phy mode
+ * @port:      usb host/otg port
+ *
+ * Target board specific, override usb_phy_mode.
+ * When usb-otg is used as usb host port, iomux pad usb_otg_id can be
+ * left disconnected in this case usb_phy_mode will not be able to identify
+ * the phy mode that usb port is used.
+ * Machine file overrides board_usb_phy_mode.
+ *
+ * Return: USB_INIT_DEVICE or USB_INIT_HOST
+ */
 int __weak board_usb_phy_mode(int port)
 {
        return usb_phy_mode(port);
 }
 
+/**
+ * board_ehci_hcd_init - set usb vbus voltage
+ * @port:      usb otg port
+ *
+ * Target board specific, setup iomux pad to setup supply vbus voltage
+ * for usb otg port. Machine board file overrides board_ehci_hcd_init
+ *
+ * Return: 0 Success
+ */
 int __weak board_ehci_hcd_init(int port)
 {
        return 0;
 }
 
+/**
+ * board_ehci_power - enables/disables usb vbus voltage
+ * @port:      usb otg port
+ * @on:        on/off vbus voltage
+ *
+ * Enables/disables supply vbus voltage for usb otg port.
+ * Machine board file overrides board_ehci_power
+ *
+ * Return: 0 Success
+ */
 int __weak board_ehci_power(int port, int on)
 {
        return 0;
@@ -229,8 +327,13 @@ int ehci_hcd_init(int index, enum usb_init_type init,
                struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
        enum usb_init_type type;
+#if defined(CONFIG_MX6)
+       u32 controller_spacing = 0x200;
+#elif defined(CONFIG_MX7)
+       u32 controller_spacing = 0x10000;
+#endif
        struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR +
-               (0x200 * index));
+               (controller_spacing * index));
 
        if (index > 3)
                return -EINVAL;
@@ -242,8 +345,11 @@ int ehci_hcd_init(int index, enum usb_init_type init,
 
        usb_power_config(index);
        usb_oc_config(index);
+
+#if defined(CONFIG_MX6)
        usb_internal_phy_clock_gate(index, 1);
        usb_phy_enable(index, ehci);
+#endif
        type = board_usb_phy_mode(index);
 
        *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
@@ -256,8 +362,9 @@ int ehci_hcd_init(int index, enum usb_init_type init,
                return -ENODEV;
        if (type == USB_INIT_DEVICE)
                return 0;
+
        setbits_le32(&ehci->usbmode, CM_HOST);
-       __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+       writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
        setbits_le32(&ehci->portsc, USB_EN);
 
        mdelay(10);
index 210ee9e88e2c758d75458ea95c0dcdf1b03aed88..9e90e18cfe0cc14aa61a4f27f3c9d24ed5fbe2eb 100644 (file)
 #include <usb.h>
 #include "ehci.h"
 #include <asm/arch/hardware.h>
+#include <asm/arch/spr_misc.h>
 
+static void spear6xx_usbh_stop(void)
+{
+       struct misc_regs *const misc_p =
+           (struct misc_regs *)CONFIG_SPEAR_MISCBASE;
+       u32 periph1_rst = readl(misc_p->periph1_rst);
+
+       periph1_rst |= PERIPH_USBH1 | PERIPH_USBH2;
+       writel(periph1_rst, misc_p->periph1_rst);
+
+       udelay(1000);
+       periph1_rst &= ~(PERIPH_USBH1 | PERIPH_USBH2);
+       writel(periph1_rst, misc_p->periph1_rst);
+}
 
 /*
  * Create the appropriate control structures to manage
 int ehci_hcd_init(int index, enum usb_init_type init,
                struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
-       *hccr = (struct ehci_hccr *)(CONFIG_SYS_UHC0_EHCI_BASE + 0x100);
-       *hcor = (struct ehci_hcor *)((uint32_t)*hccr
-                       + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+       u32 ehci = 0;
+
+       switch (index) {
+       case 0:
+               ehci = CONFIG_SYS_UHC0_EHCI_BASE;
+               break;
+       case 1:
+               ehci = CONFIG_SYS_UHC1_EHCI_BASE;
+               break;
+       default:
+               printf("ERROR: wrong controller index!\n");
+               break;
+       };
+
+       *hccr = (struct ehci_hccr *)(ehci + 0x100);
+       *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
+                       HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
 
        debug("SPEAr-ehci: init hccr %x and hcor %x hc_length %d\n",
                (uint32_t)*hccr, (uint32_t)*hcor,
@@ -40,5 +68,9 @@ int ehci_hcd_init(int index, enum usb_init_type init,
  */
 int ehci_hcd_stop(int index)
 {
+#if defined(CONFIG_SPEAR600)
+       spear6xx_usbh_stop();
+#endif
+
        return 0;
 }
index 3a5520838447d75102e383ffb771e5ab0cab6213..104e7a7282cf0b7787afac90ab5f8d1a7c55bfe2 100644 (file)
@@ -96,4 +96,5 @@ void xhci_hcd_stop(int index)
        struct omap_xhci *ctx = &omap;
 
        omap_xhci_core_exit(ctx);
+       board_usb_cleanup(index, USB_INIT_HOST);
 }
index 0b09643e09ea3ee0965e2982be91d15d4d11d640..307e1a6f6101410047abafc64f86f0ea35053ba4 100644 (file)
@@ -199,7 +199,7 @@ int xhci_reset(struct xhci_hcor *hcor)
        int ret;
 
        /* Halting the Host first */
-       debug("// Halt the HC\n");
+       debug("// Halt the HC: %p\n", hcor);
        state = xhci_readl(&hcor->or_usbsts) & STS_HALT;
        if (!state) {
                cmd = xhci_readl(&hcor->or_usbcmd);
@@ -1064,6 +1064,8 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
        struct xhci_ctrl *ctrl;
        int ret;
 
+       *controller = NULL;
+
        if (xhci_hcd_init(index, &hccr, (struct xhci_hcor **)&hcor) != 0)
                return -ENODEV;
 
@@ -1077,7 +1079,12 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
 
        ret = xhci_lowlevel_init(ctrl);
 
-       *controller = &xhcic[index];
+       if (ret) {
+               ctrl->hccr = NULL;
+               ctrl->hcor = NULL;
+       } else {
+               *controller = &xhcic[index];
+       }
 
        return ret;
 }
@@ -1093,9 +1100,11 @@ int usb_lowlevel_stop(int index)
 {
        struct xhci_ctrl *ctrl = (xhcic + index);
 
-       xhci_lowlevel_stop(ctrl);
-       xhci_hcd_stop(index);
-       xhci_cleanup(ctrl);
+       if (ctrl->hcor) {
+               xhci_lowlevel_stop(ctrl);
+               xhci_hcd_stop(index);
+               xhci_cleanup(ctrl);
+       }
 
        return 0;
 }