Message ID | 1449783707-23594-6-git-send-email-mateusz.kulikowski@gmail.com |
---|---|
State | RFC |
Delegated to: | Tom Rini |
Headers | show |
On Thursday, December 10, 2015 at 10:41:41 PM, Mateusz Kulikowski wrote: > This driver is able to reconfigure OTG controller into HOST mode. > Board can add board-specific initialization as board_prepare_usb(). > It requires USB_ULPI_VIEWPORT enabled in board configuration. > > Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com> Hi, minor nits below. [...] > diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c > new file mode 100644 > index 0000000..d17a29a > --- /dev/null > +++ b/drivers/usb/host/ehci-msm.c > @@ -0,0 +1,198 @@ > +/* > + * Qualcomm EHCI driver > + * > + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> > + * > + * Based on Linux driver > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <common.h> > +#include <asm/gpio.h> > +#include <asm-generic/errno.h> > +#include <linux/compat.h> > +#include <dm.h> > +#include <fdtdec.h> > +#include <libfdt.h> > +#include <asm/io.h> > +#include <usb.h> > +#include <usb/ulpi.h> > +#include "ehci.h" > + > +#ifndef CONFIG_USB_ULPI_VIEWPORT > +#error Please enable CONFIG_USB_ULPI_VIEWPORT > +#endif The driver should select this in Kconfig instead of this check, right ? > +#define MSM_USB_ULPI_OFFSET 0x170 /* ULPI viewport (PHY) */ > +#define MSM_USB_EHCI_OFFSET 0x100 /* Start of EHCI registers */ > + > +/* PHY viewport regs */ > +#define ULPI_MISC_A_READ 0x96 > +#define ULPI_MISC_A_SET 0x97 > +#define ULPI_MISC_A_CLEAR 0x98 > +#define ULPI_MISC_A_VBUSVLDEXTSEL (1 << 1) > +#define ULPI_MISC_A_VBUSVLDEXT (1 << 0) > + > +/* qcom specific registers (OTG) */ > +#define USB_GENCONFIG_2 0x00A0 > +#define GEN2_SESS_VLD_CTRL_EN (1 << 7) > + > +#define USB_USBCMD (0x0140) Please drop the parenthesis. btw. this register layout looks very similar to struct usb_ehci in include/usb/ehci-fsl.h , can the header be made more universal to cover your driver as well ? Then these macros here won't be needed. > +#define SESS_VLD_CTRL (1 << 25) > +#define USBCMD_RESET 2 > +#define USBCMD_ATTACH 1 > + > +/* USB2_HSIC_USB_OTG_HS_BASE_USB_OTG_HS_PORTSC */ > +#define USB_PORTSC 0x0184 > +#define USB_SBUSCFG 0x0090 > +#define USB_AHB_MODE 0x0098 > + > +#define USB_USBMODE 0x01A8 > +#define USBMODE_DEVICE 2 > +#define USBMODE_HOST 3 > + > +struct msm_ehci_priv { > + struct ehci_ctrl ctrl; /* Needed by EHCI */ > + phys_addr_t base; > + phys_addr_t ehci_base; > + u32 ulpi_base; > + u32 ulpi_port; > +}; > + > +int __weak board_prepare_usb(enum usb_init_type type) > +{ > + return 0; > +} > + > +static void setup_usb_phy(struct msm_ehci_priv *priv) > +{ > + struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port, > + .viewport_addr = priv->ulpi_base}; > + > + /* Select and enable external configuration with USB PHY */ > + ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_SET, > + ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT); > +} > + > +static void reset_usb_phy(struct msm_ehci_priv *priv) > +{ > + struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port, > + .viewport_addr = priv->ulpi_base}; > + > + /* Disable VBUS mimicing in the controller. */ > + ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR, This should be a pointer to a field in struct ulpi_regs, so the (u8 *) cast does not seem right. See for example ehci-zynq.c > + ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT); > +} [...] > +static int ehci_usb_remove(struct udevice *dev) > +{ > + struct msm_ehci_priv *p = dev_get_priv(dev); > + phys_addr_t reg = p->base + USB_USBCMD; > + int ret; > + > + ret = ehci_deregister(dev); > + if (ret) > + return ret; > + > + /* Stop controller. */ > + writel(readl(reg) & ~USBCMD_ATTACH, reg); This should use clrbits_le32() instead. > + reset_usb_phy(p); > + > + ret = board_prepare_usb(USB_INIT_DEVICE); /* Board specific hook */ > + if (ret < 0) > + return ret; > + > + /* Reset controller */ > + writel(0x00080002, reg); /* reset usb */ > + mdelay(20); > + /* Wait for completion */ > + while (readl(reg) & 2) > + ; Look at wait_for_bit() implementations in the U-Boot tree and avoid the unbounded waiting here please. > + return 0; > +} > + > +static int ehci_usb_ofdata_to_platdata(struct udevice *dev) > +{ > + struct msm_ehci_priv *priv = dev_get_priv(dev); > + > + priv->base = dev_get_addr(dev); > + priv->ehci_base = priv->base + MSM_USB_EHCI_OFFSET; > + priv->ulpi_base = priv->base + MSM_USB_ULPI_OFFSET; > + priv->ulpi_port = 0; > + return 0; > +} > + > +static const struct udevice_id ehci_usb_ids[] = { > + { .compatible = "qcom,ehci-host", }, > + { } > +}; > + > +U_BOOT_DRIVER(usb_ehci) = { > + .name = "ehci_msm", > + .id = UCLASS_USB, > + .of_match = ehci_usb_ids, > + .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, > + .probe = ehci_usb_probe, > + .remove = ehci_usb_remove, > + .ops = &ehci_usb_ops, > + .priv_auto_alloc_size = sizeof(struct msm_ehci_priv), > + .flags = DM_FLAG_ALLOC_PRIV_DMA, > +};
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Hi, Thanks for quick review; On 11.12.2015 00:22, Marek Vasut wrote: > On Thursday, December 10, 2015 at 10:41:41 PM, Mateusz Kulikowski wrote: [...] >> + >> +#ifndef CONFIG_USB_ULPI_VIEWPORT >> +#error Please enable CONFIG_USB_ULPI_VIEWPORT >> +#endif > > The driver should select this in Kconfig instead of this check, right ? That was my first attempt, but ULPI_VIEWPORT is not Kconfig option, and it seems it just doesn't work :( It doesn't matter if I add it as select USB_ULPI_VIEWPORT in usb KConfig, or forcibly add CONFIG_USB_ULPI_VIEWPORT to .config [...] >> +#define USB_USBCMD (0x0140) > > Please drop the parenthesis. Doh, missed this one - surely will do it. > > btw. this register layout looks very similar to struct usb_ehci in > include/usb/ehci-fsl.h , can the header be made more universal to > cover your driver as well ? Then these macros here won't be needed. You're right.. in fact contrary to what I expected, Qualcomm didn't implemented their own USB controller. It is designed by Chipidea, and PHY as far as I see is made by Synapsys. I can use fsl headers with little exception that two registers are marked as reserved: USB_AHB_MODE (0x98) and USB_GENCONFIG_2 (0xA0) My guess is that it's just different revision/config of IP core. Do you think it wouldn't look awkward if I use fsl headers? I think once this series gets to mainline we can create shared driver that will support both vendors. I also noticed that U-Boot have ci_udc already so there is a chance I make device controller working pretty fast (but I prefer not to include it in this series yet). [...] >> + struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port, >> + .viewport_addr = priv->ulpi_base}; >> + >> + /* Disable VBUS mimicing in the controller. */ >> + ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR, > > This should be a pointer to a field in struct ulpi_regs, so the (u8 *) > cast does not seem right. See for example ehci-zynq.c > Perhaps I misussed ulpi_viewport code in that case; The reason is I need to access MISC_A register (0x96+) that is not in ulpi_regs structure - afaik it's vendor-specific. Any hints how to tackle that properly? I can of course duplicate ulpi code, but it probably doesn't make much sense. [...] >> + >> + /* Stop controller. */ >> + writel(readl(reg) & ~USBCMD_ATTACH, reg); > > This should use clrbits_le32() instead. Ok [...] >> + /* Wait for completion */ >> + while (readl(reg) & 2) >> + ; > > Look at wait_for_bit() implementations in the U-Boot tree and avoid the > unbounded waiting here please. Ok, btw I noticed there are 3 copies of almost the same code that does that :) Perhaps I can add a patch to add this function to /lib as it seems it's common use case? The following drivers would benefit: ehci-msm, zynq_gem, dwc2, ehci-mx6, ohci-lpc32xx Regards, Mateusz -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAEBCAAGBQJWbWbJAAoJELvtohmVtQzBvEEH/iwqONAqWwqQzpUR4izzZ97Y CAEUWi4GacxwUVt0vZMcK5KV0sRJVP947daMxVkNoDWWkpREuPby+OecFe3mk7iJ cJzTAlYs/OOIkGBuza2wkfaxXq0AItpn2lBF/Vwe8u5hFGSPgYY0quek8SKma6NQ rtNFVdc+4+pgGMy1Pl8Fym9UXOJ/aVv806+XS34UrgGSsnv5qWudRiT3HA0ZR38A VPzgRXs+kIwVAhPe2AlXW0K8w/ipaEF41qAMvHUdXopi0h4Tgsc2QEijC0sIQmBf kSM6gvzYq+gFOJifxcEt3EJj6hOQ4U7nEOi/PqtjBl3BsTw6IdUWLdakCVzQq1I= =eUF2 -----END PGP SIGNATURE-----
On Sunday, December 13, 2015 at 01:38:41 PM, Mateusz Kulikowski wrote: > Hi, > > Thanks for quick review; > > On 11.12.2015 00:22, Marek Vasut wrote: > > On Thursday, December 10, 2015 at 10:41:41 PM, Mateusz Kulikowski wrote: > [...] > > >> + > >> +#ifndef CONFIG_USB_ULPI_VIEWPORT > >> +#error Please enable CONFIG_USB_ULPI_VIEWPORT > >> +#endif > > > > The driver should select this in Kconfig instead of this check, right ? > > That was my first attempt, but ULPI_VIEWPORT is not Kconfig option, > and it seems it just doesn't work :( > > It doesn't matter if I add it as > select USB_ULPI_VIEWPORT > in usb KConfig, or forcibly add CONFIG_USB_ULPI_VIEWPORT to .config I think it should be quite easily possible to add this to USB Kconfig. > [...] > > >> +#define USB_USBCMD (0x0140) > > > > Please drop the parenthesis. > > Doh, missed this one - surely will do it. > > > btw. this register layout looks very similar to struct usb_ehci in > > include/usb/ehci-fsl.h , can the header be made more universal to > > cover your driver as well ? Then these macros here won't be needed. > > You're right.. in fact contrary to what I expected, Qualcomm didn't > implemented their own USB controller. Well building a chip is like going to a IP block supermarket afterall ;-) > It is designed by Chipidea, and PHY as far as I see is made by Synapsys. All of the drivers/usb/host/ehci-{mxs,mx5,mx6,vf}.c are also chipidea cores. MXS and MX6 have chipidea PHY too. > I can use fsl headers with little exception that two registers are > marked as reserved: USB_AHB_MODE (0x98) and USB_GENCONFIG_2 (0xA0) > > My guess is that it's just different revision/config of IP core. > > Do you think it wouldn't look awkward if I use fsl headers? Just rename them to ehci-ci.h, that should be the quickest. > I think once this series gets to mainline we can create shared > driver that will support both vendors. I'm all for that. > I also noticed that U-Boot have ci_udc already so there is > a chance I make device controller working pretty fast > (but I prefer not to include it in this series yet). Correct, that works too. I think it was also tested on some marvell chip. > [...] > > >> + struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port, > >> + .viewport_addr = priv->ulpi_base}; > >> + > >> + /* Disable VBUS mimicing in the controller. */ > >> + ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR, > > > > This should be a pointer to a field in struct ulpi_regs, so the (u8 *) > > cast does not seem right. See for example ehci-zynq.c > > Perhaps I misussed ulpi_viewport code in that case; > > The reason is I need to access MISC_A register (0x96+) that is > not in ulpi_regs structure - afaik it's vendor-specific. > > Any hints how to tackle that properly? > > I can of course duplicate ulpi code, but it probably doesn't make much > sense. I don't have a better suggestion, sorry. Let's keep this as-is unless someone can come up with something better. Code duplication is not a good idea, so we won't do that. > [...] > > >> + > >> + /* Stop controller. */ > >> + writel(readl(reg) & ~USBCMD_ATTACH, reg); > > > > This should use clrbits_le32() instead. > > Ok > > [...] > > >> + /* Wait for completion */ > >> + while (readl(reg) & 2) > >> + ; > > > > Look at wait_for_bit() implementations in the U-Boot tree and avoid the > > unbounded waiting here please. > > Ok, btw I noticed there are 3 copies of almost the same code that does that > :) > > Perhaps I can add a patch to add this function to /lib as it seems it's > common use case? That'd be great, it was on my list to do it for a while, but I didn't get around doing that yet. > The following drivers would benefit: ehci-msm, zynq_gem, dwc2, > ehci-mx6, ohci-lpc32xx Thanks!
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Hi Marek, On 13.12.2015 16:48, Marek Vasut wrote: > On Sunday, December 13, 2015 at 01:38:41 PM, Mateusz Kulikowski wrote: [...] >> It doesn't matter if I add it as >> select USB_ULPI_VIEWPORT >> in usb KConfig, or forcibly add CONFIG_USB_ULPI_VIEWPORT to .config > > I think it should be quite easily possible to add this to USB Kconfig. Will do. >> I can use fsl headers with little exception that two registers are >> marked as reserved: USB_AHB_MODE (0x98) and USB_GENCONFIG_2 (0xA0) >> >> My guess is that it's just different revision/config of IP core. >> >> Do you think it wouldn't look awkward if I use fsl headers? > > Just rename them to ehci-ci.h, that should be the quickest. Will do. [...] >>>> + struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port, >>>> + .viewport_addr = priv->ulpi_base}; >>>> + >>>> + /* Disable VBUS mimicing in the controller. */ >>>> + ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR, >>> >>> This should be a pointer to a field in struct ulpi_regs, so the (u8 *) >>> cast does not seem right. See for example ehci-zynq.c >> >> Perhaps I misussed ulpi_viewport code in that case; >> >> The reason is I need to access MISC_A register (0x96+) that is >> not in ulpi_regs structure - afaik it's vendor-specific. >> >> Any hints how to tackle that properly? >> >> I can of course duplicate ulpi code, but it probably doesn't make much >> sense. > > I don't have a better suggestion, sorry. Let's keep this as-is unless > someone can come up with something better. Code duplication is not a > good idea, so we won't do that. OK Thanks, Mateusz -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAEBCAAGBQJWcerfAAoJELvtohmVtQzB1AMH/260Ioo6W6+skWJJhmm+g3yD B3kWhJWWyGPSkY4QcA7O/dgzU9i/n9a6gwlqcwYLhYlzyKG/p0aRBim0RWEFWK+S V1SMYA3iQhYLkjMdOfqNXdQ5NrG2osll1Nk2GK9wBthVtPkjqfQkOupw7oZq3kd5 3pNpbsREIuxfct26C7kaTJccRf7MIYdlslYu53h4T/t03oO8xBIrSDGAR+9UD841 yCWuATbg461uhPrD1/WBG/wiIzMaOsITyiXIkxr7Z0GNrOeaZ38YqSwASwLTUmxO NB+UkOvA9eM1oz79Qaoxyrfm/rDtds+CHXuFco2LY2gOl1280ffwKG1UQWCWDsk= =XMV7 -----END PGP SIGNATURE-----
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0096a2f..5a63475 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -66,6 +66,14 @@ config USB_EHCI_MX6 ---help--- Enables support for the on-chip EHCI controller on i.MX6 SoCs. +config USB_EHCI_MSM + bool "Support for Qualcomm on-chip EHCI USB controller" + depends on DM_USB + default n + ---help--- + Enables support for the on-chip EHCI controller on Qualcomm + Snapdragon SoCs. + config USB_EHCI_UNIPHIER bool "Support for UniPhier on-chip EHCI USB controller" depends on ARCH_UNIPHIER && OF_CONTROL diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 0b4b458..d4a556a 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_USB_EHCI_MX7) += ehci-mx6.o obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o obj-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o +obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c new file mode 100644 index 0000000..d17a29a --- /dev/null +++ b/drivers/usb/host/ehci-msm.c @@ -0,0 +1,198 @@ +/* + * Qualcomm EHCI driver + * + * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> + * + * Based on Linux driver + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/gpio.h> +#include <asm-generic/errno.h> +#include <linux/compat.h> +#include <dm.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <asm/io.h> +#include <usb.h> +#include <usb/ulpi.h> +#include "ehci.h" + +#ifndef CONFIG_USB_ULPI_VIEWPORT +#error Please enable CONFIG_USB_ULPI_VIEWPORT +#endif + +#define MSM_USB_ULPI_OFFSET 0x170 /* ULPI viewport (PHY) */ +#define MSM_USB_EHCI_OFFSET 0x100 /* Start of EHCI registers */ + +/* PHY viewport regs */ +#define ULPI_MISC_A_READ 0x96 +#define ULPI_MISC_A_SET 0x97 +#define ULPI_MISC_A_CLEAR 0x98 +#define ULPI_MISC_A_VBUSVLDEXTSEL (1 << 1) +#define ULPI_MISC_A_VBUSVLDEXT (1 << 0) + +/* qcom specific registers (OTG) */ +#define USB_GENCONFIG_2 0x00A0 +#define GEN2_SESS_VLD_CTRL_EN (1 << 7) + +#define USB_USBCMD (0x0140) +#define SESS_VLD_CTRL (1 << 25) +#define USBCMD_RESET 2 +#define USBCMD_ATTACH 1 + +/* USB2_HSIC_USB_OTG_HS_BASE_USB_OTG_HS_PORTSC */ +#define USB_PORTSC 0x0184 +#define USB_SBUSCFG 0x0090 +#define USB_AHB_MODE 0x0098 + +#define USB_USBMODE 0x01A8 +#define USBMODE_DEVICE 2 +#define USBMODE_HOST 3 + +struct msm_ehci_priv { + struct ehci_ctrl ctrl; /* Needed by EHCI */ + phys_addr_t base; + phys_addr_t ehci_base; + u32 ulpi_base; + u32 ulpi_port; +}; + +int __weak board_prepare_usb(enum usb_init_type type) +{ + return 0; +} + +static void setup_usb_phy(struct msm_ehci_priv *priv) +{ + struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port, + .viewport_addr = priv->ulpi_base}; + + /* Select and enable external configuration with USB PHY */ + ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_SET, + ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT); +} + +static void reset_usb_phy(struct msm_ehci_priv *priv) +{ + struct ulpi_viewport ulpi_vp = {.port_num = priv->ulpi_port, + .viewport_addr = priv->ulpi_base}; + + /* Disable VBUS mimicing in the controller. */ + ulpi_write(&ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR, + ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT); +} + + +static int msm_init_after_reset(struct ehci_ctrl *dev) +{ + struct msm_ehci_priv *p = container_of(dev, struct msm_ehci_priv, ctrl); + uint32_t val; + + /* select ULPI phy */ + writel(0x80000000, p->base + USB_PORTSC); + setup_usb_phy(p); + + /* Enable sess_vld */ + val = readl(p->base + USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN; + writel(val, p->base + USB_GENCONFIG_2); + + /* Enable external vbus configuration in the LINK */ + val = readl(p->base + USB_USBCMD); + val |= SESS_VLD_CTRL; + writel(val, p->base + USB_USBCMD); + + /* USB_OTG_HS_AHB_BURST */ + writel(0x0, p->base + USB_SBUSCFG); + + /* USB_OTG_HS_AHB_MODE: HPROT_MODE */ + /* Bus access related config. */ + writel(0x08, p->base + USB_AHB_MODE); + + /* set mode to host controller */ + writel(USBMODE_HOST, p->base + USB_USBMODE); + + return 0; +} + +static const struct ehci_ops msm_ehci_ops = { + .init_after_reset = msm_init_after_reset +}; + +static int ehci_usb_probe(struct udevice *dev) +{ + struct msm_ehci_priv *p = dev_get_priv(dev); + struct ehci_hccr *cr; + struct ehci_hcor *or; + int ret; + + cr = (struct ehci_hccr *)p->ehci_base; + or = (struct ehci_hcor *)(p->ehci_base + + HC_LENGTH(readl(p->ehci_base))); + + ret = board_prepare_usb(USB_INIT_HOST); + if (ret < 0) + return ret; + + + return ehci_register(dev, cr, or, &msm_ehci_ops, 0, USB_INIT_HOST); +} + +static int ehci_usb_remove(struct udevice *dev) +{ + struct msm_ehci_priv *p = dev_get_priv(dev); + phys_addr_t reg = p->base + USB_USBCMD; + int ret; + + ret = ehci_deregister(dev); + if (ret) + return ret; + + /* Stop controller. */ + writel(readl(reg) & ~USBCMD_ATTACH, reg); + + reset_usb_phy(p); + + ret = board_prepare_usb(USB_INIT_DEVICE); /* Board specific hook */ + if (ret < 0) + return ret; + + /* Reset controller */ + writel(0x00080002, reg); /* reset usb */ + mdelay(20); + /* Wait for completion */ + while (readl(reg) & 2) + ; + + return 0; +} + +static int ehci_usb_ofdata_to_platdata(struct udevice *dev) +{ + struct msm_ehci_priv *priv = dev_get_priv(dev); + + priv->base = dev_get_addr(dev); + priv->ehci_base = priv->base + MSM_USB_EHCI_OFFSET; + priv->ulpi_base = priv->base + MSM_USB_ULPI_OFFSET; + priv->ulpi_port = 0; + return 0; +} + +static const struct udevice_id ehci_usb_ids[] = { + { .compatible = "qcom,ehci-host", }, + { } +}; + +U_BOOT_DRIVER(usb_ehci) = { + .name = "ehci_msm", + .id = UCLASS_USB, + .of_match = ehci_usb_ids, + .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, + .probe = ehci_usb_probe, + .remove = ehci_usb_remove, + .ops = &ehci_usb_ops, + .priv_auto_alloc_size = sizeof(struct msm_ehci_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};
This driver is able to reconfigure OTG controller into HOST mode. Board can add board-specific initialization as board_prepare_usb(). It requires USB_ULPI_VIEWPORT enabled in board configuration. Signed-off-by: Mateusz Kulikowski <mateusz.kulikowski@gmail.com> --- drivers/usb/host/Kconfig | 8 ++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-msm.c | 198 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 drivers/usb/host/ehci-msm.c