[PATCH v1] usb: host: nuvoton: Add nuvoton NPCM7xx ehci/ohci driver

Add nuvoton BMC NPCM750 ehci/ohci driver
Signed-off-by: Jim Liu JJLIU0@nuvoton.com --- drivers/usb/host/Kconfig | 16 +++++ drivers/usb/host/Makefile | 2 + drivers/usb/host/ehci-npcm.c | 119 +++++++++++++++++++++++++++++++++++ drivers/usb/host/ohci-npcm.c | 108 +++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 drivers/usb/host/ehci-npcm.c create mode 100644 drivers/usb/host/ohci-npcm.c
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 8f77412cc7..e2a16cb186 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -188,6 +188,14 @@ config USB_EHCI_MXS Enables support for the on-chip EHCI controller on i.MX23 and i.MX28 SoCs.
+config USB_EHCI_NPCM + bool "Support for Nuvoton NPCM on-chip EHCI USB controller" + depends on ARCH_NPCM + default n + ---help--- + Enables support for the on-chip EHCI controller on + Nuvoton NPCM chips. + config USB_EHCI_OMAP bool "Support for OMAP3+ on-chip EHCI USB controller" depends on ARCH_OMAP2PLUS @@ -290,6 +298,14 @@ config USB_OHCI_DA8XX help Enable support for the da850 USB controller.
+config USB_OHCI_NPCM + bool "Support for Nuvoton NPCM on-chip OHCI USB controller" + depends on ARCH_NPCM + default n + ---help--- + Enables support for the on-chip OHCI controller on + Nuvoton NPCM chips. + endif # USB_OHCI_HCD
config USB_UHCI_HCD diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 7785b3744e..a1de788d8c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_USB_SL811HS) += sl811-hcd.o obj-$(CONFIG_USB_OHCI_LPC32XX) += ohci-lpc32xx.o obj-$(CONFIG_USB_OHCI_PCI) += ohci-pci.o obj-$(CONFIG_USB_OHCI_GENERIC) += ohci-generic.o +obj-$(CONFIG_USB_OHCI_NPCM) += ohci-npcm.o
# echi obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o @@ -35,6 +36,7 @@ obj-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o obj-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o obj-$(CONFIG_USB_EHCI_MX6) += ehci-mx6.o obj-$(CONFIG_USB_EHCI_MX7) += ehci-mx6.o +obj-$(CONFIG_USB_EHCI_NPCM) += ehci-npcm.o obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o diff --git a/drivers/usb/host/ehci-npcm.c b/drivers/usb/host/ehci-npcm.c new file mode 100644 index 0000000000..357a5614ed --- /dev/null +++ b/drivers/usb/host/ehci-npcm.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include <common.h> +#include <dm.h> +#include <generic-phy.h> +#include <reset.h> +#include <asm/io.h> +#include <dm/device_compat.h> +#include <linux/delay.h> +#include "ehci.h" + +struct npcm_ehci_priv { + struct ehci_ctrl ctrl; + struct ehci_hccr *hcd; + struct phy phy; +}; + +static int npcm_ehci_setup_phy(struct udevice *dev, struct phy *phy) +{ + int ret; + + if (!phy) + return 0; + + ret = generic_phy_get_by_index(dev, 0, phy); + if (ret) { + if (ret != -ENOENT) { + dev_err(dev, "failed to get usb phy\n"); + return ret; + } + } else { + ret = generic_phy_init(phy); + if (ret) { + dev_err(dev, "failed to init usb phy\n"); + return ret; + } + } + + return 0; +} + +static int npcm_ehci_init(struct udevice *dev) +{ + struct npcm_ehci_priv *priv = dev_get_priv(dev); + struct reset_ctl reset; + int ret; + + ret = reset_get_by_index(dev, 0, &reset); + if (ret && ret != -ENOENT && ret != -ENOTSUPP) { + dev_err(dev, "failed to get reset\n"); + return ret; + } + + /* reset controller */ + if (reset_valid(&reset)) + reset_assert(&reset); + + /* setup phy */ + ret = npcm_ehci_setup_phy(dev, &priv->phy); + if (ret) + return ret; + + /* release controller from reset */ + if (reset_valid(&reset)) + reset_deassert(&reset); + + return 0; +} + +static int npcm_ehci_probe(struct udevice *dev) +{ + struct npcm_ehci_priv *priv = dev_get_priv(dev); + struct ehci_hcor *hcor; + enum usb_init_type type = dev_get_driver_data(dev); + int ret; + + ret = npcm_ehci_init(dev); + if (ret) + return ret; + + priv->hcd = (struct ehci_hccr *)dev_read_addr_ptr(dev); + debug("USB HCD @0x%p\n", priv->hcd); + hcor = (struct ehci_hcor *)((uintptr_t)priv->hcd + + HC_LENGTH(ehci_readl(&priv->hcd->cr_capbase))); + + return ehci_register(dev, priv->hcd, hcor, NULL, 0, type); +} + +static int npcm_ehci_remove(struct udevice *dev) +{ + struct npcm_ehci_priv *priv = dev_get_priv(dev); + + generic_phy_exit(&priv->phy); + + return ehci_deregister(dev); +} + +static const struct udevice_id npcm_ehci_ids[] = { + { .compatible = "nuvoton,npcm845-ehci", .data = USB_INIT_HOST }, + { .compatible = "nuvoton,npcm845-udc", .data = USB_INIT_DEVICE }, + { .compatible = "nuvoton,npcm750-ehci", .data = USB_INIT_HOST }, + { .compatible = "nuvoton,npcm750-udc", .data = USB_INIT_DEVICE }, + { } +}; + +U_BOOT_DRIVER(ehci_npcm) = { + .name = "ehci_npcm", + .id = UCLASS_USB, + .of_match = npcm_ehci_ids, + .probe = npcm_ehci_probe, + .remove = npcm_ehci_remove, + .ops = &ehci_usb_ops, + .priv_auto = sizeof(struct npcm_ehci_priv), + .plat_auto = sizeof(struct usb_plat), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/usb/host/ohci-npcm.c b/drivers/usb/host/ohci-npcm.c new file mode 100644 index 0000000000..9e1d529880 --- /dev/null +++ b/drivers/usb/host/ohci-npcm.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include <common.h> +#include <dm.h> +#include <generic-phy.h> +#include <reset.h> +#include <asm/io.h> +#include <dm/device_compat.h> +#include <linux/delay.h> +#include "ohci.h" + +struct npcm_ohci_priv { + ohci_t ohci; + struct phy phy; +}; + +static int npcm_ohci_setup_phy(struct udevice *dev, struct phy *phy) +{ + int ret; + + if (!phy) + return 0; + + ret = generic_phy_get_by_index(dev, 0, phy); + if (ret) { + if (ret != -ENOENT) { + dev_err(dev, "failed to get usb phy\n"); + return ret; + } + } else { + ret = generic_phy_init(phy); + if (ret) { + dev_err(dev, "failed to init usb phy\n"); + return ret; + } + } + + return 0; +} + +static int npcm_ohci_init(struct udevice *dev) +{ + struct npcm_ohci_priv *priv = dev_get_priv(dev); + struct reset_ctl reset; + int ret; + + ret = reset_get_by_index(dev, 0, &reset); + if (ret && ret != -ENOENT && ret != -ENOTSUPP) { + dev_err(dev, "failed to get reset\n"); + return ret; + } + + /* reset controller */ + if (reset_valid(&reset)) + reset_assert(&reset); + + /* setup phy */ + ret = npcm_ohci_setup_phy(dev, &priv->phy); + if (ret) + return ret; + + /* release controller from reset */ + if (reset_valid(&reset)) + reset_deassert(&reset); + + return 0; +} + +static int npcm_ohci_probe(struct udevice *dev) +{ + struct ohci_regs *regs = dev_read_addr_ptr(dev); + int ret; + + ret = npcm_ohci_init(dev); + if (ret) + return ret; + + return ohci_register(dev, regs); +} + +static int npcm_ohci_remove(struct udevice *dev) +{ + struct npcm_ohci_priv *priv = dev_get_priv(dev); + + generic_phy_exit(&priv->phy); + + return ohci_deregister(dev); +} + +static const struct udevice_id npcm_ohci_ids[] = { + { .compatible = "nuvoton,npcm845-ohci" }, + { .compatible = "nuvoton,npcm750-ohci" }, + { } +}; + +U_BOOT_DRIVER(ohci_npcm) = { + .name = "ohci_npcm", + .id = UCLASS_USB, + .of_match = npcm_ohci_ids, + .probe = npcm_ohci_probe, + .remove = npcm_ohci_remove, + .ops = &ohci_usb_ops, + .priv_auto = sizeof(struct npcm_ohci_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};

