usb: sunxi: Switch to use generic-phy
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>
This commit is contained in:
		
							parent
							
								
									aa29b11b3f
								
							
						
					
					
						commit
						dd3228170a
					
				|  | @ -124,6 +124,7 @@ endif | ||||||
| config MACH_SUNXI_H3_H5 | config MACH_SUNXI_H3_H5 | ||||||
| 	bool | 	bool | ||||||
| 	select DM_I2C | 	select DM_I2C | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select SUNXI_DE2 | 	select SUNXI_DE2 | ||||||
| 	select SUNXI_DRAM_DW | 	select SUNXI_DRAM_DW | ||||||
| 	select SUNXI_DRAM_DW_32BIT | 	select SUNXI_DRAM_DW_32BIT | ||||||
|  | @ -138,6 +139,7 @@ config MACH_SUN4I | ||||||
| 	bool "sun4i (Allwinner A10)" | 	bool "sun4i (Allwinner A10)" | ||||||
| 	select CPU_V7A | 	select CPU_V7A | ||||||
| 	select ARM_CORTEX_CPU_IS_UP | 	select ARM_CORTEX_CPU_IS_UP | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select DRAM_SUN4I | 	select DRAM_SUN4I | ||||||
| 	select SUNXI_GEN_SUN4I | 	select SUNXI_GEN_SUN4I | ||||||
| 	select SUPPORT_SPL | 	select SUPPORT_SPL | ||||||
|  | @ -147,6 +149,7 @@ config MACH_SUN5I | ||||||
| 	select CPU_V7A | 	select CPU_V7A | ||||||
| 	select ARM_CORTEX_CPU_IS_UP | 	select ARM_CORTEX_CPU_IS_UP | ||||||
| 	select DRAM_SUN4I | 	select DRAM_SUN4I | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select SUNXI_GEN_SUN4I | 	select SUNXI_GEN_SUN4I | ||||||
| 	select SUPPORT_SPL | 	select SUPPORT_SPL | ||||||
| 	imply CONS_INDEX_2 if !DM_SERIAL | 	imply CONS_INDEX_2 if !DM_SERIAL | ||||||
|  | @ -158,6 +161,7 @@ config MACH_SUN6I | ||||||
| 	select CPU_V7_HAS_VIRT | 	select CPU_V7_HAS_VIRT | ||||||
| 	select ARCH_SUPPORT_PSCI | 	select ARCH_SUPPORT_PSCI | ||||||
| 	select DRAM_SUN6I | 	select DRAM_SUN6I | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select SUN6I_P2WI | 	select SUN6I_P2WI | ||||||
| 	select SUN6I_PRCM | 	select SUN6I_PRCM | ||||||
| 	select SUNXI_GEN_SUN6I | 	select SUNXI_GEN_SUN6I | ||||||
|  | @ -171,6 +175,7 @@ config MACH_SUN7I | ||||||
| 	select CPU_V7_HAS_VIRT | 	select CPU_V7_HAS_VIRT | ||||||
| 	select ARCH_SUPPORT_PSCI | 	select ARCH_SUPPORT_PSCI | ||||||
| 	select DRAM_SUN4I | 	select DRAM_SUN4I | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select SUNXI_GEN_SUN4I | 	select SUNXI_GEN_SUN4I | ||||||
| 	select SUPPORT_SPL | 	select SUPPORT_SPL | ||||||
| 	select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT | 	select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT | ||||||
|  | @ -182,6 +187,7 @@ config MACH_SUN8I_A23 | ||||||
| 	select CPU_V7_HAS_VIRT | 	select CPU_V7_HAS_VIRT | ||||||
| 	select ARCH_SUPPORT_PSCI | 	select ARCH_SUPPORT_PSCI | ||||||
| 	select DRAM_SUN8I_A23 | 	select DRAM_SUN8I_A23 | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select SUNXI_GEN_SUN6I | 	select SUNXI_GEN_SUN6I | ||||||
| 	select SUPPORT_SPL | 	select SUPPORT_SPL | ||||||
| 	select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT | 	select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT | ||||||
|  | @ -194,6 +200,7 @@ config MACH_SUN8I_A33 | ||||||
| 	select CPU_V7_HAS_VIRT | 	select CPU_V7_HAS_VIRT | ||||||
| 	select ARCH_SUPPORT_PSCI | 	select ARCH_SUPPORT_PSCI | ||||||
| 	select DRAM_SUN8I_A33 | 	select DRAM_SUN8I_A33 | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select SUNXI_GEN_SUN6I | 	select SUNXI_GEN_SUN6I | ||||||
| 	select SUPPORT_SPL | 	select SUPPORT_SPL | ||||||
| 	select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT | 	select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT | ||||||
|  | @ -203,6 +210,7 @@ config MACH_SUN8I_A83T | ||||||
| 	bool "sun8i (Allwinner A83T)" | 	bool "sun8i (Allwinner A83T)" | ||||||
| 	select CPU_V7A | 	select CPU_V7A | ||||||
| 	select DRAM_SUN8I_A83T | 	select DRAM_SUN8I_A83T | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select SUNXI_GEN_SUN6I | 	select SUNXI_GEN_SUN6I | ||||||
| 	select MMC_SUNXI_HAS_NEW_MODE | 	select MMC_SUNXI_HAS_NEW_MODE | ||||||
| 	select SUPPORT_SPL | 	select SUPPORT_SPL | ||||||
|  | @ -253,6 +261,7 @@ config MACH_SUN50I | ||||||
| 	bool "sun50i (Allwinner A64)" | 	bool "sun50i (Allwinner A64)" | ||||||
| 	select ARM64 | 	select ARM64 | ||||||
| 	select DM_I2C | 	select DM_I2C | ||||||
|  | 	select PHY_SUN4I_USB | ||||||
| 	select SUNXI_DE2 | 	select SUNXI_DE2 | ||||||
| 	select SUNXI_GEN_SUN6I | 	select SUNXI_GEN_SUN6I | ||||||
| 	select SUNXI_HIGH_SRAM | 	select SUNXI_HIGH_SRAM | ||||||
|  |  | ||||||
|  | @ -11,16 +11,14 @@ | ||||||
| 
 | 
 | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <asm/arch/clock.h> | #include <asm/arch/clock.h> | ||||||
