aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/isp1760-if.c
diff options
context:
space:
mode:
authorJoachim Foerster <joachim.foerster@missinglinkelectronics.com>2011-10-19 08:18:41 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-10-19 16:29:06 -0400
commit3a7655fcb210b349111251689d0a56b7250885ea (patch)
treeb909f3f73d89d1af8807036a3922a19aca41b514 /drivers/usb/host/isp1760-if.c
parent0f8fd43c42f2cc249943be76a4db0d058c16b6dc (diff)
usb/isp1760: Allow to optionally trigger low-level chip reset via GPIOLIB.
Properly triggering the reset wire is necessary with the ISP1761 used on Terasic DE4 Altera-FPGA boards using a NIOS2 processor, for example. This is an optional implementation for the OF binding only. The other bindings just pass an invalid GPIO to the isp1760_register() routine. Example, usage in DTS: gpios = <&pio_isp1761rst_0 0 1>; to point to a GPIO controller from within the ISP1761 node: GPIO 0, active low. Signed-off-by: Joachim Foerster <joachim.foerster@missinglinkelectronics.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/isp1760-if.c')
-rw-r--r--drivers/usb/host/isp1760-if.c68
1 files changed, 53 insertions, 15 deletions
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index 791792db6e12..2c7fc830c9e4 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -18,10 +18,12 @@
18#include "isp1760-hcd.h" 18#include "isp1760-hcd.h"
19 19
20#ifdef CONFIG_OF 20#ifdef CONFIG_OF
21#include <linux/slab.h>
21#include <linux/of.h> 22#include <linux/of.h>
22#include <linux/of_platform.h> 23#include <linux/of_platform.h>
23#include <linux/of_address.h> 24#include <linux/of_address.h>
24#include <linux/of_irq.h> 25#include <linux/of_irq.h>
26#include <linux/of_gpio.h>
25#endif 27#endif
26 28
27#ifdef CONFIG_PCI 29#ifdef CONFIG_PCI
@@ -29,9 +31,14 @@
29#endif 31#endif
30 32
31#ifdef CONFIG_OF 33#ifdef CONFIG_OF
34struct isp1760 {
35 struct usb_hcd *hcd;
36 int rst_gpio;
37};
38
32static int of_isp1760_probe(struct platform_device *dev) 39static int of_isp1760_probe(struct platform_device *dev)
33{ 40{
34 struct usb_hcd *hcd; 41 struct isp1760 *drvdata;
35 struct device_node *dp = dev->dev.of_node; 42 struct device_node *dp = dev->dev.of_node;
36 struct resource *res; 43 struct resource *res;
37 struct resource memory; 44 struct resource memory;
@@ -41,6 +48,11 @@ static int of_isp1760_probe(struct platform_device *dev)
41 int ret; 48 int ret;
42 const unsigned int *prop; 49 const unsigned int *prop;
43 unsigned int devflags = 0; 50 unsigned int devflags = 0;
51 enum of_gpio_flags gpio_flags;
52
53 drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
54 if (!drvdata)
55 return -ENOMEM;
44 56
45 ret = of_address_to_resource(dp, 0, &memory); 57 ret = of_address_to_resource(dp, 0, &memory);
46 if (ret) 58 if (ret)
@@ -80,32 +92,57 @@ static int of_isp1760_probe(struct platform_device *dev)
80 if (of_get_property(dp, "dreq-polarity", NULL) != NULL) 92 if (of_get_property(dp, "dreq-polarity", NULL) != NULL)
81 devflags |= ISP1760_FLAG_DREQ_POL_HIGH; 93 devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
82 94
83 hcd = isp1760_register(memory.start, res_len, virq, 95 drvdata->rst_gpio = of_get_gpio_flags(dp, 0, &gpio_flags);
84 IRQF_SHARED, &dev->dev, dev_name(&dev->dev), 96 if (gpio_is_valid(drvdata->rst_gpio)) {
85 devflags); 97 ret = gpio_request(drvdata->rst_gpio, dev_name(&dev->dev));
86 if (IS_ERR(hcd)) { 98 if (!ret) {
87 ret = PTR_ERR(hcd); 99 if (!(gpio_flags & OF_GPIO_ACTIVE_LOW)) {
88 goto release_reg; 100 devflags |= ISP1760_FLAG_RESET_ACTIVE_HIGH;
101 gpio_direction_output(drvdata->rst_gpio, 0);
102 } else {
103 gpio_direction_output(drvdata->rst_gpio, 1);
104 }
105 } else {
106 drvdata->rst_gpio = ret;
107 }
89 } 108 }
90 109
91 dev_set_drvdata(&dev->dev, hcd); 110 drvdata->hcd = isp1760_register(memory.start, res_len, virq,
111 IRQF_SHARED, drvdata->rst_gpio,
112 &dev->dev, dev_name(&dev->dev),
113 devflags);
114 if (IS_ERR(drvdata->hcd)) {
115 ret = PTR_ERR(drvdata->hcd);
116 goto free_gpio;
117 }
118
119 dev_set_drvdata(&dev->dev, drvdata);
92 return ret; 120 return ret;
93 121
122free_gpio:
123 if (gpio_is_valid(drvdata->rst_gpio))
124 gpio_free(drvdata->rst_gpio);
94release_reg: 125release_reg:
95 release_mem_region(memory.start, res_len); 126 release_mem_region(memory.start, res_len);
127 kfree(drvdata);
96 return ret; 128 return ret;
97} 129}
98 130
99static int of_isp1760_remove(struct platform_device *dev) 131static int of_isp1760_remove(struct platform_device *dev)
100{ 132{
101 struct usb_hcd *hcd = dev_get_drvdata(&dev->dev); 133 struct isp1760 *drvdata = dev_get_drvdata(&dev->dev);
102 134
103 dev_set_drvdata(&dev->dev, NULL); 135 dev_set_drvdata(&dev->dev, NULL);
104 136
105 usb_remove_hcd(hcd); 137 usb_remove_hcd(drvdata->hcd);
106 iounmap(hcd->regs); 138 iounmap(drvdata->hcd->regs);
107 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 139 release_mem_region(drvdata->hcd->rsrc_start, drvdata->hcd->rsrc_len);
108 usb_put_hcd(hcd); 140 usb_put_hcd(drvdata->hcd);
141
142 if (gpio_is_valid(drvdata->rst_gpio))
143 gpio_free(drvdata->rst_gpio);
144
145 kfree(drvdata);
109 return 0; 146 return 0;
110} 147}
111 148
@@ -242,7 +279,7 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev,
242 279
243 dev->dev.dma_mask = NULL; 280 dev->dev.dma_mask = NULL;
244 hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq, 281 hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq,
245 IRQF_SHARED, &dev->dev, dev_name(&dev->dev), 282 IRQF_SHARED, -ENOENT, &dev->dev, dev_name(&dev->dev),
246 devflags); 283 devflags);
247 if (IS_ERR(hcd)) { 284 if (IS_ERR(hcd)) {
248 ret_status = -ENODEV; 285 ret_status = -ENODEV;
@@ -353,7 +390,8 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev)
353 } 390 }
354 391
355 hcd = isp1760_register(mem_res->start, mem_size, irq_res->start, 392 hcd = isp1760_register(mem_res->start, mem_size, irq_res->start,
356 irqflags, &pdev->dev, dev_name(&pdev->dev), devflags); 393 irqflags, -ENOENT,
394 &pdev->dev, dev_name(&pdev->dev), devflags);
357 if (IS_ERR(hcd)) { 395 if (IS_ERR(hcd)) {
358 pr_warning("isp1760: Failed to register the HCD device\n"); 396 pr_warning("isp1760: Failed to register the HCD device\n");
359 ret = -ENODEV; 397 ret = -ENODEV;