usb: sunxi: Switch to use generic-phy
authorJagan Teki <jagan@amarulasolutions.com>
Mon, 7 May 2018 07:33:38 +0000 (13:03 +0530)
committerJagan Teki <jagan@amarulasolutions.com>
Mon, 28 May 2018 11:10:43 +0000 (16:40 +0530)
Allwinner USB PHY handling can be done through driver-model
generic-phy so add the generic-phy ops to relevant places
on host and musb sunxi driver and enable them in respective
SOC's.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Jun Nie <jun.nie@linaro.org>
arch/arm/mach-sunxi/Kconfig
drivers/usb/host/ehci-sunxi.c
drivers/usb/host/ohci-sunxi.c
drivers/usb/musb-new/musb_uboot.c
drivers/usb/musb-new/sunxi.c

index f0c9d1b05847058c86a566f8c16667cab775523c..a3f772302863894f23b057146b9ceea2e7090051 100644 (file)
@@ -124,6 +124,7 @@ endif
 config MACH_SUNXI_H3_H5
        bool
        select DM_I2C
+       select PHY_SUN4I_USB
        select SUNXI_DE2
        select SUNXI_DRAM_DW
        select SUNXI_DRAM_DW_32BIT
@@ -138,6 +139,7 @@ config MACH_SUN4I
        bool "sun4i (Allwinner A10)"
        select CPU_V7A
        select ARM_CORTEX_CPU_IS_UP
+       select PHY_SUN4I_USB
        select DRAM_SUN4I
        select SUNXI_GEN_SUN4I
        select SUPPORT_SPL
@@ -147,6 +149,7 @@ config MACH_SUN5I
        select CPU_V7A
        select ARM_CORTEX_CPU_IS_UP
        select DRAM_SUN4I
+       select PHY_SUN4I_USB
        select SUNXI_GEN_SUN4I
        select SUPPORT_SPL
        imply CONS_INDEX_2 if !DM_SERIAL
@@ -158,6 +161,7 @@ config MACH_SUN6I
        select CPU_V7_HAS_VIRT
        select ARCH_SUPPORT_PSCI
        select DRAM_SUN6I
+       select PHY_SUN4I_USB
        select SUN6I_P2WI
        select SUN6I_PRCM
        select SUNXI_GEN_SUN6I
@@ -171,6 +175,7 @@ config MACH_SUN7I
        select CPU_V7_HAS_VIRT
        select ARCH_SUPPORT_PSCI
        select DRAM_SUN4I
+       select PHY_SUN4I_USB
        select SUNXI_GEN_SUN4I
        select SUPPORT_SPL
        select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
@@ -182,6 +187,7 @@ config MACH_SUN8I_A23
        select CPU_V7_HAS_VIRT
        select ARCH_SUPPORT_PSCI
        select DRAM_SUN8I_A23
+       select PHY_SUN4I_USB
        select SUNXI_GEN_SUN6I
        select SUPPORT_SPL
        select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
@@ -194,6 +200,7 @@ config MACH_SUN8I_A33
        select CPU_V7_HAS_VIRT
        select ARCH_SUPPORT_PSCI
        select DRAM_SUN8I_A33
+       select PHY_SUN4I_USB
        select SUNXI_GEN_SUN6I
        select SUPPORT_SPL
        select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
@@ -203,6 +210,7 @@ config MACH_SUN8I_A83T
        bool "sun8i (Allwinner A83T)"
        select CPU_V7A
        select DRAM_SUN8I_A83T
+       select PHY_SUN4I_USB
        select SUNXI_GEN_SUN6I
        select MMC_SUNXI_HAS_NEW_MODE
        select SUPPORT_SPL
@@ -253,6 +261,7 @@ config MACH_SUN50I
        bool "sun50i (Allwinner A64)"
        select ARM64
        select DM_I2C
+       select PHY_SUN4I_USB
        select SUNXI_DE2
        select SUNXI_GEN_SUN6I
        select SUNXI_HIGH_SRAM
index bbfcd6e080c6b69bb5ba14511332bf9a3262093c..360efc9116086f2b021bdfe1b471516a5a3fb104 100644 (file)
 
 #include <common.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/usb_phy.h>
 #include <asm/io.h>
 #include <dm.h>
 #include "ehci.h"
+#include <generic-phy.h>
 
 #ifdef CONFIG_SUNXI_GEN_SUN4I
