linux/drivers/usb/host/ehci-lpm.c
<<
>>
Prefs
   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 */
  20static 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 */
  41static 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}
  85
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.