[PATCH 0/3] usb: ehci ppc device-tree-aware driver

STALE6876d

Revision v1 of 2 in this series.

8 messages, 5 authors, 2007-10-23 · open the first message on its own page

[PATCH 0/3] usb: ehci ppc device-tree-aware driver

From: Valentine Barshak <hidden>
Date: 2007-09-24 19:26:36

Some PowerPC systems have a built-in EHCI controller.
This is a device tree aware version of the EHCI controller driver.
Currently it's been tested on the PowerPC 440EPx Sequoia board.
Other platforms can be added later.
The code is based on the ehci-ppc-soc driver by Stefan Roese [off-list ref].

[PATCH 1/3] usb: add device-tree-aware ehci driver

From: Valentine Barshak <hidden>
Date: 2007-09-24 19:27:57

This adds device-tree-aware ehci-ppc-of driver.
The code is based on the ehci-ppc-soc driver by
Stefan Roese [off-list ref].

Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Valentine Barshak <redacted>
---
 drivers/usb/host/Kconfig       |    8 +
 drivers/usb/host/ehci-hcd.c    |   16 ++
 drivers/usb/host/ehci-ppc-of.c |  243 +++++++++++++++++++++++++++++++++++++++++
 drivers/usb/host/ehci.h        |    2 
 4 files changed, 267 insertions(+), 2 deletions(-)

diff -ruN linux-2.6.orig/drivers/usb/host/ehci.h linux-2.6/drivers/usb/host/ehci.h
--- linux-2.6.orig/drivers/usb/host/ehci.h	2007-09-24 14:55:44.000000000 +0400
+++ linux-2.6/drivers/usb/host/ehci.h	2007-09-24 23:07:16.000000000 +0400
@@ -725,7 +725,7 @@
  * definition below can die once the 4xx support is
  * finally ported over.
  */
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE)
 #define readl_be(addr)		in_be32((__force unsigned *)addr)
 #define writel_be(val, addr)	out_be32((__force unsigned *)addr, val)
 #endif
diff -ruN linux-2.6.orig/drivers/usb/host/ehci-hcd.c linux-2.6/drivers/usb/host/ehci-hcd.c
--- linux-2.6.orig/drivers/usb/host/ehci-hcd.c	2007-09-24 14:55:44.000000000 +0400
+++ linux-2.6/drivers/usb/host/ehci-hcd.c	2007-09-24 23:07:16.000000000 +0400
@@ -944,11 +944,16 @@
 #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
 #endif
 
-#ifdef CONFIG_440EPX
+#if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE)
 #include "ehci-ppc-soc.c"
 #define	PLATFORM_DRIVER		ehci_ppc_soc_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_HCD_PPC_OF
+#include "ehci-ppc-of.c"
+#define OF_PLATFORM_DRIVER	ehci_hcd_ppc_of_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER)
 #error "missing bus glue for ehci-hcd"
@@ -963,6 +968,12 @@
 		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
 		 sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
 
+#ifdef OF_PLATFORM_DRIVER
+	retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
+	if (retval < 0)
+		return retval;
+#endif
+
 #ifdef PLATFORM_DRIVER
 	retval = platform_driver_register(&PLATFORM_DRIVER);
 	if (retval < 0)
