10f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 20f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * xHCI host controller driver 30f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * 40f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Copyright (C) 2008 Intel Corp. 50f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * 60f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Author: Sarah Sharp 70f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Some code borrowed from the Linux EHCI driver. 80f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * 90f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * This program is free software; you can redistribute it and/or modify 100f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * it under the terms of the GNU General Public License version 2 as 110f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * published by the Free Software Foundation. 120f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * 130f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * This program is distributed in the hope that it will be useful, but 140f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 150f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 160f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * for more details. 170f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * 180f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * You should have received a copy of the GNU General Public License 190f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * along with this program; if not, write to the Free Software Foundation, 200f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 210f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 220f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 23ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman 24ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman#include <linux/slab.h> 250f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp#include <asm/unaligned.h> 260f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 270f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp#include "xhci.h" 284bdfe4c38fd5b06da558050a3288a0a48825a3e7Xenia Ragiadakou#include "xhci-trace.h" 290f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 309777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E) 319777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ 329777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu PORT_RC | PORT_PLC | PORT_PE) 339777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 343415fc94bba86b397f1fefec3c904bfc57de7038Sebastian Andrzej Siewior/* USB 3.0 BOS descriptor and a capability descriptor, combined */ 3548e8236114c12c5366e032fc517e1bd376369a56Sarah Sharpstatic u8 usb_bos_descriptor [] = { 3648e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp USB_DT_BOS_SIZE, /* __u8 bLength, 5 bytes */ 3748e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp USB_DT_BOS, /* __u8 bDescriptorType */ 3848e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 0x0F, 0x00, /* __le16 wTotalLength, 15 bytes */ 3948e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 0x1, /* __u8 bNumDeviceCaps */ 4048e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp /* First device capability */ 4148e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp USB_DT_USB_SS_CAP_SIZE, /* __u8 bLength, 10 bytes */ 4248e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp USB_DT_DEVICE_CAPABILITY, /* Device Capability */ 4348e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp USB_SS_CAP_TYPE, /* bDevCapabilityType, SUPERSPEED_USB */ 4448e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 0x00, /* bmAttributes, LTM off by default */ 4548e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp USB_5GBPS_OPERATION, 0x00, /* wSpeedsSupported, 5Gbps only */ 4648e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 0x03, /* bFunctionalitySupport, 4748e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp USB 3.0 speed only */ 4848e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 0x00, /* bU1DevExitLat, set later. */ 4948e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 0x00, 0x00 /* __le16 bU2DevExitLat, set later. */ 5048e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp}; 5148e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 5248e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 534bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharpstatic void xhci_common_hub_descriptor(struct xhci_hcd *xhci, 544bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp struct usb_hub_descriptor *desc, int ports) 550f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp{ 560f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp u16 temp; 570f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 580f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp desc->bPwrOn2PwrGood = 10; /* xhci section 5.4.9 says 20ms max */ 590f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp desc->bHubContrCurrent = 0; 600f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 610f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp desc->bNbrPorts = ports; 620f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp temp = 0; 63c8421147926fcacf53081a36438a0bed394da9f5Aman Deep /* Bits 1:0 - support per-port power switching, or power always on */ 640f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp if (HCC_PPC(xhci->hcc_params)) 65c8421147926fcacf53081a36438a0bed394da9f5Aman Deep temp |= HUB_CHAR_INDV_PORT_LPSM; 660f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp else 67c8421147926fcacf53081a36438a0bed394da9f5Aman Deep temp |= HUB_CHAR_NO_LPSM; 680f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* Bit 2 - root hubs are not part of a compound device */ 690f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* Bits 4:3 - individual port over current protection */ 70c8421147926fcacf53081a36438a0bed394da9f5Aman Deep temp |= HUB_CHAR_INDV_PORT_OCPM; 710f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* Bits 6:5 - no TTs in root ports */ 720f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* Bit 7 - no port indicators */ 7328ccd2962c66556d7037b2d9f1c11cdcd3b805d5Matt Evans desc->wHubCharacteristics = cpu_to_le16(temp); 740f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp} 750f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 764bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp/* Fill in the USB 2.0 roothub descriptor */ 774bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharpstatic void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, 784bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp struct usb_hub_descriptor *desc) 794bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp{ 804bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp int ports; 814bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp u16 temp; 824bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp __u8 port_removable[(USB_MAXCHILDREN + 1 + 7) / 8]; 834bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp u32 portsc; 844bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp unsigned int i; 854bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 864bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp ports = xhci->num_usb2_ports; 874bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 884bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp xhci_common_hub_descriptor(xhci, desc, ports); 89c8421147926fcacf53081a36438a0bed394da9f5Aman Deep desc->bDescriptorType = USB_DT_HUB; 904bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp temp = 1 + (ports / 8); 91c8421147926fcacf53081a36438a0bed394da9f5Aman Deep desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * temp; 924bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 934bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* The Device Removable bits are reported on a byte granularity. 944bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * If the port doesn't exist within that byte, the bit is set to 0. 954bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp */ 964bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp memset(port_removable, 0, sizeof(port_removable)); 974bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp for (i = 0; i < ports; i++) { 98b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou portsc = readl(xhci->usb2_ports[i]); 994bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* If a device is removable, PORTSC reports a 0, same as in the 1004bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * hub descriptor DeviceRemovable bits. 1014bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp */ 1024bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp if (portsc & PORT_DEV_REMOVE) 1034bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* This math is hairy because bit 0 of DeviceRemovable 1044bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * is reserved, and bit 1 is for port 1, etc. 1054bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp */ 1064bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp port_removable[(i + 1) / 8] |= 1 << ((i + 1) % 8); 1074bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp } 1084bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1094bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* ch11.h defines a hub descriptor that has room for USB_MAXCHILDREN 1104bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * ports on it. The USB 2.0 specification says that there are two 1114bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * variable length fields at the end of the hub descriptor: 1124bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * DeviceRemovable and PortPwrCtrlMask. But since we can have less than 1134bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * USB_MAXCHILDREN ports, we may need to use the DeviceRemovable array 1144bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * to set PortPwrCtrlMask bits. PortPwrCtrlMask must always be set to 1154bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * 0xFF, so we initialize the both arrays (DeviceRemovable and 1164bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * PortPwrCtrlMask) to 0xFF. Then we set the DeviceRemovable for each 1174bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * set of ports that actually exist. 1184bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp */ 1194bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp memset(desc->u.hs.DeviceRemovable, 0xff, 1204bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp sizeof(desc->u.hs.DeviceRemovable)); 1214bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp memset(desc->u.hs.PortPwrCtrlMask, 0xff, 1224bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp sizeof(desc->u.hs.PortPwrCtrlMask)); 1234bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1244bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp for (i = 0; i < (ports + 1 + 7) / 8; i++) 1254bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp memset(&desc->u.hs.DeviceRemovable[i], port_removable[i], 1264bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp sizeof(__u8)); 1274bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp} 1284bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1294bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp/* Fill in the USB 3.0 roothub descriptor */ 1304bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharpstatic void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, 1314bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp struct usb_hub_descriptor *desc) 1324bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp{ 1334bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp int ports; 1344bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp u16 port_removable; 1354bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp u32 portsc; 1364bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp unsigned int i; 1374bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1384bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp ports = xhci->num_usb3_ports; 1394bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp xhci_common_hub_descriptor(xhci, desc, ports); 140c8421147926fcacf53081a36438a0bed394da9f5Aman Deep desc->bDescriptorType = USB_DT_SS_HUB; 141c8421147926fcacf53081a36438a0bed394da9f5Aman Deep desc->bDescLength = USB_DT_SS_HUB_SIZE; 1424bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1434bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* header decode latency should be zero for roothubs, 1444bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * see section 4.23.5.2. 1454bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp */ 1464bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp desc->u.ss.bHubHdrDecLat = 0; 1474bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp desc->u.ss.wHubDelay = 0; 1484bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1494bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp port_removable = 0; 1504bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* bit 0 is reserved, bit 1 is for port 1, etc. */ 1514bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp for (i = 0; i < ports; i++) { 152b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou portsc = readl(xhci->usb3_ports[i]); 1534bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp if (portsc & PORT_DEV_REMOVE) 1544bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp port_removable |= 1 << (i + 1); 1554bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp } 15627c411c95a8e9ed92be658abf1d63e22873a3a66Lan Tianyu 15727c411c95a8e9ed92be658abf1d63e22873a3a66Lan Tianyu desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); 1584bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp} 1594bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1604bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharpstatic void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, 1614bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp struct usb_hub_descriptor *desc) 1624bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp{ 1634bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1644bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp if (hcd->speed == HCD_USB3) 1654bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp xhci_usb3_hub_descriptor(hcd, xhci, desc); 1664bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp else 1674bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp xhci_usb2_hub_descriptor(hcd, xhci, desc); 1684bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1694bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp} 1704bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp 1710f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharpstatic unsigned int xhci_port_speed(unsigned int port_status) 1720f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp{ 1730f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp if (DEV_LOWSPEED(port_status)) 174288ead45fa6637e959015d055304f521cbbc0575Alan Stern return USB_PORT_STAT_LOW_SPEED; 1750f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp if (DEV_HIGHSPEED(port_status)) 176288ead45fa6637e959015d055304f521cbbc0575Alan Stern return USB_PORT_STAT_HIGH_SPEED; 1770f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* 1780f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * FIXME: Yes, we should check for full speed, but the core uses that as 1790f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * a default in portspeed() in usb/core/hub.c (which is the only place 180288ead45fa6637e959015d055304f521cbbc0575Alan Stern * USB_PORT_STAT_*_SPEED is used). 1810f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 1820f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp return 0; 1830f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp} 1840f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 1850f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 1860f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * These bits are Read Only (RO) and should be saved and written to the 1870f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * registers: 0, 3, 10:13, 30 1880f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * connect status, over-current status, port speed, and device removable. 1890f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * connect status and port speed are also sticky - meaning they're in 1900f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * the AUX well and they aren't changed by a hot, warm, or cold reset. 1910f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 1920f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp#define XHCI_PORT_RO ((1<<0) | (1<<3) | (0xf<<10) | (1<<30)) 1930f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 1940f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * These bits are RW; writing a 0 clears the bit, writing a 1 sets the bit: 1950f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * bits 5:8, 9, 14:15, 25:27 1960f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * link state, port power, port indicator state, "wake on" enable state 1970f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 1980f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp#define XHCI_PORT_RWS ((0xf<<5) | (1<<9) | (0x3<<14) | (0x7<<25)) 1990f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 2000f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * These bits are RW; writing a 1 sets the bit, writing a 0 has no effect: 2010f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * bit 4 (port reset) 2020f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 2030f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp#define XHCI_PORT_RW1S ((1<<4)) 2040f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 2050f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * These bits are RW; writing a 1 clears the bit, writing a 0 has no effect: 2060f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * bits 1, 17, 18, 19, 20, 21, 22, 23 2070f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * port enable/disable, and 2080f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * change bits: connect, PED, warm port reset changed (reserved zero for USB 2.0 ports), 2090f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * over-current, reset, link state, and L1 change 2100f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 2110f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp#define XHCI_PORT_RW1CS ((1<<1) | (0x7f<<17)) 2120f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 2130f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Bit 16 is RW, and writing a '1' to it causes the link state control to be 2140f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * latched in 2150f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 2160f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp#define XHCI_PORT_RW ((1<<16)) 2170f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 2180f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * These bits are Reserved Zero (RsvdZ) and zero should be written to them: 2190f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * bits 2, 24, 28:31 2200f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 2210f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp#define XHCI_PORT_RZ ((1<<2) | (1<<24) | (0xf<<28)) 2220f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 2230f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 2240f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Given a port state, this function returns a value that would result in the 2250f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * port being in the same state, if the value was written to the port status 2260f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * control register. 2270f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Save Read Only (RO) bits and save read/write bits where 2280f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * writing a 0 clears the bit and writing a 1 sets the bit (RWS). 2290f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * For all other types (RW1S, RW1CS, RW, and RZ), writing a '0' has no effect. 2300f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 231561925318725a41189a69f36ebe99199b3fb84c4Andiry Xuu32 xhci_port_state_to_neutral(u32 state) 2320f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp{ 2330f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* Save read-only status and port state */ 2340f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS); 2350f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp} 2360f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 237be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu/* 238be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu * find slot id based on port number. 239f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharp * @port: The one-based port number from one of the two split roothubs. 240be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu */ 2415233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharpint xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, 2425233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharp u16 port) 243be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu{ 244be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu int slot_id; 245be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu int i; 246f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharp enum usb_device_speed speed; 247be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 248be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu slot_id = 0; 249be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu for (i = 0; i < MAX_HC_SLOTS; i++) { 250be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu if (!xhci->devs[i]) 251be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu continue; 252f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharp speed = xhci->devs[i]->udev->speed; 253f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharp if (((speed == USB_SPEED_SUPER) == (hcd->speed == HCD_USB3)) 254fe30182c2553f491e5dc12074c8e52163d3bfbc7Sarah Sharp && xhci->devs[i]->fake_port == port) { 255be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu slot_id = i; 256be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu break; 257be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 258be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 259be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 260be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu return slot_id; 261be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu} 262be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 263be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu/* 264be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu * Stop device 265be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu * It issues stop endpoint command for EP 0 to 30. And wait the last command 266be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu * to complete. 267be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu * suspend will set to 1, if suspend bit need to set in command. 268be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu */ 269be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xustatic int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) 270be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu{ 271be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu struct xhci_virt_device *virt_dev; 272be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu struct xhci_command *cmd; 273be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu unsigned long flags; 274be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu int ret; 275be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu int i; 276be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 277be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu ret = 0; 278be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu virt_dev = xhci->devs[slot_id]; 279be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO); 280be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu if (!cmd) { 281be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_dbg(xhci, "Couldn't allocate command structure.\n"); 282be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu return -ENOMEM; 283be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 284be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 285be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 286be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu for (i = LAST_EP_INDEX; i > 0; i--) { 287ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) { 288ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman struct xhci_command *command; 289ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman command = xhci_alloc_command(xhci, false, false, 290be3de32107091c266b00a48265fe7e06233af4f0Mathias Nyman GFP_NOWAIT); 291ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman if (!command) { 292ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman spin_unlock_irqrestore(&xhci->lock, flags); 293ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman xhci_free_command(xhci, cmd); 294ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman return -ENOMEM; 295ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman 296ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman } 297ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman xhci_queue_stop_endpoint(xhci, command, slot_id, i, 298ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman suspend); 299ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman } 300be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 301ddba5cd0aeff5bbed92ebdf4b1223300b0541e78Mathias Nyman xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); 302be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_ring_cmd_db(xhci); 303be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 304be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 305be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu /* Wait for last stop endpoint command to finish */ 306c311e391a7efd101250c0e123286709b7e736249Mathias Nyman wait_for_completion(cmd->completion); 307c311e391a7efd101250c0e123286709b7e736249Mathias Nyman 308c311e391a7efd101250c0e123286709b7e736249Mathias Nyman if (cmd->status == COMP_CMD_ABORT || cmd->status == COMP_CMD_STOP) { 309c311e391a7efd101250c0e123286709b7e736249Mathias Nyman xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); 310be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu ret = -ETIME; 311be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 312be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_free_command(xhci, cmd); 313be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu return ret; 314be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu} 315be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 316be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu/* 317be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu * Ring device, it rings the all doorbells unconditionally. 318be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu */ 319561925318725a41189a69f36ebe99199b3fb84c4Andiry Xuvoid xhci_ring_device(struct xhci_hcd *xhci, int slot_id) 320be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu{ 321b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede int i, s; 322b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede struct xhci_virt_ep *ep; 323b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede 324b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede for (i = 0; i < LAST_EP_INDEX + 1; i++) { 325b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede ep = &xhci->devs[slot_id]->eps[i]; 326be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 327b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede if (ep->ep_state & EP_HAS_STREAMS) { 328b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede for (s = 1; s < ep->stream_info->num_streams; s++) 329b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede xhci_ring_ep_doorbell(xhci, slot_id, i, s); 330b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede } else if (ep->ring && ep->ring->dequeue) { 331be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_ring_ep_doorbell(xhci, slot_id, i, 0); 332b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede } 333b7f9696bd1b170dbff44b1b374b1473278bd2c53Hans de Goede } 334be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 335be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu return; 336be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu} 337be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 338f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharpstatic void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, 33928ccd2962c66556d7037b2d9f1c11cdcd3b805d5Matt Evans u16 wIndex, __le32 __iomem *addr, u32 port_status) 3406219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp{ 3416dd0a3a7e0793dbeae1b951f091025d8cf896cb4Sarah Sharp /* Don't allow the USB core to disable SuperSpeed ports. */ 342f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharp if (hcd->speed == HCD_USB3) { 3436dd0a3a7e0793dbeae1b951f091025d8cf896cb4Sarah Sharp xhci_dbg(xhci, "Ignoring request to disable " 3446dd0a3a7e0793dbeae1b951f091025d8cf896cb4Sarah Sharp "SuperSpeed port.\n"); 3456dd0a3a7e0793dbeae1b951f091025d8cf896cb4Sarah Sharp return; 3466dd0a3a7e0793dbeae1b951f091025d8cf896cb4Sarah Sharp } 3476dd0a3a7e0793dbeae1b951f091025d8cf896cb4Sarah Sharp 3486219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp /* Write 1 to disable the port */ 349204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(port_status | PORT_PE, addr); 350b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou port_status = readl(addr); 3516219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp xhci_dbg(xhci, "disable port, actual port %d status = 0x%x\n", 3526219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp wIndex, port_status); 3536219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp} 3546219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp 35534fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharpstatic void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, 35628ccd2962c66556d7037b2d9f1c11cdcd3b805d5Matt Evans u16 wIndex, __le32 __iomem *addr, u32 port_status) 35734fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp{ 35834fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp char *port_change_bit; 35934fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp u32 status; 36034fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp 36134fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp switch (wValue) { 36234fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp case USB_PORT_FEAT_C_RESET: 36334fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp status = PORT_RC; 36434fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp port_change_bit = "reset"; 36534fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp break; 366a11496ebf37534177d67222285e8debed7a39788Andiry Xu case USB_PORT_FEAT_C_BH_PORT_RESET: 367a11496ebf37534177d67222285e8debed7a39788Andiry Xu status = PORT_WRC; 368a11496ebf37534177d67222285e8debed7a39788Andiry Xu port_change_bit = "warm(BH) reset"; 369a11496ebf37534177d67222285e8debed7a39788Andiry Xu break; 37034fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp case USB_PORT_FEAT_C_CONNECTION: 37134fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp status = PORT_CSC; 37234fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp port_change_bit = "connect"; 37334fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp break; 37434fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp case USB_PORT_FEAT_C_OVER_CURRENT: 37534fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp status = PORT_OCC; 37634fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp port_change_bit = "over-current"; 37734fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp break; 3786219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp case USB_PORT_FEAT_C_ENABLE: 3796219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp status = PORT_PEC; 3806219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp port_change_bit = "enable/disable"; 3816219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp break; 382be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu case USB_PORT_FEAT_C_SUSPEND: 383be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu status = PORT_PLC; 384be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu port_change_bit = "suspend/resume"; 385be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu break; 38685387c0ea3e1cd85ad9d7215917ff5e71ca2aea3Andiry Xu case USB_PORT_FEAT_C_PORT_LINK_STATE: 38785387c0ea3e1cd85ad9d7215917ff5e71ca2aea3Andiry Xu status = PORT_PLC; 38885387c0ea3e1cd85ad9d7215917ff5e71ca2aea3Andiry Xu port_change_bit = "link state"; 38985387c0ea3e1cd85ad9d7215917ff5e71ca2aea3Andiry Xu break; 39034fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp default: 39134fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp /* Should never happen */ 39234fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp return; 39334fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp } 39434fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp /* Change bits are all write 1 to clear */ 395204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(port_status | status, addr); 396b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou port_status = readl(addr); 39734fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp xhci_dbg(xhci, "clear port %s change, actual port %d status = 0x%x\n", 39834fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp port_change_bit, wIndex, port_status); 39934fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp} 40034fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp 401a0885924326f79e157847010a9aaf49b058b30dchuajun listatic int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array) 402a0885924326f79e157847010a9aaf49b058b30dchuajun li{ 403a0885924326f79e157847010a9aaf49b058b30dchuajun li int max_ports; 404a0885924326f79e157847010a9aaf49b058b30dchuajun li struct xhci_hcd *xhci = hcd_to_xhci(hcd); 405a0885924326f79e157847010a9aaf49b058b30dchuajun li 406a0885924326f79e157847010a9aaf49b058b30dchuajun li if (hcd->speed == HCD_USB3) { 407a0885924326f79e157847010a9aaf49b058b30dchuajun li max_ports = xhci->num_usb3_ports; 408a0885924326f79e157847010a9aaf49b058b30dchuajun li *port_array = xhci->usb3_ports; 409a0885924326f79e157847010a9aaf49b058b30dchuajun li } else { 410a0885924326f79e157847010a9aaf49b058b30dchuajun li max_ports = xhci->num_usb2_ports; 411a0885924326f79e157847010a9aaf49b058b30dchuajun li *port_array = xhci->usb2_ports; 412a0885924326f79e157847010a9aaf49b058b30dchuajun li } 413a0885924326f79e157847010a9aaf49b058b30dchuajun li 414a0885924326f79e157847010a9aaf49b058b30dchuajun li return max_ports; 415a0885924326f79e157847010a9aaf49b058b30dchuajun li} 416a0885924326f79e157847010a9aaf49b058b30dchuajun li 417c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xuvoid xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, 418c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu int port_id, u32 link_state) 419c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu{ 420c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu u32 temp; 421c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu 422b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[port_id]); 423c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu temp = xhci_port_state_to_neutral(temp); 424c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu temp &= ~PORT_PLS_MASK; 425c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu temp |= PORT_LINK_STROBE | link_state; 426204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, port_array[port_id]); 427c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu} 428c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu 429ed384bd3a8faab3b3e09fd2cab8a7dc95851d771Felipe Balbistatic void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, 4304296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp __le32 __iomem **port_array, int port_id, u16 wake_mask) 4314296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp{ 4324296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp u32 temp; 4334296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp 434b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[port_id]); 4354296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp temp = xhci_port_state_to_neutral(temp); 4364296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp 4374296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT) 4384296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp temp |= PORT_WKCONN_E; 4394296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp else 4404296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp temp &= ~PORT_WKCONN_E; 4414296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp 4424296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT) 4434296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp temp |= PORT_WKDISC_E; 4444296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp else 4454296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp temp &= ~PORT_WKDISC_E; 4464296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp 4474296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT) 4484296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp temp |= PORT_WKOC_E; 4494296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp else 4504296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp temp &= ~PORT_WKOC_E; 4514296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp 452204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, port_array[port_id]); 4534296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp} 4544296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp 455d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu/* Test and clear port RWC bit */ 456d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xuvoid xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, 457d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu int port_id, u32 port_bit) 458d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu{ 459d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu u32 temp; 460d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu 461b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[port_id]); 462d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu if (temp & port_bit) { 463d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu temp = xhci_port_state_to_neutral(temp); 464d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu temp |= port_bit; 465204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, port_array[port_id]); 466d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu } 467d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu} 468d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu 469063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp/* Updates Link Status for USB 2.1 port */ 470063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharpstatic void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg) 471063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp{ 472063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp if ((status_reg & PORT_PLS_MASK) == XDEV_U2) 473063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp *status |= USB_PORT_STAT_L1; 474063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp} 475063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp 4768bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon/* Updates Link Status for super Speed port */ 47796908589a8b2584b1185f834d365f5cc360e8226Felipe Balbistatic void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, 47896908589a8b2584b1185f834d365f5cc360e8226Felipe Balbi u32 *status, u32 status_reg) 4798bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon{ 4808bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon u32 pls = status_reg & PORT_PLS_MASK; 4818bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon 4828bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon /* resume state is a xHCI internal state. 4838bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * Do not report it to usb core. 4848bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon */ 4858bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon if (pls == XDEV_RESUME) 4868bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon return; 4878bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon 4888bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon /* When the CAS bit is set then warm reset 4898bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * should be performed on port 4908bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon */ 4918bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon if (status_reg & PORT_CAS) { 4928bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon /* The CAS bit can be set while the port is 4938bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * in any link state. 4948bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * Only roothubs have CAS bit, so we 4958bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * pretend to be in compliance mode 4968bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * unless we're already in compliance 4978bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * or the inactive state. 4988bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon */ 4998bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon if (pls != USB_SS_PORT_LS_COMP_MOD && 5008bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon pls != USB_SS_PORT_LS_SS_INACTIVE) { 5018bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon pls = USB_SS_PORT_LS_COMP_MOD; 5028bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon } 5038bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon /* Return also connection bit - 5048bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * hub state machine resets port 5058bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon * when this bit is set. 5068bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon */ 5078bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon pls |= USB_PORT_STAT_CONNECTION; 50871c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes } else { 50971c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes /* 51071c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * If CAS bit isn't set but the Port is already at 51171c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * Compliance Mode, fake a connection so the USB core 51271c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * notices the Compliance state and resets the port. 51371c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * This resolves an issue generated by the SN65LVPE502CP 51471c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * in which sometimes the port enters compliance mode 51571c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * caused by a delay on the host-device negotiation. 51671c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes */ 51796908589a8b2584b1185f834d365f5cc360e8226Felipe Balbi if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && 51896908589a8b2584b1185f834d365f5cc360e8226Felipe Balbi (pls == USB_SS_PORT_LS_COMP_MOD)) 51971c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes pls |= USB_PORT_STAT_CONNECTION; 5208bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon } 52171c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes 5228bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon /* update status field */ 5238bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon *status |= pls; 5248bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon} 5258bea2bd37df08aaa599aa361a9f8b836ba98e554Stanislaw Ledwon 52671c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes/* 52771c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * Function for Compliance Mode Quirk. 52871c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * 52971c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * This Function verifies if all xhc USB3 ports have entered U0, if so, 53071c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * the compliance mode timer is deleted. A port won't enter 53171c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes * compliance mode if it has previously entered U0. 53271c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes */ 5335f20cf12a63650afe1871c7b2c89ee84ec3c6182Sachin Kamatstatic void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, 5345f20cf12a63650afe1871c7b2c89ee84ec3c6182Sachin Kamat u16 wIndex) 53571c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes{ 53671c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1); 53771c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); 53871c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes 53971c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) 54071c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes return; 54171c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes 54271c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { 54371c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes xhci->port_status_u0 |= 1 << wIndex; 54471c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes if (xhci->port_status_u0 == all_ports_seen_u0) { 54571c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes del_timer_sync(&xhci->comp_mode_recovery_timer); 5464bdfe4c38fd5b06da558050a3288a0a48825a3e7Xenia Ragiadakou xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, 5474bdfe4c38fd5b06da558050a3288a0a48825a3e7Xenia Ragiadakou "All USB3 ports have entered U0 already!"); 5484bdfe4c38fd5b06da558050a3288a0a48825a3e7Xenia Ragiadakou xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, 5494bdfe4c38fd5b06da558050a3288a0a48825a3e7Xenia Ragiadakou "Compliance Mode Recovery Timer Deleted."); 55071c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes } 55171c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes } 55271c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes} 55371c731a296f1b08a3724bd1b514b64f1bda87a23Alexis R. Cortes 554eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp/* 555eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * Converts a raw xHCI port status into the format that external USB 2.0 or USB 556eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * 3.0 hubs use. 557eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * 558eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * Possible side effects: 559eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * - Mark a port as being done with device resume, 560eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * and ring the endpoint doorbells. 561eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * - Stop the Synopsys redriver Compliance Mode polling. 5628b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp * - Drop and reacquire the xHCI lock, in order to wait for port resume. 563eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp */ 564eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharpstatic u32 xhci_get_port_status(struct usb_hcd *hcd, 565eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp struct xhci_bus_state *bus_state, 566eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp __le32 __iomem **port_array, 5678b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp u16 wIndex, u32 raw_port_status, 5688b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp unsigned long flags) 5698b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp __releases(&xhci->lock) 5708b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp __acquires(&xhci->lock) 571eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp{ 572eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp struct xhci_hcd *xhci = hcd_to_xhci(hcd); 573eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp u32 status = 0; 574eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp int slot_id; 575eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp 576eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp /* wPortChange bits */ 577eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (raw_port_status & PORT_CSC) 578eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_C_CONNECTION << 16; 579eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (raw_port_status & PORT_PEC) 580eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_C_ENABLE << 16; 581eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if ((raw_port_status & PORT_OCC)) 582eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_C_OVERCURRENT << 16; 583eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if ((raw_port_status & PORT_RC)) 584eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_C_RESET << 16; 585eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp /* USB3.0 only */ 586eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (hcd->speed == HCD_USB3) { 587eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if ((raw_port_status & PORT_PLC)) 588eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_C_LINK_STATE << 16; 589eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if ((raw_port_status & PORT_WRC)) 590eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_C_BH_RESET << 16; 591eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 592eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp 593eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (hcd->speed != HCD_USB3) { 594eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3 595eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp && (raw_port_status & PORT_POWER)) 596eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_SUSPEND; 597eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 598eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && 599eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp !DEV_SUPERSPEED(raw_port_status)) { 600eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if ((raw_port_status & PORT_RESET) || 601eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp !(raw_port_status & PORT_PE)) 602eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp return 0xffffffff; 603eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (time_after_eq(jiffies, 604eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp bus_state->resume_done[wIndex])) { 6058b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp int time_left; 6068b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp 607eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp xhci_dbg(xhci, "Resume USB2 port %d\n", 608eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp wIndex + 1); 609eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp bus_state->resume_done[wIndex] = 0; 610eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp clear_bit(wIndex, &bus_state->resuming_ports); 6118b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp 6128b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp set_bit(wIndex, &bus_state->rexit_ports); 613eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp xhci_set_link_state(xhci, port_array, wIndex, 614eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp XDEV_U0); 6158b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp 6168b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp spin_unlock_irqrestore(&xhci->lock, flags); 6178b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp time_left = wait_for_completion_timeout( 6188b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp &bus_state->rexit_done[wIndex], 6198b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp msecs_to_jiffies( 6208b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp XHCI_MAX_REXIT_TIMEOUT)); 6218b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp spin_lock_irqsave(&xhci->lock, flags); 6228b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp 6238b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp if (time_left) { 6248b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp slot_id = xhci_find_slot_id_by_port(hcd, 6258b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp xhci, wIndex + 1); 6268b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp if (!slot_id) { 6278b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp xhci_dbg(xhci, "slot_id is zero\n"); 6288b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp return 0xffffffff; 6298b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp } 6308b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp xhci_ring_device(xhci, slot_id); 6318b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp } else { 632b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou int port_status = readl(port_array[wIndex]); 6338b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", 6348b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp XHCI_MAX_REXIT_TIMEOUT, 6358b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp port_status); 6368b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp status |= USB_PORT_STAT_SUSPEND; 6378b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp clear_bit(wIndex, &bus_state->rexit_ports); 638eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 6398b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp 640eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp bus_state->port_c_suspend |= 1 << wIndex; 641eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp bus_state->suspended_ports &= ~(1 << wIndex); 642eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } else { 643eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp /* 644eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * The resume has been signaling for less than 645eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * 20ms. Report the port status as SUSPEND, 646eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * let the usbcore check port status again 647eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * and clear resume signaling later. 648eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp */ 649eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_SUSPEND; 650eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 651eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 652eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 653eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp && (raw_port_status & PORT_POWER) 654eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp && (bus_state->suspended_ports & (1 << wIndex))) { 655eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp bus_state->suspended_ports &= ~(1 << wIndex); 656eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (hcd->speed != HCD_USB3) 657eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp bus_state->port_c_suspend |= 1 << wIndex; 658eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 659eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (raw_port_status & PORT_CONNECT) { 660eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_CONNECTION; 661eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= xhci_port_speed(raw_port_status); 662eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 663eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (raw_port_status & PORT_PE) 664eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_ENABLE; 665eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (raw_port_status & PORT_OC) 666eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_OVERCURRENT; 667eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (raw_port_status & PORT_RESET) 668eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_RESET; 669eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (raw_port_status & PORT_POWER) { 670eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (hcd->speed == HCD_USB3) 671eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_SS_PORT_STAT_POWER; 672eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp else 673eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= USB_PORT_STAT_POWER; 674eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 675063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp /* Update Port Link State */ 676eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (hcd->speed == HCD_USB3) { 67796908589a8b2584b1185f834d365f5cc360e8226Felipe Balbi xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status); 678eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp /* 679eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * Verify if all USB3 Ports Have entered U0 already. 680eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp * Delete Compliance Mode Timer if so. 681eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp */ 682eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex); 683063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp } else { 684063ebeb4335312d05bdf6fb4fc0e41500c6c0afbSarah Sharp xhci_hub_report_usb2_link_state(&status, raw_port_status); 685eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp } 686eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (bus_state->port_c_suspend & (1 << wIndex)) 687eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status |= 1 << USB_PORT_FEAT_C_SUSPEND; 688eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp 689eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp return status; 690eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp} 691eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp 6920f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharpint xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, 6930f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp u16 wIndex, char *buf, u16 wLength) 6940f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp{ 6950f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp struct xhci_hcd *xhci = hcd_to_xhci(hcd); 696a0885924326f79e157847010a9aaf49b058b30dchuajun li int max_ports; 6970f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp unsigned long flags; 698c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu u32 temp, status; 6990f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp int retval = 0; 70028ccd2962c66556d7037b2d9f1c11cdcd3b805d5Matt Evans __le32 __iomem **port_array; 701be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu int slot_id; 70220b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp struct xhci_bus_state *bus_state; 7032c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu u16 link_state = 0; 7044296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp u16 wake_mask = 0; 705797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp u16 timeout = 0; 7060f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 707a0885924326f79e157847010a9aaf49b058b30dchuajun li max_ports = xhci_get_ports(hcd, &port_array); 70820b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state = &xhci->bus_state[hcd_index(hcd)]; 7090f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 7100f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp spin_lock_irqsave(&xhci->lock, flags); 7110f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp switch (typeReq) { 7120f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case GetHubStatus: 7130f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* No power source, over-current reported per port */ 7140f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp memset(buf, 0, 4); 7150f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp break; 7160f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case GetHubDescriptor: 7174bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* Check to make sure userspace is asking for the USB 3.0 hub 7184bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * descriptor for the USB 3.0 roothub. If not, we stall the 7194bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp * endpoint, like external hubs do. 7204bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp */ 7214bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp if (hcd->speed == HCD_USB3 && 7224bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp (wLength < USB_DT_SS_HUB_SIZE || 7234bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp wValue != (USB_DT_SS_HUB << 8))) { 7244bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp xhci_dbg(xhci, "Wrong hub descriptor type for " 7254bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp "USB 3.0 roothub.\n"); 7264bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp goto error; 7274bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp } 728f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharp xhci_hub_descriptor(hcd, xhci, 729f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharp (struct usb_hub_descriptor *) buf); 7300f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp break; 73148e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp case DeviceRequest | USB_REQ_GET_DESCRIPTOR: 73248e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp if ((wValue & 0xff00) != (USB_DT_BOS << 8)) 73348e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp goto error; 73448e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 73548e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp if (hcd->speed != HCD_USB3) 73648e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp goto error; 73748e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 738af3a23ef4e5fbaf33f0afdda7d26442f036ba795Sarah Sharp /* Set the U1 and U2 exit latencies. */ 73948e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp memcpy(buf, &usb_bos_descriptor, 74048e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE); 74125cd2882e2fc8bd8ed7acaee0ec979f11feda6d7Sarah Sharp if ((xhci->quirks & XHCI_LPM_SUPPORT)) { 74225cd2882e2fc8bd8ed7acaee0ec979f11feda6d7Sarah Sharp temp = readl(&xhci->cap_regs->hcs_params3); 74325cd2882e2fc8bd8ed7acaee0ec979f11feda6d7Sarah Sharp buf[12] = HCS_U1_LATENCY(temp); 74425cd2882e2fc8bd8ed7acaee0ec979f11feda6d7Sarah Sharp put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); 74525cd2882e2fc8bd8ed7acaee0ec979f11feda6d7Sarah Sharp } 74648e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp 747af3a23ef4e5fbaf33f0afdda7d26442f036ba795Sarah Sharp /* Indicate whether the host has LTM support. */ 748b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(&xhci->cap_regs->hcc_params); 749af3a23ef4e5fbaf33f0afdda7d26442f036ba795Sarah Sharp if (HCC_LTC(temp)) 750af3a23ef4e5fbaf33f0afdda7d26442f036ba795Sarah Sharp buf[8] |= USB_LTM_SUPPORT; 751af3a23ef4e5fbaf33f0afdda7d26442f036ba795Sarah Sharp 75248e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp spin_unlock_irqrestore(&xhci->lock, flags); 75348e8236114c12c5366e032fc517e1bd376369a56Sarah Sharp return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE; 7540f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case GetPortStatus: 755a0885924326f79e157847010a9aaf49b058b30dchuajun li if (!wIndex || wIndex > max_ports) 7560f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp goto error; 7570f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp wIndex--; 758b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 759f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp if (temp == 0xffffffff) { 760f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp retval = -ENODEV; 761f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp break; 762f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp } 763eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp status = xhci_get_port_status(hcd, bus_state, port_array, 7648b3d45705e54075cfb9d4212dbca9ea82c85c4b8Sarah Sharp wIndex, temp, flags); 765eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp if (status == 0xffffffff) 766eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp goto error; 7670ed9a57e052a3d20df052a2ff12a3b42380867aaAndiry Xu 768eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n", 769eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp wIndex, temp); 7700f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp xhci_dbg(xhci, "Get port status returned 0x%x\n", status); 771eae5b17621d1053c81bec24e5dd5094bf50b31c6Sarah Sharp 7720f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp put_unaligned(cpu_to_le32(status), (__le32 *) buf); 7730f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp break; 7740f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case SetPortFeature: 7752c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu if (wValue == USB_PORT_FEAT_LINK_STATE) 7762c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu link_state = (wIndex & 0xff00) >> 3; 7774296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK) 7784296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp wake_mask = wIndex & 0xff00; 779797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp /* The MSB of wIndex is the U1/U2 timeout */ 780797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp timeout = (wIndex & 0xff00) >> 8; 7810f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp wIndex &= 0xff; 782a0885924326f79e157847010a9aaf49b058b30dchuajun li if (!wIndex || wIndex > max_ports) 7830f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp goto error; 7840f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp wIndex--; 785b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 786f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp if (temp == 0xffffffff) { 787f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp retval = -ENODEV; 788f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp break; 789f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp } 7900f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp temp = xhci_port_state_to_neutral(temp); 7914bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* FIXME: What new port features do we need to support? */ 7920f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp switch (wValue) { 793be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu case USB_PORT_FEAT_SUSPEND: 794b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 79565580b4321eb36f16ae8b5987bfa1bb948fc5112Andiry Xu if ((temp & PORT_PLS_MASK) != XDEV_U0) { 79665580b4321eb36f16ae8b5987bfa1bb948fc5112Andiry Xu /* Resume the port to U0 first */ 79765580b4321eb36f16ae8b5987bfa1bb948fc5112Andiry Xu xhci_set_link_state(xhci, port_array, wIndex, 79865580b4321eb36f16ae8b5987bfa1bb948fc5112Andiry Xu XDEV_U0); 79965580b4321eb36f16ae8b5987bfa1bb948fc5112Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 80065580b4321eb36f16ae8b5987bfa1bb948fc5112Andiry Xu msleep(10); 80165580b4321eb36f16ae8b5987bfa1bb948fc5112Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 80265580b4321eb36f16ae8b5987bfa1bb948fc5112Andiry Xu } 803be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu /* In spec software should not attempt to suspend 804be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu * a port unless the port reports that it is in the 805be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu * enabled (PED = ‘1’,PLS < ‘3’) state. 806be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu */ 807b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 808be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) 809be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu || (temp & PORT_PLS_MASK) >= XDEV_U3) { 810be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_warn(xhci, "USB core suspending device " 811be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu "not in U0/U1/U2.\n"); 812be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu goto error; 813be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 814be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 8155233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharp slot_id = xhci_find_slot_id_by_port(hcd, xhci, 8165233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharp wIndex + 1); 817be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu if (!slot_id) { 818be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_warn(xhci, "slot_id is zero\n"); 819be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu goto error; 820be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 821be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu /* unlock to execute stop endpoint commands */ 822be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 823be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_stop_device(xhci, slot_id, 1); 824be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 825be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 826c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu xhci_set_link_state(xhci, port_array, wIndex, XDEV_U3); 827be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 828be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 829be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu msleep(10); /* wait device to enter */ 830be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 831be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 832b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 83320b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state->suspended_ports |= 1 << wIndex; 834be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu break; 8352c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu case USB_PORT_FEAT_LINK_STATE: 836b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 83741e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp 83841e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp /* Disable port */ 83941e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp if (link_state == USB_SS_PORT_LS_SS_DISABLED) { 84041e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp xhci_dbg(xhci, "Disable port %d\n", wIndex); 84141e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp temp = xhci_port_state_to_neutral(temp); 84241e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp /* 84341e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp * Clear all change bits, so that we get a new 84441e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp * connection event. 84541e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp */ 84641e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp temp |= PORT_CSC | PORT_PEC | PORT_WRC | 84741e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp PORT_OCC | PORT_RC | PORT_PLC | 84841e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp PORT_CEC; 849204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp | PORT_PE, port_array[wIndex]); 850b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 85141e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp break; 85241e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp } 85341e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp 85441e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp /* Put link in RxDetect (enable port) */ 85541e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp if (link_state == USB_SS_PORT_LS_RX_DETECT) { 85641e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp xhci_dbg(xhci, "Enable port %d\n", wIndex); 85741e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp xhci_set_link_state(xhci, port_array, wIndex, 85841e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp link_state); 859b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 86041e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp break; 86141e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp } 86241e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp 8632c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu /* Software should not attempt to set 86441e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp * port link state above '3' (U3) and the port 8652c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu * must be enabled. 8662c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu */ 8672c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu if ((temp & PORT_PE) == 0 || 86841e7e056cdc662f704fa9262e5c6e213b4ab45ddSarah Sharp (link_state > USB_SS_PORT_LS_U3)) { 8692c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu xhci_warn(xhci, "Cannot set link state.\n"); 8702c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu goto error; 8712c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu } 8722c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu 8732c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu if (link_state == USB_SS_PORT_LS_U3) { 8742c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu slot_id = xhci_find_slot_id_by_port(hcd, xhci, 8752c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu wIndex + 1); 8762c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu if (slot_id) { 8772c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu /* unlock to execute stop endpoint 8782c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu * commands */ 8792c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu spin_unlock_irqrestore(&xhci->lock, 8802c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu flags); 8812c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu xhci_stop_device(xhci, slot_id, 1); 8822c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 8832c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu } 8842c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu } 8852c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu 886c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu xhci_set_link_state(xhci, port_array, wIndex, 887c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu link_state); 8882c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu 8892c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 8902c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu msleep(20); /* wait device to enter */ 8912c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 8922c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu 893b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 8942c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu if (link_state == USB_SS_PORT_LS_U3) 8952c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu bus_state->suspended_ports |= 1 << wIndex; 8962c44178032b046c4113c40d0d459a0d36e39b920Andiry Xu break; 8970f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case USB_PORT_FEAT_POWER: 8980f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* 8990f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Turn on ports, even if there isn't per-port switching. 9000f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * HC will report connect events even before this is set. 90137ebb54915dc42944f6ae92fe53b9531c3903801Petr Mladek * However, hub_wq will ignore the roothub events until 9020f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * the roothub is registered. 9030f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 904204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp | PORT_POWER, port_array[wIndex]); 9050f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 906b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 9070f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); 908f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu 909170ed807340b4db0a5e010c2e4da43cf5a2c9a29Lan Tianyu spin_unlock_irqrestore(&xhci->lock, flags); 910f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu temp = usb_acpi_power_manageable(hcd->self.root_hub, 911f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu wIndex); 912f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu if (temp) 913f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu usb_acpi_set_power_state(hcd->self.root_hub, 914f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu wIndex, true); 915170ed807340b4db0a5e010c2e4da43cf5a2c9a29Lan Tianyu spin_lock_irqsave(&xhci->lock, flags); 9160f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp break; 9170f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case USB_PORT_FEAT_RESET: 9180f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp temp = (temp | PORT_RESET); 919204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, port_array[wIndex]); 9200f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 921b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 9220f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); 9230f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp break; 9244296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp case USB_PORT_FEAT_REMOTE_WAKE_MASK: 9254296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp xhci_set_remote_wake_mask(xhci, port_array, 9264296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp wIndex, wake_mask); 927b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 9284296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp xhci_dbg(xhci, "set port remote wake mask, " 9294296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp "actual port %d status = 0x%x\n", 9304296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp wIndex, temp); 9314296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp break; 932a11496ebf37534177d67222285e8debed7a39788Andiry Xu case USB_PORT_FEAT_BH_PORT_RESET: 933a11496ebf37534177d67222285e8debed7a39788Andiry Xu temp |= PORT_WR; 934204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, port_array[wIndex]); 935a11496ebf37534177d67222285e8debed7a39788Andiry Xu 936b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 937a11496ebf37534177d67222285e8debed7a39788Andiry Xu break; 938797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp case USB_PORT_FEAT_U1_TIMEOUT: 939797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp if (hcd->speed != HCD_USB3) 940797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp goto error; 941b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex] + PORTPMSC); 942797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp temp &= ~PORT_U1_TIMEOUT_MASK; 943797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp temp |= PORT_U1_TIMEOUT(timeout); 944204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, port_array[wIndex] + PORTPMSC); 945797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp break; 946797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp case USB_PORT_FEAT_U2_TIMEOUT: 947797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp if (hcd->speed != HCD_USB3) 948797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp goto error; 949b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex] + PORTPMSC); 950797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp temp &= ~PORT_U2_TIMEOUT_MASK; 951797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp temp |= PORT_U2_TIMEOUT(timeout); 952204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, port_array[wIndex] + PORTPMSC); 953797b0ca5e6283b4cc0bdeeb0e5915f21522ba85fSarah Sharp break; 9540f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp default: 9550f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp goto error; 9560f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp } 9575308a91b9fc1a8f94b860c2589b06908a97cba7eSarah Sharp /* unblock any posted writes */ 958b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 9590f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp break; 9600f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case ClearPortFeature: 961a0885924326f79e157847010a9aaf49b058b30dchuajun li if (!wIndex || wIndex > max_ports) 9620f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp goto error; 9630f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp wIndex--; 964b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 965f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp if (temp == 0xffffffff) { 966f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp retval = -ENODEV; 967f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp break; 968f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp } 9694bbb0ace9a3de8392527e3c87926309d541d3b00Sarah Sharp /* FIXME: What new port features do we need to support? */ 9700f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp temp = xhci_port_state_to_neutral(temp); 9710f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp switch (wValue) { 972be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu case USB_PORT_FEAT_SUSPEND: 973b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[wIndex]); 974be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n"); 975be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_dbg(xhci, "PORTSC %04x\n", temp); 976be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu if (temp & PORT_RESET) 977be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu goto error; 9785ac04bf190e6f8b17238aef179ebd7f2bdfec919Andiry Xu if ((temp & PORT_PLS_MASK) == XDEV_U3) { 979be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu if ((temp & PORT_PE) == 0) 980be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu goto error; 981be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 982c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu xhci_set_link_state(xhci, port_array, wIndex, 983c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu XDEV_RESUME); 984c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 985a7114230f6bd925f1c734d8ca1c32c93bf956aedAndiry Xu msleep(20); 986a7114230f6bd925f1c734d8ca1c32c93bf956aedAndiry Xu spin_lock_irqsave(&xhci->lock, flags); 987c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu xhci_set_link_state(xhci, port_array, wIndex, 988c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu XDEV_U0); 989be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 990a7114230f6bd925f1c734d8ca1c32c93bf956aedAndiry Xu bus_state->port_c_suspend |= 1 << wIndex; 991be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu 9925233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharp slot_id = xhci_find_slot_id_by_port(hcd, xhci, 9935233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharp wIndex + 1); 994be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu if (!slot_id) { 995be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_dbg(xhci, "slot_id is zero\n"); 996be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu goto error; 997be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu } 998be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu xhci_ring_device(xhci, slot_id); 999be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu break; 1000be88fe4f4dda93e3264a887745123b1e6c4a6845Andiry Xu case USB_PORT_FEAT_C_SUSPEND: 100120b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state->port_c_suspend &= ~(1 << wIndex); 10020f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case USB_PORT_FEAT_C_RESET: 1003a11496ebf37534177d67222285e8debed7a39788Andiry Xu case USB_PORT_FEAT_C_BH_PORT_RESET: 10040f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case USB_PORT_FEAT_C_CONNECTION: 10050f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp case USB_PORT_FEAT_C_OVER_CURRENT: 10066219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp case USB_PORT_FEAT_C_ENABLE: 100785387c0ea3e1cd85ad9d7215917ff5e71ca2aea3Andiry Xu case USB_PORT_FEAT_C_PORT_LINK_STATE: 100834fb562a436ca50e13c05e7584c9d62f151052bfSarah Sharp xhci_clear_port_change_bit(xhci, wValue, wIndex, 10095308a91b9fc1a8f94b860c2589b06908a97cba7eSarah Sharp port_array[wIndex], temp); 10100f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp break; 10116219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp case USB_PORT_FEAT_ENABLE: 1012f6ff0ac878eb420011fa2448851dd48c3a7e7b31Sarah Sharp xhci_disable_port(hcd, xhci, wIndex, 10135308a91b9fc1a8f94b860c2589b06908a97cba7eSarah Sharp port_array[wIndex], temp); 10146219c047d3fe18dee4916d6898fc94f5a7ffd156Sarah Sharp break; 1015693d8eb853f62a1341cf59df151b12c053f34e8aLan Tianyu case USB_PORT_FEAT_POWER: 1016204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp & ~PORT_POWER, port_array[wIndex]); 1017f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu 1018170ed807340b4db0a5e010c2e4da43cf5a2c9a29Lan Tianyu spin_unlock_irqrestore(&xhci->lock, flags); 1019f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu temp = usb_acpi_power_manageable(hcd->self.root_hub, 1020f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu wIndex); 1021f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu if (temp) 1022f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu usb_acpi_set_power_state(hcd->self.root_hub, 1023f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu wIndex, false); 1024170ed807340b4db0a5e010c2e4da43cf5a2c9a29Lan Tianyu spin_lock_irqsave(&xhci->lock, flags); 1025693d8eb853f62a1341cf59df151b12c053f34e8aLan Tianyu break; 10260f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp default: 10270f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp goto error; 10280f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp } 10290f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp break; 10300f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp default: 10310f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharperror: 10320f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* "stall" on error */ 10330f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp retval = -EPIPE; 10340f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp } 10350f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp spin_unlock_irqrestore(&xhci->lock, flags); 10360f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp return retval; 10370f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp} 10380f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 10390f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp/* 10400f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Returns 0 if the status hasn't changed, or the number of bytes in buf. 10410f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Ports are 0-indexed from the HCD point of view, 10420f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * and 1-indexed from the USB core pointer of view. 10430f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * 10440f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * Note that the status change bits will be cleared as soon as a port status 10450f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp * change event is generated, so we use the saved status from that event. 10460f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp */ 10470f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharpint xhci_hub_status_data(struct usb_hcd *hcd, char *buf) 10480f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp{ 10490f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp unsigned long flags; 10500f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp u32 temp, status; 1051561925318725a41189a69f36ebe99199b3fb84c4Andiry Xu u32 mask; 10520f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp int i, retval; 10530f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp struct xhci_hcd *xhci = hcd_to_xhci(hcd); 1054a0885924326f79e157847010a9aaf49b058b30dchuajun li int max_ports; 105528ccd2962c66556d7037b2d9f1c11cdcd3b805d5Matt Evans __le32 __iomem **port_array; 105620b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp struct xhci_bus_state *bus_state; 1057c52804a472649b2e5005342308739434cbd51119Sarah Sharp bool reset_change = false; 10580f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 1059a0885924326f79e157847010a9aaf49b058b30dchuajun li max_ports = xhci_get_ports(hcd, &port_array); 106020b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state = &xhci->bus_state[hcd_index(hcd)]; 10610f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 10620f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* Initial status is no changes */ 1063a0885924326f79e157847010a9aaf49b058b30dchuajun li retval = (max_ports + 8) / 8; 1064419a8e81686b844c9682e8f1721e6795f3264ee6William Gulland memset(buf, 0, retval); 1065f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu 1066f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu /* 1067f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu * Inform the usbcore about resume-in-progress by returning 1068f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu * a non-zero value even if there are no status changes. 1069f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu */ 1070f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu status = bus_state->resuming_ports; 10710f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp 107244f4c3ed60fb21e1d2dd98304390ac121e6c7c6dGreg Kroah-Hartman mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC; 1073561925318725a41189a69f36ebe99199b3fb84c4Andiry Xu 10740f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp spin_lock_irqsave(&xhci->lock, flags); 10750f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp /* For each port, did anything change? If so, set that bit in buf. */ 1076a0885924326f79e157847010a9aaf49b058b30dchuajun li for (i = 0; i < max_ports; i++) { 1077b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[i]); 1078f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp if (temp == 0xffffffff) { 1079f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp retval = -ENODEV; 1080f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp break; 1081f9de8151877b4f01cc8e124b0e213a6c6c78d970Sarah Sharp } 1082561925318725a41189a69f36ebe99199b3fb84c4Andiry Xu if ((temp & mask) != 0 || 108320b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp (bus_state->port_c_suspend & 1 << i) || 108420b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp (bus_state->resume_done[i] && time_after_eq( 108520b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp jiffies, bus_state->resume_done[i]))) { 1086419a8e81686b844c9682e8f1721e6795f3264ee6William Gulland buf[(i + 1) / 8] |= 1 << (i + 1) % 8; 10870f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp status = 1; 10880f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp } 1089c52804a472649b2e5005342308739434cbd51119Sarah Sharp if ((temp & PORT_RC)) 1090c52804a472649b2e5005342308739434cbd51119Sarah Sharp reset_change = true; 1091c52804a472649b2e5005342308739434cbd51119Sarah Sharp } 1092c52804a472649b2e5005342308739434cbd51119Sarah Sharp if (!status && !reset_change) { 1093c52804a472649b2e5005342308739434cbd51119Sarah Sharp xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); 1094c52804a472649b2e5005342308739434cbd51119Sarah Sharp clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); 10950f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp } 10960f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp spin_unlock_irqrestore(&xhci->lock, flags); 10970f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp return status ? retval : 0; 10980f2a79300a1471cf92ab43af165ea13555c8b0a5Sarah Sharp} 10999777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11009777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu#ifdef CONFIG_PM 11019777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11029777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xuint xhci_bus_suspend(struct usb_hcd *hcd) 11039777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu{ 11049777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu struct xhci_hcd *xhci = hcd_to_xhci(hcd); 1105518e848ea8e2932ce18ce2daef8ad5f55a145f27Sarah Sharp int max_ports, port_index; 110628ccd2962c66556d7037b2d9f1c11cdcd3b805d5Matt Evans __le32 __iomem **port_array; 110720b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp struct xhci_bus_state *bus_state; 11089777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu unsigned long flags; 11099777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1110a0885924326f79e157847010a9aaf49b058b30dchuajun li max_ports = xhci_get_ports(hcd, &port_array); 111120b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state = &xhci->bus_state[hcd_index(hcd)]; 11129777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11139777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 11149777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11159777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if (hcd->self.root_hub->do_remote_wakeup) { 1116f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu if (bus_state->resuming_ports) { 1117f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 1118f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu xhci_dbg(xhci, "suspend failed because " 1119f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu "a port is resuming\n"); 1120f370b9968a220a3d79d870dd7dee674cc0ff3d10Andiry Xu return -EBUSY; 11219777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 11229777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 11239777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1124518e848ea8e2932ce18ce2daef8ad5f55a145f27Sarah Sharp port_index = max_ports; 112520b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state->bus_suspended = 0; 1126518e848ea8e2932ce18ce2daef8ad5f55a145f27Sarah Sharp while (port_index--) { 11279777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu /* suspend the port if the port is not suspended */ 11289777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu u32 t1, t2; 11299777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu int slot_id; 11309777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1131b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou t1 = readl(port_array[port_index]); 11329777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t2 = xhci_port_state_to_neutral(t1); 11339777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11349777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) { 1135518e848ea8e2932ce18ce2daef8ad5f55a145f27Sarah Sharp xhci_dbg(xhci, "port %d not suspended\n", port_index); 11365233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharp slot_id = xhci_find_slot_id_by_port(hcd, xhci, 1137518e848ea8e2932ce18ce2daef8ad5f55a145f27Sarah Sharp port_index + 1); 11389777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if (slot_id) { 11399777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 11409777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu xhci_stop_device(xhci, slot_id, 1); 11419777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 11429777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 11439777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t2 &= ~PORT_PLS_MASK; 11449777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t2 |= PORT_LINK_STROBE | XDEV_U3; 114520b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp set_bit(port_index, &bus_state->bus_suspended); 11469777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 11474296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp /* USB core sets remote wake mask for USB 3.0 hubs, 114884ebc10294a3d7be4c66f51070b7aedbaa24de9bAlan Stern * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME 11494296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp * is enabled, so also enable remote wake here. 11504296c70a5ec316903ef037ed15f154dd3d354ad7Sarah Sharp */ 11519b41ebd3cf0f68d8cad779d3eeba336f78262e43Lu Baolu if (hcd->self.root_hub->do_remote_wakeup) { 11529777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if (t1 & PORT_CONNECT) { 11539777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t2 |= PORT_WKOC_E | PORT_WKDISC_E; 11549777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t2 &= ~PORT_WKCONN_E; 11559777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } else { 11569777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t2 |= PORT_WKOC_E | PORT_WKCONN_E; 11579777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t2 &= ~PORT_WKDISC_E; 11589777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 11599777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } else 11609777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t2 &= ~PORT_WAKE_BITS; 11619777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11629777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu t1 = xhci_port_state_to_neutral(t1); 11639777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if (t1 != t2) 1164204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(t2, port_array[port_index]); 11659777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 11669777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu hcd->state = HC_STATE_SUSPENDED; 116720b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state->next_statechange = jiffies + msecs_to_jiffies(10); 11689777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 11699777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu return 0; 11709777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu} 11719777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11729777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xuint xhci_bus_resume(struct usb_hcd *hcd) 11739777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu{ 11749777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu struct xhci_hcd *xhci = hcd_to_xhci(hcd); 1175518e848ea8e2932ce18ce2daef8ad5f55a145f27Sarah Sharp int max_ports, port_index; 117628ccd2962c66556d7037b2d9f1c11cdcd3b805d5Matt Evans __le32 __iomem **port_array; 117720b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp struct xhci_bus_state *bus_state; 11789777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu u32 temp; 11799777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu unsigned long flags; 11809777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1181a0885924326f79e157847010a9aaf49b058b30dchuajun li max_ports = xhci_get_ports(hcd, &port_array); 118220b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state = &xhci->bus_state[hcd_index(hcd)]; 11839777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 118420b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp if (time_before(jiffies, bus_state->next_statechange)) 11859777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu msleep(5); 11869777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11879777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 11889777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if (!HCD_HW_ACCESSIBLE(hcd)) { 11899777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 11909777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu return -ESHUTDOWN; 11919777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 11929777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 11939777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu /* delay the irqs */ 1194b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(&xhci->op_regs->command); 11959777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu temp &= ~CMD_EIE; 1196204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, &xhci->op_regs->command); 11979777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1198518e848ea8e2932ce18ce2daef8ad5f55a145f27Sarah Sharp port_index = max_ports; 1199518e848ea8e2932ce18ce2daef8ad5f55a145f27Sarah Sharp while (port_index--) { 12009777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu /* Check whether need resume ports. If needed 12019777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu resume port and disable remote wakeup */ 12029777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu u32 temp; 12039777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu int slot_id; 12049777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1205b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(port_array[port_index]); 12069777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if (DEV_SUPERSPEED(temp)) 12079777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); 12089777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu else 12099777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 121020b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp if (test_bit(port_index, &bus_state->bus_suspended) && 12119777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu (temp & PORT_PLS_MASK)) { 12129777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if (DEV_SUPERSPEED(temp)) { 1213c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu xhci_set_link_state(xhci, port_array, 1214c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu port_index, XDEV_U0); 12159777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } else { 1216c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu xhci_set_link_state(xhci, port_array, 1217c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu port_index, XDEV_RESUME); 12189777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 12199777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 12209777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu msleep(20); 12219777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 12229777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1223c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu xhci_set_link_state(xhci, port_array, 1224c9682dffceb4bb3bdf6df4c0c87c4b887b03f5b7Andiry Xu port_index, XDEV_U0); 12259777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 12264f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu /* wait for the port to enter U0 and report port link 12274f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu * state change. 12284f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu */ 12294f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 12304f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu msleep(20); 12314f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu spin_lock_irqsave(&xhci->lock, flags); 12324f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu 12334f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu /* Clear PLC */ 1234d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu xhci_test_and_clear_bit(xhci, port_array, port_index, 1235d2f52c9e585bbb1a3c164e02b8dcd0d996c67353Andiry Xu PORT_PLC); 12364f0871a6c7811a433513c3788a7cce27033bb8b8Andiry Xu 12375233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharp slot_id = xhci_find_slot_id_by_port(hcd, 12385233630fcdd6f7d415dcbed264031439cab73f9dSarah Sharp xhci, port_index + 1); 12399777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu if (slot_id) 12409777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu xhci_ring_device(xhci, slot_id); 12419777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } else 1242204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, port_array[port_index]); 12439777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu } 12449777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1245b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou (void) readl(&xhci->op_regs->command); 12469777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 124720b67cf51fa606442bb343afad0ee1a393a6afb3Sarah Sharp bus_state->next_statechange = jiffies + msecs_to_jiffies(5); 12489777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu /* re-enable irqs */ 1249b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(&xhci->op_regs->command); 12509777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu temp |= CMD_EIE; 1251204b7793f2a9935e9a08524d0b4bb51b990d518eXenia Ragiadakou writel(temp, &xhci->op_regs->command); 1252b0ba9720846c980d053b1ffcd766fddfbef95d4cXenia Ragiadakou temp = readl(&xhci->op_regs->command); 12539777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 12549777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu spin_unlock_irqrestore(&xhci->lock, flags); 12559777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu return 0; 12569777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu} 12579777e3ce907d4cb5a513902a87ecd03b52499569Andiry Xu 1258436a389096e1feda2c382cad83b6a8d6de8615a0Sarah Sharp#endif /* CONFIG_PM */ 1259