aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-at91/include/mach/board.h13
-rw-r--r--drivers/usb/host/ohci-at91.c66
2 files changed, 43 insertions, 36 deletions
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 544a5d5ce416..49a821192c65 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -86,14 +86,15 @@ extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *d
86extern void __init at91_add_device_eth(struct macb_platform_data *data); 86extern void __init at91_add_device_eth(struct macb_platform_data *data);
87 87
88 /* USB Host */ 88 /* USB Host */
89#define AT91_MAX_USBH_PORTS 3
89struct at91_usbh_data { 90struct at91_usbh_data {
90 u8 ports; /* number of ports on root hub */ 91 int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */
91 int vbus_pin[2]; /* port power-control pin */ 92 int overcurrent_pin[AT91_MAX_USBH_PORTS];
92 u8 vbus_pin_active_low[2]; 93 u8 ports; /* number of ports on root hub */
93 u8 overcurrent_supported; 94 u8 overcurrent_supported;
94 int overcurrent_pin[2]; 95 u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
95 u8 overcurrent_status[2]; 96 u8 overcurrent_status[AT91_MAX_USBH_PORTS];
96 u8 overcurrent_changed[2]; 97 u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
97}; 98};
98extern void __init at91_add_device_usbh(struct at91_usbh_data *data); 99extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
99extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data); 100extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index c30da6ab9f92..7cf4797a601e 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -27,6 +27,10 @@
27#error "CONFIG_ARCH_AT91 must be defined." 27#error "CONFIG_ARCH_AT91 must be defined."
28#endif 28#endif
29 29
30#define valid_port(index) ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS)
31#define at91_for_each_port(index) \
32 for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++)
33
30/* interface and function clocks; sometimes also an AHB clock */ 34/* interface and function clocks; sometimes also an AHB clock */
31static struct clk *iclk, *fclk, *hclk; 35static struct clk *iclk, *fclk, *hclk;
32static int clocked; 36static int clocked;
@@ -240,7 +244,7 @@ ohci_at91_start (struct usb_hcd *hcd)
240 244
241static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable) 245static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable)
242{ 246{
243 if (port < 0 || port >= 2) 247 if (!valid_port(port))
244 return; 248 return;
245 249
246 if (!gpio_is_valid(pdata->vbus_pin[port])) 250 if (!gpio_is_valid(pdata->vbus_pin[port]))
@@ -252,7 +256,7 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int
252 256
253static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) 257static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
254{ 258{
255 if (port < 0 || port >= 2) 259 if (!valid_port(port))
256 return -EINVAL; 260 return -EINVAL;
257 261
258 if (!gpio_is_valid(pdata->vbus_pin[port])) 262 if (!gpio_is_valid(pdata->vbus_pin[port]))
@@ -271,9 +275,9 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
271 int length = ohci_hub_status_data(hcd, buf); 275 int length = ohci_hub_status_data(hcd, buf);
272 int port; 276 int port;
273 277
274 for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) { 278 at91_for_each_port(port) {
275 if (pdata->overcurrent_changed[port]) { 279 if (pdata->overcurrent_changed[port]) {
276 if (! length) 280 if (!length)
277 length = 1; 281 length = 1;
278 buf[0] |= 1 << (port + 1); 282 buf[0] |= 1 << (port + 1);
279 } 283 }
@@ -297,11 +301,17 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
297 "ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", 301 "ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
298 hcd, typeReq, wValue, wIndex, buf, wLength); 302 hcd, typeReq, wValue, wIndex, buf, wLength);
299 303
304 wIndex--;
305
300 switch (typeReq) { 306 switch (typeReq) {
301 case SetPortFeature: 307 case SetPortFeature:
302 if (wValue == USB_PORT_FEAT_POWER) { 308 if (wValue == USB_PORT_FEAT_POWER) {
303 dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); 309 dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n");
304 ohci_at91_usb_set_power(pdata, wIndex - 1, 1); 310 if (valid_port(wIndex)) {
311 ohci_at91_usb_set_power(pdata, wIndex, 1);
312 ret = 0;
313 }
314
305 goto out; 315 goto out;
306 } 316 }
307 break; 317 break;
@@ -312,9 +322,9 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
312 dev_dbg(hcd->self.controller, 322 dev_dbg(hcd->self.controller,
313 "ClearPortFeature: C_OVER_CURRENT\n"); 323 "ClearPortFeature: C_OVER_CURRENT\n");
314 324
315 if (wIndex == 1 || wIndex == 2) { 325 if (valid_port(wIndex)) {
316 pdata->overcurrent_changed[wIndex-1] = 0; 326 pdata->overcurrent_changed[wIndex] = 0;
317 pdata->overcurrent_status[wIndex-1] = 0; 327 pdata->overcurrent_status[wIndex] = 0;
318 } 328 }
319 329
320 goto out; 330 goto out;
@@ -323,9 +333,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
323 dev_dbg(hcd->self.controller, 333 dev_dbg(hcd->self.controller,
324 "ClearPortFeature: OVER_CURRENT\n"); 334 "ClearPortFeature: OVER_CURRENT\n");
325 335
326 if (wIndex == 1 || wIndex == 2) { 336 if (valid_port(wIndex))
327 pdata->overcurrent_status[wIndex-1] = 0; 337 pdata->overcurrent_status[wIndex] = 0;
328 }
329 338
330 goto out; 339 goto out;
331 340
@@ -333,15 +342,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
333 dev_dbg(hcd->self.controller, 342 dev_dbg(hcd->self.controller,
334 "ClearPortFeature: POWER\n"); 343 "ClearPortFeature: POWER\n");
335 344
336 if (wIndex == 1 || wIndex == 2) { 345 if (valid_port(wIndex)) {
337 ohci_at91_usb_set_power(pdata, wIndex - 1, 0); 346 ohci_at91_usb_set_power(pdata, wIndex, 0);
338 return 0; 347 return 0;
339 } 348 }
340 } 349 }
341 break; 350 break;
342 } 351 }
343 352
344 ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 353 ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength);
345 if (ret) 354 if (ret)
346 goto out; 355 goto out;
347 356
@@ -377,18 +386,15 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
377 386
378 dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); 387 dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
379 388
380 if (wIndex == 1 || wIndex == 2) { 389 if (valid_port(wIndex)) {
381 if (! ohci_at91_usb_get_power(pdata, wIndex-1)) { 390 if (!ohci_at91_usb_get_power(pdata, wIndex))
382 *data &= ~cpu_to_le32(RH_PS_PPS); 391 *data &= ~cpu_to_le32(RH_PS_PPS);
383 }
384 392
385 if (pdata->overcurrent_changed[wIndex-1]) { 393 if (pdata->overcurrent_changed[wIndex])
386 *data |= cpu_to_le32(RH_PS_OCIC); 394 *data |= cpu_to_le32(RH_PS_OCIC);
387 }
388 395
389 if (pdata->overcurrent_status[wIndex-1]) { 396 if (pdata->overcurrent_status[wIndex])
390 *data |= cpu_to_le32(RH_PS_POCI); 397 *data |= cpu_to_le32(RH_PS_POCI);
391 }
392 } 398 }
393 } 399 }
394 400
@@ -450,14 +456,14 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
450 456
451 /* From the GPIO notifying the over-current situation, find 457 /* From the GPIO notifying the over-current situation, find
452 * out the corresponding port */ 458 * out the corresponding port */
453 for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) { 459 at91_for_each_port(port) {
454 if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { 460 if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
455 gpio = pdata->overcurrent_pin[port]; 461 gpio = pdata->overcurrent_pin[port];
456 break; 462 break;
457 } 463 }
458 } 464 }
459 465
460 if (port == ARRAY_SIZE(pdata->overcurrent_pin)) { 466 if (port == AT91_MAX_USBH_PORTS) {
461 dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n"); 467 dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n");
462 return IRQ_HANDLED; 468 return IRQ_HANDLED;
463 } 469 }
@@ -467,7 +473,7 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
467 /* When notified of an over-current situation, disable power 473 /* When notified of an over-current situation, disable power
468 on the corresponding port, and mark this port in 474 on the corresponding port, and mark this port in
469 over-current. */ 475 over-current. */
470 if (! val) { 476 if (!val) {
471 ohci_at91_usb_set_power(pdata, port, 0); 477 ohci_at91_usb_set_power(pdata, port, 0);
472 pdata->overcurrent_status[port] = 1; 478 pdata->overcurrent_status[port] = 1;
473 pdata->overcurrent_changed[port] = 1; 479 pdata->overcurrent_changed[port] = 1;
@@ -514,7 +520,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
514 if (!of_property_read_u32(np, "num-ports", &ports)) 520 if (!of_property_read_u32(np, "num-ports", &ports))
515 pdata->ports = ports; 521 pdata->ports = ports;
516 522
517 for (i = 0; i < 2; i++) { 523 at91_for_each_port(i) {
518 gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags); 524 gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
519 pdata->vbus_pin[i] = gpio; 525 pdata->vbus_pin[i] = gpio;
520 if (!gpio_is_valid(gpio)) 526 if (!gpio_is_valid(gpio))
@@ -522,7 +528,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev)
522 pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW; 528 pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
523 } 529 }
524 530
525 for (i = 0; i < 2; i++) 531 at91_for_each_port(i)
526 pdata->overcurrent_pin[i] = 532 pdata->overcurrent_pin[i] =
527 of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); 533 of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
528 534
@@ -554,7 +560,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
554 pdata = pdev->dev.platform_data; 560 pdata = pdev->dev.platform_data;
555 561
556 if (pdata) { 562 if (pdata) {
557 for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { 563 at91_for_each_port(i) {
558 if (!gpio_is_valid(pdata->vbus_pin[i])) 564 if (!gpio_is_valid(pdata->vbus_pin[i]))
559 continue; 565 continue;
560 gpio = pdata->vbus_pin[i]; 566 gpio = pdata->vbus_pin[i];
@@ -578,7 +584,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
578 ohci_at91_usb_set_power(pdata, i, 1); 584 ohci_at91_usb_set_power(pdata, i, 1);
579 } 585 }
580 586
581 for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { 587 at91_for_each_port(i) {
582 if (!gpio_is_valid(pdata->overcurrent_pin[i])) 588 if (!gpio_is_valid(pdata->overcurrent_pin[i]))
583 continue; 589 continue;
584 gpio = pdata->overcurrent_pin[i]; 590 gpio = pdata->overcurrent_pin[i];
@@ -621,14 +627,14 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
621 int i; 627 int i;
622 628
623 if (pdata) { 629 if (pdata) {
624 for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) { 630 at91_for_each_port(i) {
625 if (!gpio_is_valid(pdata->vbus_pin[i])) 631 if (!gpio_is_valid(pdata->vbus_pin[i]))
626 continue; 632 continue;
627 ohci_at91_usb_set_power(pdata, i, 0); 633 ohci_at91_usb_set_power(pdata, i, 0);
628 gpio_free(pdata->vbus_pin[i]); 634 gpio_free(pdata->vbus_pin[i]);
629 } 635 }
630 636
631 for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) { 637 at91_for_each_port(i) {
632 if (!gpio_is_valid(pdata->overcurrent_pin[i])) 638 if (!gpio_is_valid(pdata->overcurrent_pin[i]))
633 continue; 639 continue;
634 free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev); 640 free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev);