[U-Boot] [PATCH V2 1/2] usb: ohci: ohci-da8xx: Enable da850-ohci driver with DM support

Adam Ford aford173 at gmail.com
Tue Apr 30 10:21:41 UTC 2019


This patch reuses some former code for the hawkboard, combines it
with some some similar DM_USB compatible code for the OHCI driver,
and enables the use of the da850's OHCI controller with DM_USB
compatibility.

Signed-off-by: Adam Ford <aford173 at gmail.com>
---
V2:  Replace timeout with get_timer and read/modify/write registers with
     clrsetbits_le32 instead of doing it manually.

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0fbc115801..0d8ab3b651 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -239,6 +239,11 @@ config USB_OHCI_GENERIC
 	---help---
 	  Enables support for generic OHCI controller.
 
+config USB_OHCI_DA8XX
+	bool "Support for da850 OHCI USB controller"
+	help
+	  Enable support for the da850 USB controller.
+
 endif # USB_OHCI_HCD
 
 config USB_UHCI_HCD
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 47ad3f34d5..e8a495fde5 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -4,9 +4,54 @@
  */
 
 #include <common.h>
-
+#include <asm/io.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/ofnode.h>
+#include <generic-phy.h>
+#include <reset.h>
+#include "ohci.h"
 #include <asm/arch/da8xx-usb.h>
 
+struct da8xx_ohci {
+	ohci_t ohci;
+	struct clk *clocks;	/* clock list */
+	struct phy phy;
+	int clock_count;	/* number of clock in clock list */
+};
+
+static int usb_phy_on(void)
+{
+	unsigned long timeout;
+
+	clrsetbits_le32(&davinci_syscfg_regs->cfgchip2,
+			(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN |
+			CFGCHIP2_OTGPWRDN | CFGCHIP2_OTGMODE |
+			CFGCHIP2_REFFREQ | CFGCHIP2_USB1PHYCLKMUX),
+			(CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN |
+			CFGCHIP2_PHY_PLLON | CFGCHIP2_REFFREQ_24MHZ |
+			CFGCHIP2_USB2PHYCLKMUX | CFGCHIP2_USB1SUSPENDM));
+
+	/* wait until the usb phy pll locks */
+	timeout = get_timer(0);
+	while (get_timer(timeout) < 10) {
+		if (readl(&davinci_syscfg_regs->cfgchip2) & CFGCHIP2_PHYCLKGD)
+			return 1;
+	}
+
+	/* USB phy was not turned on */
+	return 0;
+}
+
+static void usb_phy_off(void)
+{
+	/* Power down the on-chip PHY. */
+	clrsetbits_le32(&davinci_syscfg_regs->cfgchip2,
+			CFGCHIP2_PHY_PLLON | CFGCHIP2_USB1SUSPENDM,
+			CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN |
+			CFGCHIP2_RESET);
+}
+
 int usb_cpu_init(void)
 {
 	/* enable psc for usb2.0 */
@@ -37,3 +82,94 @@ int usb_cpu_init_fail(void)
 {
 	return usb_cpu_stop();
 }
+
+#if CONFIG_IS_ENABLED(DM_USB)
+static int ohci_da8xx_probe(struct udevice *dev)
+{
+	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
+	struct da8xx_ohci *priv = dev_get_priv(dev);
+	int i, err, ret, clock_nb;
+
+	err = 0;
+	priv->clock_count = 0;
+	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
+	if (clock_nb > 0) {
+		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
+					    GFP_KERNEL);
+		if (!priv->clocks)
+			return -ENOMEM;
+
+		for (i = 0; i < clock_nb; i++) {
+			err = clk_get_by_index(dev, i, &priv->clocks[i]);
+			if (err < 0)
+				break;
+
+			err = clk_enable(&priv->clocks[i]);
+			if (err) {
+				dev_err(dev, "failed to enable clock %d\n", i);
+				clk_free(&priv->clocks[i]);
+				goto clk_err;
+			}
+			priv->clock_count++;
+		}
+	} else if (clock_nb != -ENOENT) {
+		dev_err(dev, "failed to get clock phandle(%d)\n", clock_nb);
+		return clock_nb;
+	}
+
+	err = usb_cpu_init();
+
+	if (err)
+		goto clk_err;
+
+	err = ohci_register(dev, regs);
+	if (err)
+		goto phy_err;
+
+	return 0;
+
+phy_err:
+	ret = usb_cpu_stop();
+	if (ret)
+		dev_err(dev, "failed to shutdown usb phy\n");
+
+clk_err:
+	ret = clk_release_all(priv->clocks, priv->clock_count);
+	if (ret)
+		dev_err(dev, "failed to disable all clocks\n");
+
+	return err;
+}
+
+static int ohci_da8xx_remove(struct udevice *dev)
+{
+	struct da8xx_ohci *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = ohci_deregister(dev);
+	if (ret)
+		return ret;
+
+	ret = usb_cpu_stop();
+	if (ret)
+		return ret;
+
+	return clk_release_all(priv->clocks, priv->clock_count);
+}
+
+static const struct udevice_id da8xx_ohci_ids[] = {
+	{ .compatible = "ti,da830-ohci" },
+	{ }
+};
+
+U_BOOT_DRIVER(ohci_generic) = {
+	.name	= "ohci-da8xx",
+	.id	= UCLASS_USB,
+	.of_match = da8xx_ohci_ids,
+	.probe = ohci_da8xx_probe,
+	.remove = ohci_da8xx_remove,
+	.ops	= &ohci_usb_ops,
+	.priv_auto_alloc_size = sizeof(struct da8xx_ohci),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif
-- 
2.17.1



More information about the U-Boot mailing list