diff options
| -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; |
