[U-Boot] [PATCH V2 0/2] Enable DA830 OHCI USB Controller with DM_USB

This patch enables the DA830 USB Host controller with DM_USB.
Adam Ford (2): usb: ohci: ohci-da8xx: Enable da850-ohci driver with DM support ARM: da850evm: Enable da850-ohci USB host controller
configs/da850evm_defconfig | 7 +- drivers/usb/host/Kconfig | 5 ++ drivers/usb/host/ohci-da8xx.c | 138 +++++++++++++++++++++++++++++++++- include/configs/da850evm.h | 8 ++ 4 files changed, 156 insertions(+), 2 deletions(-)

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@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

On 4/30/19 12:21 PM, Adam Ford wrote: [..]
+#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) {
What happens if clock_nb == -ENOENT ?
I think what you want here is
if (clock_nb < 0) { ... return clock_nb; }
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,
Add DM_FLAG_OS_PREPARE for this to work IIRC.
- .ops = &ohci_usb_ops,
- .priv_auto_alloc_size = sizeof(struct da8xx_ohci),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+}; +#endif

On Tue, Apr 30, 2019 at 05:21:41AM -0500, 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 aford173@gmail.com
Applied to u-boot/master, thanks!

The DA850 EVM has one USB 1.1 OHCI Host controller. With the host controller now support DM_USB, this patch enables the respective functions for the da850evm.
Signed-off-by: Adam Ford aford173@gmail.com --- V2: No changes
diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig index ee39b0b1bc..1845813b2e 100644 --- a/configs/da850evm_defconfig +++ b/configs/da850evm_defconfig @@ -8,8 +8,8 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SYS_MALLOC_F_LEN=0x800 CONFIG_SPL_SERIAL_SUPPORT=y -CONFIG_SPL=y CONFIG_NR_DRAM_BANKS=1 +CONFIG_SPL=y CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y CONFIG_SYS_EXTRA_OPTIONS="MAC_ADDR_IN_SPIFLASH" @@ -67,5 +67,10 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_DAVINCI_SPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +# CONFIG_SPL_DM_USB is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_DA8XX=y # CONFIG_FAT_WRITE is not set CONFIG_USE_TINY_PRINTF=y diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h index 94848f5128..9aaecdd1d5 100644 --- a/include/configs/da850evm.h +++ b/include/configs/da850evm.h @@ -267,6 +267,14 @@ #define CONFIG_ENV_SIZE (16 << 10) #endif
+/* USB Configs */ +#define CONFIG_SYS_USB_OHCI_CPU_INIT +#define CONFIG_USB_OHCI_NEW +#define CONFIG_USB_STORAGE +#define CONFIG_SYS_USB_OHCI_REGS_BASE 0x01E25000 +#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 15 +#define CONFIG_SYS_USB_OHCI_SLOT_NAME "da850evm" + #ifndef CONFIG_DIRECT_NOR_BOOT /* defines for SPL */ #define CONFIG_SYS_SPL_MALLOC_START (CONFIG_SYS_TEXT_BASE - \

On Tue, Apr 30, 2019 at 05:21:42AM -0500, Adam Ford wrote:
The DA850 EVM has one USB 1.1 OHCI Host controller. With the host controller now support DM_USB, this patch enables the respective functions for the da850evm.
Signed-off-by: Adam Ford aford173@gmail.com
Applied to u-boot/master, thanks!
participants (3)
-
Adam Ford
-
Marek Vasut
-
Tom Rini