Hi Marek
Thanks for your reply. The answer is yes. Our customer Dell is using our driver now. so need upstream uboot source to uboot master.
On Sat, Jun 25, 2022 at 2:12 AM Marek Vasut marex@denx.de wrote:
On 6/21/22 11:09, Jim Liu wrote:
Add nuvoton BMC NPCM750 ehci/ohci driver
Is there going to be any user of this driver (soon) ?

On 6/27/22 07:30, Jim Liu wrote:
Hi Marek
Hello all,
Thanks for your reply. The answer is yes. Our customer Dell is using our driver now. so need upstream uboot source to uboot master.
All right, so this Dell device is also going to be upstreamed then ?
If the driver is just going to be upstream and never enabled, it would bitrot and be useless -- that's my concern.

Hi Marek
Thank you for your reminder. Dell is use novuton uboot git repo now. and request us upstream it.
npcm7xx normal defconfig is poleg_evb_defconfig, so all people use this config to build uboot. and poleg_evb_defconfig is in uboot master now.
I separate all the drivers to several commits,after I modify each driver coding style. and the poleg_evb_defconfig will be updated in the last commit
When the upstream task is finished , Dell or others will use upstream uboot.
If you have any suggestions please let me know.
On Mon, Jun 27, 2022 at 5:31 PM Marek Vasut marex@denx.de wrote:
On 6/27/22 07:30, Jim Liu wrote:
Hi Marek
Hello all,
Thanks for your reply. The answer is yes. Our customer Dell is using our driver now. so need upstream uboot source to uboot master.
All right, so this Dell device is also going to be upstreamed then ?
If the driver is just going to be upstream and never enabled, it would bitrot and be useless -- that's my concern.

