xref: /openbmc/linux/drivers/usb/host/uhci-hub.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1 /*
2  * Universal Host Controller Interface driver for USB.
3  *
4  * Maintainer: Alan Stern <stern@rowland.harvard.edu>
5  *
6  * (C) Copyright 1999 Linus Torvalds
7  * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
8  * (C) Copyright 1999 Randy Dunlap
9  * (C) Copyright 1999 Georg Acher, acher@in.tum.de
10  * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
11  * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
12  * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
13  */
14 
15 static __u8 root_hub_hub_des[] =
16 {
17 	0x09,			/*  __u8  bLength; */
18 	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
19 	0x02,			/*  __u8  bNbrPorts; */
20 	0x0a,			/* __u16  wHubCharacteristics; */
21 	0x00,			/*   (per-port OC, no power switching) */
22 	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
23 	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
24 	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
25 	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
26 };
27 
28 #define	UHCI_RH_MAXCHILD	7
29 
30 /* must write as zeroes */
31 #define WZ_BITS		(USBPORTSC_RES2 | USBPORTSC_RES3 | USBPORTSC_RES4)
32 
33 /* status change bits:  nonzero writes will clear */
34 #define RWC_BITS	(USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
35 
36 static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
37 {
38 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
39 	int port;
40 
41 	*buf = 0;
42 	for (port = 0; port < uhci->rh_numports; ++port) {
43 		if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
44 				test_bit(port, &uhci->port_c_suspend))
45 			*buf |= (1 << (port + 1));
46 	}
47 	if (*buf && uhci->state == UHCI_SUSPENDED)
48 		uhci->resume_detect = 1;
49 	return !!*buf;
50 }
51 
52 #define OK(x)			len = (x); break
53 
54 #define CLR_RH_PORTSTAT(x) \
55 	status = inw(port_addr); \
56 	status &= ~(RWC_BITS|WZ_BITS); \
57 	status &= ~(x); \
58 	status |= RWC_BITS & (x); \
59 	outw(status, port_addr)
60 
61 #define SET_RH_PORTSTAT(x) \
62 	status = inw(port_addr); \
63 	status |= (x); \
64 	status &= ~(RWC_BITS|WZ_BITS); \
65 	outw(status, port_addr)
66 
67 /* UHCI controllers don't automatically stop resume signalling after 20 msec,
68  * so we have to poll and check timeouts in order to take care of it.
69  */
70 static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
71 		unsigned long port_addr)
72 {
73 	int status;
74 
75 	if (test_bit(port, &uhci->suspended_ports)) {
76 		CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
77 		clear_bit(port, &uhci->suspended_ports);
78 		clear_bit(port, &uhci->resuming_ports);
79 		set_bit(port, &uhci->port_c_suspend);
80 
81 		/* The controller won't actually turn off the RD bit until
82 		 * it has had a chance to send a low-speed EOP sequence,
83 		 * which takes 3 bit times (= 2 microseconds).  We'll delay
84 		 * slightly longer for good luck. */
85 		udelay(4);
86 	}
87 }
88 
89 static void uhci_check_ports(struct uhci_hcd *uhci)
90 {
91 	unsigned int port;
92 	unsigned long port_addr;
93 	int status;
94 
95 	for (port = 0; port < uhci->rh_numports; ++port) {
96 		port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
97 		status = inw(port_addr);
98 		if (unlikely(status & USBPORTSC_PR)) {
99 			if (time_after_eq(jiffies, uhci->ports_timeout)) {
100 				CLR_RH_PORTSTAT(USBPORTSC_PR);
101 				udelay(10);
102 
103 				/* If the port was enabled before, turning
104 				 * reset on caused a port enable change.
105 				 * Turning reset off causes a port connect
106 				 * status change.  Clear these changes. */
107 				CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC);
108 				SET_RH_PORTSTAT(USBPORTSC_PE);
109 			}
110 		}
111 		if (unlikely(status & USBPORTSC_RD)) {
112 			if (!test_bit(port, &uhci->resuming_ports)) {
113 
114 				/* Port received a wakeup request */
115 				set_bit(port, &uhci->resuming_ports);
116 				uhci->ports_timeout = jiffies +
117 						msecs_to_jiffies(20);
118 			} else if (time_after_eq(jiffies,
119 						uhci->ports_timeout)) {
120 				uhci_finish_suspend(uhci, port, port_addr);
121 			}
122 		}
123 	}
124 }
125 
126 /* size of returned buffer is part of USB spec */
127 static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
128 			u16 wIndex, char *buf, u16 wLength)
129 {
130 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
131 	int status, lstatus, retval = 0, len = 0;
132 	unsigned int port = wIndex - 1;
133 	unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
134 	u16 wPortChange, wPortStatus;
135 	unsigned long flags;
136 
137 	spin_lock_irqsave(&uhci->lock, flags);
138 	switch (typeReq) {
139 
140 	case GetHubStatus:
141 		*(__le32 *)buf = cpu_to_le32(0);
142 		OK(4);		/* hub power */
143 	case GetPortStatus:
144 		if (port >= uhci->rh_numports)
145 			goto err;
146 
147 		uhci_check_ports(uhci);
148 		status = inw(port_addr);
149 
150 		/* Intel controllers report the OverCurrent bit active on.
151 		 * VIA controllers report it active off, so we'll adjust the
152 		 * bit value.  (It's not standardized in the UHCI spec.)
153 		 */
154 		if (to_pci_dev(hcd->self.controller)->vendor ==
155 				PCI_VENDOR_ID_VIA)
156 			status ^= USBPORTSC_OC;
157 
158 		/* UHCI doesn't support C_RESET (always false) */
159 		wPortChange = lstatus = 0;
160 		if (status & USBPORTSC_CSC)
161 			wPortChange |= USB_PORT_STAT_C_CONNECTION;
162 		if (status & USBPORTSC_PEC)
163 			wPortChange |= USB_PORT_STAT_C_ENABLE;
164 		if (status & USBPORTSC_OCC)
165 			wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
166 
167 		if (test_bit(port, &uhci->port_c_suspend)) {
168 			wPortChange |= USB_PORT_STAT_C_SUSPEND;
169 			lstatus |= 1;
170 		}
171 		if (test_bit(port, &uhci->suspended_ports))
172 			lstatus |= 2;
173 		if (test_bit(port, &uhci->resuming_ports))
174 			lstatus |= 4;
175 
176 		/* UHCI has no power switching (always on) */
177 		wPortStatus = USB_PORT_STAT_POWER;
178 		if (status & USBPORTSC_CCS)
179 			wPortStatus |= USB_PORT_STAT_CONNECTION;
180 		if (status & USBPORTSC_PE) {
181 			wPortStatus |= USB_PORT_STAT_ENABLE;
182 			if (status & (USBPORTSC_SUSP | USBPORTSC_RD))
183 				wPortStatus |= USB_PORT_STAT_SUSPEND;
184 		}
185 		if (status & USBPORTSC_OC)
186 			wPortStatus |= USB_PORT_STAT_OVERCURRENT;
187 		if (status & USBPORTSC_PR)
188 			wPortStatus |= USB_PORT_STAT_RESET;
189 		if (status & USBPORTSC_LSDA)
190 			wPortStatus |= USB_PORT_STAT_LOW_SPEED;
191 
192 		if (wPortChange)
193 			dev_dbg(uhci_dev(uhci), "port %d portsc %04x,%02x\n",
194 					wIndex, status, lstatus);
195 
196 		*(__le16 *)buf = cpu_to_le16(wPortStatus);
197 		*(__le16 *)(buf + 2) = cpu_to_le16(wPortChange);
198 		OK(4);
199 	case SetHubFeature:		/* We don't implement these */
200 	case ClearHubFeature:
201 		switch (wValue) {
202 		case C_HUB_OVER_CURRENT:
203 		case C_HUB_LOCAL_POWER:
204 			OK(0);
205 		default:
206 			goto err;
207 		}
208 		break;
209 	case SetPortFeature:
210 		if (port >= uhci->rh_numports)
211 			goto err;
212 
213 		switch (wValue) {
214 		case USB_PORT_FEAT_SUSPEND:
215 			set_bit(port, &uhci->suspended_ports);
216 			SET_RH_PORTSTAT(USBPORTSC_SUSP);
217 			OK(0);
218 		case USB_PORT_FEAT_RESET:
219 			SET_RH_PORTSTAT(USBPORTSC_PR);
220 
221 			/* Reset terminates Resume signalling */
222 			uhci_finish_suspend(uhci, port, port_addr);
223 
224 			/* USB v2.0 7.1.7.5 */
225 			uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
226 			OK(0);
227 		case USB_PORT_FEAT_POWER:
228 			/* UHCI has no power switching */
229 			OK(0);
230 		default:
231 			goto err;
232 		}
233 		break;
234 	case ClearPortFeature:
235 		if (port >= uhci->rh_numports)
236 			goto err;
237 
238 		switch (wValue) {
239 		case USB_PORT_FEAT_ENABLE:
240 			CLR_RH_PORTSTAT(USBPORTSC_PE);
241 
242 			/* Disable terminates Resume signalling */
243 			uhci_finish_suspend(uhci, port, port_addr);
244 			OK(0);
245 		case USB_PORT_FEAT_C_ENABLE:
246 			CLR_RH_PORTSTAT(USBPORTSC_PEC);
247 			OK(0);
248 		case USB_PORT_FEAT_SUSPEND:
249 			if (test_bit(port, &uhci->suspended_ports) &&
250 					!test_and_set_bit(port,
251 						&uhci->resuming_ports)) {
252 				SET_RH_PORTSTAT(USBPORTSC_RD);
253 
254 				/* The controller won't allow RD to be set
255 				 * if the port is disabled.  When this happens
256 				 * just skip the Resume signalling.
257 				 */
258 				if (!(inw(port_addr) & USBPORTSC_RD))
259 					uhci_finish_suspend(uhci, port,
260 							port_addr);
261 				else
262 					/* USB v2.0 7.1.7.7 */
263 					uhci->ports_timeout = jiffies +
264 						msecs_to_jiffies(20);
265 			}
266 			OK(0);
267 		case USB_PORT_FEAT_C_SUSPEND:
268 			clear_bit(port, &uhci->port_c_suspend);
269 			OK(0);
270 		case USB_PORT_FEAT_POWER:
271 			/* UHCI has no power switching */
272 			goto err;
273 		case USB_PORT_FEAT_C_CONNECTION:
274 			CLR_RH_PORTSTAT(USBPORTSC_CSC);
275 			OK(0);
276 		case USB_PORT_FEAT_C_OVER_CURRENT:
277 			CLR_RH_PORTSTAT(USBPORTSC_OCC);
278 			OK(0);
279 		case USB_PORT_FEAT_C_RESET:
280 			/* this driver won't report these */
281 			OK(0);
282 		default:
283 			goto err;
284 		}
285 		break;
286 	case GetHubDescriptor:
287 		len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
288 		memcpy(buf, root_hub_hub_des, len);
289 		if (len > 2)
290 			buf[2] = uhci->rh_numports;
291 		OK(len);
292 	default:
293 err:
294 		retval = -EPIPE;
295 	}
296 	spin_unlock_irqrestore(&uhci->lock, flags);
297 
298 	return retval;
299 }
300