| #include <asm/arch/usb_phy.h> |  | ||||||
| #include <asm/io.h> | #include <asm/io.h> | ||||||
| #include <dm.h> | #include <dm.h> | ||||||
| #include "ehci.h" | #include "ehci.h" | ||||||
|  | #include <generic-phy.h> | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_SUNXI_GEN_SUN4I | #ifdef CONFIG_SUNXI_GEN_SUN4I | ||||||
| #define BASE_DIST		0x8000 |  | ||||||
| #define AHB_CLK_DIST		2 | #define AHB_CLK_DIST		2 | ||||||
| #else | #else | ||||||
| #define BASE_DIST		0x1000 |  | ||||||
| #define AHB_CLK_DIST		1 | #define AHB_CLK_DIST		1 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -28,7 +26,7 @@ struct ehci_sunxi_priv { | ||||||
| 	struct ehci_ctrl ehci; | 	struct ehci_ctrl ehci; | ||||||
| 	struct sunxi_ccm_reg *ccm; | 	struct sunxi_ccm_reg *ccm; | ||||||
| 	int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ | 	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) | 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_hccr *hccr = (struct ehci_hccr *)devfdt_get_addr(dev); | ||||||
| 	struct ehci_hcor *hcor; | 	struct ehci_hcor *hcor; | ||||||
| 	int extra_ahb_gate_mask = 0; | 	int extra_ahb_gate_mask = 0; | ||||||
|  | 	int phys, ret; | ||||||
| 
 | 
 | ||||||
