2010-11-25 15:58:28

by Lin Mac

[permalink] [raw]
Subject: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

From: Mac Lin <[email protected]>

The CNS3XXX SOC has include USB EHCI and OHCI compatible controllers. This
patch adds the necessary glue logic to allow ehci-hcd and ohci-hcd drivers to
work on CNS3XXX

The EHCI and OHCI controllers share a common clock control and reset bit,
therefore additional check for the timming of enabling and disabling is
required. The USB bit of PLL Power Down Control is also shared by OTG, 24MHz
UART clock, Crypto clock, PCIe reference clock, and Clock Scale Generator.
Therefore we only ensure it is enabled, while not disabling it.

Signed-off-by: Mac Lin <[email protected]>
---
drivers/usb/Kconfig | 2 +
drivers/usb/host/Kconfig | 15 ++++
drivers/usb/host/ehci-cns3xxx.c | 171 +++++++++++++++++++++++++++++++++++++++
drivers/usb/host/ehci-hcd.c | 5 +
drivers/usb/host/ohci-cns3xxx.c | 165 +++++++++++++++++++++++++++++++++++++
drivers/usb/host/ohci-hcd.c | 5 +
6 files changed, 363 insertions(+), 0 deletions(-)
create mode 100644 drivers/usb/host/ehci-cns3xxx.c
create mode 100644 drivers/usb/host/ohci-cns3xxx.c

diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 67eb377..5a7c8f1 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -41,6 +41,7 @@ config USB_ARCH_HAS_OHCI
default y if MFD_TC6393XB
default y if ARCH_W90X900
default y if ARCH_DAVINCI_DA8XX
+ default y if ARCH_CNS3XXX
# PPC:
default y if STB03xxx
default y if PPC_MPC52xx
@@ -66,6 +67,7 @@ config USB_ARCH_HAS_EHCI
default y if ARCH_AT91SAM9G45
default y if ARCH_MXC
default y if ARCH_OMAP3
+ default y if ARCH_CNS3XXX
default PCI

# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 6f4f8e6..f8970d1 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -147,6 +147,14 @@ config USB_W90X900_EHCI
---help---
Enables support for the W90X900 USB controller

+config USB_CNS3XXX_EHCI
+ bool "Cavium CNS3XXX EHCI Module"
+ depends on USB_EHCI_HCD && ARCH_CNS3XXX
+ ---help---
+ Enable support for the CNS3XXX SOC's on-chip EHCI controller.
+ It is needed for high-speed (480Mbit/sec) USB 2.0 device
+ support.
+
config USB_OXU210HP_HCD
tristate "OXU210HP HCD support"
depends on USB
@@ -286,6 +294,13 @@ config USB_OHCI_HCD_SSB

If unsure, say N.

+config USB_CNS3XXX_OHCI
+ bool "Cavium CNS3XXX OHCI Module"
+ depends on USB_OHCI_HCD && ARCH_CNS3XXX
+ ---help---
+ Enable support for the CNS3XXX SOC's on-chip OHCI controller.
+ It is needed for low-speed USB 1.0 device support.
+
config USB_OHCI_BIG_ENDIAN_DESC
bool
depends on USB_OHCI_HCD
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
new file mode 100644
index 0000000..9cf6696
--- /dev/null
+++ b/drivers/usb/host/ehci-cns3xxx.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/atomic.h>
+#include <mach/cns3xxx.h>
+#include <mach/pm.h>
+
+static int cns3xxx_ehci_init(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ int retval;
+
+ /*
+ * EHCI and OHCI share the same clock and power,
+ * resetting twice would cause the 1st controller been reset.
+ * Therefore only do power up at the first up device, and
+ * power down at the last down device.
+ *
+ * Set USB AHB INCR length to 16
+ */
+ if (atomic_inc_return(&usb_pwr_ref) == 0) {
+ cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+ cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+ cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+ __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+ MISC_CHIP_CONFIG_REG);
+ }
+
+ ehci->caps = hcd->regs;
+ ehci->regs = hcd->regs
+ + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+ hcd->has_tt = 0;
+ ehci_reset(ehci);
+
+ retval = ehci_init(hcd);
+ if (retval)
+ return retval;
+
+ ehci_port_power(ehci, 0);
+
+ return retval;
+}
+
+static const struct hc_driver cns3xxx_ehci_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "CNS3XXX EHCI Host Controller",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+ .reset = cns3xxx_ehci_init,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+ .get_frame_number = ehci_get_frame,
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+#ifdef CONFIG_PM
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
+#endif
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static int cns3xxx_ehci_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct usb_hcd *hcd;
+ const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
+ struct resource *res;
+ int irq;
+ int retval;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(dev, "Found HC with no IRQ.\n");
+ return -ENODEV;
+ }
+ irq = res->start;
+
+ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+ if (!hcd)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "Found HC with no register addr.\n");
+ retval = -ENODEV;
+ goto err1;
+ }
+
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = res->end - res->start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+ driver->description)) {
+ dev_dbg(dev, "controller already in use\n");
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (hcd->regs == NULL) {
+ dev_dbg(dev, "error mapping memory\n");
+ retval = -EFAULT;
+ goto err2;
+ }
+
+ retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (retval == 0)
+ return retval;
+
+ iounmap(hcd->regs);
+err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+ usb_put_hcd(hcd);
+
+ return retval;
+}
+
+static int cns3xxx_ehci_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ usb_remove_hcd(hcd);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+ /*
+ * EHCI and OHCI share the same clock and power,
+ * resetting twice would cause the 1st controller been reset.
+ * Therefore only do power up at the first up device, and
+ * power down at the last down device.
+ */
+ if (atomic_dec_return(&usb_pwr_ref) == 0)
+ cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+
+ usb_put_hcd(hcd);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:cns3xxx-ehci");
+
+static struct platform_driver cns3xxx_ehci_driver = {
+ .probe = cns3xxx_ehci_probe,
+ .remove = cns3xxx_ehci_remove,
+ .driver = {
+ .name = "cns3xxx-ehci",
+ },
+};
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 502a7e6..c5dd1c3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1216,6 +1216,11 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_octeon_driver
#endif

+#ifdef CONFIG_USB_CNS3XXX_EHCI
+#include "ehci-cns3xxx.c"
+#define PLATFORM_DRIVER cns3xxx_ehci_driver
+#endif
+
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
new file mode 100644
index 0000000..f05ef87
--- /dev/null
+++ b/drivers/usb/host/ohci-cns3xxx.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/atomic.h>
+#include <mach/cns3xxx.h>
+#include <mach/pm.h>
+
+static int __devinit
+cns3xxx_ohci_start(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int ret;
+
+ /*
+ * EHCI and OHCI share the same clock and power,
+ * resetting twice would cause the 1st controller been reset.
+ * Therefore only do power up at the first up device, and
+ * power down at the last down device.
+ *
+ * Set USB AHB INCR length to 16
+ */
+ if (atomic_inc_return(&usb_pwr_ref) == 1) {
+ cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
+ cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+ cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
+ __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
+ MISC_CHIP_CONFIG_REG);
+ }
+
+ ret = ohci_init(ohci);
+ if (ret < 0)
+ return ret;
+
+ ohci->num_ports = 1;
+
+ ret = ohci_run(ohci);
+ if (ret < 0) {
+ err("can't start %s", hcd->self.bus_name);
+ ohci_stop(hcd);
+ return ret;
+ }
+ return 0;
+}
+
+static const struct hc_driver cns3xxx_ohci_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "CNS3XXX OHCI Host controller",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
+ .irq = ohci_irq,
+ .flags = HCD_USB11 | HCD_MEMORY,
+ .start = cns3xxx_ohci_start,
+ .stop = ohci_stop,
+ .shutdown = ohci_shutdown,
+ .urb_enqueue = ohci_urb_enqueue,
+ .urb_dequeue = ohci_urb_dequeue,
+ .endpoint_disable = ohci_endpoint_disable,
+ .get_frame_number = ohci_get_frame,
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+#endif
+ .start_port_reset = ohci_start_port_reset,
+};
+
+static int cns3xxx_ohci_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct usb_hcd *hcd;
+ const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
+ struct resource *res;
+ int irq;
+ int retval;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(dev, "Found HC with no IRQ.\n");
+ return -ENODEV;
+ }
+ irq = res->start;
+
+ hcd = usb_create_hcd(driver, dev, dev_name(dev));
+ if (!hcd)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "Found HC with no register addr.\n");
+ retval = -ENODEV;
+ goto err1;
+ }
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = res->end - res->start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+ driver->description)) {
+ dev_dbg(dev, "controller already in use\n");
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ dev_dbg(dev, "error mapping memory\n");
+ retval = -EFAULT;
+ goto err2;
+ }
+
+ ohci_hcd_init(hcd_to_ohci(hcd));
+
+ retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ if (retval == 0)
+ return retval;
+
+ iounmap(hcd->regs);
+err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+ usb_put_hcd(hcd);
+ return retval;
+}
+
+static int cns3xxx_ohci_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ usb_remove_hcd(hcd);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+ /*
+ * EHCI and OHCI share the same clock and power,
+ * resetting twice would cause the 1st controller been reset.
+ * Therefore only do power up at the first up device, and
+ * power down at the last down device.
+ */
+ if (atomic_dec_return(&usb_pwr_ref) == 0)
+ cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
+
+ usb_put_hcd(hcd);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+MODULE_ALIAS("platform:cns3xxx-ohci");
+
+static struct platform_driver ohci_hcd_cns3xxx_driver = {
+ .probe = cns3xxx_ohci_probe,
+ .remove = cns3xxx_ohci_remove,
+ .driver = {
+ .name = "cns3xxx-ohci",
+ },
+};
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 5179acb..5cb6731 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1111,6 +1111,11 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ohci_octeon_driver
#endif

+#ifdef CONFIG_USB_CNS3XXX_OHCI
+#include "ohci-cns3xxx.c"
+#define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver
+#endif
+
#if !defined(PCI_DRIVER) && \
!defined(PLATFORM_DRIVER) && \
!defined(OMAP1_PLATFORM_DRIVER) && \
--
1.7.3


2010-11-25 16:22:07

by Anton Vorontsov

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

On Thu, Nov 25, 2010 at 11:58:00PM +0800, [email protected] wrote:
> From: Mac Lin <[email protected]>
>
> The CNS3XXX SOC has include USB EHCI and OHCI compatible controllers. This
> patch adds the necessary glue logic to allow ehci-hcd and ohci-hcd drivers to
> work on CNS3XXX
>
> The EHCI and OHCI controllers share a common clock control and reset bit,
> therefore additional check for the timming of enabling and disabling is
> required. The USB bit of PLL Power Down Control is also shared by OTG, 24MHz
> UART clock, Crypto clock, PCIe reference clock, and Clock Scale Generator.
> Therefore we only ensure it is enabled, while not disabling it.
>
> Signed-off-by: Mac Lin <[email protected]>

Thanks for the patch!

Cc'ing Greg.

Greg, the patch doesn't touch any sensitive parts of EHCI and OHCI
drivers, can I take it via ARM subtree? This is to not introduce
cross-tree dependencies (the patch depends on some arch-specific
changes).

Thanks!

