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