]> git.sur5r.net Git - u-boot/blobdiff - drivers/usb/host/ohci-sunxi.c
usb: sunxi: Switch to use generic-phy
[u-boot] / drivers / usb / host / ohci-sunxi.c
index 0c45eec04aad3a5c762a87380638e854ef10eac0..ce2b47a5c4bacbbf4965c2f32da9dfda878c9d50 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Sunxi ohci glue
  *
@@ -5,41 +6,67 @@
  *
  * Based on code from
  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #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 *)dev_get_addr(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;
 
        /*
@@ -51,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;
 }