aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/uhci-hcd.c
diff options
context:
space:
mode:
authorJan Andersson <jan@gaisler.com>2011-05-06 06:00:13 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-06 21:23:59 -0400
commite7652e1ebc0f5e07929067ece14ca869dad20dd6 (patch)
treecbdca7e57d94be0be8fcee5f6f412eec937188ef /drivers/usb/host/uhci-hcd.c
parentdfeca7a8750296a7d065d45257b3cd86aadc3fb9 (diff)
USB: UHCI: Allow dynamic assignment of bus specific functions
This patch is part of a series that extend the UHCI HCD to support non-PCI controllers. This patch changes calls to uhci_reset_hc, uhci_check_and_reset_hc, configure_hc, resume_detect_interrupts_are_broken and global_suspend_mode_is_broken so that they are made through pointers in the uhci hcd struct. This will allow these functions to be replaced with bus/arch specific functions. Signed-off-by: Jan Andersson <jan@gaisler.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r--drivers/usb/host/uhci-hcd.c87
1 files changed, 68 insertions, 19 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 214851a6244f..683e87e49a03 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -143,13 +143,22 @@ static void finish_reset(struct uhci_hcd *uhci)
143} 143}
144 144
145/* 145/*
146 * Make sure the controller is completely inactive, unable to
147 * generate interrupts or do DMA.
148 */
149static void uhci_pci_reset_hc(struct uhci_hcd *uhci)
150{
151 uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
152}
153
154/*
146 * Last rites for a defunct/nonfunctional controller 155 * Last rites for a defunct/nonfunctional controller
147 * or one we don't want to use any more. 156 * or one we don't want to use any more.
148 */ 157 */
149static void uhci_hc_died(struct uhci_hcd *uhci) 158static void uhci_hc_died(struct uhci_hcd *uhci)
150{ 159{
151 uhci_get_current_frame_number(uhci); 160 uhci_get_current_frame_number(uhci);
152 uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); 161 uhci->reset_hc(uhci);
153 finish_reset(uhci); 162 finish_reset(uhci);
154 uhci->dead = 1; 163 uhci->dead = 1;
155 164
@@ -158,23 +167,45 @@ static void uhci_hc_died(struct uhci_hcd *uhci)
158} 167}
159 168
160/* 169/*
170 * Initialize a controller that was newly discovered or has just been
171 * resumed. In either case we can't be sure of its previous state.
172 *
173 * Returns: 1 if the controller was reset, 0 otherwise.
174 */
175static int uhci_pci_check_and_reset_hc(struct uhci_hcd *uhci)
176{
177 return uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)),
178 uhci->io_addr);
179}
180
181/*
161 * Initialize a controller that was newly discovered or has lost power 182 * Initialize a controller that was newly discovered or has lost power
162 * or otherwise been reset while it was suspended. In none of these cases 183 * or otherwise been reset while it was suspended. In none of these cases
163 * can we be sure of its previous state. 184 * can we be sure of its previous state.
164 */ 185 */
165static void check_and_reset_hc(struct uhci_hcd *uhci) 186static void check_and_reset_hc(struct uhci_hcd *uhci)
166{ 187{
167 if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr)) 188 if (uhci->check_and_reset_hc(uhci))
168 finish_reset(uhci); 189 finish_reset(uhci);
169} 190}
170 191
192static void uhci_pci_configure_hc(struct uhci_hcd *uhci)
193{
194 struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
195
196 /* Enable PIRQ */
197 pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT);
198
199 /* Disable platform-specific non-PME# wakeup */
200 if (pdev->vendor == PCI_VENDOR_ID_INTEL)
201 pci_write_config_byte(pdev, USBRES_INTEL, 0);
202}
203
171/* 204/*
172 * Store the basic register settings needed by the controller. 205 * Store the basic register settings needed by the controller.
173 */ 206 */
174static void configure_hc(struct uhci_hcd *uhci) 207static void configure_hc(struct uhci_hcd *uhci)
175{ 208{
176 struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci));
177
178 /* Set the frame length to the default: 1 ms exactly */ 209 /* Set the frame length to the default: 1 ms exactly */
179 outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); 210 outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
180 211
@@ -185,24 +216,15 @@ static void configure_hc(struct uhci_hcd *uhci)
185 outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER, 216 outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER,
186 uhci->io_addr + USBFRNUM); 217 uhci->io_addr + USBFRNUM);
187 218
188 /* Enable PIRQ */ 219 /* perform any arch/bus specific configuration */
189 pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT); 220 if (uhci->configure_hc)
190 221 uhci->configure_hc(uhci);
191 /* Disable platform-specific non-PME# wakeup */
192 if (pdev->vendor == PCI_VENDOR_ID_INTEL)
193 pci_write_config_byte(pdev, USBRES_INTEL, 0);
194} 222}
195 223
196 224static int uhci_pci_resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
197static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
198{ 225{
199 int port; 226 int port;
200 227
201 /* If we have to ignore overcurrent events then almost by definition
202 * we can't depend on resume-detect interrupts. */
203 if (ignore_oc)
204 return 1;
205
206 switch (to_pci_dev(uhci_dev(uhci))->vendor) { 228 switch (to_pci_dev(uhci_dev(uhci))->vendor) {
207 default: 229 default:
208 break; 230 break;
@@ -231,7 +253,18 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
231 return 0; 253 return 0;
232} 254}
233 255
234static int global_suspend_mode_is_broken(struct uhci_hcd *uhci) 256static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
257{
258 /* If we have to ignore overcurrent events then almost by definition
259 * we can't depend on resume-detect interrupts. */
260 if (ignore_oc)
261 return 1;
262
263 return uhci->resume_detect_interrupts_are_broken ?
264 uhci->resume_detect_interrupts_are_broken(uhci) : 0;
265}
266
267static int uhci_pci_global_suspend_mode_is_broken(struct uhci_hcd *uhci)
235{ 268{
236 int port; 269 int port;
237 const char *sys_info; 270 const char *sys_info;
@@ -253,6 +286,12 @@ static int global_suspend_mode_is_broken(struct uhci_hcd *uhci)
253 return 0; 286 return 0;
254} 287}
255 288
289static int global_suspend_mode_is_broken(struct uhci_hcd *uhci)
290{
291 return uhci->global_suspend_mode_is_broken ?
292 uhci->global_suspend_mode_is_broken(uhci) : 0;
293}
294
256static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state) 295static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
257__releases(uhci->lock) 296__releases(uhci->lock)
258__acquires(uhci->lock) 297__acquires(uhci->lock)
@@ -557,6 +596,16 @@ static int uhci_init(struct usb_hcd *hcd)
557 if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_HP) 596 if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_HP)
558 uhci->wait_for_hp = 1; 597 uhci->wait_for_hp = 1;
559 598
599 /* Set up pointers to PCI-specific functions */
600 uhci->reset_hc = uhci_pci_reset_hc;
601 uhci->check_and_reset_hc = uhci_pci_check_and_reset_hc;
602 uhci->configure_hc = uhci_pci_configure_hc;
603 uhci->resume_detect_interrupts_are_broken =
604 uhci_pci_resume_detect_interrupts_are_broken;
605 uhci->global_suspend_mode_is_broken =
606 uhci_pci_global_suspend_mode_is_broken;
607
608
560 /* Kick BIOS off this hardware and reset if the controller 609 /* Kick BIOS off this hardware and reset if the controller
561 * isn't already safely quiescent. 610 * isn't already safely quiescent.
562 */ 611 */
@@ -847,7 +896,7 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
847 896
848 /* Make sure resume from hibernation re-enumerates everything */ 897 /* Make sure resume from hibernation re-enumerates everything */
849 if (hibernated) { 898 if (hibernated) {
850 uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); 899 uhci->reset_hc(uhci);
851 finish_reset(uhci); 900 finish_reset(uhci);
852 } 901 }
853 902