diff options
-rw-r--r-- | drivers/usb/host/isp1760-hcd.c | 67 | ||||
-rw-r--r-- | drivers/usb/host/isp1760-hcd.h | 20 | ||||
-rw-r--r-- | drivers/usb/host/isp1760-if.c | 35 |
3 files changed, 104 insertions, 18 deletions
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index d318af39c27f..c858f2adb929 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
@@ -38,6 +38,7 @@ struct isp1760_hcd { | |||
38 | unsigned i_thresh; | 38 | unsigned i_thresh; |
39 | unsigned long reset_done; | 39 | unsigned long reset_done; |
40 | unsigned long next_statechange; | 40 | unsigned long next_statechange; |
41 | unsigned int devflags; | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) | 44 | static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) |
@@ -378,9 +379,31 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) | |||
378 | { | 379 | { |
379 | struct isp1760_hcd *priv = hcd_to_priv(hcd); | 380 | struct isp1760_hcd *priv = hcd_to_priv(hcd); |
380 | int result; | 381 | int result; |
381 | u32 scratch; | 382 | u32 scratch, hwmode; |
383 | |||
384 | /* Setup HW Mode Control: This assumes a level active-low interrupt */ | ||
385 | hwmode = HW_DATA_BUS_32BIT; | ||
386 | |||
387 | if (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) | ||
388 | hwmode &= ~HW_DATA_BUS_32BIT; | ||
389 | if (priv->devflags & ISP1760_FLAG_ANALOG_OC) | ||
390 | hwmode |= HW_ANA_DIGI_OC; | ||
391 | if (priv->devflags & ISP1760_FLAG_DACK_POL_HIGH) | ||
392 | hwmode |= HW_DACK_POL_HIGH; | ||
393 | if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH) | ||
394 | hwmode |= HW_DREQ_POL_HIGH; | ||
395 | |||
396 | /* | ||
397 | * We have to set this first in case we're in 16-bit mode. | ||
398 | * Write it twice to ensure correct upper bits if switching | ||
399 | * to 16-bit mode. | ||
400 | */ | ||
401 | isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL); | ||
402 | isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL); | ||
382 | 403 | ||
383 | isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG); | 404 | isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG); |
405 | /* Change bus pattern */ | ||
406 | scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG); | ||
384 | scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG); | 407 | scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG); |
385 | if (scratch != 0xdeadbabe) { | 408 | if (scratch != 0xdeadbabe) { |
386 | printk(KERN_ERR "ISP1760: Scratch test failed.\n"); | 409 | printk(KERN_ERR "ISP1760: Scratch test failed.\n"); |
@@ -403,17 +426,29 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) | |||
403 | 426 | ||
404 | /* Step 11 passed */ | 427 | /* Step 11 passed */ |
405 | 428 | ||
406 | isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG); | 429 | isp1760_info(priv, "bus width: %d, oc: %s\n", |
407 | isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE); | 430 | (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ? |
431 | 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ? | ||
432 | "analog" : "digital"); | ||
408 | 433 | ||
409 | /* ATL reset */ | 434 | /* ATL reset */ |
410 | scratch = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); | 435 | isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL); |
411 | isp1760_writel(scratch | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL); | ||
412 | mdelay(10); | 436 | mdelay(10); |
413 | isp1760_writel(scratch, hcd->regs + HC_HW_MODE_CTRL); | 437 | isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL); |
414 | 438 | ||
415 | isp1760_writel(PORT1_POWER | PORT1_INIT2, hcd->regs + HC_PORT1_CTRL); | 439 | isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG); |
416 | mdelay(10); | 440 | isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE); |
441 | |||
442 | /* | ||
443 | * PORT 1 Control register of the ISP1760 is the OTG control | ||
444 | * register on ISP1761. | ||
445 | */ | ||
446 | if (!(priv->devflags & ISP1760_FLAG_ISP1761) && | ||
447 | !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) { | ||
448 | isp1760_writel(PORT1_POWER | PORT1_INIT2, | ||
449 | hcd->regs + HC_PORT1_CTRL); | ||
450 | mdelay(10); | ||
451 | } | ||
417 | 452 | ||
418 | priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS); | 453 | priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS); |
419 | 454 | ||
@@ -453,8 +488,7 @@ static int isp1760_run(struct usb_hcd *hcd) | |||
453 | hcd->state = HC_STATE_RUNNING; | 488 | hcd->state = HC_STATE_RUNNING; |
454 | isp1760_enable_interrupts(hcd); | 489 | isp1760_enable_interrupts(hcd); |
455 | temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); | 490 | temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); |
456 | temp |= FINAL_HW_CONFIG; | 491 | isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL); |
457 | isp1760_writel(temp, hcd->regs + HC_HW_MODE_CTRL); | ||
458 | 492 | ||
459 | command = isp1760_readl(hcd->regs + HC_USBCMD); | 493 | command = isp1760_readl(hcd->regs + HC_USBCMD); |
460 | command &= ~(CMD_LRESET|CMD_RESET); | 494 | command &= ~(CMD_LRESET|CMD_RESET); |
@@ -2112,6 +2146,7 @@ static int isp1760_get_frame(struct usb_hcd *hcd) | |||
2112 | static void isp1760_stop(struct usb_hcd *hcd) | 2146 | static void isp1760_stop(struct usb_hcd *hcd) |
2113 | { | 2147 | { |
2114 | struct isp1760_hcd *priv = hcd_to_priv(hcd); | 2148 | struct isp1760_hcd *priv = hcd_to_priv(hcd); |
2149 | u32 temp; | ||
2115 | 2150 | ||
2116 | isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, | 2151 | isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, |
2117 | NULL, 0); | 2152 | NULL, 0); |
@@ -2120,7 +2155,8 @@ static void isp1760_stop(struct usb_hcd *hcd) | |||
2120 | spin_lock_irq(&priv->lock); | 2155 | spin_lock_irq(&priv->lock); |
2121 | ehci_reset(priv); | 2156 | ehci_reset(priv); |
2122 | /* Disable IRQ */ | 2157 | /* Disable IRQ */ |
2123 | isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL); | 2158 | temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); |
2159 | isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL); | ||
2124 | spin_unlock_irq(&priv->lock); | 2160 | spin_unlock_irq(&priv->lock); |
2125 | 2161 | ||
2126 | isp1760_writel(0, hcd->regs + HC_CONFIGFLAG); | 2162 | isp1760_writel(0, hcd->regs + HC_CONFIGFLAG); |
@@ -2128,10 +2164,11 @@ static void isp1760_stop(struct usb_hcd *hcd) | |||
2128 | 2164 | ||
2129 | static void isp1760_shutdown(struct usb_hcd *hcd) | 2165 | static void isp1760_shutdown(struct usb_hcd *hcd) |
2130 | { | 2166 | { |
2131 | u32 command; | 2167 | u32 command, temp; |
2132 | 2168 | ||
2133 | isp1760_stop(hcd); | 2169 | isp1760_stop(hcd); |
2134 | isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL); | 2170 | temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL); |
2171 | isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL); | ||
2135 | 2172 | ||
2136 | command = isp1760_readl(hcd->regs + HC_USBCMD); | 2173 | command = isp1760_readl(hcd->regs + HC_USBCMD); |
2137 | command &= ~CMD_RUN; | 2174 | command &= ~CMD_RUN; |
@@ -2183,7 +2220,8 @@ void deinit_kmem_cache(void) | |||
2183 | } | 2220 | } |
2184 | 2221 | ||
2185 | struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, | 2222 | struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, |
2186 | u64 irqflags, struct device *dev, const char *busname) | 2223 | u64 irqflags, struct device *dev, const char *busname, |
2224 | unsigned int devflags) | ||
2187 | { | 2225 | { |
2188 | struct usb_hcd *hcd; | 2226 | struct usb_hcd *hcd; |
2189 | struct isp1760_hcd *priv; | 2227 | struct isp1760_hcd *priv; |
@@ -2200,6 +2238,7 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, | |||
2200 | return ERR_PTR(-ENOMEM); | 2238 | return ERR_PTR(-ENOMEM); |
2201 | 2239 | ||
2202 | priv = hcd_to_priv(hcd); | 2240 | priv = hcd_to_priv(hcd); |
2241 | priv->devflags = devflags; | ||
2203 | init_memory(priv); | 2242 | init_memory(priv); |
2204 | hcd->regs = ioremap(res_start, res_len); | 2243 | hcd->regs = ioremap(res_start, res_len); |
2205 | if (!hcd->regs) { | 2244 | if (!hcd->regs) { |
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 3d86d0f6b147..6473dd86993c 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h | |||
@@ -3,7 +3,8 @@ | |||
3 | 3 | ||
4 | /* exports for if */ | 4 | /* exports for if */ |
5 | struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, | 5 | struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, |
6 | u64 irqflags, struct device *dev, const char *busname); | 6 | u64 irqflags, struct device *dev, const char *busname, |
7 | unsigned int devflags); | ||
7 | int init_kmem_once(void); | 8 | int init_kmem_once(void); |
8 | void deinit_kmem_cache(void); | 9 | void deinit_kmem_cache(void); |
9 | 10 | ||
@@ -31,6 +32,7 @@ void deinit_kmem_cache(void); | |||
31 | /* Configuration Register */ | 32 | /* Configuration Register */ |
32 | #define HC_HW_MODE_CTRL 0x300 | 33 | #define HC_HW_MODE_CTRL 0x300 |
33 | #define ALL_ATX_RESET (1 << 31) | 34 | #define ALL_ATX_RESET (1 << 31) |
35 | #define HW_ANA_DIGI_OC (1 << 15) | ||
34 | #define HW_DATA_BUS_32BIT (1 << 8) | 36 | #define HW_DATA_BUS_32BIT (1 << 8) |
35 | #define HW_DACK_POL_HIGH (1 << 6) | 37 | #define HW_DACK_POL_HIGH (1 << 6) |
36 | #define HW_DREQ_POL_HIGH (1 << 5) | 38 | #define HW_DREQ_POL_HIGH (1 << 5) |
@@ -56,13 +58,14 @@ void deinit_kmem_cache(void); | |||
56 | #define PORT1_POWER (3 << 3) | 58 | #define PORT1_POWER (3 << 3) |
57 | #define PORT1_INIT1 (1 << 7) | 59 | #define PORT1_INIT1 (1 << 7) |
58 | #define PORT1_INIT2 (1 << 23) | 60 | #define PORT1_INIT2 (1 << 23) |
61 | #define HW_OTG_CTRL_SET 0x374 | ||
62 | #define HW_OTG_CTRL_CLR 0x376 | ||
59 | 63 | ||
60 | /* Interrupt Register */ | 64 | /* Interrupt Register */ |
61 | #define HC_INTERRUPT_REG 0x310 | 65 | #define HC_INTERRUPT_REG 0x310 |
62 | 66 | ||
63 | #define HC_INTERRUPT_ENABLE 0x314 | 67 | #define HC_INTERRUPT_ENABLE 0x314 |
64 | #define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT) | 68 | #define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT) |
65 | #define FINAL_HW_CONFIG (HW_GLOBAL_INTR_EN | HW_DATA_BUS_32BIT) | ||
66 | 69 | ||
67 | #define HC_ISO_INT (1 << 9) | 70 | #define HC_ISO_INT (1 << 9) |
68 | #define HC_ATL_INT (1 << 8) | 71 | #define HC_ATL_INT (1 << 8) |
@@ -122,6 +125,19 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, | |||
122 | #define isp1760_err(priv, fmt, args...) \ | 125 | #define isp1760_err(priv, fmt, args...) \ |
123 | dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args) | 126 | dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args) |
124 | 127 | ||
128 | /* | ||
129 | * Device flags that can vary from board to board. All of these | ||
130 | * indicate the most "atypical" case, so that a devflags of 0 is | ||
131 | * a sane default configuration. | ||
132 | */ | ||
133 | #define ISP1760_FLAG_PORT1_DIS 0x00000001 /* Port 1 disabled */ | ||
134 | #define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */ | ||
135 | #define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */ | ||
136 | #define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */ | ||
137 | #define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */ | ||
138 | #define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */ | ||
139 | #define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ | ||
140 | |||
125 | /* chip memory management */ | 141 | /* chip memory management */ |
126 | struct memory_chunk { | 142 | struct memory_chunk { |
127 | unsigned int start; | 143 | unsigned int start; |
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index ad833661ff34..051ef7b6bdc6 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -35,6 +35,8 @@ static int of_isp1760_probe(struct of_device *dev, | |||
35 | int virq; | 35 | int virq; |
36 | u64 res_len; | 36 | u64 res_len; |
37 | int ret; | 37 | int ret; |
38 | const unsigned int *prop; | ||
39 | unsigned int devflags = 0; | ||
38 | 40 | ||
39 | ret = of_address_to_resource(dp, 0, &memory); | 41 | ret = of_address_to_resource(dp, 0, &memory); |
40 | if (ret) | 42 | if (ret) |
@@ -55,8 +57,32 @@ static int of_isp1760_probe(struct of_device *dev, | |||
55 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | 57 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, |
56 | oirq.size); | 58 | oirq.size); |
57 | 59 | ||
60 | if (of_device_is_compatible(dp, "nxp,usb-isp1761")) | ||
61 | devflags |= ISP1760_FLAG_ISP1761; | ||
62 | |||
63 | if (of_get_property(dp, "port1-disable", NULL) != NULL) | ||
64 | devflags |= ISP1760_FLAG_PORT1_DIS; | ||
65 | |||
66 | /* Some systems wire up only 16 of the 32 data lines */ | ||
67 | prop = of_get_property(dp, "bus-width", NULL); | ||
68 | if (prop && *prop == 16) | ||
69 | devflags |= ISP1760_FLAG_BUS_WIDTH_16; | ||
70 | |||
71 | if (of_get_property(dp, "port1-otg", NULL) != NULL) | ||
72 | devflags |= ISP1760_FLAG_OTG_EN; | ||
73 | |||
74 | if (of_get_property(dp, "analog-oc", NULL) != NULL) | ||
75 | devflags |= ISP1760_FLAG_ANALOG_OC; | ||
76 | |||
77 | if (of_get_property(dp, "dack-polarity", NULL) != NULL) | ||
78 | devflags |= ISP1760_FLAG_DACK_POL_HIGH; | ||
79 | |||
80 | if (of_get_property(dp, "dreq-polarity", NULL) != NULL) | ||
81 | devflags |= ISP1760_FLAG_DREQ_POL_HIGH; | ||
82 | |||
58 | hcd = isp1760_register(memory.start, res_len, virq, | 83 | hcd = isp1760_register(memory.start, res_len, virq, |
59 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev)); | 84 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), |
85 | devflags); | ||
60 | if (IS_ERR(hcd)) { | 86 | if (IS_ERR(hcd)) { |
61 | ret = PTR_ERR(hcd); | 87 | ret = PTR_ERR(hcd); |
62 | goto release_reg; | 88 | goto release_reg; |
@@ -87,6 +113,9 @@ static struct of_device_id of_isp1760_match[] = { | |||
87 | { | 113 | { |
88 | .compatible = "nxp,usb-isp1760", | 114 | .compatible = "nxp,usb-isp1760", |
89 | }, | 115 | }, |
116 | { | ||
117 | .compatible = "nxp,usb-isp1761", | ||
118 | }, | ||
90 | { }, | 119 | { }, |
91 | }; | 120 | }; |
92 | MODULE_DEVICE_TABLE(of, of_isp1760_match); | 121 | MODULE_DEVICE_TABLE(of, of_isp1760_match); |
@@ -116,6 +145,7 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, | |||
116 | int length; | 145 | int length; |
117 | int status = 1; | 146 | int status = 1; |
118 | struct usb_hcd *hcd; | 147 | struct usb_hcd *hcd; |
148 | unsigned int devflags = 0; | ||
119 | 149 | ||
120 | if (usb_disabled()) | 150 | if (usb_disabled()) |
121 | return -ENODEV; | 151 | return -ENODEV; |
@@ -200,7 +230,8 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, | |||
200 | 230 | ||
201 | dev->dev.dma_mask = NULL; | 231 | dev->dev.dma_mask = NULL; |
202 | hcd = isp1760_register(pci_mem_phy0, length, dev->irq, | 232 | hcd = isp1760_register(pci_mem_phy0, length, dev->irq, |
203 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev)); | 233 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), |
234 | devflags); | ||
204 | pci_set_drvdata(dev, hcd); | 235 | pci_set_drvdata(dev, hcd); |
205 | if (!hcd) | 236 | if (!hcd) |
206 | return 0; | 237 | return 0; |