usb: ehci-omap: Add Support for DM_USB and OF_CONTROL
authorAdam Ford <aford173@gmail.com>
Sat, 16 May 2020 06:19:53 +0000 (01:19 -0500)
committerMarek Vasut <marek.vasut+renesas@gmail.com>
Fri, 22 May 2020 13:22:35 +0000 (15:22 +0200)
The omap3.dtsi file shows the usbhshost node with two sub-nodes
for ohci and ehci.  This patch file creates the usbhshost, and
pulls the portX-mode information.  It then locates the EHCI
sub-node, and initializes the EHCI controller with the info
pulled from the usbhshost node.

There is still more to do since there isn't an actual link
between the 'phys' reference and the corresponding phy driver,
and there is no nop-xceiv driver yet.

In the meantime, the older style reference to
CONFIG_OMAP_EHCI_PHYx_RESET_GPIO is still needed to pull
the phy out of reset until the phy driver is completed and the
phandle reference is made.

Signed-off-by: Adam Ford <aford173@gmail.com>
arch/arm/include/asm/ehci-omap.h
drivers/usb/host/ehci-omap.c

index 1549f7bf214fb6fdf567b9d7273c6a6fc72022bc..f970bba937588b48e3504bf7f56dd9d0be5c12cc 100644 (file)
@@ -123,6 +123,7 @@ struct omap_ehci {
        u32 insreg08;           /* 0xb0 */
 };
 
+#if !CONFIG_IS_ENABLED(DM_USB) || !CONFIG_IS_ENABLED(OF_CONTROL)
 /*
  * FIXME: forward declaration of this structs needed because omap got the
  * ehci implementation backwards. move out ehci_hcd_x from board files
@@ -133,5 +134,6 @@ struct ehci_hcor;
 int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata,
                       struct ehci_hccr **hccr, struct ehci_hcor **hcor);
 int omap_ehci_hcd_stop(void);
+#endif
 
 #endif /* _OMAP_COMMON_EHCI_H_ */
index 5fee5371400c6d42f2bf8ab7501fec7c7c1ed818..93ab83941de23f58b4e3149dcc1ccd41a7634688 100644 (file)
 #include <asm/gpio.h>
 #include <asm/arch/ehci.h>
 #include <asm/ehci-omap.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <power/regulator.h>
 
 #include "ehci.h"
 
@@ -179,9 +183,17 @@ int omap_ehci_hcd_stop(void)
  * Based on "drivers/usb/host/ehci-omap.c" from Linux 3.1
  * See there for additional Copyrights.
  */
+#if !CONFIG_IS_ENABLED(DM_USB) || !CONFIG_IS_ENABLED(OF_CONTROL)
+
 int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata,
                       struct ehci_hccr **hccr, struct ehci_hcor **hcor)
 {
+       *hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
+       *hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
+#else
+int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata)
+{
+#endif
        int ret;
        unsigned int i, reg = 0, rev = 0;
 
@@ -288,9 +300,114 @@ int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata,
                if (is_ehci_phy_mode(usbhs_pdata->port_mode[i]))
                        omap_ehci_soft_phy_reset(i);
 
-       *hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
-       *hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
-
        debug("OMAP EHCI init done\n");
        return 0;
 }
+
+#if CONFIG_IS_ENABLED(DM_USB)
+
+static struct omap_usbhs_board_data usbhs_bdata = {
+       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+       .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
+};
+
+static void omap_usbhs_set_mode(u8 index, const char *mode)
+{
+       if (!strcmp(mode, "ehci-phy"))
+               usbhs_bdata.port_mode[index] = OMAP_EHCI_PORT_MODE_PHY;
+       else if (!strcmp(mode, "ehci-tll"))
+               usbhs_bdata.port_mode[index] = OMAP_EHCI_PORT_MODE_TLL;
+       else if (!strcmp(mode, "ehci-hsic"))
+               usbhs_bdata.port_mode[index] = OMAP_EHCI_PORT_MODE_HSIC;
+}
+
+static int omap_usbhs_probe(struct udevice *dev)
+{
+       u8 i;
+       const char *mode;
+       char prop[11];
+
+       /* Go through each port portX-mode to determing phy mode */
+       for (i = 0; i < OMAP_HS_USB_PORTS; i++) {
+               snprintf(prop, sizeof(prop), "port%d-mode", i + 1);
+               mode = dev_read_string(dev, prop);
+
+               /* If the portX-mode exists, set the mode */
+               if (mode)
+                       omap_usbhs_set_mode(i, mode);
+       }
+
+       return omap_ehci_hcd_init(0, &usbhs_bdata);
+}
+
+static const struct udevice_id omap_usbhs_dt_ids[] = {
+       { .compatible = "ti,usbhs-host" },
+       { }
+};
+
+U_BOOT_DRIVER(usb_omaphs_host) = {
+       .name   = "usbhs-host",
+       .id     = UCLASS_SIMPLE_BUS,
+       .of_match = omap_usbhs_dt_ids,
+       .probe  = omap_usbhs_probe,
+       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
+struct ehci_omap_priv_data {
+       struct ehci_ctrl ctrl;
+       struct omap_ehci *ehci;
+#ifdef CONFIG_DM_REGULATOR
+       struct udevice *vbus_supply;
+#endif
+       enum usb_init_type init_type;
+       int portnr;
+       struct phy phy[OMAP_HS_USB_PORTS];
+       int nports;
+};
+
+static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+       struct usb_platdata *plat = dev_get_platdata(dev);
+
+       plat->init_type = USB_INIT_HOST;
+
+       return 0;
+}
+
+static int omap_ehci_probe(struct udevice *dev)
+{
+       struct usb_platdata *plat = dev_get_platdata(dev);
+       struct ehci_omap_priv_data *priv = dev_get_priv(dev);
+       struct ehci_hccr *hccr;
+       struct ehci_hcor *hcor;
+
+       priv->ehci = (struct omap_ehci *)devfdt_get_addr(dev);
+       priv->portnr = dev->seq;
+       priv->init_type = plat->init_type;
+
+       hccr = (struct ehci_hccr *)&priv->ehci->hccapbase;
+       hcor = (struct ehci_hcor *)&priv->ehci->usbcmd;
+
+       return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+}
+
+static const struct udevice_id omap_ehci_dt_ids[] = {
+       { .compatible = "ti,ehci-omap" },
+       { }
+};
+
+U_BOOT_DRIVER(usb_omap_ehci) = {
+       .name   = "omap-ehci",
+       .id     = UCLASS_USB,
+       .of_match = omap_ehci_dt_ids,
+       .probe = omap_ehci_probe,
+       .ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct usb_platdata),
+       .priv_auto_alloc_size = sizeof(struct ehci_omap_priv_data),
+       .remove = ehci_deregister,
+       .ops    = &ehci_usb_ops,
+       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
+#endif