> ---
> drivers/usb/Kconfig | 2 +
> drivers/usb/host/Kconfig | 15 ++++
> drivers/usb/host/ehci-cns3xxx.c | 171 +++++++++++++++++++++++++++++++++++++++
> drivers/usb/host/ehci-hcd.c | 5 +
> drivers/usb/host/ohci-cns3xxx.c | 165 +++++++++++++++++++++++++++++++++++++
> drivers/usb/host/ohci-hcd.c | 5 +
> 6 files changed, 363 insertions(+), 0 deletions(-)
> create mode 100644 drivers/usb/host/ehci-cns3xxx.c
> create mode 100644 drivers/usb/host/ohci-cns3xxx.c
>
> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
> index 67eb377..5a7c8f1 100644
> --- a/drivers/usb/Kconfig
> +++ b/drivers/usb/Kconfig
> @@ -41,6 +41,7 @@ config USB_ARCH_HAS_OHCI
> default y if MFD_TC6393XB
> default y if ARCH_W90X900
> default y if ARCH_DAVINCI_DA8XX
> + default y if ARCH_CNS3XXX
> # PPC:
> default y if STB03xxx
> default y if PPC_MPC52xx
> @@ -66,6 +67,7 @@ config USB_ARCH_HAS_EHCI
> default y if ARCH_AT91SAM9G45
> default y if ARCH_MXC
> default y if ARCH_OMAP3
> + default y if ARCH_CNS3XXX
> default PCI
>
> # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 6f4f8e6..f8970d1 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -147,6 +147,14 @@ config USB_W90X900_EHCI
> ---help---
> Enables support for the W90X900 USB controller
>
> +config USB_CNS3XXX_EHCI
> + bool "Cavium CNS3XXX EHCI Module"
> + depends on USB_EHCI_HCD && ARCH_CNS3XXX
> + ---help---
> + Enable support for the CNS3XXX SOC's on-chip EHCI controller.
> + It is needed for high-speed (480Mbit/sec) USB 2.0 device
> + support.
> +
> config USB_OXU210HP_HCD
> tristate "OXU210HP HCD support"
> depends on USB
> @@ -286,6 +294,13 @@ config USB_OHCI_HCD_SSB
>
> If unsure, say N.
>
> +config USB_CNS3XXX_OHCI
> + bool "Cavium CNS3XXX OHCI Module"
> + depends on USB_OHCI_HCD && ARCH_CNS3XXX
> + ---help---
> + Enable support for the CNS3XXX SOC's on-chip OHCI controller.
> + It is needed for low-speed USB 1.0 device support.
> +
> config USB_OHCI_BIG_ENDIAN_DESC
> bool
> depends on USB_OHCI_HCD
> diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
> new file mode 100644
> index 0000000..9cf6696
> --- /dev/null
> +++ b/drivers/usb/host/ehci-cns3xxx.c
> @@ -0,0 +1,171 @@
> +/*
> + * Copyright 2008 Cavium Networks
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, Version 2, as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/atomic.h>
> +#include <mach/cns3xxx.h>
> +#include <mach/pm.h>
> +
> +static int cns3xxx_ehci_init(struct usb_hcd *hcd)
> +{
> + struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> + int retval;
> +
> + /*
> + * EHCI and OHCI share the same clock and power,
> + * resetting twice would cause the 1st controller been reset.
> + * Therefore only do power up at the first up device, and
> + * power down at the last down device.
> + *
> + * Set USB AHB INCR length to 16
> + */
> + if (atomic_inc_return(&usb_pwr_ref) == 0) {
> + cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
> + cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
> + cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
> + __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
> + MISC_CHIP_CONFIG_REG);
> + }
> +
> + ehci->caps = hcd->regs;
> + ehci->regs = hcd->regs
> + + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
> + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
> +
> + hcd->has_tt = 0;
> + ehci_reset(ehci);
> +
> + retval = ehci_init(hcd);
> + if (retval)
> + return retval;
> +
> + ehci_port_power(ehci, 0);
> +
> + return retval;
> +}
> +
> +static const struct hc_driver cns3xxx_ehci_hc_driver = {
> + .description = hcd_name,
> + .product_desc = "CNS3XXX EHCI Host Controller",
> + .hcd_priv_size = sizeof(struct ehci_hcd),
> + .irq = ehci_irq,
> + .flags = HCD_MEMORY | HCD_USB2,
> + .reset = cns3xxx_ehci_init,
> + .start = ehci_run,
> + .stop = ehci_stop,
> + .shutdown = ehci_shutdown,
> + .urb_enqueue = ehci_urb_enqueue,
> + .urb_dequeue = ehci_urb_dequeue,
> + .endpoint_disable = ehci_endpoint_disable,
> + .endpoint_reset = ehci_endpoint_reset,
> + .get_frame_number = ehci_get_frame,
> + .hub_status_data = ehci_hub_status_data,
> + .hub_control = ehci_hub_control,
> +#ifdef CONFIG_PM
> + .bus_suspend = ehci_bus_suspend,
> + .bus_resume = ehci_bus_resume,
> +#endif
> + .relinquish_port = ehci_relinquish_port,
> + .port_handed_over = ehci_port_handed_over,
> +
> + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
> +};
> +
> +static int cns3xxx_ehci_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct usb_hcd *hcd;
> + const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
> + struct resource *res;
> + int irq;
> + int retval;
> +
> + if (usb_disabled())
> + return -ENODEV;
> +
> + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (!res) {
> + dev_err(dev, "Found HC with no IRQ.\n");
> + return -ENODEV;
> + }
> + irq = res->start;
> +
> + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
> + if (!hcd)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(dev, "Found HC with no register addr.\n");
> + retval = -ENODEV;
> + goto err1;
> + }
> +
> + hcd->rsrc_start = res->start;
> + hcd->rsrc_len = res->end - res->start + 1;
> +
> + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
> + driver->description)) {
> + dev_dbg(dev, "controller already in use\n");
> + retval = -EBUSY;
> + goto err1;
> + }
> +
> + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
> + if (hcd->regs == NULL) {
> + dev_dbg(dev, "error mapping memory\n");
> + retval = -EFAULT;
> + goto err2;
> + }
> +
> + retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
> + if (retval == 0)
> + return retval;
> +
> + iounmap(hcd->regs);
> +err2:
> + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +err1:
> + usb_put_hcd(hcd);
> +
> + return retval;
> +}
> +
> +static int cns3xxx_ehci_remove(struct platform_device *pdev)
> +{
> + struct usb_hcd *hcd = platform_get_drvdata(pdev);
> +
> + usb_remove_hcd(hcd);
> + iounmap(hcd->regs);
> + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +
> + /*
> + * EHCI and OHCI share the same clock and power,
> + * resetting twice would cause the 1st controller been reset.
> + * Therefore only do power up at the first up device, and
> + * power down at the last down device.
> + */
> + if (atomic_dec_return(&usb_pwr_ref) == 0)
> + cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
> +
> + usb_put_hcd(hcd);
> +
> + platform_set_drvdata(pdev, NULL);
> +
> + return 0;
> +}
> +
> +MODULE_ALIAS("platform:cns3xxx-ehci");
> +
> +static struct platform_driver cns3xxx_ehci_driver = {
> + .probe = cns3xxx_ehci_probe,
> + .remove = cns3xxx_ehci_remove,
> + .driver = {
> + .name = "cns3xxx-ehci",
> + },
> +};
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index 502a7e6..c5dd1c3 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -1216,6 +1216,11 @@ MODULE_LICENSE ("GPL");
> #define PLATFORM_DRIVER ehci_octeon_driver
> #endif
>
> +#ifdef CONFIG_USB_CNS3XXX_EHCI
> +#include "ehci-cns3xxx.c"
> +#define PLATFORM_DRIVER cns3xxx_ehci_driver
> +#endif
> +
> #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
> !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
> !defined(XILINX_OF_PLATFORM_DRIVER)
> diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
> new file mode 100644
> index 0000000..f05ef87
> --- /dev/null
> +++ b/drivers/usb/host/ohci-cns3xxx.c
> @@ -0,0 +1,165 @@
> +/*
> + * Copyright 2008 Cavium Networks
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, Version 2, as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/atomic.h>
> +#include <mach/cns3xxx.h>
> +#include <mach/pm.h>
> +
> +static int __devinit
> +cns3xxx_ohci_start(struct usb_hcd *hcd)
> +{
> + struct ohci_hcd *ohci = hcd_to_ohci(hcd);
> + int ret;
> +
> + /*
> + * EHCI and OHCI share the same clock and power,
> + * resetting twice would cause the 1st controller been reset.
> + * Therefore only do power up at the first up device, and
> + * power down at the last down device.
> + *
> + * Set USB AHB INCR length to 16
> + */
> + if (atomic_inc_return(&usb_pwr_ref) == 1) {
> + cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
> + cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
> + cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
> + __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
> + MISC_CHIP_CONFIG_REG);
> + }
> +
> + ret = ohci_init(ohci);
> + if (ret < 0)
> + return ret;
> +
> + ohci->num_ports = 1;
> +
> + ret = ohci_run(ohci);
> + if (ret < 0) {
> + err("can't start %s", hcd->self.bus_name);
> + ohci_stop(hcd);
> + return ret;
> + }
> + return 0;
> +}
> +
> +static const struct hc_driver cns3xxx_ohci_hc_driver = {
> + .description = hcd_name,
> + .product_desc = "CNS3XXX OHCI Host controller",
> + .hcd_priv_size = sizeof(struct ohci_hcd),
> + .irq = ohci_irq,
> + .flags = HCD_USB11 | HCD_MEMORY,
> + .start = cns3xxx_ohci_start,
> + .stop = ohci_stop,
> + .shutdown = ohci_shutdown,
> + .urb_enqueue = ohci_urb_enqueue,
> + .urb_dequeue = ohci_urb_dequeue,
> + .endpoint_disable = ohci_endpoint_disable,
> + .get_frame_number = ohci_get_frame,
> + .hub_status_data = ohci_hub_status_data,
> + .hub_control = ohci_hub_control,
> +#ifdef CONFIG_PM
> + .bus_suspend = ohci_bus_suspend,
> + .bus_resume = ohci_bus_resume,
> +#endif
> + .start_port_reset = ohci_start_port_reset,
> +};
> +
> +static int cns3xxx_ohci_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct usb_hcd *hcd;
> + const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
> + struct resource *res;
> + int irq;
> + int retval;
> +
> + if (usb_disabled())
> + return -ENODEV;
> +
> + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (!res) {
> + dev_err(dev, "Found HC with no IRQ.\n");
> + return -ENODEV;
> + }
> + irq = res->start;
> +
> + hcd = usb_create_hcd(driver, dev, dev_name(dev));
> + if (!hcd)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(dev, "Found HC with no register addr.\n");
> + retval = -ENODEV;
> + goto err1;
> + }
> + hcd->rsrc_start = res->start;
> + hcd->rsrc_len = res->end - res->start + 1;
> +
> + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
> + driver->description)) {
> + dev_dbg(dev, "controller already in use\n");
> + retval = -EBUSY;
> + goto err1;
> + }
> +
> + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
> + if (!hcd->regs) {
> + dev_dbg(dev, "error mapping memory\n");
> + retval = -EFAULT;
> + goto err2;
> + }
> +
> + ohci_hcd_init(hcd_to_ohci(hcd));
> +
> + retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
> + if (retval == 0)
> + return retval;
> +
> + iounmap(hcd->regs);
> +err2:
> + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +err1:
> + usb_put_hcd(hcd);
> + return retval;
> +}
> +
> +static int cns3xxx_ohci_remove(struct platform_device *pdev)
> +{
> + struct usb_hcd *hcd = platform_get_drvdata(pdev);
> +
> + usb_remove_hcd(hcd);
> + iounmap(hcd->regs);
> + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +
> + /*
> + * EHCI and OHCI share the same clock and power,
> + * resetting twice would cause the 1st controller been reset.
> + * Therefore only do power up at the first up device, and
> + * power down at the last down device.
> + */
> + if (atomic_dec_return(&usb_pwr_ref) == 0)
> + cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
> +
> + usb_put_hcd(hcd);
> +
> + platform_set_drvdata(pdev, NULL);
> +
> + return 0;
> +}
> +
> +MODULE_ALIAS("platform:cns3xxx-ohci");
> +
> +static struct platform_driver ohci_hcd_cns3xxx_driver = {
> + .probe = cns3xxx_ohci_probe,
> + .remove = cns3xxx_ohci_remove,
> + .driver = {
> + .name = "cns3xxx-ohci",
> + },
> +};
> diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
> index 5179acb..5cb6731 100644
> --- a/drivers/usb/host/ohci-hcd.c
> +++ b/drivers/usb/host/ohci-hcd.c
> @@ -1111,6 +1111,11 @@ MODULE_LICENSE ("GPL");
> #define PLATFORM_DRIVER ohci_octeon_driver
> #endif
>
> +#ifdef CONFIG_USB_CNS3XXX_OHCI
> +#include "ohci-cns3xxx.c"
> +#define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver
> +#endif
> +
> #if !defined(PCI_DRIVER) && \
> !defined(PLATFORM_DRIVER) && \
> !defined(OMAP1_PLATFORM_DRIVER) && \
> --
> 1.7.3