| 	priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | 	priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | ||||||
| 	if (IS_ERR(priv->ccm)) | 	if (IS_ERR(priv->ccm)) | ||||||
| 		return PTR_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 | 	 * This should go away once we've moved to the driver model for | ||||||
| 	 * clocks resp. phys. | 	 * 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) | #if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I) | ||||||
| 	extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0; | 	extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0; | ||||||
| #endif | #endif | ||||||
| 	priv->phy_index = ((uintptr_t)hccr - SUNXI_USB1_BASE) / BASE_DIST; | 	priv->ahb_gate_mask <<= phys * AHB_CLK_DIST; | ||||||
| 	priv->ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; | 	extra_ahb_gate_mask <<= phys * AHB_CLK_DIST; | ||||||
| 	extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; |  | ||||||
| 	priv->phy_index++; /* Non otg phys start at 1 */ |  | ||||||
| 
 | 
 | ||||||
| 	setbits_le32(&priv->ccm->ahb_gate0, | 	setbits_le32(&priv->ccm->ahb_gate0, | ||||||
| 		     priv->ahb_gate_mask | extra_ahb_gate_mask); | 		     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); | 		     priv->ahb_gate_mask | extra_ahb_gate_mask); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	sunxi_usb_phy_init(priv->phy_index); |  | ||||||
| 	sunxi_usb_phy_power_on(priv->phy_index); |  | ||||||
| 
 |  | ||||||
| 	hcor = (struct ehci_hcor *)((uintptr_t)hccr + | 	hcor = (struct ehci_hcor *)((uintptr_t)hccr + | ||||||
| 				    HC_LENGTH(ehci_readl(&hccr->cr_capbase))); | 				    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); | 	struct ehci_sunxi_priv *priv = dev_get_priv(dev); | ||||||
| 	int ret; | 	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); | 	ret = ehci_deregister(dev); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	sunxi_usb_phy_exit(priv->phy_index); |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_SUNXI_GEN_SUN6I | #ifdef CONFIG_SUNXI_GEN_SUN6I | ||||||
| 	clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); | 	clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -10,17 +10,15 @@ | ||||||
| 
 | 
 | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <asm/arch/clock.h> | #include <asm/arch/clock.h> | ||||||
| #include <asm/arch/usb_phy.h> |  | ||||||
| #include <asm/io.h> | #include <asm/io.h> | ||||||
| #include <dm.h> | #include <dm.h> | ||||||
| #include <usb.h> | #include <usb.h> | ||||||
| #include "ohci.h" | #include "ohci.h" | ||||||
|  | #include <generic-phy.h> | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_SUNXI_GEN_SUN4I | #ifdef CONFIG_SUNXI_GEN_SUN4I | ||||||
| #define BASE_DIST		0x8000 |  | ||||||
| #define AHB_CLK_DIST		2 | #define AHB_CLK_DIST		2 | ||||||
| #else | #else | ||||||
| #define BASE_DIST		0x1000 |  | ||||||
| #define AHB_CLK_DIST		1 | #define AHB_CLK_DIST		1 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -29,7 +27,7 @@ struct ohci_sunxi_priv { | ||||||
| 	ohci_t ohci; | 	ohci_t ohci; | ||||||
| 	int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */ | 	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 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) | 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_sunxi_priv *priv = dev_get_priv(dev); | ||||||
| 	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); | 	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); | ||||||
| 	int extra_ahb_gate_mask = 0; | 	int extra_ahb_gate_mask = 0; | ||||||
|  | 	int phys, ret; | ||||||
| 
 | 
 | ||||||
| 	priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | 	priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | ||||||
| 	if (IS_ERR(priv->ccm)) | 	if (IS_ERR(priv->ccm)) | ||||||
| 		return PTR_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; | 	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; | 	extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0; | ||||||
| #endif | #endif | ||||||
| 	priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK; | 	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 <<= phys * AHB_CLK_DIST; | ||||||
| 	priv->ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; | 	extra_ahb_gate_mask <<= phys * AHB_CLK_DIST; | ||||||
| 	extra_ahb_gate_mask <<= priv->phy_index * AHB_CLK_DIST; | 	priv->usb_gate_mask <<= phys; | ||||||
| 	priv->usb_gate_mask <<= priv->phy_index; |  | ||||||
| 	priv->phy_index++; /* Non otg phys start at 1 */ |  | ||||||
| 
 | 
 | ||||||
