diff options
author | Tom Rini | 2018-06-04 08:55:00 -0400 |
---|---|---|
committer | Tom Rini | 2018-06-04 08:55:00 -0400 |
commit | 809e0e398a91db7bf8b4d6259d9bfc6fbd6bce83 (patch) | |
tree | 7ae663a2a108d27eae7ce25f912d337282d94c66 /drivers/usb/host | |
parent | b5351a439088dfffd83bfaac81f604344ee2e3bd (diff) | |
parent | 2e8dbe14e766deae16c75f357f926f08b881dc66 (diff) |
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-sunxi.c | 66 | ||||
-rw-r--r-- | drivers/usb/host/ohci-sunxi.c | 72 |
2 files changed, 97 insertions, 41 deletions
diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 1297fdb6a71..360efc91160 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -11,34 +11,62 @@ #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 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) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct usb_platdata *plat = dev_get_platdata(dev); struct ehci_sunxi_priv *priv = dev_get_priv(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. @@ -47,21 +75,16 @@ 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(&ccm->ahb_gate0, + setbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask | extra_ahb_gate_mask); #ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&ccm->ahb_reset0_cfg, + setbits_le32(&priv->ccm->ahb_reset0_cfg, 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))); @@ -70,20 +93,25 @@ static int ehci_usb_probe(struct udevice *dev) static int ehci_usb_remove(struct udevice *dev) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 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(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); + clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); #endif - clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); + clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask); return 0; } diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c index b78fad29a35..ce2b47a5c4b 100644 --- a/drivers/usb/host/ohci-sunxi.c +++ b/drivers/usb/host/ohci-sunxi.c @@ -10,35 +10,63 @@ #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 struct ohci_sunxi_priv { + struct sunxi_ccm_reg *ccm; 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) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct usb_bus_priv *bus_priv = dev_get_uclass_priv(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; /* @@ -50,43 +78,43 @@ 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(&ccm->ahb_gate0, + setbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask | extra_ahb_gate_mask); - setbits_le32(&ccm->usb_clk_cfg, priv->usb_gate_mask); + setbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask); #ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&ccm->ahb_reset0_cfg, + setbits_le32(&priv->ccm->ahb_reset0_cfg, 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); } static int ohci_usb_remove(struct udevice *dev) { - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 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(&ccm->ahb_reset0_cfg, priv->ahb_gate_mask); + clrbits_le32(&priv->ccm->ahb_reset0_cfg, priv->ahb_gate_mask); #endif - clrbits_le32(&ccm->usb_clk_cfg, priv->usb_gate_mask); - clrbits_le32(&ccm->ahb_gate0, priv->ahb_gate_mask); + clrbits_le32(&priv->ccm->usb_clk_cfg, priv->usb_gate_mask); + clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask); return 0; } |