--
Anton Vorontsov
Email: [email protected]

2010-11-25 17:15:25

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

On Thu, Nov 25, 2010 at 07:21:58PM +0300, Anton Vorontsov wrote:
> On Thu, Nov 25, 2010 at 11:58:00PM +0800, [email protected] wrote:
> > From: Mac Lin <[email protected]>
> >
> > The CNS3XXX SOC has include USB EHCI and OHCI compatible controllers. This
> > patch adds the necessary glue logic to allow ehci-hcd and ohci-hcd drivers to
> > work on CNS3XXX
> >
> > The EHCI and OHCI controllers share a common clock control and reset bit,
> > therefore additional check for the timming of enabling and disabling is
> > required. The USB bit of PLL Power Down Control is also shared by OTG, 24MHz
> > UART clock, Crypto clock, PCIe reference clock, and Clock Scale Generator.
> > Therefore we only ensure it is enabled, while not disabling it.
> >
> > Signed-off-by: Mac Lin <[email protected]>
>
> Thanks for the patch!
>
> Cc'ing Greg.
>
> Greg, the patch doesn't touch any sensitive parts of EHCI and OHCI
> drivers, can I take it via ARM subtree? This is to not introduce
> cross-tree dependencies (the patch depends on some arch-specific
> changes).

Please get Alan Stern to ack it as well, as he knows the proper
callbacks that you need to ensure are present.

thanks,

greg k-h

2010-11-25 20:22:09

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

On Thu, 25 Nov 2010, Greg KH wrote:

> On Thu, Nov 25, 2010 at 07:21:58PM +0300, Anton Vorontsov wrote:
> > On Thu, Nov 25, 2010 at 11:58:00PM +0800, [email protected] wrote:
> > > From: Mac Lin <[email protected]>
> > >
> > > The CNS3XXX SOC has include USB EHCI and OHCI compatible controllers. This
> > > patch adds the necessary glue logic to allow ehci-hcd and ohci-hcd drivers to
> > > work on CNS3XXX
> > >
> > > The EHCI and OHCI controllers share a common clock control and reset bit,
> > > therefore additional check for the timming of enabling and disabling is
> > > required. The USB bit of PLL Power Down Control is also shared by OTG, 24MHz
> > > UART clock, Crypto clock, PCIe reference clock, and Clock Scale Generator.
> > > Therefore we only ensure it is enabled, while not disabling it.
> > >
> > > Signed-off-by: Mac Lin <[email protected]>
> >
> > Thanks for the patch!
> >
> > Cc'ing Greg.
> >
> > Greg, the patch doesn't touch any sensitive parts of EHCI and OHCI
> > drivers, can I take it via ARM subtree? This is to not introduce
> > cross-tree dependencies (the patch depends on some arch-specific
> > changes).
>
> Please get Alan Stern to ack it as well, as he knows the proper
> callbacks that you need to ensure are present.

As far as the callbacks are concerned, this looks fine.

Acked-by: Alan Stern <[email protected]>

2010-11-26 15:11:38

by Anton Vorontsov

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

On Thu, Nov 25, 2010 at 03:22:06PM -0500, Alan Stern wrote:
[...]
> > > > From: Mac Lin <[email protected]>
> > > >
> > > > The CNS3XXX SOC has include USB EHCI and OHCI compatible controllers. This
> > > > patch adds the necessary glue logic to allow ehci-hcd and ohci-hcd drivers to
> > > > work on CNS3XXX
> > > >
> > > > The EHCI and OHCI controllers share a common clock control and reset bit,
> > > > therefore additional check for the timming of enabling and disabling is
> > > > required. The USB bit of PLL Power Down Control is also shared by OTG, 24MHz
> > > > UART clock, Crypto clock, PCIe reference clock, and Clock Scale Generator.
> > > > Therefore we only ensure it is enabled, while not disabling it.
> > > >
> > > > Signed-off-by: Mac Lin <[email protected]>
> > >
> > > Thanks for the patch!
> > >
> > > Cc'ing Greg.
> > >
> > > Greg, the patch doesn't touch any sensitive parts of EHCI and OHCI
> > > drivers, can I take it via ARM subtree? This is to not introduce
> > > cross-tree dependencies (the patch depends on some arch-specific
> > > changes).
> >
> > Please get Alan Stern to ack it as well, as he knows the proper
> > callbacks that you need to ensure are present.
>
> As far as the callbacks are concerned, this looks fine.
>
> Acked-by: Alan Stern <[email protected]>

Thanks Alan!

Greg, should I treat your 'to ack it as well' as 'Acked-by'? :-)

--
Anton Vorontsov
Email: [email protected]

2010-11-26 17:18:14

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

On Fri, Nov 26, 2010 at 06:11:31PM +0300, Anton Vorontsov wrote:
> On Thu, Nov 25, 2010 at 03:22:06PM -0500, Alan Stern wrote:
> [...]
> > > > > From: Mac Lin <[email protected]>
> > > > >
> > > > > The CNS3XXX SOC has include USB EHCI and OHCI compatible controllers. This
> > > > > patch adds the necessary glue logic to allow ehci-hcd and ohci-hcd drivers to
> > > > > work on CNS3XXX
> > > > >
> > > > > The EHCI and OHCI controllers share a common clock control and reset bit,
> > > > > therefore additional check for the timming of enabling and disabling is
> > > > > required. The USB bit of PLL Power Down Control is also shared by OTG, 24MHz
> > > > > UART clock, Crypto clock, PCIe reference clock, and Clock Scale Generator.
> > > > > Therefore we only ensure it is enabled, while not disabling it.
> > > > >
> > > > > Signed-off-by: Mac Lin <[email protected]>
> > > >
> > > > Thanks for the patch!
> > > >
> > > > Cc'ing Greg.
> > > >
> > > > Greg, the patch doesn't touch any sensitive parts of EHCI and OHCI
> > > > drivers, can I take it via ARM subtree? This is to not introduce
> > > > cross-tree dependencies (the patch depends on some arch-specific
> > > > changes).
> > >
> > > Please get Alan Stern to ack it as well, as he knows the proper
> > > callbacks that you need to ensure are present.
> >
> > As far as the callbacks are concerned, this looks fine.
> >
> > Acked-by: Alan Stern <[email protected]>
>
> Thanks Alan!
>
> Greg, should I treat your 'to ack it as well' as 'Acked-by'? :-)