| 	setbits_le32(&priv->ccm->ahb_gate0, | 	setbits_le32(&priv->ccm->ahb_gate0, | ||||||
| 		     priv->ahb_gate_mask | extra_ahb_gate_mask); | 		     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); | 		     priv->ahb_gate_mask | extra_ahb_gate_mask); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	sunxi_usb_phy_init(priv->phy_index); |  | ||||||
| 	sunxi_usb_phy_power_on(priv->phy_index); |  | ||||||
| 
 |  | ||||||
| 	return ohci_register(dev, regs); | 	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); | 	struct ohci_sunxi_priv *priv = dev_get_priv(dev); | ||||||
| 	int ret; | 	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); | 	ret = ohci_deregister(dev); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	sunxi_usb_phy_exit(priv->phy_index); |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_SUNXI_GEN_SUN6I | #ifdef CONFIG_SUNXI_GEN_SUN6I | ||||||
| 	clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); | 	clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -1,9 +1,6 @@ | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <console.h> | #include <console.h> | ||||||
| #include <watchdog.h> | #include <watchdog.h> | ||||||
| #ifdef CONFIG_ARCH_SUNXI |  | ||||||
| #include <asm/arch/usb_phy.h> |  | ||||||
| #endif |  | ||||||
| #include <linux/errno.h> | #include <linux/errno.h> | ||||||
| #include <linux/usb/ch9.h> | #include <linux/usb/ch9.h> | ||||||
| #include <linux/usb/gadget.h> | #include <linux/usb/gadget.h> | ||||||
|  |  | ||||||
|  | @ -17,10 +17,11 @@ | ||||||
|  */ |  */ | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <dm.h> | #include <dm.h> | ||||||
|  | #include <generic-phy.h> | ||||||
|  | #include <phy-sun4i-usb.h> | ||||||
| #include <asm/arch/cpu.h> | #include <asm/arch/cpu.h> | ||||||
| #include <asm/arch/clock.h> | #include <asm/arch/clock.h> | ||||||
| #include <asm/arch/gpio.h> | #include <asm/arch/gpio.h> | ||||||
| #include <asm/arch/usb_phy.h> |  | ||||||
| #include <asm-generic/gpio.h> | #include <asm-generic/gpio.h> | ||||||
| #include <dm/lists.h> | #include <dm/lists.h> | ||||||
| #include <dm/root.h> | #include <dm/root.h> | ||||||
|  | @ -86,6 +87,7 @@ struct sunxi_glue { | ||||||
| 	struct sunxi_ccm_reg *ccm; | 	struct sunxi_ccm_reg *ccm; | ||||||
| 	struct sunxi_musb_config *cfg; | 	struct sunxi_musb_config *cfg; | ||||||
| 	struct device dev; | 	struct device dev; | ||||||
|  | 	struct phy *phy; | ||||||
| }; | }; | ||||||
| #define to_sunxi_glue(d)	container_of(d, struct sunxi_glue, dev) | #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) | static int sunxi_musb_enable(struct musb *musb) | ||||||
| { | { | ||||||
|  | 	struct sunxi_glue *glue = to_sunxi_glue(musb->controller); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	pr_debug("%s():\n", __func__); | 	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); | 	musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); | ||||||
| 
 | 
 | ||||||