-#define BASE_DIST              0x8000
 #define AHB_CLK_DIST           2
 #else
-#define BASE_DIST              0x1000
 #define AHB_CLK_DIST           1
 #endif
 
@@ -28,7 +26,7 @@ struct ehci_sunxi_priv {
        struct ehci_ctrl ehci;
        struct sunxi_ccm_reg *ccm;
        int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
-       int phy_index;     /* Index of the usb-phy attached to this hcd */
+       struct phy phy;
 };
 
 static int ehci_usb_probe(struct udevice *dev)
@@ -38,11 +36,37 @@ static int ehci_usb_probe(struct udevice *dev)
        struct ehci_hccr *hccr = (struct ehci_hccr *)devfdt_get_addr(dev);
        struct ehci_hcor *hcor;
        int extra_ahb_gate_mask = 0;
+       int phys, ret;
 
        priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
        if (IS_ERR(priv->ccm))
                return PTR_ERR(priv->ccm);
 
+       phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
+       if (phys < 0) {
+               phys = 0;
+               goto no_phy;
+       }
+
+       ret = generic_phy_get_by_name(dev, "usb", &priv->phy);
+       if (ret) {
+               pr_err("failed to get %s usb PHY\n", dev->name);
+               return ret;
+       }
+
+       ret = generic_phy_init(&priv->phy);
+       if (ret) {
+               pr_err("failed to init %s USB PHY\n", dev->name);
+               return ret;
+       }
+
+       ret = generic_phy_power_on(&priv->phy);
+       if (ret) {
+               pr_err("failed to power on %s USB PHY\n", dev->name);
+               return ret;
+       }
+
+no_phy:
        /*
         * This should go away once we've moved to the driver model for
         * clocks resp. phys.
@@ -51,10 +75,8 @@ static int ehci_usb_probe(struct udevice *dev)
 #if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I)
        extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0;
 #endif
-       priv->phy_index = ((uintptr_t)hccr - SUNXI_USB1_BASE) / BASE_DIST;
-       priv->ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST;
-       extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST;
-       priv->phy_index++; /* Non otg phys start at 1 */
+       priv->ahb_gate_mask <<= phys * AHB_CLK_DIST;
+       extra_ahb_gate_mask <<= phys * AHB_CLK_DIST;
 
        setbits_le32(&priv->ccm->ahb_gate0,
                     priv->ahb_gate_mask | extra_ahb_gate_mask);
@@ -63,9 +85,6 @@ static int ehci_usb_probe(struct udevice *dev)
                     priv->ahb_gate_mask | extra_ahb_gate_mask);
 #endif
 
