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 <ja...@amarulasolutions.com> --- arch/arm/mach-sunxi/Kconfig | 9 +++++++ drivers/usb/host/ehci-sunxi.c | 51 ++++++++++++++++++++++++++--------- drivers/usb/host/ohci-sunxi.c | 53 ++++++++++++++++++++++++++---------- drivers/usb/musb-new/musb_uboot.c | 3 --- drivers/usb/musb-new/sunxi.c | 56 ++++++++++++++++++++++++++++++++------- 5 files changed, 133 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index b868f0e350..0a7bd3086a 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -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_V7 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_V7 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_V7 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 diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index ed9763c63d..38ffbc18ba 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -12,16 +12,14 @@ #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 @@ -29,7 +27,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) @@ -39,11 +37,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. @@ -52,10 +76,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); @@ -64,9 +86,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))); @@ -78,12 +97,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 diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c index 35efa88795..a70fe2c382 100644 --- a/drivers/usb/host/ohci-sunxi.c +++ b/drivers/usb/host/ohci-sunxi.c @@ -11,17 +11,15 @@ #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 @@ -30,7 +28,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) @@ -39,11 +37,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; /* @@ -55,11 +79,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); @@ -69,9 +91,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); } @@ -80,12 +99,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 diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 48242c0475..2b04fbd046 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -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> diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 349653cd33..18d83d24c5 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -18,10 +18,11 @@ */ #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> @@ -87,6 +88,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) @@ -219,6 +221,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__); @@ -233,17 +236,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); @@ -254,13 +263,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 */ @@ -271,9 +288,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)); @@ -287,8 +311,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); @@ -384,6 +406,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) @@ -397,6 +420,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)); @@ -427,10 +457,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) -- 2.14.3 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot