diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-08 20:21:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-08 20:21:02 -0400 |
commit | 54205209732a05f51f5fbb3eb3e5c36ac81e79d9 (patch) | |
tree | 4992850c7d5d5ed4034cbd4fe5f5ea23aeff317e /drivers/usb/host/isp116x-hcd.c | |
parent | 6d8de3a26b5c20b04a9317b4446582167d5883da (diff) | |
parent | b71e318cdb1dc301d734fdd4983dfc6dc167235a (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
Diffstat (limited to 'drivers/usb/host/isp116x-hcd.c')
-rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 88 |
1 files changed, 33 insertions, 55 deletions
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 75128c371800..41bbae83fc71 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -83,7 +83,7 @@ | |||
83 | #include "../core/hcd.h" | 83 | #include "../core/hcd.h" |
84 | #include "isp116x.h" | 84 | #include "isp116x.h" |
85 | 85 | ||
86 | #define DRIVER_VERSION "08 Apr 2005" | 86 | #define DRIVER_VERSION "05 Aug 2005" |
87 | #define DRIVER_DESC "ISP116x USB Host Controller Driver" | 87 | #define DRIVER_DESC "ISP116x USB Host Controller Driver" |
88 | 88 | ||
89 | MODULE_DESCRIPTION(DRIVER_DESC); | 89 | MODULE_DESCRIPTION(DRIVER_DESC); |
@@ -629,14 +629,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
629 | ERR("Unrecoverable error\n"); | 629 | ERR("Unrecoverable error\n"); |
630 | /* What should we do here? Reset? */ | 630 | /* What should we do here? Reset? */ |
631 | } | 631 | } |
632 | if (intstat & HCINT_RHSC) { | 632 | if (intstat & HCINT_RHSC) |
633 | isp116x->rhstatus = | 633 | /* When root hub or any of its ports is going |
634 | isp116x_read_reg32(isp116x, HCRHSTATUS); | 634 | to come out of suspend, it may take more |
635 | isp116x->rhport[0] = | 635 | than 10ms for status bits to stabilize. */ |
636 | isp116x_read_reg32(isp116x, HCRHPORT1); | 636 | mod_timer(&hcd->rh_timer, jiffies |
637 | isp116x->rhport[1] = | 637 | + msecs_to_jiffies(20) + 1); |
638 | isp116x_read_reg32(isp116x, HCRHPORT2); | ||
639 | } | ||
640 | if (intstat & HCINT_RD) { | 638 | if (intstat & HCINT_RD) { |
641 | DBG("---- remote wakeup\n"); | 639 | DBG("---- remote wakeup\n"); |
642 | schedule_work(&isp116x->rh_resume); | 640 | schedule_work(&isp116x->rh_resume); |
@@ -925,20 +923,27 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
925 | { | 923 | { |
926 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 924 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
927 | int ports, i, changed = 0; | 925 | int ports, i, changed = 0; |
926 | unsigned long flags; | ||
928 | 927 | ||
929 | if (!HC_IS_RUNNING(hcd->state)) | 928 | if (!HC_IS_RUNNING(hcd->state)) |
930 | return -ESHUTDOWN; | 929 | return -ESHUTDOWN; |
931 | 930 | ||
932 | ports = isp116x->rhdesca & RH_A_NDP; | 931 | /* Report no status change now, if we are scheduled to be |
932 | called later */ | ||
933 | if (timer_pending(&hcd->rh_timer)) | ||
934 | return 0; | ||
933 | 935 | ||
934 | /* init status */ | 936 | ports = isp116x->rhdesca & RH_A_NDP; |
937 | spin_lock_irqsave(&isp116x->lock, flags); | ||
938 | isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS); | ||
935 | if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC)) | 939 | if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC)) |
936 | buf[0] = changed = 1; | 940 | buf[0] = changed = 1; |
937 | else | 941 | else |
938 | buf[0] = 0; | 942 | buf[0] = 0; |
939 | 943 | ||
940 | for (i = 0; i < ports; i++) { | 944 | for (i = 0; i < ports; i++) { |
941 | u32 status = isp116x->rhport[i]; | 945 | u32 status = isp116x->rhport[i] = |
946 | isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1); | ||
942 | 947 | ||
943 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | 948 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC |
944 | | RH_PS_OCIC | RH_PS_PRSC)) { | 949 | | RH_PS_OCIC | RH_PS_PRSC)) { |
@@ -947,6 +952,7 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
947 | continue; | 952 | continue; |
948 | } | 953 | } |
949 | } | 954 | } |
955 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
950 | return changed; | 956 | return changed; |
951 | } | 957 | } |
952 | 958 | ||
@@ -1463,10 +1469,6 @@ static int isp116x_sw_reset(struct isp116x *isp116x) | |||
1463 | return ret; | 1469 | return ret; |
1464 | } | 1470 | } |
1465 | 1471 | ||
1466 | /* | ||
1467 | Reset. Tries to perform platform-specific hardware | ||
1468 | reset first; falls back to software reset. | ||
1469 | */ | ||
1470 | static int isp116x_reset(struct usb_hcd *hcd) | 1472 | static int isp116x_reset(struct usb_hcd *hcd) |
1471 | { | 1473 | { |
1472 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 1474 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
@@ -1474,17 +1476,7 @@ static int isp116x_reset(struct usb_hcd *hcd) | |||
1474 | u16 clkrdy = 0; | 1476 | u16 clkrdy = 0; |
1475 | int ret = 0, timeout = 15 /* ms */ ; | 1477 | int ret = 0, timeout = 15 /* ms */ ; |
1476 | 1478 | ||
1477 | if (isp116x->board && isp116x->board->reset) { | 1479 | ret = isp116x_sw_reset(isp116x); |
1478 | /* Hardware reset */ | ||
1479 | isp116x->board->reset(hcd->self.controller, 1); | ||
1480 | msleep(10); | ||
1481 | if (isp116x->board->clock) | ||
1482 | isp116x->board->clock(hcd->self.controller, 1); | ||
1483 | msleep(1); | ||
1484 | isp116x->board->reset(hcd->self.controller, 0); | ||
1485 | } else | ||
1486 | ret = isp116x_sw_reset(isp116x); | ||
1487 | |||
1488 | if (ret) | 1480 | if (ret) |
1489 | return ret; | 1481 | return ret; |
1490 | 1482 | ||
@@ -1501,10 +1493,7 @@ static int isp116x_reset(struct usb_hcd *hcd) | |||
1501 | ERR("Clock not ready after 20ms\n"); | 1493 | ERR("Clock not ready after 20ms\n"); |
1502 | /* After sw_reset the clock won't report to be ready, if | 1494 | /* After sw_reset the clock won't report to be ready, if |
1503 | H_WAKEUP pin is high. */ | 1495 | H_WAKEUP pin is high. */ |
1504 | if (!isp116x->board || !isp116x->board->reset) | 1496 | ERR("Please make sure that the H_WAKEUP pin is pulled low!\n"); |
1505 | ERR("The driver does not support hardware wakeup.\n"); | ||
1506 | ERR("Please make sure that the H_WAKEUP pin " | ||
1507 | "is pulled low!\n"); | ||
1508 | ret = -ENODEV; | 1497 | ret = -ENODEV; |
1509 | } | 1498 | } |
1510 | return ret; | 1499 | return ret; |
@@ -1527,15 +1516,7 @@ static void isp116x_stop(struct usb_hcd *hcd) | |||
1527 | isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); | 1516 | isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); |
1528 | spin_unlock_irqrestore(&isp116x->lock, flags); | 1517 | spin_unlock_irqrestore(&isp116x->lock, flags); |
1529 | 1518 | ||
1530 | /* Put the chip into reset state */ | 1519 | isp116x_sw_reset(isp116x); |
1531 | if (isp116x->board && isp116x->board->reset) | ||
1532 | isp116x->board->reset(hcd->self.controller, 0); | ||
1533 | else | ||
1534 | isp116x_sw_reset(isp116x); | ||
1535 | |||
1536 | /* Stop the clock */ | ||
1537 | if (isp116x->board && isp116x->board->clock) | ||
1538 | isp116x->board->clock(hcd->self.controller, 0); | ||
1539 | } | 1520 | } |
1540 | 1521 | ||
1541 | /* | 1522 | /* |
@@ -1561,6 +1542,9 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
1561 | return -ENODEV; | 1542 | return -ENODEV; |
1562 | } | 1543 | } |
1563 | 1544 | ||
1545 | /* To be removed in future */ | ||
1546 | hcd->uses_new_polling = 1; | ||
1547 | |||
1564 | isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); | 1548 | isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); |
1565 | isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); | 1549 | isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); |
1566 | 1550 | ||
@@ -1569,7 +1553,7 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
1569 | if (board->sel15Kres) | 1553 | if (board->sel15Kres) |
1570 | val |= HCHWCFG_15KRSEL; | 1554 | val |= HCHWCFG_15KRSEL; |
1571 | /* Remote wakeup won't work without working clock */ | 1555 | /* Remote wakeup won't work without working clock */ |
1572 | if (board->clknotstop || board->remote_wakeup_enable) | 1556 | if (board->remote_wakeup_enable) |
1573 | val |= HCHWCFG_CLKNOTSTOP; | 1557 | val |= HCHWCFG_CLKNOTSTOP; |
1574 | if (board->oc_enable) | 1558 | if (board->oc_enable) |
1575 | val |= HCHWCFG_ANALOG_OC; | 1559 | val |= HCHWCFG_ANALOG_OC; |
@@ -1580,16 +1564,13 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
1580 | isp116x_write_reg16(isp116x, HCHWCFG, val); | 1564 | isp116x_write_reg16(isp116x, HCHWCFG, val); |
1581 | 1565 | ||
1582 | /* ----- Root hub conf */ | 1566 | /* ----- Root hub conf */ |
1583 | val = 0; | 1567 | val = (25 << 24) & RH_A_POTPGT; |
1584 | /* AN10003_1.pdf recommends NPS to be always 1 */ | 1568 | /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to |
1585 | if (board->no_power_switching) | 1569 | be always set. Yet, instead, we request individual port |
1586 | val |= RH_A_NPS; | 1570 | power switching. */ |
1587 | if (board->power_switching_mode) | 1571 | val |= RH_A_PSM; |
1588 | val |= RH_A_PSM; | 1572 | /* Report overcurrent per port */ |
1589 | if (board->potpg) | 1573 | val |= RH_A_OCPM; |
1590 | val |= (board->potpg << 24) & RH_A_POTPGT; | ||
1591 | else | ||
1592 | val |= (25 << 24) & RH_A_POTPGT; | ||
1593 | isp116x_write_reg32(isp116x, HCRHDESCA, val); | 1574 | isp116x_write_reg32(isp116x, HCRHDESCA, val); |
1594 | isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); | 1575 | isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); |
1595 | 1576 | ||
@@ -1619,9 +1600,6 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
1619 | 1600 | ||
1620 | /* Go operational */ | 1601 | /* Go operational */ |
1621 | val = HCCONTROL_USB_OPER; | 1602 | val = HCCONTROL_USB_OPER; |
1622 | /* Remote wakeup connected - NOT SUPPORTED */ | ||
1623 | /* if (board->remote_wakeup_connected) | ||
1624 | val |= HCCONTROL_RWC; */ | ||
1625 | if (board->remote_wakeup_enable) | 1603 | if (board->remote_wakeup_enable) |
1626 | val |= HCCONTROL_RWE; | 1604 | val |= HCCONTROL_RWE; |
1627 | isp116x_write_reg32(isp116x, HCCONTROL, val); | 1605 | isp116x_write_reg32(isp116x, HCCONTROL, val); |
@@ -1670,7 +1648,7 @@ static int __init_or_module isp116x_remove(struct device *dev) | |||
1670 | struct platform_device *pdev; | 1648 | struct platform_device *pdev; |
1671 | struct resource *res; | 1649 | struct resource *res; |
1672 | 1650 | ||
1673 | if(!hcd) | 1651 | if (!hcd) |
1674 | return 0; | 1652 | return 0; |
1675 | isp116x = hcd_to_isp116x(hcd); | 1653 | isp116x = hcd_to_isp116x(hcd); |
1676 | pdev = container_of(dev, struct platform_device, dev); | 1654 | pdev = container_of(dev, struct platform_device, dev); |