@@ -998,6 +1009,9 @@
 
 static void __exit ehci_hcd_cleanup(void)
 {
+#ifdef OF_PLATFORM_DRIVER
+	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+#endif
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
diff -ruN linux-2.6.orig/drivers/usb/host/ehci-ppc-of.c linux-2.6/drivers/usb/host/ehci-ppc-of.c
--- linux-2.6.orig/drivers/usb/host/ehci-ppc-of.c	1970-01-01 03:00:00.000000000 +0300
+++ linux-2.6/drivers/usb/host/ehci-ppc-of.c	2007-09-24 23:13:31.000000000 +0400
@@ -0,0 +1,243 @@
+/*
+ * EHCI HCD (Host Controller Driver) for USB.
+ *
+ * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
+ * Tested on AMCC PPC 440EPx
+ *
+ * Valentine Barshak <vbarshak@ru.mvista.com>
+ *
+ * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
+ * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/signal.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+/* called during probe() after chip reset completes */
+static int ehci_ppc_of_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int		retval;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci->sbrn = 0x20;
+	return ehci_reset(ehci);
+}
+
+
+static const struct hc_driver ehci_ppc_of_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "OF EHCI",
+	.hcd_priv_size = sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ehci_irq,
+	.flags = HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset = ehci_ppc_of_setup,
+	.start = ehci_run,
+	.stop = ehci_stop,
+	.shutdown = ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ehci_urb_enqueue,
+	.urb_dequeue = ehci_urb_dequeue,
+	.endpoint_disable = ehci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ehci_hub_status_data,
+	.hub_control = ehci_hub_control,
+#ifdef	CONFIG_PM
+	.hub_suspend = ehci_hub_suspend,
+	.hub_resume = ehci_hub_resume,
+#endif
+};
+
+
+/*
+ * 440EPx Errata USBH_3
+ * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
+ */
+#define PPC440EPX_EHCI0_INSREG_BMT	(0x1 << 0)
+static int __devinit
+ppc44x_enable_bmt(struct device_node *dn)
+{
+	__iomem u32 *insreg_virt;
+
+	insreg_virt = of_iomap(dn, 1);
+	if (!insreg_virt)
+		return  -EINVAL;
+
+	out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
+
+	iounmap(insreg_virt);
+	return 0;
+}
+
+
+static int __devinit
+ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
+{
+	struct device_node *dn = op->node;
+	struct usb_hcd *hcd;
+	struct ehci_hcd	*ehci;
+	struct resource res;
+	int irq;
+	int rv;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
+
+	rv = of_address_to_resource(dn, 0, &res);
+	if (rv)
+		return rv;
+
+	hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res.start;
+	hcd->rsrc_len = res.end - res.start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
+		rv = -EBUSY;
+		goto err_rmr;
+	}
+
+	irq = irq_of_parse_and_map(dn, 0);
+	if (irq == NO_IRQ) {
+		printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+		rv = -EBUSY;
+		goto err_irq;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		printk(KERN_ERR __FILE__ ": ioremap failed\n");
+		rv = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	ehci = hcd_to_ehci(hcd);
+
+	if (of_get_property(dn, "big-endian", NULL)) {
+		ehci->big_endian_mmio = 1;
+		ehci->big_endian_desc = 1;
+	}
+	if (of_get_property(dn, "big-endian-regs", NULL))
+		ehci->big_endian_mmio = 1;
+	if (of_get_property(dn, "big-endian-desc", NULL))
+		ehci->big_endian_desc = 1;
+
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs +
+			HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
+		rv = ppc44x_enable_bmt(dn);
+		ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
+				rv ? "NOT ": "");
+	}
+
+	rv = usb_add_hcd(hcd, irq, 0);
+	if (rv == 0)
+		return 0;
+
+	iounmap(hcd->regs);
+err_ioremap:
+	irq_dispose_mapping(irq);
+err_irq:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_rmr:
+	usb_put_hcd(hcd);
+
+	return rv;
+}
+
+
+static int ehci_hcd_ppc_of_remove(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+	dev_set_drvdata(&op->dev, NULL);
+
+	dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
+
+	usb_remove_hcd(hcd);
+
+	iounmap(hcd->regs);
+	irq_dispose_mapping(hcd->irq);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+
+static int ehci_hcd_ppc_of_shutdown(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+
+	return 0;
+}
+
+
+static struct of_device_id ehci_hcd_ppc_of_match[] = {
+	{
+		.compatible = "usb-ehci",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
+
+
+static struct of_platform_driver ehci_hcd_ppc_of_driver = {
+	.name		= "ppc-of-ehci",
+	.match_table	= ehci_hcd_ppc_of_match,
+	.probe		= ehci_hcd_ppc_of_probe,
+	.remove		= ehci_hcd_ppc_of_remove,
+	.shutdown 	= ehci_hcd_ppc_of_shutdown,
+#ifdef CONFIG_PM
+	/*.suspend	= ehci_hcd_ppc_of_drv_suspend,*/
+	/*.resume	= ehci_hcd_ppc_of_drv_resume,*/
+#endif
+	.driver		= {
+		.name	= "ppc-of-ehci",
+		.owner	= THIS_MODULE,
+	},
+};
+
diff -ruN linux-2.6.orig/drivers/usb/host/Kconfig linux-2.6/drivers/usb/host/Kconfig
--- linux-2.6.orig/drivers/usb/host/Kconfig	2007-09-24 14:55:44.000000000 +0400
+++ linux-2.6/drivers/usb/host/Kconfig	2007-09-24 23:07:16.000000000 +0400
@@ -84,6 +84,14 @@
 	---help---
 	  Variation of ARC USB block used in some Freescale chips.
 
+config USB_EHCI_HCD_PPC_OF
+	bool "EHCI support for PPC USB controller on OF platform bus"
+	depends on USB_EHCI_HCD && PPC_OF
+	default y
+	---help---
+	  Enables support for the USB controller PowerPC present on the
+	  OpenFirmware platform bus.
+
 config USB_ISP116X_HCD
 	tristate "ISP116X HCD support"
 	depends on USB

[PATCH 2/3] usb: ehci-ppc-of dts bindings.

From: Valentine Barshak <hidden>
Date: 2007-09-24 19:29:12

Adds EHCI OF bindings to documentation.

Signed-off-by: Valentine Barshak <redacted>
---
 Documentation/powerpc/booting-without-of.txt |   28 +++++++++++++++++++++++++++
 1 files changed, 28 insertions(+)

diff -ruN linux-2.6.orig/Documentation/powerpc/booting-without-of.txt linux-2.6/Documentation/powerpc/booting-without-of.txt
--- linux-2.6.orig/Documentation/powerpc/booting-without-of.txt	2007-09-24 14:55:04.000000000 +0400
+++ linux-2.6/Documentation/powerpc/booting-without-of.txt	2007-09-24 22:42:35.000000000 +0400
@@ -52,6 +52,7 @@
       i) Freescale QUICC Engine module (QE)
       j) CFI or JEDEC memory-mapped NOR flash
       k) Global Utilities Block