Yes please:
Acked-by: Greg Kroah-Hartman <[email protected]>

2010-11-26 18:23:35

by Anton Vorontsov

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

On Fri, Nov 26, 2010 at 09:03:48AM -0800, Greg KH wrote:
[...]
> > > As far as the callbacks are concerned, this looks fine.
> > >
> > > Acked-by: Alan Stern <[email protected]>
> >
> > Thanks Alan!
> >
> > Greg, should I treat your 'to ack it as well' as 'Acked-by'? :-)
>
> Yes please:
> Acked-by: Greg Kroah-Hartman <[email protected]>

Thanks!


Lin,

Now that I tried these patches on the real hardware (EV1.3,
silicon ver. 0xA), USB doesn't seem to work for me. FWIW,
I use U-Boot from BSP release 1.0.

Here is how it looks:

ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
cns3xxx-ehci cns3xxx-ehci.0: CNS3XXX EHCI Host Controller
cns3xxx-ehci cns3xxx-ehci.0: new USB bus registered, assigned bus number 1
cns3xxx-ehci cns3xxx-ehci.0: irq 64, io mem 0x82000000
cns3xxx-ehci cns3xxx-ehci.0: USB 0.0 started, EHCI 0.00
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 0 ports detected
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
cns3xxx-ohci cns3xxx-ohci.0: CNS3XXX OHCI Host controller
cns3xxx-ohci cns3xxx-ohci.0: new USB bus registered, assigned bus number 2
cns3xxx-ohci cns3xxx-ohci.0: irq 91, io mem 0x88000000
cns3xxx-ohci cns3xxx-ohci.0: init err (00000000 0000)
ohci_hcd: can't start cns3xxx-ohci.0
cns3xxx-ohci cns3xxx-ohci.0: startup error -75
cns3xxx-ohci cns3xxx-ohci.0: USB bus 2 deregistered
cns3xxx-ohci: probe of cns3xxx-ohci.0 failed with error -75

I assume this is somehow related to the old hardware I use,
but please take a look.

I tried this on both 2.6.36 and 2.6.37-rc3. You can find your
patches in this tree

git://git.infradead.org/users/cbou/linux-cns3xxx.git master

I'll try to investigate (found a small issue already, patch
down below), but if you beat me to it, please send a patch
agaist the cns3xxx tree.

Thanks,

- - - -
ARM: cns3xxx: Make cns3xxx_pwr_soft_rst_force() to actually reset blocks

commit 6eb5d146d4535 ("ARM: cns3xxx: Use IO memory accessors everywhere")
breaks cns3xxx_pwr_soft_rst_force() function, so that it doesn't write
cleared bit into the register.

This patch fixes the issue by adding the necessary __raw_writel().

Signed-off-by: Anton Vorontsov <[email protected]>
---
arch/arm/mach-cns3xxx/pm.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-cns3xxx/pm.c b/arch/arm/mach-cns3xxx/pm.c
index 78fbaba..5e57955 100644
--- a/arch/arm/mach-cns3xxx/pm.c
+++ b/arch/arm/mach-cns3xxx/pm.c
@@ -67,6 +67,7 @@ static void cns3xxx_pwr_soft_rst_force(unsigned int block)
reg &= ~(block & PM_SOFT_RST_REG_MASK);
} else {
reg &= ~(block & PM_SOFT_RST_REG_MASK);
+ __raw_writel(reg, PM_SOFT_RST_REG);
reg |= (block & PM_SOFT_RST_REG_MASK);
}

--
1.7.0.5

2010-11-27 15:02:42

by Lin Mac

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

2010/11/27 Anton Vorontsov <[email protected]>:
> On Fri, Nov 26, 2010 at 09:03:48AM -0800, Greg KH wrote:
> [...]
>> > > As far as the callbacks are concerned, this looks fine.
>> > >
>> > > Acked-by: Alan Stern <[email protected]>
>> >
>> > Thanks Alan!
>> >
>> > Greg, should I treat your 'to ack it as well' as 'Acked-by'? :-)
>>
>> Yes please:
>> ? ? ? Acked-by: Greg Kroah-Hartman <[email protected]>
>
> Thanks!
>
>
> Lin,
>
> Now that I tried these patches on the real hardware (EV1.3,
> silicon ver. 0xA), USB doesn't seem to work for me. FWIW,
> I use U-Boot from BSP release 1.0.
>
> Here is how it looks:
>
> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
> cns3xxx-ehci cns3xxx-ehci.0: CNS3XXX EHCI Host Controller
> cns3xxx-ehci cns3xxx-ehci.0: new USB bus registered, assigned bus number 1
> cns3xxx-ehci cns3xxx-ehci.0: irq 64, io mem 0x82000000
> cns3xxx-ehci cns3xxx-ehci.0: USB 0.0 started, EHCI 0.00
> hub 1-0:1.0: USB hub found
> hub 1-0:1.0: 0 ports detected
> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
> cns3xxx-ohci cns3xxx-ohci.0: CNS3XXX OHCI Host controller
> cns3xxx-ohci cns3xxx-ohci.0: new USB bus registered, assigned bus number 2
> cns3xxx-ohci cns3xxx-ohci.0: irq 91, io mem 0x88000000
> cns3xxx-ohci cns3xxx-ohci.0: init err (00000000 0000)
> ohci_hcd: can't start cns3xxx-ohci.0
> cns3xxx-ohci cns3xxx-ohci.0: startup error -75
> cns3xxx-ohci cns3xxx-ohci.0: USB bus 2 deregistered
> cns3xxx-ohci: probe of cns3xxx-ohci.0 failed with error -75
>
> I assume this is somehow related to the old hardware I use,
> but please take a look.
>
> I tried this on both 2.6.36 and 2.6.37-rc3. You can find your
> patches in this tree
>
> ?git://git.infradead.org/users/cbou/linux-cns3xxx.git master
>
> I'll try to investigate (found a small issue already, patch
> down below), but if you beat me to it, please send a patch
> agaist the cns3xxx tree.
> Thanks,
I saw this issue on EVB v1.3 chip rev B, with your tree.
I'll do more test and see what I can do there.
Sorry that I didn't notice it more earlier.

