diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/isp1760-hcd.c | 17 | ||||
-rw-r--r-- | drivers/usb/host/isp1760-hcd.h | 2 | ||||
-rw-r--r-- | drivers/usb/host/isp1760-if.c | 68 |
3 files changed, 72 insertions, 15 deletions
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 5b08bd743acc..27dfab80ed8f 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/timer.h> | 24 | #include <linux/timer.h> |
25 | #include <asm/unaligned.h> | 25 | #include <asm/unaligned.h> |
26 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
27 | #include <linux/gpio.h> | ||
27 | 28 | ||
28 | #include "isp1760-hcd.h" | 29 | #include "isp1760-hcd.h" |
29 | 30 | ||
@@ -48,6 +49,8 @@ struct isp1760_hcd { | |||
48 | unsigned long reset_done; | 49 | unsigned long reset_done; |
49 | unsigned long next_statechange; | 50 | unsigned long next_statechange; |
50 | unsigned int devflags; | 51 | unsigned int devflags; |
52 | |||
53 | int rst_gpio; | ||
51 | }; | 54 | }; |
52 | 55 | ||
53 | static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) | 56 | static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) |
@@ -433,6 +436,18 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) | |||
433 | int result; | 436 | int result; |
434 | u32 scratch, hwmode; | 437 | u32 scratch, hwmode; |
435 | 438 | ||
439 | /* low-level chip reset */ | ||
440 | if (gpio_is_valid(priv->rst_gpio)) { | ||
441 | unsigned int rst_lvl; | ||
442 | |||
443 | rst_lvl = (priv->devflags & | ||
444 | ISP1760_FLAG_RESET_ACTIVE_HIGH) ? 1 : 0; | ||
445 | |||
446 | gpio_set_value(priv->rst_gpio, rst_lvl); | ||
447 | mdelay(50); | ||
448 | gpio_set_value(priv->rst_gpio, !rst_lvl); | ||
449 | } | ||
450 | |||
436 | /* Setup HW Mode Control: This assumes a level active-low interrupt */ | 451 | /* Setup HW Mode Control: This assumes a level active-low interrupt */ |
437 | hwmode = HW_DATA_BUS_32BIT; | 452 | hwmode = HW_DATA_BUS_32BIT; |
438 | 453 | ||
@@ -2207,6 +2222,7 @@ void deinit_kmem_cache(void) | |||
2207 | 2222 | ||
2208 | struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, | 2223 | struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, |
2209 | int irq, unsigned long irqflags, | 2224 | int irq, unsigned long irqflags, |
2225 | int rst_gpio, | ||
2210 | struct device *dev, const char *busname, | 2226 | struct device *dev, const char *busname, |
2211 | unsigned int devflags) | 2227 | unsigned int devflags) |
2212 | { | 2228 | { |
@@ -2226,6 +2242,7 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, | |||
2226 | 2242 | ||
2227 | priv = hcd_to_priv(hcd); | 2243 | priv = hcd_to_priv(hcd); |
2228 | priv->devflags = devflags; | 2244 | priv->devflags = devflags; |
2245 | priv->rst_gpio = rst_gpio; | ||
2229 | init_memory(priv); | 2246 | init_memory(priv); |
2230 | hcd->regs = ioremap(res_start, res_len); | 2247 | hcd->regs = ioremap(res_start, res_len); |
2231 | if (!hcd->regs) { | 2248 | if (!hcd->regs) { |
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index fda0f2d54e3d..33dc79ccaa6b 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h | |||
@@ -4,6 +4,7 @@ | |||
4 | /* exports for if */ | 4 | /* exports for if */ |
5 | struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, | 5 | struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, |
6 | int irq, unsigned long irqflags, | 6 | int irq, unsigned long irqflags, |
7 | int rst_gpio, | ||
7 | struct device *dev, const char *busname, | 8 | struct device *dev, const char *busname, |
8 | unsigned int devflags); | 9 | unsigned int devflags); |
9 | int init_kmem_once(void); | 10 | int init_kmem_once(void); |
@@ -126,6 +127,7 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, | |||
126 | #define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ | 127 | #define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ |
127 | #define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */ | 128 | #define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */ |
128 | #define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */ | 129 | #define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */ |
130 | #define ISP1760_FLAG_RESET_ACTIVE_HIGH 0x80000000 /* RESET GPIO active high */ | ||
129 | 131 | ||
130 | /* chip memory management */ | 132 | /* chip memory management */ |
131 | struct memory_chunk { | 133 | struct memory_chunk { |
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 |
34 | struct isp1760 { | ||
35 | struct usb_hcd *hcd; | ||
36 | int rst_gpio; | ||
37 | }; | ||
38 | |||
32 | static int of_isp1760_probe(struct platform_device *dev) | 39 | static 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 | ||
122 | free_gpio: | ||
123 | if (gpio_is_valid(drvdata->rst_gpio)) | ||
124 | gpio_free(drvdata->rst_gpio); | ||
94 | release_reg: | 125 | release_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 | ||
99 | static int of_isp1760_remove(struct platform_device *dev) | 131 | static 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; |