+      l) USB EHCI controllers
 
   VII - Specifying interrupt information for devices
     1) interrupts property
@@ -1848,6 +1849,33 @@
 		fsl,has-rstcr;
 	};
 
+  l) USB EHCI controllers
+
+  Required properties:
+  - compatible : should be "usb-ehci".
+  - reg : should contain at least address and length of the standard EHCI
+    register set for the device. Optional platform-dependent registers
+    (debug-port or other) can be also specified here, but only after
+    definition of standard EHCI registers.
+  - interrupts : one EHCI interrupt should be described here.
+  If device registers are implemented in big endian mode, the device
+  node should have "big-endian-regs" property.
+  If controller implementation operates with big endian descriptors,
+  "big-endian-desc" property should be specified.
+  If both big endian registers and descriptors are used by the controller
+  implementation, "big-endian" property can be specified instead of having
+  both "big-endian-regs" and "big-endian-desc".
+
+   Example (Sequoia 440EPx):
+	ehci@e0000300 {
+		compatible = "ibm,usb-ehci-440epx", "usb-ehci";
+		interrupt-parent = <&UIC0>;
+		interrupts = <1a 4>;
+		reg = <0 e0000300 90 0 e0000390 70>;
+		big-endian;
+	};
+
+
    More devices will be defined as this spec matures.
 
 VII - Specifying interrupt information for devices

[PATCH 3/3] Add PowerPC 440EPx Sequoia ehci dts entry

From: Valentine Barshak <hidden>
Date: 2007-09-24 19:31:04

Adds USB EHCI entry to PowerPC 440EPx Sequoia DTS.

Signed-off-by: Valentine Barshak <redacted>
---
 arch/powerpc/boot/dts/sequoia.dts |    8 ++++++++
 1 files changed, 8 insertions(+)

diff -ruN linux-2.6.orig/arch/powerpc/boot/dts/sequoia.dts linux-2.6/arch/powerpc/boot/dts/sequoia.dts
--- linux-2.6.orig/arch/powerpc/boot/dts/sequoia.dts	2007-09-24 14:55:15.000000000 +0400
+++ linux-2.6/arch/powerpc/boot/dts/sequoia.dts	2007-09-24 21:50:24.000000000 +0400
@@ -122,6 +122,14 @@
 			interrupt-map-mask = <ffffffff>;
 		};
 
+		USB0: ehci@e0000300 {
+			compatible = "ibm,usb-ehci-440epx", "usb-ehci";
+			interrupt-parent = <&UIC0>;
+			interrupts = <1a 4>;
+			reg = <0 e0000300 90 0 e0000390 70>;
+			big-endian;
+		};
+
 		POB0: opb {
 		  	compatible = "ibm,opb-440epx", "ibm,opb";
 			#address-cells = <1>;

Re: [linux-usb-devel] [PATCH 0/3] usb: ehci ppc device-tree-aware driver

From: David Brownell <hidden>
Date: 2007-10-10 06:34:08

On Monday 24 September 2007, Valentine Barshak wrote:
Some PowerPC systems have a built-in EHCI controller.
This is a device tree aware version of the EHCI controller driver.
Currently it's been tested on the PowerPC 440EPx Sequoia board.
Other platforms can be added later.
The code is based on the ehci-ppc-soc driver by Stefan Roese [off-list ref].
Do PPC folk sign off on how this is done?

I don't follow all the ins/outs of the OF devtree stuff...

Re: [linux-usb-devel] [PATCH 0/3] usb: ehci ppc device-tree-aware driver

From: Arnd Bergmann <arnd@arndb.de>
Date: 2007-10-10 08:16:22

On Wednesday 10 October 2007, David Brownell wrote:
On Monday 24 September 2007, Valentine Barshak wrote:
quoted
Some PowerPC systems have a built-in EHCI controller.
This is a device tree aware version of the EHCI controller driver.
Currently it's been tested on the PowerPC 440EPx Sequoia board.
Other platforms can be added later.
The code is based on the ehci-ppc-soc driver by Stefan Roese [off-list ref].
Do PPC folk sign off on how this is done?

I don't follow all the ins/outs of the OF devtree stuff...
The driver looks good to me, both the interaction with the of_platform_bus
layer and the handling of I/O addresses. I haven't actually tried running
it, but I'm rather confident that if it works on the Sequoia, it should
also do the right thing on any other powerpc system that has an EHCI on
some other (non-PCI) bus.

Acked-by: Arnd Bergmann <arnd@arndb.de>

Re: [linux-usb-devel] [PATCH 0/3] usb: ehci ppc device-tree-aware driver

From: Stefan Roese <sr@denx.de>
Date: 2007-10-10 08:29:45

On Wednesday 10 October 2007, Arnd Bergmann wrote:
quoted
Do PPC folk sign off on how this is done?

I don't follow all the ins/outs of the OF devtree stuff...
The driver looks good to me, both the interaction with the of_platform_bus
layer and the handling of I/O addresses. I haven't actually tried running
it, but I'm rather confident that if it works on the Sequoia, it should
also do the right thing on any other powerpc system that has an EHCI on
some other (non-PCI) bus.

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Stefan Roese <sr@denx.de>

Best regards,
Stefan

Re: [linux-usb-devel] [PATCH 0/3] usb: ehci ppc device-tree-aware driver

From: Josh Boyer <hidden>
Date: 2007-10-23 15:45:36

On Wed, 10 Oct 2007 10:30:02 +0200
Stefan Roese [off-list ref] wrote:
On Wednesday 10 October 2007, Arnd Bergmann wrote:
quoted
quoted
Do PPC folk sign off on how this is done?

I don't follow all the ins/outs of the OF devtree stuff...
The driver looks good to me, both the interaction with the of_platform_bus
layer and the handling of I/O addresses. I haven't actually tried running
it, but I'm rather confident that if it works on the Sequoia, it should
also do the right thing on any other powerpc system that has an EHCI on
some other (non-PCI) bus.

Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Stefan Roese <sr@denx.de>
David, were you going to pull in the echi-ppc-of driver (patch 1 of
this series) for 2.6.24?  Just trying to figure out if I need to pull
the other two patches into my tree.

josh
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help