| From 4abdbaec4f9833feb302cdea5c0c98cc9ab2a983 Mon Sep 17 00:00:00 2001 |
| From: David Wang <davidwang@quantatw.com> |
| Date: Mon, 6 Nov 2023 11:00:40 +0800 |
| Subject: [PATCH 09/16] drivers: usb: host: sync npcm ehci/ohci |
| |
| --- |
| drivers/usb/host/Kconfig | 16 ++- |
| drivers/usb/host/Makefile | 1 + |
| drivers/usb/host/ehci-npcm7xx.c | 50 --------- |
| drivers/usb/host/ohci-npcm7xx.c | 181 ++++++++++++++++++++++++++++++++ |
| 4 files changed, 194 insertions(+), 54 deletions(-) |
| create mode 100644 drivers/usb/host/ohci-npcm7xx.c |
| |
| diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig |
| index c4736d1d020c..028864f27b74 100644 |
| --- a/drivers/usb/host/Kconfig |
| +++ b/drivers/usb/host/Kconfig |
| @@ -205,12 +205,12 @@ config USB_EHCI_FSL |
| Variation of ARC USB block used in some Freescale chips. |
| |
| config USB_EHCI_HCD_NPCM7XX |
| - tristate "Support for Nuvoton NPCM7XX on-chip EHCI USB controller" |
| - depends on (USB_EHCI_HCD && ARCH_NPCM7XX) || COMPILE_TEST |
| - default y if (USB_EHCI_HCD && ARCH_NPCM7XX) |
| + tristate "Support for Nuvoton NPCM on-chip EHCI USB controller" |
| + depends on (USB_EHCI_HCD && ARCH_NPCM) || COMPILE_TEST |
| + default y if (USB_EHCI_HCD && ARCH_NPCM) |
| help |
| Enables support for the on-chip EHCI controller on |
| - Nuvoton NPCM7XX chips. |
| + Nuvoton NPCM chips. |
| |
| config USB_EHCI_HCD_OMAP |
| tristate "EHCI support for OMAP3 and later chips" |
| @@ -418,6 +418,14 @@ config USB_OHCI_HCD |
| |
| if USB_OHCI_HCD |
| |
| +config USB_OHCI_HCD_NPCM7XX |
| + tristate "Support for Nuvoton NPCM7XX on-chip OHCI USB controller" |
| + depends on (USB_OHCI_HCD && ARCH_NPCM) || COMPILE_TEST |
| + default y if (USB_OHCI_HCD && ARCH_NPCM) |
| + help |
| + Enables support for the on-chip OHCI controller on |
| + Nuvoton NPCM chips. |
| + |
| config USB_OHCI_HCD_OMAP1 |
| tristate "OHCI support for OMAP1/2 chips" |
| depends on ARCH_OMAP1 |
| diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile |
| index 171de4df50bd..3f4f4604d229 100644 |
| --- a/drivers/usb/host/Makefile |
| +++ b/drivers/usb/host/Makefile |
| @@ -63,6 +63,7 @@ obj-$(CONFIG_USB_OHCI_HCD_S3C2410) += ohci-s3c2410.o |
| obj-$(CONFIG_USB_OHCI_HCD_LPC32XX) += ohci-nxp.o |
| obj-$(CONFIG_USB_OHCI_HCD_PXA27X) += ohci-pxa27x.o |
| obj-$(CONFIG_USB_OHCI_HCD_DAVINCI) += ohci-da8xx.o |
| +obj-$(CONFIG_USB_OHCI_HCD_NPCM7XX) += ohci-npcm7xx.o |
| |
| obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o |
| obj-$(CONFIG_USB_FHCI_HCD) += fhci.o |
| diff --git a/drivers/usb/host/ehci-npcm7xx.c b/drivers/usb/host/ehci-npcm7xx.c |
| index 6b5a7a873e01..1d2e2c3c0bf0 100644 |
| --- a/drivers/usb/host/ehci-npcm7xx.c |
| +++ b/drivers/usb/host/ehci-npcm7xx.c |
| @@ -22,19 +22,9 @@ |
| |
| #include "ehci.h" |
| |
| -#include <linux/regmap.h> |
| -#include <linux/mfd/syscon.h> |
| - |
| #define DRIVER_DESC "EHCI npcm7xx driver" |
| |
| static const char hcd_name[] = "npcm7xx-ehci"; |
| - |
| -#define USB2PHYCTL_OFFSET 0x144 |
| - |
| -#define IPSRST2_OFFSET 0x24 |
| -#define IPSRST3_OFFSET 0x34 |
| - |
| - |
| static struct hc_driver __read_mostly ehci_npcm7xx_hc_driver; |
| |
| static int __maybe_unused ehci_npcm7xx_drv_suspend(struct device *dev) |
| @@ -60,52 +50,12 @@ static int npcm7xx_ehci_hcd_drv_probe(struct platform_device *pdev) |
| { |
| struct usb_hcd *hcd; |
| struct resource *res; |
| - struct regmap *gcr_regmap; |
| - struct regmap *rst_regmap; |
| const struct hc_driver *driver = &ehci_npcm7xx_hc_driver; |
| int irq; |
| int retval; |
| |
| dev_dbg(&pdev->dev, "initializing npcm7xx ehci USB Controller\n"); |
| |
| - gcr_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr"); |
| - if (IS_ERR(gcr_regmap)) { |
| - dev_err(&pdev->dev, "%s: failed to find nuvoton,npcm750-gcr\n", |
| - __func__); |
| - return PTR_ERR(gcr_regmap); |
| - } |
| - |
| - rst_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-rst"); |
| - if (IS_ERR(rst_regmap)) { |
| - dev_err(&pdev->dev, "%s: failed to find nuvoton,npcm750-rst\n", |
| - __func__); |
| - return PTR_ERR(rst_regmap); |
| - } |
| - |
| - /********* phy init ******/ |
| - // reset usb host |
| - regmap_update_bits(rst_regmap, IPSRST2_OFFSET, |
| - (0x1 << 26), (0x1 << 26)); |
| - regmap_update_bits(rst_regmap, IPSRST3_OFFSET, |
| - (0x1 << 25), (0x1 << 25)); |
| - regmap_update_bits(gcr_regmap, USB2PHYCTL_OFFSET, |
| - (0x1 << 28), 0); |
| - |
| - udelay(1); |
| - |
| - // enable phy |
| - regmap_update_bits(rst_regmap, IPSRST3_OFFSET, |
| - (0x1 << 25), 0); |
| - |
| - udelay(50); // enable phy |
| - |
| - regmap_update_bits(gcr_regmap, USB2PHYCTL_OFFSET, |
| - (0x1 << 28), (0x1 << 28)); |
| - |
| - // enable host |
| - regmap_update_bits(rst_regmap, IPSRST2_OFFSET, |
| - (0x1 << 26), 0); |
| - |
| if (usb_disabled()) |
| return -ENODEV; |
| |
| diff --git a/drivers/usb/host/ohci-npcm7xx.c b/drivers/usb/host/ohci-npcm7xx.c |
| new file mode 100644 |
| index 000000000000..815d2e084c85 |
| --- /dev/null |
| +++ b/drivers/usb/host/ohci-npcm7xx.c |
| @@ -0,0 +1,181 @@ |
| +// SPDX-License-Identifier: GPL-2.0 |
| +/* |
| + * Nuvoton NPCM7xx driver for OHCI HCD |
| + * |
| + * Copyright (C) 2019 Nuvoton Technologies, |
| + * Tomer Maimon <tomer.maimon@nuvoton.com> <tmaimon77@gmail.com> |
| + * Joseph Liu <kwliun@nuvoton.com> |
| + * |
| + */ |
| + |
| +#include <linux/clk.h> |
| +#include <linux/dma-mapping.h> |
| +#include <linux/io.h> |
| +#include <linux/kernel.h> |
| +#include <linux/module.h> |
| +#include <linux/of.h> |
| +#include <linux/platform_device.h> |
| +#include <linux/phy/phy.h> |
| +#include <linux/usb.h> |
| +#include <linux/usb/hcd.h> |
| + |
| +#include "ohci.h" |
| + |
| +#define DRIVER_DESC "OHCI NPCM7XX driver" |
| + |
| +static const char hcd_name[] = "ohci-npcm7xx"; |
| +static struct hc_driver __read_mostly ohci_npcm7xx_driver; |
| + |
| +static int ohci_hcd_npcm7xx_probe(struct platform_device *pdev) |
| +{ |
| + struct resource *res = NULL; |
| + struct usb_hcd *hcd = NULL; |
| + int irq; |
| + int ret; |
| + |
| + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| + if (!res) { |
| + pr_err("platform_get_resource error."); |
| + return -ENODEV; |
| + } |
| + |
| + irq = platform_get_irq(pdev, 0); |
| + if (irq < 0) { |
| + pr_err("platform_get_irq error."); |
| + return -ENODEV; |
| + } |
| + |
| +#ifdef CONFIG_OF |
| + /* |
| + * Right now device-tree probed devices don't get dma_mask set. |
| + * Since shared usb code relies on it, set it here for now. |
| + * Once we have dma capability bindings this can go away. |
| + */ |
| + ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); |
| + if (ret) |
| + return -ENODEV; |
| +#endif |
| + |
| + /* initialize hcd */ |
| + hcd = usb_create_hcd(&ohci_npcm7xx_driver, &pdev->dev, (char *)hcd_name); |
| + if (!hcd) { |
| + pr_err("Failed to create hcd"); |
| + return -ENOMEM; |
| + } |
| + |
| + hcd->regs = (void __iomem *)res->start; |
| + hcd->rsrc_start = res->start; |
| + hcd->rsrc_len = resource_size(res); |
| + |
| + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { |
| + dev_dbg(&pdev->dev, "controller already in use\n"); |
| + ret = -EBUSY; |
| + goto err_put_hcd; |
| + } |
| + |
| + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); |
| + if (hcd->regs == NULL) { |
| + dev_dbg(&pdev->dev, "error mapping memory\n"); |
| + ret = -EFAULT; |
| + goto err_release_region; |
| + } |
| + |
| + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| + if (ret != 0) { |
| + pr_err("Failed to add hcd"); |
| + usb_put_hcd(hcd); |
| + return ret; |
| + } |
| + |
| + return ret; |
| + |
| + err_release_region: |
| + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| + err_put_hcd: |
| + usb_put_hcd(hcd); |
| + return ret; |
| + |
| +} |
| + |
| +static int ohci_hcd_npcm7xx_remove(struct platform_device *pdev) |
| +{ |
| + struct usb_hcd *hcd = platform_get_drvdata(pdev); |
| + |
| + usb_remove_hcd(hcd); |
| + usb_put_hcd(hcd); |
| + |
| + return 0; |
| +} |
| + |
| +#ifdef CONFIG_PM |
| +static int ohci_npcm7xx_suspend(struct device *dev) |
| +{ |
| + struct usb_hcd *hcd = dev_get_drvdata(dev); |
| + bool do_wakeup = device_may_wakeup(dev); |
| + int rc = ohci_suspend(hcd, do_wakeup); |
| + |
| + if (rc) |
| + return rc; |
| + |
| + return 0; |
| +} |
| + |
| +static int ohci_npcm7xx_resume(struct device *dev) |
| +{ |
| + struct usb_hcd *hcd = dev_get_drvdata(dev); |
| + |
| + ohci_resume(hcd, false); |
| + |
| + return 0; |
| +} |
| +#else |
| +#define ohci_npcm7xx_suspend NULL |
| +#define ohci_npcm7xx_resume NULL |
| +#endif |
| + |
| + |
| +#ifdef CONFIG_OF |
| +static const struct of_device_id npcm750_ohci_match[] = { |
| + { .compatible = "nuvoton,npcm750-ohci" }, |
| + {}, |
| +}; |
| +MODULE_DEVICE_TABLE(of, npcm750_ohci_match); |
| +#endif |
| + |
| +static const struct dev_pm_ops npcm7xx_ohci_pm_ops = { |
| + .suspend = ohci_npcm7xx_suspend, |
| + .resume = ohci_npcm7xx_resume, |
| +}; |
| + |
| +static struct platform_driver ohci_hcd_npcm7xx_driver = { |
| + .probe = ohci_hcd_npcm7xx_probe, |
| + .remove = ohci_hcd_npcm7xx_remove, |
| + .shutdown = usb_hcd_platform_shutdown, |
| + .driver = { |
| + .name = "npcm7xx-ohci", |
| + .pm = &npcm7xx_ohci_pm_ops, |
| + .of_match_table = of_match_ptr(npcm750_ohci_match), |
| + }, |
| +}; |
| + |
| +static int __init ohci_npcm7xx_init(void) |
| +{ |
| + if (usb_disabled()) |
| + return -ENODEV; |
| + |
| + pr_info("%s: " DRIVER_DESC "\n", hcd_name); |
| + ohci_init_driver(&ohci_npcm7xx_driver, NULL); |
| + return platform_driver_register(&ohci_hcd_npcm7xx_driver); |
| +} |
| +module_init(ohci_npcm7xx_init); |
| + |
| +static void __exit ohci_npcm7xx_cleanup(void) |
| +{ |
| + platform_driver_unregister(&ohci_hcd_npcm7xx_driver); |
| +} |
| +module_exit(ohci_npcm7xx_cleanup); |
| + |
| +MODULE_ALIAS("platform:npcm7xx_ohci"); |
| +MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>"); |
| +MODULE_AUTHOR("Joseph Liu<kwliun@nuvoton.com>"); |
| +MODULE_LICENSE("GPL v2"); |
| -- |
| 2.25.1 |
| |