-       sunxi_usb_phy_init(priv->phy_index);
-       sunxi_usb_phy_power_on(priv->phy_index);
-
        hcor = (struct ehci_hcor *)((uintptr_t)hccr +
                                    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
@@ -77,12 +96,18 @@ static int ehci_usb_remove(struct udevice *dev)
        struct ehci_sunxi_priv *priv = dev_get_priv(dev);
        int ret;
 
+       if (generic_phy_valid(&priv->phy)) {
+               ret = generic_phy_exit(&priv->phy);
+               if (ret) {
+                       pr_err("failed to exit %s USB PHY\n", dev->name);
+                       return ret;
+               }
+       }
+
        ret = ehci_deregister(dev);
        if (ret)
                return ret;
 
-       sunxi_usb_phy_exit(priv->phy_index);
-
 #ifdef CONFIG_SUNXI_GEN_SUN6I
        clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
 #endif
index af35a304bc430d530c6da593062cfc9e457ca974..ce2b47a5c4bacbbf4965c2f32da9dfda878c9d50 100644 (file)
 
 #include <common.h>
 #include <asm/arch/clock.h>
-#include <asm/arch/usb_phy.h>
 #include <asm/io.h>
 #include <dm.h>
 #include <usb.h>
 #include "ohci.h"
+#include <generic-phy.h>
 
 #ifdef CONFIG_SUNXI_GEN_SUN4I
-#define BASE_DIST              0x8000
 #define AHB_CLK_DIST           2
 #else
-#define BASE_DIST              0x1000
 #define AHB_CLK_DIST           1
 #endif
 
@@ -29,7 +27,7 @@ struct ohci_sunxi_priv {
        ohci_t ohci;
        int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
        int usb_gate_mask; /* Mask of usb_clk_cfg clk gate bits for this hcd */
-       int phy_index;     /* Index of the usb-phy attached to this hcd */
+       struct phy phy;
 };
 
 static int ohci_usb_probe(struct udevice *dev)
@@ -38,11 +36,37 @@ static int ohci_usb_probe(struct udevice *dev)
        struct ohci_sunxi_priv *priv = dev_get_priv(dev);
        struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
        int extra_ahb_gate_mask = 0;
+       int phys, ret;
 
        priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
        if (IS_ERR(priv->ccm))
                return PTR_ERR(priv->ccm);
 
+       phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
+       if (phys < 0) {
+               phys = 0;
+               goto no_phy;
+       }
+
+       ret = generic_phy_get_by_name(dev, "usb", &priv->phy);
+       if (ret) {
+               pr_err("failed to get %s usb PHY\n", dev->name);
+               return ret;
+       }
+
+       ret = generic_phy_init(&priv->phy);
+       if (ret) {
+               pr_err("failed to init %s USB PHY\n", dev->name);
+               return ret;
+       }
+
+       ret = generic_phy_power_on(&priv->phy);
+       if (ret) {
+               pr_err("failed to power on %s USB PHY\n", dev->name);
+               return ret;
+       }
+
+no_phy:
        bus_priv->companion = true;
 
        /*
@@ -54,11 +78,9 @@ static int ohci_usb_probe(struct udevice *dev)
        extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
 #endif
        priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK;
-       priv->phy_index = ((uintptr_t)regs - (SUNXI_USB1_BASE + 0x400)) / BASE_DIST;
-       priv->ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST;
-       extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST;
-       priv->usb_gate_mask <<= priv->phy_index;
-       priv->phy_index++; /* Non otg phys start at 1 */
+       priv->ahb_gate_mask <<= phys * AHB_CLK_DIST;
+       extra_ahb_gate_mask <<= phys * AHB_CLK_DIST;
+       priv->usb_gate_mask <<= phys;
 
        setbits_le32(&priv->ccm->ahb_gate0,
                     priv->ahb_gate_mask | extra_ahb_gate_mask);
@@ -68,9 +90,6 @@ static int ohci_usb_probe(struct udevice *dev)
                     priv->ahb_gate_mask | extra_ahb_gate_mask);
 #endif
 
-       sunxi_usb_phy_init(priv->phy_index);
-       sunxi_usb_phy_power_on(priv->phy_index);
-
        return ohci_register(dev, regs);
 }
 
@@ -79,12 +98,18 @@ static int ohci_usb_remove(struct udevice *dev)
        struct ohci_sunxi_priv *priv = dev_get_priv(dev);
        int ret;
 
+       if (generic_phy_valid(&priv->phy)) {
+               ret = generic_phy_exit(&priv->phy);
+               if (ret) {
+                       pr_err("failed to exit %s USB PHY\n", dev->name);
+                       return ret;
+               }
+       }
+
        ret = ohci_deregister(dev);
        if (ret)
                return ret;
 
-       sunxi_usb_phy_exit(priv->phy_index);
-
 #ifdef CONFIG_SUNXI_GEN_SUN6I
        clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask);
 #endif
index 48242c04756f082ca844a6820b9f52c806fe6836..2b04fbd046e7dba99dd6e4ae97389be10e9983eb 100644 (file)
@@ -1,9 +1,6 @@
 #include <common.h>
 #include <console.h>
 #include <watchdog.h>
-#ifdef CONFIG_ARCH_SUNXI
-#include <asm/arch/usb_phy.h>
-#endif
 #include <linux/errno.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
index 5728a3f384f5512c837ec373b25511066cf7765a..08de9c69c71c2462cb6b815d891e51c06395d18d 100644 (file)
  */
 #include <common.h>
 #include <dm.h>
+#include <generic-phy.h>
+#include <phy-sun4i-usb.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
-#include <asm/arch/usb_phy.h>
 #include <asm-generic/gpio.h>
 #include <dm/lists.h>
 #include <dm/root.h>
@@ -86,6 +87,7 @@ struct sunxi_glue {
        struct sunxi_ccm_reg *ccm;
        struct sunxi_musb_config *cfg;
        struct device dev;
+       struct phy *phy;
 };
 #define to_sunxi_glue(d)       container_of(d, struct sunxi_glue, dev)
 
