On 4/28/19 11:45 PM, Adam Ford wrote: > 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 <aford...@gmail.com> > > 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..0f38791973 100644 > --- a/drivers/usb/host/ohci-da8xx.c > +++ b/drivers/usb/host/ohci-da8xx.c > @@ -4,9 +4,63 @@ > */ > > #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) > +{ > + u32 timeout; > + u32 cfgchip2; > + > + cfgchip2 = readl(&davinci_syscfg_regs->cfgchip2); > + > + cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN | > + CFGCHIP2_OTGMODE | CFGCHIP2_REFFREQ | > + CFGCHIP2_USB1PHYCLKMUX); > + cfgchip2 |= CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN | CFGCHIP2_PHY_PLLON | > + CFGCHIP2_REFFREQ_24MHZ | CFGCHIP2_USB2PHYCLKMUX | > + CFGCHIP2_USB1SUSPENDM; > + > + writel(cfgchip2, &davinci_syscfg_regs->cfgchip2); > + > + /* wait until the usb phy pll locks */ > + timeout = 0x7FFFFFF; > + > + while (timeout--) {
Use get_timer() for the timeout. > + if (readl(&davinci_syscfg_regs->cfgchip2) & CFGCHIP2_PHYCLKGD) > + return 1; > + } > + > + /* USB phy was not turned on */ > + return 0; > +} > + > +static void usb_phy_off(void) > +{ > + u32 cfgchip2; > + > + /* > + * Power down the on-chip PHY. > + */ > + cfgchip2 = readl(&davinci_syscfg_regs->cfgchip2); > + cfgchip2 &= ~(CFGCHIP2_PHY_PLLON | CFGCHIP2_USB1SUSPENDM); > + cfgchip2 |= CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN | CFGCHIP2_RESET; > + writel(cfgchip2, &davinci_syscfg_regs->cfgchip2); clrsetbits > +} > + > int usb_cpu_init(void) > { > /* enable psc for usb2.0 */ > @@ -37,3 +91,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; clk_enable_bulk() > + 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 > -- Best regards, Marek Vasut _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot