xref: /openbmc/linux/drivers/usb/host/uhci-pci.c (revision dddb342b)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2c31a65f8SJan Andersson /*
3c31a65f8SJan Andersson  * UHCI HCD (Host Controller Driver) PCI Bus Glue.
4c31a65f8SJan Andersson  *
5c31a65f8SJan Andersson  * Extracted from uhci-hcd.c:
6c31a65f8SJan Andersson  * Maintainer: Alan Stern <stern@rowland.harvard.edu>
7c31a65f8SJan Andersson  *
8c31a65f8SJan Andersson  * (C) Copyright 1999 Linus Torvalds
9c31a65f8SJan Andersson  * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
10c31a65f8SJan Andersson  * (C) Copyright 1999 Randy Dunlap
11c31a65f8SJan Andersson  * (C) Copyright 1999 Georg Acher, acher@in.tum.de
12c31a65f8SJan Andersson  * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
13c31a65f8SJan Andersson  * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
14c31a65f8SJan Andersson  * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
15c31a65f8SJan Andersson  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
16c31a65f8SJan Andersson  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
17c31a65f8SJan Andersson  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
18c31a65f8SJan Andersson  * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
19c31a65f8SJan Andersson  */
20c31a65f8SJan Andersson 
21c31a65f8SJan Andersson #include "pci-quirks.h"
22c31a65f8SJan Andersson 
23c31a65f8SJan Andersson /*
24c31a65f8SJan Andersson  * Make sure the controller is completely inactive, unable to
25c31a65f8SJan Andersson  * generate interrupts or do DMA.
26c31a65f8SJan Andersson  */
uhci_pci_reset_hc(struct uhci_hcd * uhci)27c31a65f8SJan Andersson static void uhci_pci_reset_hc(struct uhci_hcd *uhci)
28c31a65f8SJan Andersson {
29c31a65f8SJan Andersson 	uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
30c31a65f8SJan Andersson }
31c31a65f8SJan Andersson 
32c31a65f8SJan Andersson /*
33c31a65f8SJan Andersson  * Initialize a controller that was newly discovered or has just been
34c31a65f8SJan Andersson  * resumed.  In either case we can't be sure of its previous state.
35c31a65f8SJan Andersson  *
36c31a65f8SJan Andersson  * Returns: 1 if the controller was reset, 0 otherwise.
37c31a65f8SJan Andersson  */
uhci_pci_check_and_reset_hc(struct uhci_hcd * uhci)38c31a65f8SJan Andersson static int uhci_pci_check_and_reset_hc(struct uhci_hcd *uhci)
39c31a65f8SJan Andersson {
40c31a65f8SJan Andersson 	return uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)),
41c31a65f8SJan Andersson 				uhci->io_addr);
42c31a65f8SJan Andersson }
43c31a65f8SJan Andersson 
44c31a65f8SJan Andersson /*
45c31a65f8SJan Andersson  * Store the basic register settings needed by the controller.
46c31a65f8SJan Andersson  * This function is called at the end of configure_hc in uhci-hcd.c.
47c31a65f8SJan Andersson  */
uhci_pci_configure_hc(struct uhci_hcd * uhci)48c31a65f8SJan Andersson static void uhci_pci_configure_hc(struct uhci_hcd *uhci)
49c31a65f8SJan Andersson {
50c31a65f8SJan Andersson 	struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
51c31a65f8SJan Andersson 
52c31a65f8SJan Andersson 	/* Enable PIRQ */
53c31a65f8SJan Andersson 	pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
54c31a65f8SJan Andersson 
55c31a65f8SJan Andersson 	/* Disable platform-specific non-PME# wakeup */
56c31a65f8SJan Andersson 	if (pdev->vendor == PCI_VENDOR_ID_INTEL)
57c31a65f8SJan Andersson 		pci_write_config_byte(pdev, USBRES_INTEL, 0);
58c31a65f8SJan Andersson }
59c31a65f8SJan Andersson 
uhci_pci_resume_detect_interrupts_are_broken(struct uhci_hcd * uhci)60c31a65f8SJan Andersson static int uhci_pci_resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
61c31a65f8SJan Andersson {
62c31a65f8SJan Andersson 	int port;
63c31a65f8SJan Andersson 
64c31a65f8SJan Andersson 	switch (to_pci_dev(uhci_dev(uhci))->vendor) {
65c31a65f8SJan Andersson 	default:
66c31a65f8SJan Andersson 		break;
67c31a65f8SJan Andersson 
68c31a65f8SJan Andersson 	case PCI_VENDOR_ID_GENESYS:
69c31a65f8SJan Andersson 		/* Genesys Logic's GL880S controllers don't generate
70c31a65f8SJan Andersson 		 * resume-detect interrupts.
71c31a65f8SJan Andersson 		 */
72c31a65f8SJan Andersson 		return 1;
73c31a65f8SJan Andersson 
74c31a65f8SJan Andersson 	case PCI_VENDOR_ID_INTEL:
75c31a65f8SJan Andersson 		/* Some of Intel's USB controllers have a bug that causes
76c31a65f8SJan Andersson 		 * resume-detect interrupts if any port has an over-current
77c31a65f8SJan Andersson 		 * condition.  To make matters worse, some motherboards
78c31a65f8SJan Andersson 		 * hardwire unused USB ports' over-current inputs active!
79c31a65f8SJan Andersson 		 * To prevent problems, we will not enable resume-detect
80c31a65f8SJan Andersson 		 * interrupts if any ports are OC.
81c31a65f8SJan Andersson 		 */
82c31a65f8SJan Andersson 		for (port = 0; port < uhci->rh_numports; ++port) {
83c31a65f8SJan Andersson 			if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
84c31a65f8SJan Andersson 					USBPORTSC_OC)
85c31a65f8SJan Andersson 				return 1;
86c31a65f8SJan Andersson 		}
87c31a65f8SJan Andersson 		break;
88c31a65f8SJan Andersson 	}
89c31a65f8SJan Andersson 	return 0;
90c31a65f8SJan Andersson }
91c31a65f8SJan Andersson 
uhci_pci_global_suspend_mode_is_broken(struct uhci_hcd * uhci)92c31a65f8SJan Andersson static int uhci_pci_global_suspend_mode_is_broken(struct uhci_hcd *uhci)
93c31a65f8SJan Andersson {
94c31a65f8SJan Andersson 	int port;
95c31a65f8SJan Andersson 	const char *sys_info;
96c31a65f8SJan Andersson 	static const char bad_Asus_board[] = "A7V8X";
97c31a65f8SJan Andersson 
98c31a65f8SJan Andersson 	/* One of Asus's motherboards has a bug which causes it to
99c31a65f8SJan Andersson 	 * wake up immediately from suspend-to-RAM if any of the ports
100c31a65f8SJan Andersson 	 * are connected.  In such cases we will not set EGSM.
101c31a65f8SJan Andersson 	 */
102c31a65f8SJan Andersson 	sys_info = dmi_get_system_info(DMI_BOARD_NAME);
103c31a65f8SJan Andersson 	if (sys_info && !strcmp(sys_info, bad_Asus_board)) {
104c31a65f8SJan Andersson 		for (port = 0; port < uhci->rh_numports; ++port) {
105c31a65f8SJan Andersson 			if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
106c31a65f8SJan Andersson 					USBPORTSC_CCS)
107c31a65f8SJan Andersson 				return 1;
108c31a65f8SJan Andersson 		}
109c31a65f8SJan Andersson 	}
110c31a65f8SJan Andersson 
111c31a65f8SJan Andersson 	return 0;
112c31a65f8SJan Andersson }
113c31a65f8SJan Andersson 
uhci_pci_init(struct usb_hcd * hcd)114c31a65f8SJan Andersson static int uhci_pci_init(struct usb_hcd *hcd)
115c31a65f8SJan Andersson {
116c31a65f8SJan Andersson 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
117c31a65f8SJan Andersson 
118c31a65f8SJan Andersson 	uhci->io_addr = (unsigned long) hcd->rsrc_start;
119c31a65f8SJan Andersson 
120c31a65f8SJan Andersson 	uhci->rh_numports = uhci_count_ports(hcd);
121c31a65f8SJan Andersson 
122*dddb342bSWeitao Wang 	/*
123*dddb342bSWeitao Wang 	 * Intel controllers report the OverCurrent bit active on.  VIA
124*dddb342bSWeitao Wang 	 * and ZHAOXIN controllers report it active off, so we'll adjust
125*dddb342bSWeitao Wang 	 * the bit value.  (It's not standardized in the UHCI spec.)
126c31a65f8SJan Andersson 	 */
127*dddb342bSWeitao Wang 	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_VIA ||
128*dddb342bSWeitao Wang 			to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_ZHAOXIN)
129c31a65f8SJan Andersson 		uhci->oc_low = 1;
130c31a65f8SJan Andersson 
131c31a65f8SJan Andersson 	/* HP's server management chip requires a longer port reset delay. */
132c31a65f8SJan Andersson 	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_HP)
133c31a65f8SJan Andersson 		uhci->wait_for_hp = 1;
134c31a65f8SJan Andersson 
135ccdb6be9SAlan Stern 	/* Intel controllers use non-PME wakeup signalling */
136ccdb6be9SAlan Stern 	if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_INTEL)
137de3ef1ebSRafael J. Wysocki 		device_set_wakeup_capable(uhci_dev(uhci), true);
138ccdb6be9SAlan Stern 
139c31a65f8SJan Andersson 	/* Set up pointers to PCI-specific functions */
140c31a65f8SJan Andersson 	uhci->reset_hc = uhci_pci_reset_hc;
141c31a65f8SJan Andersson 	uhci->check_and_reset_hc = uhci_pci_check_and_reset_hc;
142c31a65f8SJan Andersson 	uhci->configure_hc = uhci_pci_configure_hc;
143c31a65f8SJan Andersson 	uhci->resume_detect_interrupts_are_broken =
144c31a65f8SJan Andersson 		uhci_pci_resume_detect_interrupts_are_broken;
145c31a65f8SJan Andersson 	uhci->global_suspend_mode_is_broken =
146c31a65f8SJan Andersson 		uhci_pci_global_suspend_mode_is_broken;
147c31a65f8SJan Andersson 
148c31a65f8SJan Andersson 
149c31a65f8SJan Andersson 	/* Kick BIOS off this hardware and reset if the controller
150c31a65f8SJan Andersson 	 * isn't already safely quiescent.
151c31a65f8SJan Andersson 	 */
152c31a65f8SJan Andersson 	check_and_reset_hc(uhci);
153c31a65f8SJan Andersson 	return 0;
154c31a65f8SJan Andersson }
155c31a65f8SJan Andersson 
156c31a65f8SJan Andersson /* Make sure the controller is quiescent and that we're not using it
157c31a65f8SJan Andersson  * any more.  This is mainly for the benefit of programs which, like kexec,
158c31a65f8SJan Andersson  * expect the hardware to be idle: not doing DMA or generating IRQs.
159c31a65f8SJan Andersson  *
160c31a65f8SJan Andersson  * This routine may be called in a damaged or failing kernel.  Hence we
161c31a65f8SJan Andersson  * do not acquire the spinlock before shutting down the controller.
162c31a65f8SJan Andersson  */
uhci_shutdown(struct pci_dev * pdev)163c31a65f8SJan Andersson static void uhci_shutdown(struct pci_dev *pdev)
164c31a65f8SJan Andersson {
165c31a65f8SJan Andersson 	struct usb_hcd *hcd = pci_get_drvdata(pdev);
166c31a65f8SJan Andersson 
167c31a65f8SJan Andersson 	uhci_hc_died(hcd_to_uhci(hcd));
168c31a65f8SJan Andersson }
169c31a65f8SJan Andersson 
170c31a65f8SJan Andersson #ifdef CONFIG_PM
171c31a65f8SJan Andersson 
1721c124c99SAlan Stern static int uhci_pci_resume(struct usb_hcd *hcd, pm_message_t state);
1731c124c99SAlan Stern 
uhci_pci_suspend(struct usb_hcd * hcd,bool do_wakeup)174c31a65f8SJan Andersson static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
175c31a65f8SJan Andersson {
176c31a65f8SJan Andersson 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
177c31a65f8SJan Andersson 	struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
178c31a65f8SJan Andersson 	int rc = 0;
179c31a65f8SJan Andersson 
180c31a65f8SJan Andersson 	dev_dbg(uhci_dev(uhci), "%s\n", __func__);
181c31a65f8SJan Andersson 
182c31a65f8SJan Andersson 	spin_lock_irq(&uhci->lock);
183c31a65f8SJan Andersson 	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
184c31a65f8SJan Andersson 		goto done_okay;		/* Already suspended or dead */
185c31a65f8SJan Andersson 
186c31a65f8SJan Andersson 	/* All PCI host controllers are required to disable IRQ generation
187c31a65f8SJan Andersson 	 * at the source, so we must turn off PIRQ.
188c31a65f8SJan Andersson 	 */
189c31a65f8SJan Andersson 	pci_write_config_word(pdev, USBLEGSUP, 0);
190c31a65f8SJan Andersson 	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
191c31a65f8SJan Andersson 
192c31a65f8SJan Andersson 	/* Enable platform-specific non-PME# wakeup */
193c31a65f8SJan Andersson 	if (do_wakeup) {
194c31a65f8SJan Andersson 		if (pdev->vendor == PCI_VENDOR_ID_INTEL)
195c31a65f8SJan Andersson 			pci_write_config_byte(pdev, USBRES_INTEL,
196c31a65f8SJan Andersson 					USBPORT1EN | USBPORT2EN);
197c31a65f8SJan Andersson 	}
198c31a65f8SJan Andersson 
199c31a65f8SJan Andersson done_okay:
200c31a65f8SJan Andersson 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
201c31a65f8SJan Andersson 	spin_unlock_irq(&uhci->lock);
2021c124c99SAlan Stern 
2031c124c99SAlan Stern 	synchronize_irq(hcd->irq);
2041c124c99SAlan Stern 
2051c124c99SAlan Stern 	/* Check for race with a wakeup request */
2061c124c99SAlan Stern 	if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
2071c124c99SAlan Stern 		uhci_pci_resume(hcd, PMSG_SUSPEND);
2081c124c99SAlan Stern 		rc = -EBUSY;
2091c124c99SAlan Stern 	}
210c31a65f8SJan Andersson 	return rc;
211c31a65f8SJan Andersson }
212c31a65f8SJan Andersson 
uhci_pci_resume(struct usb_hcd * hcd,pm_message_t msg)213c31a65f8SJan Andersson static int uhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg)
214c31a65f8SJan Andersson {
215c31a65f8SJan Andersson 	bool hibernated = (msg.event == PM_EVENT_RESTORE);
216c31a65f8SJan Andersson 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
217c31a65f8SJan Andersson 
218c31a65f8SJan Andersson 	dev_dbg(uhci_dev(uhci), "%s\n", __func__);
219c31a65f8SJan Andersson 
220c31a65f8SJan Andersson 	/* Since we aren't in D3 any more, it's safe to set this flag
221c31a65f8SJan Andersson 	 * even if the controller was dead.
222c31a65f8SJan Andersson 	 */
223c31a65f8SJan Andersson 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
224c31a65f8SJan Andersson 
225c31a65f8SJan Andersson 	spin_lock_irq(&uhci->lock);
226c31a65f8SJan Andersson 
227c31a65f8SJan Andersson 	/* Make sure resume from hibernation re-enumerates everything */
228c31a65f8SJan Andersson 	if (hibernated) {
229c31a65f8SJan Andersson 		uhci->reset_hc(uhci);
230c31a65f8SJan Andersson 		finish_reset(uhci);
231c31a65f8SJan Andersson 	}
232c31a65f8SJan Andersson 
233c31a65f8SJan Andersson 	/* The firmware may have changed the controller settings during
234c31a65f8SJan Andersson 	 * a system wakeup.  Check it and reconfigure to avoid problems.
235c31a65f8SJan Andersson 	 */
236c31a65f8SJan Andersson 	else {
237c31a65f8SJan Andersson 		check_and_reset_hc(uhci);
238c31a65f8SJan Andersson 	}
239c31a65f8SJan Andersson 	configure_hc(uhci);
240c31a65f8SJan Andersson 
241c31a65f8SJan Andersson 	/* Tell the core if the controller had to be reset */
242c31a65f8SJan Andersson 	if (uhci->rh_state == UHCI_RH_RESET)
243c31a65f8SJan Andersson 		usb_root_hub_lost_power(hcd->self.root_hub);
244c31a65f8SJan Andersson 
245c31a65f8SJan Andersson 	spin_unlock_irq(&uhci->lock);
246c31a65f8SJan Andersson 
247c31a65f8SJan Andersson 	/* If interrupts don't work and remote wakeup is enabled then
248c31a65f8SJan Andersson 	 * the suspended root hub needs to be polled.
249c31a65f8SJan Andersson 	 */
250c31a65f8SJan Andersson 	if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup)
251c31a65f8SJan Andersson 		set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
252c31a65f8SJan Andersson 
253c31a65f8SJan Andersson 	/* Does the root hub have a port wakeup pending? */
254c31a65f8SJan Andersson 	usb_hcd_poll_rh_status(hcd);
255c31a65f8SJan Andersson 	return 0;
256c31a65f8SJan Andersson }
257c31a65f8SJan Andersson 
258c31a65f8SJan Andersson #endif
259c31a65f8SJan Andersson 
260c31a65f8SJan Andersson static const struct hc_driver uhci_driver = {
261c31a65f8SJan Andersson 	.description =		hcd_name,
262c31a65f8SJan Andersson 	.product_desc =		"UHCI Host Controller",
263c31a65f8SJan Andersson 	.hcd_priv_size =	sizeof(struct uhci_hcd),
264c31a65f8SJan Andersson 
265c31a65f8SJan Andersson 	/* Generic hardware linkage */
2667b81cb6bSChristoph Hellwig 	.irq =			uhci_irq,
267c31a65f8SJan Andersson 	.flags =		HCD_DMA | HCD_USB11,
268c31a65f8SJan Andersson 
269c31a65f8SJan Andersson 	/* Basic lifecycle operations */
270c31a65f8SJan Andersson 	.reset =		uhci_pci_init,
271c31a65f8SJan Andersson 	.start =		uhci_start,
272c31a65f8SJan Andersson #ifdef CONFIG_PM
273c31a65f8SJan Andersson 	.pci_suspend =		uhci_pci_suspend,
274c31a65f8SJan Andersson 	.pci_resume =		uhci_pci_resume,
275c31a65f8SJan Andersson 	.bus_suspend =		uhci_rh_suspend,
276c31a65f8SJan Andersson 	.bus_resume =		uhci_rh_resume,
277c31a65f8SJan Andersson #endif
278c31a65f8SJan Andersson 	.stop =			uhci_stop,
279c31a65f8SJan Andersson 
280c31a65f8SJan Andersson 	.urb_enqueue =		uhci_urb_enqueue,
281c31a65f8SJan Andersson 	.urb_dequeue =		uhci_urb_dequeue,
282c31a65f8SJan Andersson 
283c31a65f8SJan Andersson 	.endpoint_disable =	uhci_hcd_endpoint_disable,
284c31a65f8SJan Andersson 	.get_frame_number =	uhci_hcd_get_frame_number,
285c31a65f8SJan Andersson 
286c31a65f8SJan Andersson 	.hub_status_data =	uhci_hub_status_data,
287c31a65f8SJan Andersson 	.hub_control =		uhci_hub_control,
288c31a65f8SJan Andersson };
2892fd3f651SJingoo Han 
290c31a65f8SJan Andersson static const struct pci_device_id uhci_pci_ids[] = { {
291c31a65f8SJan Andersson 	/* handle any USB UHCI controller */
292c31a65f8SJan Andersson 	PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0),
293c31a65f8SJan Andersson 	}, { /* end: all zeroes */ }
294c31a65f8SJan Andersson };
295c31a65f8SJan Andersson 
296c31a65f8SJan Andersson MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
297ff4c65caSVinod Koul 
uhci_pci_probe(struct pci_dev * dev,const struct pci_device_id * id)298ff4c65caSVinod Koul static int uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
2994e55e22dSHeikki Krogerus {
300ff4c65caSVinod Koul 	return usb_hcd_pci_probe(dev, &uhci_driver);
301ff4c65caSVinod Koul }
302c31a65f8SJan Andersson 
303b0700222SCorentin Labbe static struct pci_driver uhci_pci_driver = {
304c31a65f8SJan Andersson 	.name =		hcd_name,
305c31a65f8SJan Andersson 	.id_table =	uhci_pci_ids,
306ff4c65caSVinod Koul 
307c31a65f8SJan Andersson 	.probe =	uhci_pci_probe,
308c31a65f8SJan Andersson 	.remove =	usb_hcd_pci_remove,
309c31a65f8SJan Andersson 	.shutdown =	uhci_shutdown,
310f875fdbfSAlan Stern 
311c31a65f8SJan Andersson #ifdef CONFIG_PM
312c31a65f8SJan Andersson 	.driver =	{
313c31a65f8SJan Andersson 		.pm =	&usb_hcd_pci_pm_ops
314c31a65f8SJan Andersson 	},
315c31a65f8SJan Andersson #endif
31605c92da0STom Gundersen };
31705c92da0STom Gundersen 
318 MODULE_SOFTDEP("pre: ehci_pci");
319