@@ -218,6 +220,7 @@ static bool enabled = false;
 
 static int sunxi_musb_enable(struct musb *musb)
 {
+       struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
        int ret;
 
        pr_debug("%s():\n", __func__);
@@ -232,17 +235,23 @@ static int sunxi_musb_enable(struct musb *musb)
        musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
 
        if (is_host_enabled(musb)) {
-               ret = sunxi_usb_phy_vbus_detect(0);
+               ret = sun4i_usb_phy_vbus_detect(glue->phy);
                if (ret == 1) {
                        printf("A charger is plugged into the OTG: ");
                        return -ENODEV;
                }
-               ret = sunxi_usb_phy_id_detect(0);
+
+               ret = sun4i_usb_phy_id_detect(glue->phy);
                if (ret == 1) {
                        printf("No host cable detected: ");
                        return -ENODEV;
                }
-               sunxi_usb_phy_power_on(0); /* port power on */
+
+               ret = generic_phy_power_on(glue->phy);
+               if (ret) {
+                       pr_err("failed to power on USB PHY\n");
+                       return ret;
+               }
        }
 
        USBC_ForceVbusValidToHigh(musb->mregs);
@@ -253,13 +262,21 @@ static int sunxi_musb_enable(struct musb *musb)
 
 static void sunxi_musb_disable(struct musb *musb)
 {
+       struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
+       int ret;
+
        pr_debug("%s():\n", __func__);
 
        if (!enabled)
                return;
 
-       if (is_host_enabled(musb))
-               sunxi_usb_phy_power_off(0); /* port power off */
+       if (is_host_enabled(musb)) {
+               ret = generic_phy_power_off(glue->phy);
+               if (ret) {
+                       pr_err("failed to power off USB PHY\n");
+                       return;
+               }
+       }
 
        USBC_ForceVbusValidToLow(musb->mregs);
        mdelay(200); /* Wait for the current session to timeout */
@@ -270,9 +287,16 @@ static void sunxi_musb_disable(struct musb *musb)
 static int sunxi_musb_init(struct musb *musb)
 {
        struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
+       int ret;
 
        pr_debug("%s():\n", __func__);
 
+       ret = generic_phy_init(glue->phy);
+       if (ret) {
+               pr_err("failed to init USB PHY\n");
+               return ret;
+       }
+
        musb->isr = sunxi_musb_interrupt;
 
        setbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0));
@@ -286,8 +310,6 @@ static int sunxi_musb_init(struct musb *musb)
                             BIT(glue->cfg->rst_bit));
 #endif
 
-       sunxi_usb_phy_init(0);
-
        USBC_ConfigFIFO_Base();
        USBC_EnableDpDmPullUp(musb->mregs);
        USBC_EnableIdPullUp(musb->mregs);
@@ -383,6 +405,7 @@ static int musb_usb_probe(struct udevice *dev)
        struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
        struct musb_hdrc_platform_data pdata;
        void *base = dev_read_addr_ptr(dev);
+       struct phy phy;
        int ret;
 
        if (!base)
@@ -396,6 +419,13 @@ static int musb_usb_probe(struct udevice *dev)
        if (IS_ERR(glue->ccm))
                return PTR_ERR(glue->ccm);
 
+       ret = generic_phy_get_by_name(dev, "usb", &phy);
+       if (ret) {
+               pr_err("failed to get usb PHY\n");
+               return ret;
+       }
+
+       glue->phy = &phy;
        priv->desc_before_addr = true;
 
        memset(&pdata, 0, sizeof(pdata));
@@ -426,10 +456,18 @@ static int musb_usb_remove(struct udevice *dev)
 {
        struct sunxi_glue *glue = dev_get_priv(dev);
        struct musb_host_data *host = &glue->mdata;
+       int ret;
+
+       if (generic_phy_valid(glue->phy)) {
+               ret = generic_phy_exit(glue->phy);
+               if (ret) {
+                       pr_err("failed to exit %s USB PHY\n", dev->name);
+                       return ret;
+               }
+       }
 
        musb_stop(host->host);
 
-       sunxi_usb_phy_exit(0);
 #ifdef CONFIG_SUNXI_GEN_SUN6I
        clrbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0));
        if (glue->cfg->rst_bit)