~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/usb/host/ehci-lpm.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ehci-lpm.c EHCI HCD LPM support code
 
2
 * Copyright (c) 2008 - 2010,  Intel Corporation.
 
3
 * Author: Jacob Pan <jacob.jun.pan@intel.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 2 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
17
*/
 
18
 
 
19
/* this file is part of ehci-hcd.c */
 
20
static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
 
21
        int dev_addr, int port_num)
 
22
{
 
23
        u32 __iomem portsc;
 
24
 
 
25
        ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num);
 
26
        if (port_num > HCS_N_PORTS(ehci->hcs_params)) {
 
27
                ehci_dbg(ehci, "invalid port number %d\n", port_num);
 
28
                return -ENODEV;
 
29
        }
 
30
        portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]);
 
31
        portsc &= ~PORT_DEV_ADDR;
 
32
        portsc |= dev_addr<<25;
 
33
        ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]);
 
34
        return 0;
 
35
}
 
36
 
 
37
/*
 
38
 * this function is used to check if the device support LPM
 
39
 * if yes, mark the PORTSC register with PORT_LPM bit
 
40
 */
 
41
static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
 
42
{
 
43
        u32 __iomem     *portsc ;
 
44
        u32 val32;
 
45
        int retval;
 
46
 
 
47
        portsc = &ehci->regs->port_status[port-1];
 
48
        val32 = ehci_readl(ehci, portsc);
 
49
        if (!(val32 & PORT_DEV_ADDR)) {
 
50
                ehci_dbg(ehci, "LPM: no device attached\n");
 
51
                return -ENODEV;
 
52
        }
 
53
        val32 |= PORT_LPM;
 
54
        ehci_writel(ehci, val32, portsc);
 
55
        msleep(5);
 
56
        val32 |= PORT_SUSPEND;
 
57
        ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port);
 
58
        ehci_writel(ehci, val32, portsc);
 
59
        /* wait for ACK */
 
60
        msleep(10);
 
61
        retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS,
 
62
                        PORTSC_SUSPEND_STS_ACK, 125);
 
63
        dbg_port(ehci, "LPM", port, val32);
 
64
        if (retval != -ETIMEDOUT) {
 
65
                ehci_dbg(ehci, "LPM: device ACK for LPM\n");
 
66
                val32 |= PORT_LPM;
 
67
                /*
 
68
                 * now device should be in L1 sleep, let's wake up the device
 
69
                 * so that we can complete enumeration.
 
70
                 */
 
71
                ehci_writel(ehci, val32, portsc);
 
72
                msleep(10);
 
73
                val32 |= PORT_RESUME;
 
74
                ehci_writel(ehci, val32, portsc);
 
75
        } else {
 
76
                ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n",
 
77
                        retval);
 
78
                val32 &= ~PORT_LPM;
 
79
                retval = -ETIMEDOUT;
 
80
                ehci_writel(ehci, val32, portsc);
 
81
        }
 
82
 
 
83
        return retval;
 
84
}