| 	if (is_host_enabled(musb)) { | 	if (is_host_enabled(musb)) { | ||||||
| 		ret = sunxi_usb_phy_vbus_detect(0); | 		ret = sun4i_usb_phy_vbus_detect(glue->phy); | ||||||
| 		if (ret == 1) { | 		if (ret == 1) { | ||||||
| 			printf("A charger is plugged into the OTG: "); | 			printf("A charger is plugged into the OTG: "); | ||||||
| 			return -ENODEV; | 			return -ENODEV; | ||||||
| 		} | 		} | ||||||
| 		ret = sunxi_usb_phy_id_detect(0); | 
 | ||||||
|  | 		ret = sun4i_usb_phy_id_detect(glue->phy); | ||||||
| 		if (ret == 1) { | 		if (ret == 1) { | ||||||
| 			printf("No host cable detected: "); | 			printf("No host cable detected: "); | ||||||
| 			return -ENODEV; | 			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); | 	USBC_ForceVbusValidToHigh(musb->mregs); | ||||||
|  | @ -253,13 +262,21 @@ static int sunxi_musb_enable(struct musb *musb) | ||||||
| 
 | 
 | ||||||
| static void sunxi_musb_disable(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__); | 	pr_debug("%s():\n", __func__); | ||||||
| 
 | 
 | ||||||
| 	if (!enabled) | 	if (!enabled) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	if (is_host_enabled(musb)) | 	if (is_host_enabled(musb)) { | ||||||
| 		sunxi_usb_phy_power_off(0); /* port power off */ | 		ret = generic_phy_power_off(glue->phy); | ||||||
|  | 		if (ret) { | ||||||
|  | 			pr_err("failed to power off USB PHY\n"); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	USBC_ForceVbusValidToLow(musb->mregs); | 	USBC_ForceVbusValidToLow(musb->mregs); | ||||||
| 	mdelay(200); /* Wait for the current session to timeout */ | 	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) | static int sunxi_musb_init(struct musb *musb) | ||||||
| { | { | ||||||
| 	struct sunxi_glue *glue = to_sunxi_glue(musb->controller); | 	struct sunxi_glue *glue = to_sunxi_glue(musb->controller); | ||||||
|  | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	pr_debug("%s():\n", __func__); | 	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; | 	musb->isr = sunxi_musb_interrupt; | ||||||
| 
 | 
 | ||||||
| 	setbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0)); | 	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)); | 			     BIT(glue->cfg->rst_bit)); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	sunxi_usb_phy_init(0); |  | ||||||
| 
 |  | ||||||
| 	USBC_ConfigFIFO_Base(); | 	USBC_ConfigFIFO_Base(); | ||||||
| 	USBC_EnableDpDmPullUp(musb->mregs); | 	USBC_EnableDpDmPullUp(musb->mregs); | ||||||
| 	USBC_EnableIdPullUp(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 usb_bus_priv *priv = dev_get_uclass_priv(dev); | ||||||
| 	struct musb_hdrc_platform_data pdata; | 	struct musb_hdrc_platform_data pdata; | ||||||
| 	void *base = dev_read_addr_ptr(dev); | 	void *base = dev_read_addr_ptr(dev); | ||||||
|  | 	struct phy phy; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if (!base) | 	if (!base) | ||||||
|  | @ -396,6 +419,13 @@ static int musb_usb_probe(struct udevice *dev) | ||||||
| 	if (IS_ERR(glue->ccm)) | 	if (IS_ERR(glue->ccm)) | ||||||
| 		return PTR_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; | 	priv->desc_before_addr = true; | ||||||
| 
 | 
 | ||||||
| 	memset(&pdata, 0, sizeof(pdata)); | 	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 sunxi_glue *glue = dev_get_priv(dev); | ||||||
| 	struct musb_host_data *host = &glue->mdata; | 	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); | 	musb_stop(host->host); | ||||||
| 
 | 
 | ||||||
| 	sunxi_usb_phy_exit(0); |  | ||||||
| #ifdef CONFIG_SUNXI_GEN_SUN6I | #ifdef CONFIG_SUNXI_GEN_SUN6I | ||||||
| 	clrbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0)); | 	clrbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0)); | ||||||
| 	if (glue->cfg->rst_bit) | 	if (glue->cfg->rst_bit) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue