]> err.no Git - linux-2.6/commitdiff
[PATCH] USB: OHCI relies less on NDP register
authorDavid Brownell <david-b@pacbell.net>
Wed, 31 Aug 2005 18:52:57 +0000 (11:52 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 12 Sep 2005 19:23:46 +0000 (12:23 -0700)
Some OHCI implementations have differences in the way the NDP register
(in roothub_a) reports the number of ports present. This patch allows the
platform specific code to optionally supply the number of ports. The
driver just reads the value at init (if not supplied) instead of reading
it every time its needed (except for an AMD756 bug workaround).

It also sets the value correctly for the ARM pxa27x architecture.

Signed-Off-By: Richard Purdie <rpurdie@rpsys.net>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci.h

index 447f488f5d937f85de1e7c75348e04bf8400a040..7924c74f958eb28dc833de2059a1f269e0a040fb 100644 (file)
@@ -228,23 +228,22 @@ ohci_dump_roothub (
        char **next,
        unsigned *size)
 {
-       u32                     temp, ndp, i;
+       u32                     temp, i;
 
        temp = roothub_a (controller);
        if (temp == ~(u32)0)
                return;
-       ndp = (temp & RH_A_NDP);
 
        if (verbose) {
                ohci_dbg_sw (controller, next, size,
-                       "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
+                       "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp,
                        ((temp & RH_A_POTPGT) >> 24) & 0xff,
                        (temp & RH_A_NOCP) ? " NOCP" : "",
                        (temp & RH_A_OCPM) ? " OCPM" : "",
                        (temp & RH_A_DT) ? " DT" : "",
                        (temp & RH_A_NPS) ? " NPS" : "",
                        (temp & RH_A_PSM) ? " PSM" : "",
-                       ndp
+                       (temp & RH_A_NDP), controller->num_ports
                        );
                temp = roothub_b (controller);
                ohci_dbg_sw (controller, next, size,
@@ -266,7 +265,7 @@ ohci_dump_roothub (
                        );
        }
 
-       for (i = 0; i < ndp; i++) {
+       for (i = 0; i < controller->num_ports; i++) {
                temp = roothub_portstatus (controller, i);
                dbg_port_sw (controller, i, temp, next, size);
        }
index 6efb69f7c0752396384716a65000ce8fbbb85103..67c1aa5eb1c175994faa6593a33b009d496164cb 100644 (file)
@@ -484,6 +484,10 @@ static int ohci_init (struct ohci_hcd *ohci)
        // flush the writes
        (void) ohci_readl (ohci, &ohci->regs->control);
 
+       /* Read the number of ports unless overridden */
+       if (ohci->num_ports == 0)
+               ohci->num_ports = roothub_a(ohci) & RH_A_NDP;
+
        if (ohci->hcca)
                return 0;
 
@@ -560,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci)
        msleep(temp);
        temp = roothub_a (ohci);
        if (!(temp & RH_A_NPS)) {
-               unsigned ports = temp & RH_A_NDP; 
-
                /* power down each port */
-               for (temp = 0; temp < ports; temp++)
+               for (temp = 0; temp < ohci->num_ports; temp++)
                        ohci_writel (ohci, RH_PS_LSDA,
                                &ohci->regs->roothub.portstatus [temp]);
        }
@@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
                 * and that if we try to turn them back on the root hub
                 * will respond to CSC processing.
                 */
-               i = roothub_a (ohci) & RH_A_NDP;
+               i = ohci->num_ports;
                while (i--)
                        ohci_writel (ohci, RH_PS_PSS,
                                &ohci->regs->roothub.portstatus [temp]);
index 83ca4549a50ecac5f82504ba375419ad3c9b6d0a..ce7b28da7a1540c0e00c7f8e95b030d5191fd89e 100644 (file)
@@ -184,7 +184,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
        if (status != -EINPROGRESS)
                return status;
 
-       temp = roothub_a (ohci) & RH_A_NDP;
+       temp = ohci->num_ports;
        enables = 0;
        while (temp--) {
                u32 stat = ohci_readl (ohci,
@@ -304,7 +304,7 @@ static int
 ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
-       int             ports, i, changed = 0, length = 1;
+       int             i, changed = 0, length = 1;
        int             can_suspend = hcd->can_wakeup;
        unsigned long   flags;
 
@@ -319,9 +319,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
                goto done;
        }
 
-       ports = roothub_a (ohci) & RH_A_NDP; 
-       if (ports > MAX_ROOT_PORTS) {
-               ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
+       /* undocumented erratum seen on at least rev D */
+       if ((ohci->flags & OHCI_QUIRK_AMD756)
+                       && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) {
+               ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n",
                          ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
                /* retry later; "should not happen" */
                goto done;
@@ -332,13 +333,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
                buf [0] = changed = 1;
        else
                buf [0] = 0;
-       if (ports > 7) {
+       if (ohci->num_ports > 7) {
                buf [1] = 0;
                length++;
        }
 
        /* look at each port */
-       for (i = 0; i < ports; i++) {
+       for (i = 0; i < ohci->num_ports; i++) {
                u32     status = roothub_portstatus (ohci, i);
 
                if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
@@ -395,15 +396,14 @@ ohci_hub_descriptor (
        struct usb_hub_descriptor       *desc
 ) {
        u32             rh = roothub_a (ohci);
-       int             ports = rh & RH_A_NDP; 
        u16             temp;
 
        desc->bDescriptorType = 0x29;
        desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
        desc->bHubContrCurrent = 0;
 
-       desc->bNbrPorts = ports;
-       temp = 1 + (ports / 8);
+       desc->bNbrPorts = ohci->num_ports;
+       temp = 1 + (ohci->num_ports / 8);
        desc->bDescLength = 7 + 2 * temp;
 
        temp = 0;
@@ -421,7 +421,7 @@ ohci_hub_descriptor (
        rh = roothub_b (ohci);
        memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
        desc->bitmap [0] = rh & RH_B_DR;
-       if (ports > 7) {
+       if (ohci->num_ports > 7) {
                desc->bitmap [1] = (rh & RH_B_DR) >> 8;
                desc->bitmap [2] = 0xff;
        } else
index e5bc1789d18a6532b13cdaf1e367e8002c9d9b49..5dd20dbe852d6697ec88230aee4a90033b72fff2 100644 (file)
@@ -258,6 +258,9 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
 
        ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
 
+       /* The value of NDP in roothub_a is incorrect on this hardware */
+       ohci->num_ports = 3;
+
        if ((ret = ohci_init(ohci)) < 0)
                return ret;
 
index 71cdd2262860d129fc1776179b561f3f0ff5dcb4..8a9b9d9209e9276213a51fbc717d5c7aea0de85c 100644 (file)
@@ -383,6 +383,7 @@ struct ohci_hcd {
        /*
         * driver state
         */
+       int                     num_ports;
        int                     load [NUM_INTS];
        u32                     hc_control;     /* copy of hc control reg */
        unsigned long           next_statechange;       /* suspend/resume */