aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2013-03-12 06:44:48 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-15 14:51:47 -0400
commita1ae0affee119e6deb937d157aa8b43319c1d6f3 (patch)
tree217067f110ad543c5500eeec55c9781ba272406c
parent5867320dec346c2dc26f224f876d780111ca149d (diff)
USB: ehci-omap: Add device tree support and binding information
Allows the OMAP EHCI controller to be specified via device tree. Signed-off-by: Roger Quadros <rogerq@ti.com> Reviewed-by: Mark Rutland <mark.rutland@arm.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/devicetree/bindings/usb/ehci-omap.txt32
-rw-r--r--drivers/usb/host/ehci-omap.c37
2 files changed, 68 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/usb/ehci-omap.txt b/Documentation/devicetree/bindings/usb/ehci-omap.txt
new file mode 100644
index 000000000000..485a9a1efa7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ehci-omap.txt
@@ -0,0 +1,32 @@
1OMAP HS USB EHCI controller
2
3This device is usually the child of the omap-usb-host
4Documentation/devicetree/bindings/mfd/omap-usb-host.txt
5
6Required properties:
7
8- compatible: should be "ti,ehci-omap"
9- reg: should contain one register range i.e. start and length
10- interrupts: description of the interrupt line
11
12Optional properties:
13
14- phys: list of phandles to PHY nodes.
15 This property is required if at least one of the ports are in
16 PHY mode i.e. OMAP_EHCI_PORT_MODE_PHY
17
18To specify the port mode, see
19Documentation/devicetree/bindings/mfd/omap-usb-host.txt
20
21Example for OMAP4:
22
23usbhsehci: ehci@4a064c00 {
24 compatible = "ti,ehci-omap", "usb-ehci";
25 reg = <0x4a064c00 0x400>;
26 interrupts = <0 77 0x4>;
27};
28
29&usbhsehci {
30 phys = <&hsusb1_phy 0 &hsusb3_phy>;
31};
32
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 7d05cce62037..45cd01e29252 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -48,6 +48,8 @@
48#include <linux/clk.h> 48#include <linux/clk.h>
49#include <linux/usb.h> 49#include <linux/usb.h>
50#include <linux/usb/hcd.h> 50#include <linux/usb/hcd.h>
51#include <linux/of.h>
52#include <linux/dma-mapping.h>
51 53
52#include "ehci.h" 54#include "ehci.h"
53 55
@@ -121,6 +123,8 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
121 .extra_priv_size = sizeof(struct omap_hcd), 123 .extra_priv_size = sizeof(struct omap_hcd),
122}; 124};
123 125
126static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);
127
124/** 128/**
125 * ehci_hcd_omap_probe - initialize TI-based HCDs 129 * ehci_hcd_omap_probe - initialize TI-based HCDs
126 * 130 *
@@ -148,6 +152,17 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
148 return -ENODEV; 152 return -ENODEV;
149 } 153 }
150 154
155 /* For DT boot, get platform data from parent. i.e. usbhshost */
156 if (dev->of_node) {
157 pdata = dev->parent->platform_data;
158 dev->platform_data = pdata;
159 }
160
161 if (!pdata) {
162 dev_err(dev, "Missing platform data\n");
163 return -ENODEV;
164 }
165
151 irq = platform_get_irq(pdev, 0); 166 irq = platform_get_irq(pdev, 0);
152 if (irq < 0) { 167 if (irq < 0) {
153 dev_err(dev, "EHCI irq failed\n"); 168 dev_err(dev, "EHCI irq failed\n");
@@ -159,6 +174,14 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
159 if (IS_ERR(regs)) 174 if (IS_ERR(regs))
160 return PTR_ERR(regs); 175 return PTR_ERR(regs);
161 176
177 /*
178 * Right now device-tree probed devices don't get dma_mask set.
179 * Since shared usb code relies on it, set it here for now.
180 * Once we have dma capability bindings this can go away.
181 */
182 if (!pdev->dev.dma_mask)
183 pdev->dev.dma_mask = &omap_ehci_dma_mask;
184
162 hcd = usb_create_hcd(&ehci_omap_hc_driver, dev, 185 hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
163 dev_name(dev)); 186 dev_name(dev));
164 if (!hcd) { 187 if (!hcd) {
@@ -183,7 +206,10 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
183 continue; 206 continue;
184 207
185 /* get the PHY device */ 208 /* get the PHY device */
186 phy = devm_usb_get_phy_dev(dev, i); 209 if (dev->of_node)
210 phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
211 else
212 phy = devm_usb_get_phy_dev(dev, i);
187 if (IS_ERR(phy) || !phy) { 213 if (IS_ERR(phy) || !phy) {
188 ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV; 214 ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
189 dev_err(dev, "Can't get PHY device for port %d: %d\n", 215 dev_err(dev, "Can't get PHY device for port %d: %d\n",
@@ -273,6 +299,13 @@ static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
273 hcd->driver->shutdown(hcd); 299 hcd->driver->shutdown(hcd);
274} 300}
275 301
302static const struct of_device_id omap_ehci_dt_ids[] = {
303 { .compatible = "ti,ehci-omap" },
304 { }
305};
306
307MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
308
276static struct platform_driver ehci_hcd_omap_driver = { 309static struct platform_driver ehci_hcd_omap_driver = {
277 .probe = ehci_hcd_omap_probe, 310 .probe = ehci_hcd_omap_probe,
278 .remove = ehci_hcd_omap_remove, 311 .remove = ehci_hcd_omap_remove,
@@ -281,6 +314,7 @@ static struct platform_driver ehci_hcd_omap_driver = {
281 /*.resume = ehci_hcd_omap_resume, */ 314 /*.resume = ehci_hcd_omap_resume, */
282 .driver = { 315 .driver = {
283 .name = hcd_name, 316 .name = hcd_name,
317 .of_match_table = of_match_ptr(omap_ehci_dt_ids),
284 } 318 }
285}; 319};
286 320
@@ -307,6 +341,7 @@ module_exit(ehci_omap_cleanup);
307MODULE_ALIAS("platform:ehci-omap"); 341MODULE_ALIAS("platform:ehci-omap");
308MODULE_AUTHOR("Texas Instruments, Inc."); 342MODULE_AUTHOR("Texas Instruments, Inc.");
309MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); 343MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
344MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
310 345
311MODULE_DESCRIPTION(DRIVER_DESC); 346MODULE_DESCRIPTION(DRIVER_DESC);
312MODULE_LICENSE("GPL"); 347MODULE_LICENSE("GPL");