> - - - -
> ARM: cns3xxx: Make cns3xxx_pwr_soft_rst_force() to actually reset blocks
>
> commit 6eb5d146d4535 ("ARM: cns3xxx: Use IO memory accessors everywhere")
> breaks cns3xxx_pwr_soft_rst_force() function, so that it doesn't write
> cleared bit into the register.
>
> This patch fixes the issue by adding the necessary __raw_writel().
>
> Signed-off-by: Anton Vorontsov <[email protected]>
> ---
> ?arch/arm/mach-cns3xxx/pm.c | ? ?1 +
> ?1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-cns3xxx/pm.c b/arch/arm/mach-cns3xxx/pm.c
> index 78fbaba..5e57955 100644
> --- a/arch/arm/mach-cns3xxx/pm.c
> +++ b/arch/arm/mach-cns3xxx/pm.c
> @@ -67,6 +67,7 @@ static void cns3xxx_pwr_soft_rst_force(unsigned int block)
> ? ? ? ? ? ? ? ?reg &= ~(block & PM_SOFT_RST_REG_MASK);
> ? ? ? ?} else {
> ? ? ? ? ? ? ? ?reg &= ~(block & PM_SOFT_RST_REG_MASK);
> + ? ? ? ? ? ? ? __raw_writel(reg, PM_SOFT_RST_REG);
> ? ? ? ? ? ? ? ?reg |= (block & PM_SOFT_RST_REG_MASK);
> ? ? ? ?}
>
> --
> 1.7.0.5
>
>

2010-11-29 03:58:20

by Lin Mac

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

2010/11/27 Lin Mac <[email protected]>:
> 2010/11/27 Anton Vorontsov <[email protected]>:
>> On Fri, Nov 26, 2010 at 09:03:48AM -0800, Greg KH wrote:
>> [...]
>>> > > As far as the callbacks are concerned, this looks fine.
>>> > >
>>> > > Acked-by: Alan Stern <[email protected]>
>>> >
>>> > Thanks Alan!
>>> >
>>> > Greg, should I treat your 'to ack it as well' as 'Acked-by'? :-)
>>>
>>> Yes please:
>>> ? ? ? Acked-by: Greg Kroah-Hartman <[email protected]>
>>
>> Thanks!
>>
>>
>> Lin,
>>
>> Now that I tried these patches on the real hardware (EV1.3,
>> silicon ver. 0xA), USB doesn't seem to work for me. FWIW,
>> I use U-Boot from BSP release 1.0.
>>
>> Here is how it looks:
>>
>> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
>> cns3xxx-ehci cns3xxx-ehci.0: CNS3XXX EHCI Host Controller
>> cns3xxx-ehci cns3xxx-ehci.0: new USB bus registered, assigned bus number 1
>> cns3xxx-ehci cns3xxx-ehci.0: irq 64, io mem 0x82000000
>> cns3xxx-ehci cns3xxx-ehci.0: USB 0.0 started, EHCI 0.00
>> hub 1-0:1.0: USB hub found
>> hub 1-0:1.0: 0 ports detected
>> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
>> cns3xxx-ohci cns3xxx-ohci.0: CNS3XXX OHCI Host controller
>> cns3xxx-ohci cns3xxx-ohci.0: new USB bus registered, assigned bus number 2
>> cns3xxx-ohci cns3xxx-ohci.0: irq 91, io mem 0x88000000
>> cns3xxx-ohci cns3xxx-ohci.0: init err (00000000 0000)
>> ohci_hcd: can't start cns3xxx-ohci.0
>> cns3xxx-ohci cns3xxx-ohci.0: startup error -75
>> cns3xxx-ohci cns3xxx-ohci.0: USB bus 2 deregistered
>> cns3xxx-ohci: probe of cns3xxx-ohci.0 failed with error -75
>>
>> I assume this is somehow related to the old hardware I use,
>> but please take a look.
>>
>> I tried this on both 2.6.36 and 2.6.37-rc3. You can find your
>> patches in this tree
>>
>> ?git://git.infradead.org/users/cbou/linux-cns3xxx.git master
>>
>> I'll try to investigate (found a small issue already, patch
>> down below), but if you beat me to it, please send a patch
>> agaist the cns3xxx tree.
>> Thanks,
> I saw this issue on EVB v1.3 chip rev B, with your tree.
> I'll do more test and see what I can do there.
> Sorry that I didn't notice it more earlier.
>
>> - - - -
>> ARM: cns3xxx: Make cns3xxx_pwr_soft_rst_force() to actually reset blocks
>>
>> commit 6eb5d146d4535 ("ARM: cns3xxx: Use IO memory accessors everywhere")
>> breaks cns3xxx_pwr_soft_rst_force() function, so that it doesn't write
>> cleared bit into the register.
>>
>> This patch fixes the issue by adding the necessary __raw_writel().
>>
>> Signed-off-by: Anton Vorontsov <[email protected]>
>> ---
>> ?arch/arm/mach-cns3xxx/pm.c | ? ?1 +
>> ?1 files changed, 1 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch/arm/mach-cns3xxx/pm.c b/arch/arm/mach-cns3xxx/pm.c
>> index 78fbaba..5e57955 100644
>> --- a/arch/arm/mach-cns3xxx/pm.c
>> +++ b/arch/arm/mach-cns3xxx/pm.c
>> @@ -67,6 +67,7 @@ static void cns3xxx_pwr_soft_rst_force(unsigned int block)
>> ? ? ? ? ? ? ? ?reg &= ~(block & PM_SOFT_RST_REG_MASK);
>> ? ? ? ?} else {
>> ? ? ? ? ? ? ? ?reg &= ~(block & PM_SOFT_RST_REG_MASK);
>> + ? ? ? ? ? ? ? __raw_writel(reg, PM_SOFT_RST_REG);
>> ? ? ? ? ? ? ? ?reg |= (block & PM_SOFT_RST_REG_MASK);
>> ? ? ? ?}
>>
>> --
>> 1.7.0.5
>>
>>
>