On 6/28/22 05:49, Jim Liu wrote:
Hi Marek
Hi,
Thank you for your reminder. Dell is use novuton uboot git repo now. and request us upstream it.
npcm7xx normal defconfig is poleg_evb_defconfig, so all people use this config to build uboot. and poleg_evb_defconfig is in uboot master now.
I separate all the drivers to several commits,after I modify each driver coding style. and the poleg_evb_defconfig will be updated in the last commit
When the upstream task is finished , Dell or others will use upstream uboot.
If you have any suggestions please let me know.
All right, one last question, was the poleg_evb_defconfig patch posted to enable this driver yet ?

Hi Marek
no, not yet.
I will add i2c otp aes sha pinctrl usb spi mmc feature to poleg_evb_defconfig in the last commit.
about the usb patch if you have any suggestion or need modify please let me know.
On Tue, Jun 28, 2022 at 5:39 PM Marek Vasut marex@denx.de wrote:
On 6/28/22 05:49, Jim Liu wrote:
Hi Marek
Hi,
Thank you for your reminder. Dell is use novuton uboot git repo now. and request us upstream it.
npcm7xx normal defconfig is poleg_evb_defconfig, so all people use this config to build uboot. and poleg_evb_defconfig is in uboot master now.
I separate all the drivers to several commits,after I modify each driver coding style. and the poleg_evb_defconfig will be updated in the last commit
When the upstream task is finished , Dell or others will use upstream uboot.
If you have any suggestions please let me know.
All right, one last question, was the poleg_evb_defconfig patch posted to enable this driver yet ?

On 6/29/22 03:31, Jim Liu wrote:
Hi Marek
Hi,
no, not yet.
I will add i2c otp aes sha pinctrl usb spi mmc feature to poleg_evb_defconfig in the last commit.
about the usb patch if you have any suggestion or need modify please let me know.
The usb patch is already in usb/next , thanks.
participants (2)
-
Jim Liu
-
Marek Vasut