2010/11/25 <[email protected]>:
> From: Mac Lin <[email protected]>
>
> The CNS3XXX SOC has include USB EHCI and OHCI compatible controllers. This
> patch adds the necessary glue logic to allow ehci-hcd and ohci-hcd drivers to
> work on CNS3XXX
>
> The EHCI and OHCI controllers share a common clock control and reset bit,
> therefore additional check for the timming of enabling and disabling is
> required. The USB bit of PLL Power Down Control is also shared by OTG, 24MHz
> UART clock, Crypto clock, PCIe reference clock, and Clock Scale Generator.
> Therefore we only ensure it is enabled, while not disabling it.
>
> Signed-off-by: Mac Lin <[email protected]>
> ---
> drivers/usb/Kconfig | 2 +
> drivers/usb/host/Kconfig | 15 ++++
> drivers/usb/host/ehci-cns3xxx.c | 171 +++++++++++++++++++++++++++++++++++++++
> drivers/usb/host/ehci-hcd.c | 5 +
> drivers/usb/host/ohci-cns3xxx.c | 165 +++++++++++++++++++++++++++++++++++++
> drivers/usb/host/ohci-hcd.c | 5 +
> 6 files changed, 363 insertions(+), 0 deletions(-)
> create mode 100644 drivers/usb/host/ehci-cns3xxx.c
> create mode 100644 drivers/usb/host/ohci-cns3xxx.c
>
> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
> index 67eb377..5a7c8f1 100644
> --- a/drivers/usb/Kconfig
> +++ b/drivers/usb/Kconfig
> @@ -41,6 +41,7 @@ config USB_ARCH_HAS_OHCI
> default y if MFD_TC6393XB
> default y if ARCH_W90X900
> default y if ARCH_DAVINCI_DA8XX
> + default y if ARCH_CNS3XXX
> # PPC:
> default y if STB03xxx
> default y if PPC_MPC52xx
> @@ -66,6 +67,7 @@ config USB_ARCH_HAS_EHCI
> default y if ARCH_AT91SAM9G45
> default y if ARCH_MXC
> default y if ARCH_OMAP3
> + default y if ARCH_CNS3XXX
> default PCI
>
> # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 6f4f8e6..f8970d1 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -147,6 +147,14 @@ config USB_W90X900_EHCI
> ---help---
> Enables support for the W90X900 USB controller
>
> +config USB_CNS3XXX_EHCI
> + bool "Cavium CNS3XXX EHCI Module"
> + depends on USB_EHCI_HCD && ARCH_CNS3XXX
> + ---help---
> + Enable support for the CNS3XXX SOC's on-chip EHCI controller.
> + It is needed for high-speed (480Mbit/sec) USB 2.0 device
> + support.
> +
> config USB_OXU210HP_HCD
> tristate "OXU210HP HCD support"
> depends on USB
> @@ -286,6 +294,13 @@ config USB_OHCI_HCD_SSB
>
> If unsure, say N.
>
> +config USB_CNS3XXX_OHCI
> + bool "Cavium CNS3XXX OHCI Module"
> + depends on USB_OHCI_HCD && ARCH_CNS3XXX
> + ---help---
> + Enable support for the CNS3XXX SOC's on-chip OHCI controller.
> + It is needed for low-speed USB 1.0 device support.
> +
> config USB_OHCI_BIG_ENDIAN_DESC
> bool
> depends on USB_OHCI_HCD
> diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
> new file mode 100644
> index 0000000..9cf6696
> --- /dev/null
> +++ b/drivers/usb/host/ehci-cns3xxx.c
> @@ -0,0 +1,171 @@
> +/*
> + * Copyright 2008 Cavium Networks
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, Version 2, as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/atomic.h>
> +#include <mach/cns3xxx.h>
> +#include <mach/pm.h>
> +
> +static int cns3xxx_ehci_init(struct usb_hcd *hcd)
> +{
> + struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> + int retval;
> +
> + /*
> + * EHCI and OHCI share the same clock and power,
> + * resetting twice would cause the 1st controller been reset.
> + * Therefore only do power up at the first up device, and
> + * power down at the last down device.
> + *
> + * Set USB AHB INCR length to 16
> + */
> + if (atomic_inc_return(&usb_pwr_ref) == 0) {
There's a typo here, the 0 should be 1 instead.

> + cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
> + cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
> + cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
> + __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
> + MISC_CHIP_CONFIG_REG);
> + }
> +
> + ehci->caps = hcd->regs;
> + ehci->regs = hcd->regs
> + + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
> + ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
> +
> + hcd->has_tt = 0;
> + ehci_reset(ehci);
> +
> + retval = ehci_init(hcd);
> + if (retval)
> + return retval;
> +
> + ehci_port_power(ehci, 0);
> +
> + return retval;
> +}
> +
> +static const struct hc_driver cns3xxx_ehci_hc_driver = {
> + .description = hcd_name,
> + .product_desc = "CNS3XXX EHCI Host Controller",
> + .hcd_priv_size = sizeof(struct ehci_hcd),
> + .irq = ehci_irq,
> + .flags = HCD_MEMORY | HCD_USB2,
> + .reset = cns3xxx_ehci_init,
> + .start = ehci_run,
> + .stop = ehci_stop,
> + .shutdown = ehci_shutdown,
> + .urb_enqueue = ehci_urb_enqueue,
> + .urb_dequeue = ehci_urb_dequeue,
> + .endpoint_disable = ehci_endpoint_disable,
> + .endpoint_reset = ehci_endpoint_reset,
> + .get_frame_number = ehci_get_frame,
> + .hub_status_data = ehci_hub_status_data,
> + .hub_control = ehci_hub_control,
> +#ifdef CONFIG_PM
> + .bus_suspend = ehci_bus_suspend,
> + .bus_resume = ehci_bus_resume,
> +#endif
> + .relinquish_port = ehci_relinquish_port,
> + .port_handed_over = ehci_port_handed_over,
> +
> + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
> +};
> +
> +static int cns3xxx_ehci_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct usb_hcd *hcd;
> + const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
> + struct resource *res;
> + int irq;
> + int retval;
> +
> + if (usb_disabled())
> + return -ENODEV;
> +
> + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (!res) {
> + dev_err(dev, "Found HC with no IRQ.\n");
> + return -ENODEV;
> + }
> + irq = res->start;
> +
> + hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
> + if (!hcd)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(dev, "Found HC with no register addr.\n");
> + retval = -ENODEV;
> + goto err1;
> + }
> +
> + hcd->rsrc_start = res->start;
> + hcd->rsrc_len = res->end - res->start + 1;
> +
> + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
> + driver->description)) {
> + dev_dbg(dev, "controller already in use\n");
> + retval = -EBUSY;
> + goto err1;
> + }
> +
> + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
> + if (hcd->regs == NULL) {
> + dev_dbg(dev, "error mapping memory\n");
> + retval = -EFAULT;
> + goto err2;
> + }
> +
> + retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
> + if (retval == 0)
> + return retval;
> +
> + iounmap(hcd->regs);
> +err2:
> + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +err1:
> + usb_put_hcd(hcd);
> +
> + return retval;
> +}
> +
> +static int cns3xxx_ehci_remove(struct platform_device *pdev)
> +{
> + struct usb_hcd *hcd = platform_get_drvdata(pdev);
> +
> + usb_remove_hcd(hcd);
> + iounmap(hcd->regs);
> + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +
> + /*
> + * EHCI and OHCI share the same clock and power,
> + * resetting twice would cause the 1st controller been reset.
> + * Therefore only do power up at the first up device, and
> + * power down at the last down device.
> + */
> + if (atomic_dec_return(&usb_pwr_ref) == 0)
> + cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
> +
> + usb_put_hcd(hcd);
> +
> + platform_set_drvdata(pdev, NULL);
> +
> + return 0;
> +}
> +
> +MODULE_ALIAS("platform:cns3xxx-ehci");
> +
> +static struct platform_driver cns3xxx_ehci_driver = {
> + .probe = cns3xxx_ehci_probe,
> + .remove = cns3xxx_ehci_remove,
> + .driver = {
> + .name = "cns3xxx-ehci",
> + },
> +};
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index 502a7e6..c5dd1c3 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -1216,6 +1216,11 @@ MODULE_LICENSE ("GPL");
> #define PLATFORM_DRIVER ehci_octeon_driver
> #endif
>
> +#ifdef CONFIG_USB_CNS3XXX_EHCI
> +#include "ehci-cns3xxx.c"
> +#define PLATFORM_DRIVER cns3xxx_ehci_driver
> +#endif
> +
> #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
> !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
> !defined(XILINX_OF_PLATFORM_DRIVER)
> diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
> new file mode 100644
> index 0000000..f05ef87
> --- /dev/null
> +++ b/drivers/usb/host/ohci-cns3xxx.c
> @@ -0,0 +1,165 @@
> +/*
> + * Copyright 2008 Cavium Networks
> + *
> + * This file is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, Version 2, as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/atomic.h>
> +#include <mach/cns3xxx.h>
> +#include <mach/pm.h>
> +
> +static int __devinit
> +cns3xxx_ohci_start(struct usb_hcd *hcd)
> +{
> + struct ohci_hcd *ohci = hcd_to_ohci(hcd);
> + int ret;
> +
> + /*
> + * EHCI and OHCI share the same clock and power,
> + * resetting twice would cause the 1st controller been reset.
> + * Therefore only do power up at the first up device, and
> + * power down at the last down device.
> + *
> + * Set USB AHB INCR length to 16
> + */
> + if (atomic_inc_return(&usb_pwr_ref) == 1) {
> + cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
> + cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
> + cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
> + __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
> + MISC_CHIP_CONFIG_REG);
> + }
> +
> + ret = ohci_init(ohci);
> + if (ret < 0)
> + return ret;
> +
> + ohci->num_ports = 1;
> +
> + ret = ohci_run(ohci);
> + if (ret < 0) {
> + err("can't start %s", hcd->self.bus_name);
> + ohci_stop(hcd);
> + return ret;
> + }
> + return 0;
> +}
> +
> +static const struct hc_driver cns3xxx_ohci_hc_driver = {
> + .description = hcd_name,
> + .product_desc = "CNS3XXX OHCI Host controller",
> + .hcd_priv_size = sizeof(struct ohci_hcd),
> + .irq = ohci_irq,
> + .flags = HCD_USB11 | HCD_MEMORY,
> + .start = cns3xxx_ohci_start,
> + .stop = ohci_stop,
> + .shutdown = ohci_shutdown,
> + .urb_enqueue = ohci_urb_enqueue,
> + .urb_dequeue = ohci_urb_dequeue,
> + .endpoint_disable = ohci_endpoint_disable,
> + .get_frame_number = ohci_get_frame,
> + .hub_status_data = ohci_hub_status_data,
> + .hub_control = ohci_hub_control,
> +#ifdef CONFIG_PM
> + .bus_suspend = ohci_bus_suspend,
> + .bus_resume = ohci_bus_resume,
> +#endif
> + .start_port_reset = ohci_start_port_reset,
> +};
> +
> +static int cns3xxx_ohci_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct usb_hcd *hcd;
> + const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
> + struct resource *res;
> + int irq;
> + int retval;
> +
> + if (usb_disabled())
> + return -ENODEV;
> +
> + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> + if (!res) {
> + dev_err(dev, "Found HC with no IRQ.\n");
> + return -ENODEV;
> + }
> + irq = res->start;
> +
> + hcd = usb_create_hcd(driver, dev, dev_name(dev));
> + if (!hcd)
> + return -ENOMEM;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(dev, "Found HC with no register addr.\n");
> + retval = -ENODEV;
> + goto err1;
> + }
> + hcd->rsrc_start = res->start;
> + hcd->rsrc_len = res->end - res->start + 1;
> +
> + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
> + driver->description)) {
> + dev_dbg(dev, "controller already in use\n");
> + retval = -EBUSY;
> + goto err1;
> + }
> +
> + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
> + if (!hcd->regs) {
> + dev_dbg(dev, "error mapping memory\n");
> + retval = -EFAULT;
> + goto err2;
> + }
> +
> + ohci_hcd_init(hcd_to_ohci(hcd));
> +
> + retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
> + if (retval == 0)
> + return retval;
> +
> + iounmap(hcd->regs);
> +err2:
> + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +err1:
> + usb_put_hcd(hcd);
> + return retval;
> +}
> +
> +static int cns3xxx_ohci_remove(struct platform_device *pdev)
> +{
> + struct usb_hcd *hcd = platform_get_drvdata(pdev);
> +
> + usb_remove_hcd(hcd);
> + iounmap(hcd->regs);
> + release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +
> + /*
> + * EHCI and OHCI share the same clock and power,
> + * resetting twice would cause the 1st controller been reset.
> + * Therefore only do power up at the first up device, and
> + * power down at the last down device.
> + */
> + if (atomic_dec_return(&usb_pwr_ref) == 0)
> + cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
> +
> + usb_put_hcd(hcd);
> +
> + platform_set_drvdata(pdev, NULL);
> +
> + return 0;
> +}
> +
> +MODULE_ALIAS("platform:cns3xxx-ohci");
> +
> +static struct platform_driver ohci_hcd_cns3xxx_driver = {
> + .probe = cns3xxx_ohci_probe,
> + .remove = cns3xxx_ohci_remove,
> + .driver = {
> + .name = "cns3xxx-ohci",
> + },
> +};
> diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
> index 5179acb..5cb6731 100644
> --- a/drivers/usb/host/ohci-hcd.c
> +++ b/drivers/usb/host/ohci-hcd.c
> @@ -1111,6 +1111,11 @@ MODULE_LICENSE ("GPL");
> #define PLATFORM_DRIVER ohci_octeon_driver
> #endif
>
> +#ifdef CONFIG_USB_CNS3XXX_OHCI
> +#include "ohci-cns3xxx.c"
> +#define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver
> +#endif
> +
> #if !defined(PCI_DRIVER) && \
> !defined(PLATFORM_DRIVER) && \
> !defined(OMAP1_PLATFORM_DRIVER) && \
> --
> 1.7.3
>
>
Should I resend the patch?

Best Regard,
Mac Lin

2010-11-29 15:32:42

by Anton Vorontsov

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

On Mon, Nov 29, 2010 at 11:58:15AM +0800, Lin Mac wrote:
[...]
> > + * Set USB AHB INCR length to 16
> > + */
> > + if (atomic_inc_return(&usb_pwr_ref) == 0) {
> There's a typo here, the 0 should be 1 instead.

That was it. It works now.

[...]
> Should I resend the patch?

No need to, I've fixed the original commit.

Thanks!

--
Anton Vorontsov
Email: [email protected]

2010-11-29 19:23:34

by David Daney

[permalink] [raw]
Subject: Re: [PATCH v3 1/1] USB: cns3xxx: Add EHCI and OHCI bus glue for cns3xxx SOCs

On 11/25/2010 07:58 AM, [email protected] wrote:
> From: Mac Lin<[email protected]>
>
> The CNS3XXX SOC has include USB EHCI and OHCI compatible controllers. This
> patch adds the necessary glue logic to allow ehci-hcd and ohci-hcd drivers to
> work on CNS3XXX
>
> The EHCI and OHCI controllers share a common clock control and reset bit,
> therefore additional check for the timming of enabling and disabling is
> required. The USB bit of PLL Power Down Control is also shared by OTG, 24MHz
> UART clock, Crypto clock, PCIe reference clock, and Clock Scale Generator.
> Therefore we only ensure it is enabled, while not disabling it.
>
> Signed-off-by: Mac Lin<[email protected]>
> ---
> drivers/usb/Kconfig | 2 +
> drivers/usb/host/Kconfig | 15 ++++
> drivers/usb/host/ehci-cns3xxx.c | 171 +++++++++++++++++++++++++++++++++++++++
> drivers/usb/host/ehci-hcd.c | 5 +
> drivers/usb/host/ohci-cns3xxx.c | 165 +++++++++++++++++++++++++++++++++++++
> drivers/usb/host/ohci-hcd.c | 5 +
> 6 files changed, 363 insertions(+), 0 deletions(-)
> create mode 100644 drivers/usb/host/ehci-cns3xxx.c
> create mode 100644 drivers/usb/host/ohci-cns3xxx.c
>
> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
> index 67eb377..5a7c8f1 100644
> --- a/drivers/usb/Kconfig
> +++ b/drivers/usb/Kconfig
> @@ -41,6 +41,7 @@ config USB_ARCH_HAS_OHCI
> default y if MFD_TC6393XB
> default y if ARCH_W90X900
> default y if ARCH_DAVINCI_DA8XX
> + default y if ARCH_CNS3XXX
> # PPC:
> default y if STB03xxx
> default y if PPC_MPC52xx
> @@ -66,6 +67,7 @@ config USB_ARCH_HAS_EHCI
> default y if ARCH_AT91SAM9G45
> default y if ARCH_MXC
> default y if ARCH_OMAP3
> + default y if ARCH_CNS3XXX
> default PCI
>

Can these be moved to the archecture Kconfig as:

select USB_ARCH_HAS_OHCI
select USB_ARCH_HAS_EHCI

Well to answer my own question, yes they can.

Should they? I think so.

David Daney