11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * OHCI HCD (Host Controller Driver) for USB. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> 51da177e4SLinus Torvalds * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * [ Initialisation is based on Linus' ] 81da177e4SLinus Torvalds * [ uhci code and gregs ohci fragments ] 91da177e4SLinus Torvalds * [ (C) Copyright 1999 Linus Torvalds ] 101da177e4SLinus Torvalds * [ (C) Copyright 1999 Gregory P. Smith] 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller 141da177e4SLinus Torvalds * interfaces (though some non-x86 Intel chips use it). It supports 151da177e4SLinus Torvalds * smarter hardware than UHCI. A download link for the spec available 161da177e4SLinus Torvalds * through the http://www.usb.org website. 171da177e4SLinus Torvalds * 181da177e4SLinus Torvalds * This file is licenced under the GPL. 191da177e4SLinus Torvalds */ 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds #include <linux/module.h> 221da177e4SLinus Torvalds #include <linux/moduleparam.h> 231da177e4SLinus Torvalds #include <linux/pci.h> 241da177e4SLinus Torvalds #include <linux/kernel.h> 251da177e4SLinus Torvalds #include <linux/delay.h> 261da177e4SLinus Torvalds #include <linux/ioport.h> 271da177e4SLinus Torvalds #include <linux/sched.h> 281da177e4SLinus Torvalds #include <linux/slab.h> 291da177e4SLinus Torvalds #include <linux/errno.h> 301da177e4SLinus Torvalds #include <linux/init.h> 311da177e4SLinus Torvalds #include <linux/timer.h> 321da177e4SLinus Torvalds #include <linux/list.h> 331da177e4SLinus Torvalds #include <linux/usb.h> 343a16f7b4SDavid Brownell #include <linux/usb/otg.h> 3527729aadSEric Lescouet #include <linux/usb/hcd.h> 361da177e4SLinus Torvalds #include <linux/dma-mapping.h> 37f4df0e33SDavid Brownell #include <linux/dmapool.h> 38d576bb9fSMichael Hanselmann #include <linux/workqueue.h> 39684c19e0STony Jones #include <linux/debugfs.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <asm/io.h> 421da177e4SLinus Torvalds #include <asm/irq.h> 431da177e4SLinus Torvalds #include <asm/system.h> 441da177e4SLinus Torvalds #include <asm/unaligned.h> 451da177e4SLinus Torvalds #include <asm/byteorder.h> 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" 491da177e4SLinus Torvalds #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/ 521da177e4SLinus Torvalds 538de98402SBenjamin Herrenschmidt #undef OHCI_VERBOSE_DEBUG /* not always helpful */ 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds /* For initializing controller (mask in an HCFS mode too) */ 561da177e4SLinus Torvalds #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR 571da177e4SLinus Torvalds #define OHCI_INTR_INIT \ 58d413984aSDavid Brownell (OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE \ 59d413984aSDavid Brownell | OHCI_INTR_RD | OHCI_INTR_WDH) 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds #ifdef __hppa__ 621da177e4SLinus Torvalds /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ 631da177e4SLinus Torvalds #define IR_DISABLE 641da177e4SLinus Torvalds #endif 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds #ifdef CONFIG_ARCH_OMAP 671da177e4SLinus Torvalds /* OMAP doesn't support IR (no SMM; not needed) */ 681da177e4SLinus Torvalds #define IR_DISABLE 691da177e4SLinus Torvalds #endif 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/ 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds static const char hcd_name [] = "ohci_hcd"; 741da177e4SLinus Torvalds 75d413984aSDavid Brownell #define STATECHANGE_DELAY msecs_to_jiffies(300) 76d413984aSDavid Brownell 771da177e4SLinus Torvalds #include "ohci.h" 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds static void ohci_dump (struct ohci_hcd *ohci, int verbose); 801da177e4SLinus Torvalds static int ohci_init (struct ohci_hcd *ohci); 811da177e4SLinus Torvalds static void ohci_stop (struct usb_hcd *hcd); 82da6fb570SDavid Brownell 83da6fb570SDavid Brownell #if defined(CONFIG_PM) || defined(CONFIG_PCI) 84d576bb9fSMichael Hanselmann static int ohci_restart (struct ohci_hcd *ohci); 85da6fb570SDavid Brownell #endif 861da177e4SLinus Torvalds 87ab1666c1SLibin Yang #ifdef CONFIG_PCI 88ab1666c1SLibin Yang static void quirk_amd_pll(int state); 89ab1666c1SLibin Yang static void amd_iso_dev_put(void); 90a1f17a87SLibin Yang static void sb800_prefetch(struct ohci_hcd *ohci, int on); 91ab1666c1SLibin Yang #else 92ab1666c1SLibin Yang static inline void quirk_amd_pll(int state) 93ab1666c1SLibin Yang { 94ab1666c1SLibin Yang return; 95ab1666c1SLibin Yang } 96ab1666c1SLibin Yang static inline void amd_iso_dev_put(void) 97ab1666c1SLibin Yang { 98ab1666c1SLibin Yang return; 99ab1666c1SLibin Yang } 100a1f17a87SLibin Yang static inline void sb800_prefetch(struct ohci_hcd *ohci, int on) 101a1f17a87SLibin Yang { 102a1f17a87SLibin Yang return; 103a1f17a87SLibin Yang } 104ab1666c1SLibin Yang #endif 105ab1666c1SLibin Yang 106ab1666c1SLibin Yang 1071da177e4SLinus Torvalds #include "ohci-hub.c" 1081da177e4SLinus Torvalds #include "ohci-dbg.c" 1091da177e4SLinus Torvalds #include "ohci-mem.c" 1101da177e4SLinus Torvalds #include "ohci-q.c" 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds /* 1141da177e4SLinus Torvalds * On architectures with edge-triggered interrupts we must never return 1151da177e4SLinus Torvalds * IRQ_NONE. 1161da177e4SLinus Torvalds */ 1171da177e4SLinus Torvalds #if defined(CONFIG_SA1111) /* ... or other edge-triggered systems */ 1181da177e4SLinus Torvalds #define IRQ_NOTMINE IRQ_HANDLED 1191da177e4SLinus Torvalds #else 1201da177e4SLinus Torvalds #define IRQ_NOTMINE IRQ_NONE 1211da177e4SLinus Torvalds #endif 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds 1241da177e4SLinus Torvalds /* Some boards misreport power switching/overcurrent */ 1251da177e4SLinus Torvalds static int distrust_firmware = 1; 1261da177e4SLinus Torvalds module_param (distrust_firmware, bool, 0); 1271da177e4SLinus Torvalds MODULE_PARM_DESC (distrust_firmware, 1281da177e4SLinus Torvalds "true to distrust firmware power/overcurrent setup"); 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds /* Some boards leave IR set wrongly, since they fail BIOS/SMM handshakes */ 1311da177e4SLinus Torvalds static int no_handshake = 0; 1321da177e4SLinus Torvalds module_param (no_handshake, bool, 0); 1331da177e4SLinus Torvalds MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake"); 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/ 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds /* 1381da177e4SLinus Torvalds * queue up an urb for anything except the root hub 1391da177e4SLinus Torvalds */ 1401da177e4SLinus Torvalds static int ohci_urb_enqueue ( 1411da177e4SLinus Torvalds struct usb_hcd *hcd, 1421da177e4SLinus Torvalds struct urb *urb, 14355016f10SAl Viro gfp_t mem_flags 1441da177e4SLinus Torvalds ) { 1451da177e4SLinus Torvalds struct ohci_hcd *ohci = hcd_to_ohci (hcd); 1461da177e4SLinus Torvalds struct ed *ed; 1471da177e4SLinus Torvalds urb_priv_t *urb_priv; 1481da177e4SLinus Torvalds unsigned int pipe = urb->pipe; 1491da177e4SLinus Torvalds int i, size = 0; 1501da177e4SLinus Torvalds unsigned long flags; 1511da177e4SLinus Torvalds int retval = 0; 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds #ifdef OHCI_VERBOSE_DEBUG 15455d84968SAlan Stern urb_print(urb, "SUB", usb_pipein(pipe), -EINPROGRESS); 1551da177e4SLinus Torvalds #endif 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* every endpoint has a ed, locate and maybe (re)initialize it */ 158e9df41c5SAlan Stern if (! (ed = ed_get (ohci, urb->ep, urb->dev, pipe, urb->interval))) 1591da177e4SLinus Torvalds return -ENOMEM; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds /* for the private part of the URB we need the number of TDs (size) */ 1621da177e4SLinus Torvalds switch (ed->type) { 1631da177e4SLinus Torvalds case PIPE_CONTROL: 1641da177e4SLinus Torvalds /* td_submit_urb() doesn't yet handle these */ 1651da177e4SLinus Torvalds if (urb->transfer_buffer_length > 4096) 1661da177e4SLinus Torvalds return -EMSGSIZE; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /* 1 TD for setup, 1 for ACK, plus ... */ 1691da177e4SLinus Torvalds size = 2; 1701da177e4SLinus Torvalds /* FALLTHROUGH */ 1711da177e4SLinus Torvalds // case PIPE_INTERRUPT: 1721da177e4SLinus Torvalds // case PIPE_BULK: 1731da177e4SLinus Torvalds default: 1741da177e4SLinus Torvalds /* one TD for every 4096 Bytes (can be upto 8K) */ 1751da177e4SLinus Torvalds size += urb->transfer_buffer_length / 4096; 1761da177e4SLinus Torvalds /* ... and for any remaining bytes ... */ 1771da177e4SLinus Torvalds if ((urb->transfer_buffer_length % 4096) != 0) 1781da177e4SLinus Torvalds size++; 1791da177e4SLinus Torvalds /* ... and maybe a zero length packet to wrap it up */ 1801da177e4SLinus Torvalds if (size == 0) 1811da177e4SLinus Torvalds size++; 1821da177e4SLinus Torvalds else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 1831da177e4SLinus Torvalds && (urb->transfer_buffer_length 1841da177e4SLinus Torvalds % usb_maxpacket (urb->dev, pipe, 1851da177e4SLinus Torvalds usb_pipeout (pipe))) == 0) 1861da177e4SLinus Torvalds size++; 1871da177e4SLinus Torvalds break; 1881da177e4SLinus Torvalds case PIPE_ISOCHRONOUS: /* number of packets from URB */ 1891da177e4SLinus Torvalds size = urb->number_of_packets; 1901da177e4SLinus Torvalds break; 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /* allocate the private part of the URB */ 194dd00cc48SYoann Padioleau urb_priv = kzalloc (sizeof (urb_priv_t) + size * sizeof (struct td *), 1951da177e4SLinus Torvalds mem_flags); 1961da177e4SLinus Torvalds if (!urb_priv) 1971da177e4SLinus Torvalds return -ENOMEM; 1981da177e4SLinus Torvalds INIT_LIST_HEAD (&urb_priv->pending); 1991da177e4SLinus Torvalds urb_priv->length = size; 2001da177e4SLinus Torvalds urb_priv->ed = ed; 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds /* allocate the TDs (deferring hash chain updates) */ 2031da177e4SLinus Torvalds for (i = 0; i < size; i++) { 2041da177e4SLinus Torvalds urb_priv->td [i] = td_alloc (ohci, mem_flags); 2051da177e4SLinus Torvalds if (!urb_priv->td [i]) { 2061da177e4SLinus Torvalds urb_priv->length = i; 2071da177e4SLinus Torvalds urb_free_priv (ohci, urb_priv); 2081da177e4SLinus Torvalds return -ENOMEM; 2091da177e4SLinus Torvalds } 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds spin_lock_irqsave (&ohci->lock, flags); 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds /* don't submit to a dead HC */ 215541c7d43SAlan Stern if (!HCD_HW_ACCESSIBLE(hcd)) { 2168de98402SBenjamin Herrenschmidt retval = -ENODEV; 2178de98402SBenjamin Herrenschmidt goto fail; 2188de98402SBenjamin Herrenschmidt } 2191da177e4SLinus Torvalds if (!HC_IS_RUNNING(hcd->state)) { 2201da177e4SLinus Torvalds retval = -ENODEV; 2211da177e4SLinus Torvalds goto fail; 2221da177e4SLinus Torvalds } 223e9df41c5SAlan Stern retval = usb_hcd_link_urb_to_ep(hcd, urb); 224e9df41c5SAlan Stern if (retval) 2251da177e4SLinus Torvalds goto fail; 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds /* schedule the ed if needed */ 2281da177e4SLinus Torvalds if (ed->state == ED_IDLE) { 2291da177e4SLinus Torvalds retval = ed_schedule (ohci, ed); 230e9df41c5SAlan Stern if (retval < 0) { 231e9df41c5SAlan Stern usb_hcd_unlink_urb_from_ep(hcd, urb); 232e9df41c5SAlan Stern goto fail; 233e9df41c5SAlan Stern } 2341da177e4SLinus Torvalds if (ed->type == PIPE_ISOCHRONOUS) { 2351da177e4SLinus Torvalds u16 frame = ohci_frame_no(ohci); 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds /* delay a few frames before the first TD */ 2381da177e4SLinus Torvalds frame += max_t (u16, 8, ed->interval); 2391da177e4SLinus Torvalds frame &= ~(ed->interval - 1); 2401da177e4SLinus Torvalds frame |= ed->branch; 2411da177e4SLinus Torvalds urb->start_frame = frame; 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds /* yes, only URB_ISO_ASAP is supported, and 2441da177e4SLinus Torvalds * urb->start_frame is never used as input. 2451da177e4SLinus Torvalds */ 2461da177e4SLinus Torvalds } 2471da177e4SLinus Torvalds } else if (ed->type == PIPE_ISOCHRONOUS) 2481da177e4SLinus Torvalds urb->start_frame = ed->last_iso + ed->interval; 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds /* fill the TDs and link them to the ed; and 2511da177e4SLinus Torvalds * enable that part of the schedule, if needed 2521da177e4SLinus Torvalds * and update count of queued periodic urbs 2531da177e4SLinus Torvalds */ 2541da177e4SLinus Torvalds urb->hcpriv = urb_priv; 2551da177e4SLinus Torvalds td_submit_urb (ohci, urb); 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds fail: 2581da177e4SLinus Torvalds if (retval) 2591da177e4SLinus Torvalds urb_free_priv (ohci, urb_priv); 2601da177e4SLinus Torvalds spin_unlock_irqrestore (&ohci->lock, flags); 2611da177e4SLinus Torvalds return retval; 2621da177e4SLinus Torvalds } 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds /* 26555d84968SAlan Stern * decouple the URB from the HC queues (TDs, urb_priv). 26655d84968SAlan Stern * reporting is always done 2671da177e4SLinus Torvalds * asynchronously, and we might be dealing with an urb that's 2681da177e4SLinus Torvalds * partially transferred, or an ED with other urbs being unlinked. 2691da177e4SLinus Torvalds */ 270e9df41c5SAlan Stern static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) 2711da177e4SLinus Torvalds { 2721da177e4SLinus Torvalds struct ohci_hcd *ohci = hcd_to_ohci (hcd); 2731da177e4SLinus Torvalds unsigned long flags; 274e9df41c5SAlan Stern int rc; 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds #ifdef OHCI_VERBOSE_DEBUG 27755d84968SAlan Stern urb_print(urb, "UNLINK", 1, status); 2781da177e4SLinus Torvalds #endif 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds spin_lock_irqsave (&ohci->lock, flags); 281e9df41c5SAlan Stern rc = usb_hcd_check_unlink_urb(hcd, urb, status); 282e9df41c5SAlan Stern if (rc) { 283e9df41c5SAlan Stern ; /* Do nothing */ 284e9df41c5SAlan Stern } else if (HC_IS_RUNNING(hcd->state)) { 2851da177e4SLinus Torvalds urb_priv_t *urb_priv; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds /* Unless an IRQ completed the unlink while it was being 2881da177e4SLinus Torvalds * handed to us, flag it for unlink and giveback, and force 2891da177e4SLinus Torvalds * some upcoming INTR_SF to call finish_unlinks() 2901da177e4SLinus Torvalds */ 2911da177e4SLinus Torvalds urb_priv = urb->hcpriv; 2921da177e4SLinus Torvalds if (urb_priv) { 2931da177e4SLinus Torvalds if (urb_priv->ed->state == ED_OPER) 2941da177e4SLinus Torvalds start_ed_unlink (ohci, urb_priv->ed); 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds } else { 2971da177e4SLinus Torvalds /* 2981da177e4SLinus Torvalds * with HC dead, we won't respect hc queue pointers 2991da177e4SLinus Torvalds * any more ... just clean up every urb's memory. 3001da177e4SLinus Torvalds */ 3011da177e4SLinus Torvalds if (urb->hcpriv) 30255d84968SAlan Stern finish_urb(ohci, urb, status); 3031da177e4SLinus Torvalds } 3041da177e4SLinus Torvalds spin_unlock_irqrestore (&ohci->lock, flags); 305e9df41c5SAlan Stern return rc; 3061da177e4SLinus Torvalds } 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/ 3091da177e4SLinus Torvalds 3101da177e4SLinus Torvalds /* frees config/altsetting state for endpoints, 3111da177e4SLinus Torvalds * including ED memory, dummy TD, and bulk/intr data toggle 3121da177e4SLinus Torvalds */ 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds static void 3151da177e4SLinus Torvalds ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) 3161da177e4SLinus Torvalds { 3171da177e4SLinus Torvalds struct ohci_hcd *ohci = hcd_to_ohci (hcd); 3181da177e4SLinus Torvalds unsigned long flags; 3191da177e4SLinus Torvalds struct ed *ed = ep->hcpriv; 3201da177e4SLinus Torvalds unsigned limit = 1000; 3211da177e4SLinus Torvalds 3221da177e4SLinus Torvalds /* ASSERT: any requests/urbs are being unlinked */ 3231da177e4SLinus Torvalds /* ASSERT: nobody can be submitting urbs for this any more */ 3241da177e4SLinus Torvalds 3251da177e4SLinus Torvalds if (!ed) 3261da177e4SLinus Torvalds return; 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds rescan: 3291da177e4SLinus Torvalds spin_lock_irqsave (&ohci->lock, flags); 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds if (!HC_IS_RUNNING (hcd->state)) { 3321da177e4SLinus Torvalds sanitize: 3331da177e4SLinus Torvalds ed->state = ED_IDLE; 33489a0fd18SMike Nuss if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) 33589a0fd18SMike Nuss ohci->eds_scheduled--; 3367d12e780SDavid Howells finish_unlinks (ohci, 0); 3371da177e4SLinus Torvalds } 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds switch (ed->state) { 3401da177e4SLinus Torvalds case ED_UNLINK: /* wait for hw to finish? */ 3411da177e4SLinus Torvalds /* major IRQ delivery trouble loses INTR_SF too... */ 3421da177e4SLinus Torvalds if (limit-- == 0) { 34389a0fd18SMike Nuss ohci_warn(ohci, "ED unlink timeout\n"); 34489a0fd18SMike Nuss if (quirk_zfmicro(ohci)) { 34589a0fd18SMike Nuss ohci_warn(ohci, "Attempting ZF TD recovery\n"); 34689a0fd18SMike Nuss ohci->ed_to_check = ed; 34789a0fd18SMike Nuss ohci->zf_delay = 2; 34889a0fd18SMike Nuss } 3491da177e4SLinus Torvalds goto sanitize; 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds spin_unlock_irqrestore (&ohci->lock, flags); 35222c43863SNishanth Aravamudan schedule_timeout_uninterruptible(1); 3531da177e4SLinus Torvalds goto rescan; 3541da177e4SLinus Torvalds case ED_IDLE: /* fully unlinked */ 3551da177e4SLinus Torvalds if (list_empty (&ed->td_list)) { 3561da177e4SLinus Torvalds td_free (ohci, ed->dummy); 3571da177e4SLinus Torvalds ed_free (ohci, ed); 3581da177e4SLinus Torvalds break; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds /* else FALL THROUGH */ 3611da177e4SLinus Torvalds default: 3621da177e4SLinus Torvalds /* caller was supposed to have unlinked any requests; 3631da177e4SLinus Torvalds * that's not our job. can't recover; must leak ed. 3641da177e4SLinus Torvalds */ 3651da177e4SLinus Torvalds ohci_err (ohci, "leak ed %p (#%02x) state %d%s\n", 3661da177e4SLinus Torvalds ed, ep->desc.bEndpointAddress, ed->state, 3671da177e4SLinus Torvalds list_empty (&ed->td_list) ? "" : " (has tds)"); 3681da177e4SLinus Torvalds td_free (ohci, ed->dummy); 3691da177e4SLinus Torvalds break; 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds ep->hcpriv = NULL; 3721da177e4SLinus Torvalds spin_unlock_irqrestore (&ohci->lock, flags); 3731da177e4SLinus Torvalds } 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds static int ohci_get_frame (struct usb_hcd *hcd) 3761da177e4SLinus Torvalds { 3771da177e4SLinus Torvalds struct ohci_hcd *ohci = hcd_to_ohci (hcd); 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds return ohci_frame_no(ohci); 3801da177e4SLinus Torvalds } 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds static void ohci_usb_reset (struct ohci_hcd *ohci) 3831da177e4SLinus Torvalds { 3841da177e4SLinus Torvalds ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); 3851da177e4SLinus Torvalds ohci->hc_control &= OHCI_CTRL_RWC; 3861da177e4SLinus Torvalds ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 3871da177e4SLinus Torvalds } 3881da177e4SLinus Torvalds 38964a21d02SAleksey Gorelov /* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and 390f4df0e33SDavid Brownell * other cases where the next software may expect clean state from the 391f4df0e33SDavid Brownell * "firmware". this is bus-neutral, unlike shutdown() methods. 392f4df0e33SDavid Brownell */ 39364a21d02SAleksey Gorelov static void 39464a21d02SAleksey Gorelov ohci_shutdown (struct usb_hcd *hcd) 395f4df0e33SDavid Brownell { 396f4df0e33SDavid Brownell struct ohci_hcd *ohci; 397f4df0e33SDavid Brownell 39864a21d02SAleksey Gorelov ohci = hcd_to_ohci (hcd); 399f4df0e33SDavid Brownell ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); 4003df7169eSAlan Stern ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); 4013df7169eSAlan Stern 4023df7169eSAlan Stern /* If the SHUTDOWN quirk is set, don't put the controller in RESET */ 4033df7169eSAlan Stern ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ? 4043df7169eSAlan Stern OHCI_CTRL_RWC | OHCI_CTRL_HCFS : 4053df7169eSAlan Stern OHCI_CTRL_RWC); 4063df7169eSAlan Stern ohci_writel(ohci, ohci->hc_control, &ohci->regs->control); 4073df7169eSAlan Stern 408f4df0e33SDavid Brownell /* flush the writes */ 409f4df0e33SDavid Brownell (void) ohci_readl (ohci, &ohci->regs->control); 410f4df0e33SDavid Brownell } 411f4df0e33SDavid Brownell 41289a0fd18SMike Nuss static int check_ed(struct ohci_hcd *ohci, struct ed *ed) 41389a0fd18SMike Nuss { 41489a0fd18SMike Nuss return (hc32_to_cpu(ohci, ed->hwINFO) & ED_IN) != 0 41589a0fd18SMike Nuss && (hc32_to_cpu(ohci, ed->hwHeadP) & TD_MASK) 41689a0fd18SMike Nuss == (hc32_to_cpu(ohci, ed->hwTailP) & TD_MASK) 41789a0fd18SMike Nuss && !list_empty(&ed->td_list); 41889a0fd18SMike Nuss } 41989a0fd18SMike Nuss 42089a0fd18SMike Nuss /* ZF Micro watchdog timer callback. The ZF Micro chipset sometimes completes 42189a0fd18SMike Nuss * an interrupt TD but neglects to add it to the donelist. On systems with 42289a0fd18SMike Nuss * this chipset, we need to periodically check the state of the queues to look 42389a0fd18SMike Nuss * for such "lost" TDs. 42489a0fd18SMike Nuss */ 42589a0fd18SMike Nuss static void unlink_watchdog_func(unsigned long _ohci) 42689a0fd18SMike Nuss { 427da6fb570SDavid Brownell unsigned long flags; 42889a0fd18SMike Nuss unsigned max; 42989a0fd18SMike Nuss unsigned seen_count = 0; 43089a0fd18SMike Nuss unsigned i; 43189a0fd18SMike Nuss struct ed **seen = NULL; 43289a0fd18SMike Nuss struct ohci_hcd *ohci = (struct ohci_hcd *) _ohci; 43389a0fd18SMike Nuss 43489a0fd18SMike Nuss spin_lock_irqsave(&ohci->lock, flags); 43589a0fd18SMike Nuss max = ohci->eds_scheduled; 43689a0fd18SMike Nuss if (!max) 43789a0fd18SMike Nuss goto done; 43889a0fd18SMike Nuss 43989a0fd18SMike Nuss if (ohci->ed_to_check) 44089a0fd18SMike Nuss goto out; 44189a0fd18SMike Nuss 44289a0fd18SMike Nuss seen = kcalloc(max, sizeof *seen, GFP_ATOMIC); 44389a0fd18SMike Nuss if (!seen) 44489a0fd18SMike Nuss goto out; 44589a0fd18SMike Nuss 44689a0fd18SMike Nuss for (i = 0; i < NUM_INTS; i++) { 44789a0fd18SMike Nuss struct ed *ed = ohci->periodic[i]; 44889a0fd18SMike Nuss 44989a0fd18SMike Nuss while (ed) { 45089a0fd18SMike Nuss unsigned temp; 45189a0fd18SMike Nuss 45289a0fd18SMike Nuss /* scan this branch of the periodic schedule tree */ 45389a0fd18SMike Nuss for (temp = 0; temp < seen_count; temp++) { 45489a0fd18SMike Nuss if (seen[temp] == ed) { 45589a0fd18SMike Nuss /* we've checked it and what's after */ 45689a0fd18SMike Nuss ed = NULL; 45789a0fd18SMike Nuss break; 45889a0fd18SMike Nuss } 45989a0fd18SMike Nuss } 46089a0fd18SMike Nuss if (!ed) 46189a0fd18SMike Nuss break; 46289a0fd18SMike Nuss seen[seen_count++] = ed; 46389a0fd18SMike Nuss if (!check_ed(ohci, ed)) { 46489a0fd18SMike Nuss ed = ed->ed_next; 46589a0fd18SMike Nuss continue; 46689a0fd18SMike Nuss } 46789a0fd18SMike Nuss 46889a0fd18SMike Nuss /* HC's TD list is empty, but HCD sees at least one 46989a0fd18SMike Nuss * TD that's not been sent through the donelist. 47089a0fd18SMike Nuss */ 47189a0fd18SMike Nuss ohci->ed_to_check = ed; 47289a0fd18SMike Nuss ohci->zf_delay = 2; 47389a0fd18SMike Nuss 47489a0fd18SMike Nuss /* The HC may wait until the next frame to report the 47589a0fd18SMike Nuss * TD as done through the donelist and INTR_WDH. (We 47689a0fd18SMike Nuss * just *assume* it's not a multi-TD interrupt URB; 47789a0fd18SMike Nuss * those could defer the IRQ more than one frame, using 47889a0fd18SMike Nuss * DI...) Check again after the next INTR_SF. 47989a0fd18SMike Nuss */ 48089a0fd18SMike Nuss ohci_writel(ohci, OHCI_INTR_SF, 48189a0fd18SMike Nuss &ohci->regs->intrstatus); 48289a0fd18SMike Nuss ohci_writel(ohci, OHCI_INTR_SF, 48389a0fd18SMike Nuss &ohci->regs->intrenable); 48489a0fd18SMike Nuss 48589a0fd18SMike Nuss /* flush those writes */ 48689a0fd18SMike Nuss (void) ohci_readl(ohci, &ohci->regs->control); 48789a0fd18SMike Nuss 48889a0fd18SMike Nuss goto out; 48989a0fd18SMike Nuss } 49089a0fd18SMike Nuss } 49189a0fd18SMike Nuss out: 49289a0fd18SMike Nuss kfree(seen); 49389a0fd18SMike Nuss if (ohci->eds_scheduled) 4949cebcdc7SRichard Kennedy mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ)); 49589a0fd18SMike Nuss done: 49689a0fd18SMike Nuss spin_unlock_irqrestore(&ohci->lock, flags); 49789a0fd18SMike Nuss } 49889a0fd18SMike Nuss 4991da177e4SLinus Torvalds /*-------------------------------------------------------------------------* 5001da177e4SLinus Torvalds * HC functions 5011da177e4SLinus Torvalds *-------------------------------------------------------------------------*/ 5021da177e4SLinus Torvalds 5031da177e4SLinus Torvalds /* init memory, and kick BIOS/SMM off */ 5041da177e4SLinus Torvalds 5051da177e4SLinus Torvalds static int ohci_init (struct ohci_hcd *ohci) 5061da177e4SLinus Torvalds { 5071da177e4SLinus Torvalds int ret; 5086a9062f3SDavid Brownell struct usb_hcd *hcd = ohci_to_hcd(ohci); 5091da177e4SLinus Torvalds 5101133cd8aSDmitry Baryshkov if (distrust_firmware) 5111133cd8aSDmitry Baryshkov ohci->flags |= OHCI_QUIRK_HUB_POWER; 5121133cd8aSDmitry Baryshkov 5131da177e4SLinus Torvalds disable (ohci); 5146a9062f3SDavid Brownell ohci->regs = hcd->regs; 5151da177e4SLinus Torvalds 5166a9062f3SDavid Brownell /* REVISIT this BIOS handshake is now moved into PCI "quirks", and 5176a9062f3SDavid Brownell * was never needed for most non-PCI systems ... remove the code? 5186a9062f3SDavid Brownell */ 5196a9062f3SDavid Brownell 5201da177e4SLinus Torvalds #ifndef IR_DISABLE 5211da177e4SLinus Torvalds /* SMM owns the HC? not for long! */ 5221da177e4SLinus Torvalds if (!no_handshake && ohci_readl (ohci, 5231da177e4SLinus Torvalds &ohci->regs->control) & OHCI_CTRL_IR) { 5241da177e4SLinus Torvalds u32 temp; 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n"); 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds /* this timeout is arbitrary. we make it long, so systems 5291da177e4SLinus Torvalds * depending on usb keyboards may be usable even if the 5301da177e4SLinus Torvalds * BIOS/SMM code seems pretty broken. 5311da177e4SLinus Torvalds */ 5321da177e4SLinus Torvalds temp = 500; /* arbitrary: five seconds */ 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds ohci_writel (ohci, OHCI_INTR_OC, &ohci->regs->intrenable); 5351da177e4SLinus Torvalds ohci_writel (ohci, OHCI_OCR, &ohci->regs->cmdstatus); 5361da177e4SLinus Torvalds while (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_IR) { 5371da177e4SLinus Torvalds msleep (10); 5381da177e4SLinus Torvalds if (--temp == 0) { 5391da177e4SLinus Torvalds ohci_err (ohci, "USB HC takeover failed!" 5401da177e4SLinus Torvalds " (BIOS/SMM bug)\n"); 5411da177e4SLinus Torvalds return -EBUSY; 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds } 5441da177e4SLinus Torvalds ohci_usb_reset (ohci); 5451da177e4SLinus Torvalds } 5461da177e4SLinus Torvalds #endif 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds /* Disable HC interrupts */ 5491da177e4SLinus Torvalds ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); 5506a9062f3SDavid Brownell 5516a9062f3SDavid Brownell /* flush the writes, and save key bits like RWC */ 5526a9062f3SDavid Brownell if (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_RWC) 5536a9062f3SDavid Brownell ohci->hc_control |= OHCI_CTRL_RWC; 5541da177e4SLinus Torvalds 555fdd13b36SDavid Brownell /* Read the number of ports unless overridden */ 556fdd13b36SDavid Brownell if (ohci->num_ports == 0) 557fdd13b36SDavid Brownell ohci->num_ports = roothub_a(ohci) & RH_A_NDP; 558fdd13b36SDavid Brownell 5591da177e4SLinus Torvalds if (ohci->hcca) 5601da177e4SLinus Torvalds return 0; 5611da177e4SLinus Torvalds 5626a9062f3SDavid Brownell ohci->hcca = dma_alloc_coherent (hcd->self.controller, 5631da177e4SLinus Torvalds sizeof *ohci->hcca, &ohci->hcca_dma, 0); 5641da177e4SLinus Torvalds if (!ohci->hcca) 5651da177e4SLinus Torvalds return -ENOMEM; 5661da177e4SLinus Torvalds 5671da177e4SLinus Torvalds if ((ret = ohci_mem_init (ohci)) < 0) 5686a9062f3SDavid Brownell ohci_stop (hcd); 5696a9062f3SDavid Brownell else { 5706a9062f3SDavid Brownell create_debug_files (ohci); 5716a9062f3SDavid Brownell } 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds return ret; 5741da177e4SLinus Torvalds } 5751da177e4SLinus Torvalds 5761da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/ 5771da177e4SLinus Torvalds 5781da177e4SLinus Torvalds /* Start an OHCI controller, set the BUS operational 5791da177e4SLinus Torvalds * resets USB and controller 5801da177e4SLinus Torvalds * enable interrupts 5811da177e4SLinus Torvalds */ 5821da177e4SLinus Torvalds static int ohci_run (struct ohci_hcd *ohci) 5831da177e4SLinus Torvalds { 58496f90a8bSH Hartley Sweeten u32 mask, val; 5851da177e4SLinus Torvalds int first = ohci->fminterval == 0; 5866a9062f3SDavid Brownell struct usb_hcd *hcd = ohci_to_hcd(ohci); 5871da177e4SLinus Torvalds 5881da177e4SLinus Torvalds disable (ohci); 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds /* boot firmware should have set this up (5.1.1.3.1) */ 5911da177e4SLinus Torvalds if (first) { 5921da177e4SLinus Torvalds 59396f90a8bSH Hartley Sweeten val = ohci_readl (ohci, &ohci->regs->fminterval); 59496f90a8bSH Hartley Sweeten ohci->fminterval = val & 0x3fff; 5951da177e4SLinus Torvalds if (ohci->fminterval != FI) 5961da177e4SLinus Torvalds ohci_dbg (ohci, "fminterval delta %d\n", 5971da177e4SLinus Torvalds ohci->fminterval - FI); 5981da177e4SLinus Torvalds ohci->fminterval |= FSMP (ohci->fminterval) << 16; 5991da177e4SLinus Torvalds /* also: power/overcurrent flags in roothub.a */ 6001da177e4SLinus Torvalds } 6011da177e4SLinus Torvalds 6026fd9086aSAlan Stern /* Reset USB nearly "by the book". RemoteWakeupConnected has 6036fd9086aSAlan Stern * to be checked in case boot firmware (BIOS/SMM/...) has set up 6046fd9086aSAlan Stern * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM). 6056fd9086aSAlan Stern * If the bus glue detected wakeup capability then it should 606bcca06efSAlan Stern * already be enabled; if so we'll just enable it again. 6071da177e4SLinus Torvalds */ 608bcca06efSAlan Stern if ((ohci->hc_control & OHCI_CTRL_RWC) != 0) 609bcca06efSAlan Stern device_set_wakeup_capable(hcd->self.controller, 1); 6101da177e4SLinus Torvalds 6111da177e4SLinus Torvalds switch (ohci->hc_control & OHCI_CTRL_HCFS) { 6121da177e4SLinus Torvalds case OHCI_USB_OPER: 61396f90a8bSH Hartley Sweeten val = 0; 6141da177e4SLinus Torvalds break; 6151da177e4SLinus Torvalds case OHCI_USB_SUSPEND: 6161da177e4SLinus Torvalds case OHCI_USB_RESUME: 6171da177e4SLinus Torvalds ohci->hc_control &= OHCI_CTRL_RWC; 6181da177e4SLinus Torvalds ohci->hc_control |= OHCI_USB_RESUME; 61996f90a8bSH Hartley Sweeten val = 10 /* msec wait */; 6201da177e4SLinus Torvalds break; 6211da177e4SLinus Torvalds // case OHCI_USB_RESET: 6221da177e4SLinus Torvalds default: 6231da177e4SLinus Torvalds ohci->hc_control &= OHCI_CTRL_RWC; 6241da177e4SLinus Torvalds ohci->hc_control |= OHCI_USB_RESET; 62596f90a8bSH Hartley Sweeten val = 50 /* msec wait */; 6261da177e4SLinus Torvalds break; 6271da177e4SLinus Torvalds } 6281da177e4SLinus Torvalds ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 6291da177e4SLinus Torvalds // flush the writes 6301da177e4SLinus Torvalds (void) ohci_readl (ohci, &ohci->regs->control); 63196f90a8bSH Hartley Sweeten msleep(val); 632383975d7SAlan Stern 6331da177e4SLinus Torvalds memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds /* 2msec timelimit here means no irqs/preempt */ 6361da177e4SLinus Torvalds spin_lock_irq (&ohci->lock); 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds retry: 6391da177e4SLinus Torvalds /* HC Reset requires max 10 us delay */ 6401da177e4SLinus Torvalds ohci_writel (ohci, OHCI_HCR, &ohci->regs->cmdstatus); 64196f90a8bSH Hartley Sweeten val = 30; /* ... allow extra time */ 6421da177e4SLinus Torvalds while ((ohci_readl (ohci, &ohci->regs->cmdstatus) & OHCI_HCR) != 0) { 64396f90a8bSH Hartley Sweeten if (--val == 0) { 6441da177e4SLinus Torvalds spin_unlock_irq (&ohci->lock); 6451da177e4SLinus Torvalds ohci_err (ohci, "USB HC reset timed out!\n"); 6461da177e4SLinus Torvalds return -1; 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds udelay (1); 6491da177e4SLinus Torvalds } 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds /* now we're in the SUSPEND state ... must go OPERATIONAL 6521da177e4SLinus Torvalds * within 2msec else HC enters RESUME 6531da177e4SLinus Torvalds * 6541da177e4SLinus Torvalds * ... but some hardware won't init fmInterval "by the book" 6551da177e4SLinus Torvalds * (SiS, OPTi ...), so reset again instead. SiS doesn't need 6561da177e4SLinus Torvalds * this if we write fmInterval after we're OPERATIONAL. 6571da177e4SLinus Torvalds * Unclear about ALi, ServerWorks, and others ... this could 6581da177e4SLinus Torvalds * easily be a longstanding bug in chip init on Linux. 6591da177e4SLinus Torvalds */ 6601da177e4SLinus Torvalds if (ohci->flags & OHCI_QUIRK_INITRESET) { 6611da177e4SLinus Torvalds ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 6621da177e4SLinus Torvalds // flush those writes 6631da177e4SLinus Torvalds (void) ohci_readl (ohci, &ohci->regs->control); 6641da177e4SLinus Torvalds } 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds /* Tell the controller where the control and bulk lists are 6671da177e4SLinus Torvalds * The lists are empty now. */ 6681da177e4SLinus Torvalds ohci_writel (ohci, 0, &ohci->regs->ed_controlhead); 6691da177e4SLinus Torvalds ohci_writel (ohci, 0, &ohci->regs->ed_bulkhead); 6701da177e4SLinus Torvalds 6711da177e4SLinus Torvalds /* a reset clears this */ 6721da177e4SLinus Torvalds ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca); 6731da177e4SLinus Torvalds 6741da177e4SLinus Torvalds periodic_reinit (ohci); 6751da177e4SLinus Torvalds 6761da177e4SLinus Torvalds /* some OHCI implementations are finicky about how they init. 6771da177e4SLinus Torvalds * bogus values here mean not even enumeration could work. 6781da177e4SLinus Torvalds */ 6791da177e4SLinus Torvalds if ((ohci_readl (ohci, &ohci->regs->fminterval) & 0x3fff0000) == 0 6801da177e4SLinus Torvalds || !ohci_readl (ohci, &ohci->regs->periodicstart)) { 6811da177e4SLinus Torvalds if (!(ohci->flags & OHCI_QUIRK_INITRESET)) { 6821da177e4SLinus Torvalds ohci->flags |= OHCI_QUIRK_INITRESET; 6831da177e4SLinus Torvalds ohci_dbg (ohci, "enabling initreset quirk\n"); 6841da177e4SLinus Torvalds goto retry; 6851da177e4SLinus Torvalds } 6861da177e4SLinus Torvalds spin_unlock_irq (&ohci->lock); 6871da177e4SLinus Torvalds ohci_err (ohci, "init err (%08x %04x)\n", 6881da177e4SLinus Torvalds ohci_readl (ohci, &ohci->regs->fminterval), 6891da177e4SLinus Torvalds ohci_readl (ohci, &ohci->regs->periodicstart)); 6901da177e4SLinus Torvalds return -EOVERFLOW; 6911da177e4SLinus Torvalds } 6921da177e4SLinus Torvalds 693d413984aSDavid Brownell /* use rhsc irqs after khubd is fully initialized */ 694541c7d43SAlan Stern set_bit(HCD_FLAG_POLL_RH, &hcd->flags); 695d413984aSDavid Brownell hcd->uses_new_polling = 1; 696d413984aSDavid Brownell 6971da177e4SLinus Torvalds /* start controller operations */ 6981da177e4SLinus Torvalds ohci->hc_control &= OHCI_CTRL_RWC; 6991da177e4SLinus Torvalds ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; 7001da177e4SLinus Torvalds ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 7016a9062f3SDavid Brownell hcd->state = HC_STATE_RUNNING; 7021da177e4SLinus Torvalds 7031da177e4SLinus Torvalds /* wake on ConnectStatusChange, matching external hubs */ 7041da177e4SLinus Torvalds ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status); 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds /* Choose the interrupts we care about now, others later on demand */ 7071da177e4SLinus Torvalds mask = OHCI_INTR_INIT; 708d413984aSDavid Brownell ohci_writel (ohci, ~0, &ohci->regs->intrstatus); 7091da177e4SLinus Torvalds ohci_writel (ohci, mask, &ohci->regs->intrenable); 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds /* handle root hub init quirks ... */ 71296f90a8bSH Hartley Sweeten val = roothub_a (ohci); 71396f90a8bSH Hartley Sweeten val &= ~(RH_A_PSM | RH_A_OCPM); 7141da177e4SLinus Torvalds if (ohci->flags & OHCI_QUIRK_SUPERIO) { 7151da177e4SLinus Torvalds /* NSC 87560 and maybe others */ 71696f90a8bSH Hartley Sweeten val |= RH_A_NOCP; 71796f90a8bSH Hartley Sweeten val &= ~(RH_A_POTPGT | RH_A_NPS); 71896f90a8bSH Hartley Sweeten ohci_writel (ohci, val, &ohci->regs->roothub.a); 7191133cd8aSDmitry Baryshkov } else if ((ohci->flags & OHCI_QUIRK_AMD756) || 7201133cd8aSDmitry Baryshkov (ohci->flags & OHCI_QUIRK_HUB_POWER)) { 7211da177e4SLinus Torvalds /* hub power always on; required for AMD-756 and some 7221da177e4SLinus Torvalds * Mac platforms. ganged overcurrent reporting, if any. 7231da177e4SLinus Torvalds */ 72496f90a8bSH Hartley Sweeten val |= RH_A_NPS; 72596f90a8bSH Hartley Sweeten ohci_writel (ohci, val, &ohci->regs->roothub.a); 7261da177e4SLinus Torvalds } 7271da177e4SLinus Torvalds ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status); 72896f90a8bSH Hartley Sweeten ohci_writel (ohci, (val & RH_A_NPS) ? 0 : RH_B_PPCM, 7291da177e4SLinus Torvalds &ohci->regs->roothub.b); 7301da177e4SLinus Torvalds // flush those writes 7311da177e4SLinus Torvalds (void) ohci_readl (ohci, &ohci->regs->control); 7321da177e4SLinus Torvalds 733d413984aSDavid Brownell ohci->next_statechange = jiffies + STATECHANGE_DELAY; 7341da177e4SLinus Torvalds spin_unlock_irq (&ohci->lock); 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds // POTPGT delay is bits 24-31, in 2 ms units. 73796f90a8bSH Hartley Sweeten mdelay ((val >> 23) & 0x1fe); 7386a9062f3SDavid Brownell hcd->state = HC_STATE_RUNNING; 7391da177e4SLinus Torvalds 74089a0fd18SMike Nuss if (quirk_zfmicro(ohci)) { 74189a0fd18SMike Nuss /* Create timer to watch for bad queue state on ZF Micro */ 74289a0fd18SMike Nuss setup_timer(&ohci->unlink_watchdog, unlink_watchdog_func, 74389a0fd18SMike Nuss (unsigned long) ohci); 74489a0fd18SMike Nuss 74589a0fd18SMike Nuss ohci->eds_scheduled = 0; 74689a0fd18SMike Nuss ohci->ed_to_check = NULL; 74789a0fd18SMike Nuss } 74889a0fd18SMike Nuss 7491da177e4SLinus Torvalds ohci_dump (ohci, 1); 7501da177e4SLinus Torvalds 7511da177e4SLinus Torvalds return 0; 7521da177e4SLinus Torvalds } 7531da177e4SLinus Torvalds 7541da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/ 7551da177e4SLinus Torvalds 7561da177e4SLinus Torvalds /* an interrupt happens */ 7571da177e4SLinus Torvalds 7587d12e780SDavid Howells static irqreturn_t ohci_irq (struct usb_hcd *hcd) 7591da177e4SLinus Torvalds { 7601da177e4SLinus Torvalds struct ohci_hcd *ohci = hcd_to_ohci (hcd); 7611da177e4SLinus Torvalds struct ohci_regs __iomem *regs = ohci->regs; 7621da177e4SLinus Torvalds int ints; 7631da177e4SLinus Torvalds 764565227c0SBenjamin Herrenschmidt /* Read interrupt status (and flush pending writes). We ignore the 765565227c0SBenjamin Herrenschmidt * optimization of checking the LSB of hcca->done_head; it doesn't 766565227c0SBenjamin Herrenschmidt * work on all systems (edge triggering for OHCI can be a factor). 76789a0fd18SMike Nuss */ 768565227c0SBenjamin Herrenschmidt ints = ohci_readl(ohci, ®s->intrstatus); 7691da177e4SLinus Torvalds 770565227c0SBenjamin Herrenschmidt /* Check for an all 1's result which is a typical consequence 771565227c0SBenjamin Herrenschmidt * of dead, unclocked, or unplugged (CardBus...) devices 772565227c0SBenjamin Herrenschmidt */ 773565227c0SBenjamin Herrenschmidt if (ints == ~(u32)0) { 7741da177e4SLinus Torvalds disable (ohci); 7751da177e4SLinus Torvalds ohci_dbg (ohci, "device removed!\n"); 7761da177e4SLinus Torvalds return IRQ_HANDLED; 777565227c0SBenjamin Herrenschmidt } 778565227c0SBenjamin Herrenschmidt 779565227c0SBenjamin Herrenschmidt /* We only care about interrupts that are enabled */ 780565227c0SBenjamin Herrenschmidt ints &= ohci_readl(ohci, ®s->intrenable); 7811da177e4SLinus Torvalds 7821da177e4SLinus Torvalds /* interrupt for some other device? */ 783565227c0SBenjamin Herrenschmidt if (ints == 0) 7841da177e4SLinus Torvalds return IRQ_NOTMINE; 7851da177e4SLinus Torvalds 7861da177e4SLinus Torvalds if (ints & OHCI_INTR_UE) { 787d576bb9fSMichael Hanselmann // e.g. due to PCI Master/Target Abort 78889a0fd18SMike Nuss if (quirk_nec(ohci)) { 789d576bb9fSMichael Hanselmann /* Workaround for a silicon bug in some NEC chips used 790d576bb9fSMichael Hanselmann * in Apple's PowerBooks. Adapted from Darwin code. 791d576bb9fSMichael Hanselmann */ 792d576bb9fSMichael Hanselmann ohci_err (ohci, "OHCI Unrecoverable Error, scheduling NEC chip restart\n"); 793d576bb9fSMichael Hanselmann 794d576bb9fSMichael Hanselmann ohci_writel (ohci, OHCI_INTR_UE, ®s->intrdisable); 795d576bb9fSMichael Hanselmann 796d576bb9fSMichael Hanselmann schedule_work (&ohci->nec_work); 797d576bb9fSMichael Hanselmann } else { 7981da177e4SLinus Torvalds disable (ohci); 7991da177e4SLinus Torvalds ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); 800d576bb9fSMichael Hanselmann } 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds ohci_dump (ohci, 1); 8031da177e4SLinus Torvalds ohci_usb_reset (ohci); 8041da177e4SLinus Torvalds } 8051da177e4SLinus Torvalds 806583ceadaSAlan Stern if (ints & OHCI_INTR_RHSC) { 807583ceadaSAlan Stern ohci_vdbg(ohci, "rhsc\n"); 808583ceadaSAlan Stern ohci->next_statechange = jiffies + STATECHANGE_DELAY; 809583ceadaSAlan Stern ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC, 810583ceadaSAlan Stern ®s->intrstatus); 811052ac01aSAlan Stern 812052ac01aSAlan Stern /* NOTE: Vendors didn't always make the same implementation 813052ac01aSAlan Stern * choices for RHSC. Many followed the spec; RHSC triggers 814052ac01aSAlan Stern * on an edge, like setting and maybe clearing a port status 815052ac01aSAlan Stern * change bit. With others it's level-triggered, active 816052ac01aSAlan Stern * until khubd clears all the port status change bits. We'll 817052ac01aSAlan Stern * always disable it here and rely on polling until khubd 818052ac01aSAlan Stern * re-enables it. 819052ac01aSAlan Stern */ 820052ac01aSAlan Stern ohci_writel(ohci, OHCI_INTR_RHSC, ®s->intrdisable); 821583ceadaSAlan Stern usb_hcd_poll_rh_status(hcd); 822583ceadaSAlan Stern } 823583ceadaSAlan Stern 824583ceadaSAlan Stern /* For connect and disconnect events, we expect the controller 825583ceadaSAlan Stern * to turn on RHSC along with RD. But for remote wakeup events 826583ceadaSAlan Stern * this might not happen. 827583ceadaSAlan Stern */ 828583ceadaSAlan Stern else if (ints & OHCI_INTR_RD) { 8291da177e4SLinus Torvalds ohci_vdbg(ohci, "resume detect\n"); 830e0fd3cbcSDavid Brownell ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus); 831541c7d43SAlan Stern set_bit(HCD_FLAG_POLL_RH, &hcd->flags); 8328d1a243bSAlan Stern if (ohci->autostop) { 8338d1a243bSAlan Stern spin_lock (&ohci->lock); 8348d1a243bSAlan Stern ohci_rh_resume (ohci); 8358d1a243bSAlan Stern spin_unlock (&ohci->lock); 8368d1a243bSAlan Stern } else 837f197b2c5SDavid Brownell usb_hcd_resume_root_hub(hcd); 8381da177e4SLinus Torvalds } 8391da177e4SLinus Torvalds 8401da177e4SLinus Torvalds if (ints & OHCI_INTR_WDH) { 8411da177e4SLinus Torvalds spin_lock (&ohci->lock); 8427d12e780SDavid Howells dl_done_list (ohci); 8431da177e4SLinus Torvalds spin_unlock (&ohci->lock); 8441da177e4SLinus Torvalds } 8451da177e4SLinus Torvalds 84689a0fd18SMike Nuss if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) { 84789a0fd18SMike Nuss spin_lock(&ohci->lock); 84889a0fd18SMike Nuss if (ohci->ed_to_check) { 84989a0fd18SMike Nuss struct ed *ed = ohci->ed_to_check; 85089a0fd18SMike Nuss 85189a0fd18SMike Nuss if (check_ed(ohci, ed)) { 85289a0fd18SMike Nuss /* HC thinks the TD list is empty; HCD knows 85389a0fd18SMike Nuss * at least one TD is outstanding 85489a0fd18SMike Nuss */ 85589a0fd18SMike Nuss if (--ohci->zf_delay == 0) { 85689a0fd18SMike Nuss struct td *td = list_entry( 85789a0fd18SMike Nuss ed->td_list.next, 85889a0fd18SMike Nuss struct td, td_list); 85989a0fd18SMike Nuss ohci_warn(ohci, 86089a0fd18SMike Nuss "Reclaiming orphan TD %p\n", 86189a0fd18SMike Nuss td); 86289a0fd18SMike Nuss takeback_td(ohci, td); 86389a0fd18SMike Nuss ohci->ed_to_check = NULL; 86489a0fd18SMike Nuss } 86589a0fd18SMike Nuss } else 86689a0fd18SMike Nuss ohci->ed_to_check = NULL; 86789a0fd18SMike Nuss } 86889a0fd18SMike Nuss spin_unlock(&ohci->lock); 86989a0fd18SMike Nuss } 87089a0fd18SMike Nuss 8711da177e4SLinus Torvalds /* could track INTR_SO to reduce available PCI/... bandwidth */ 8721da177e4SLinus Torvalds 8731da177e4SLinus Torvalds /* handle any pending URB/ED unlinks, leaving INTR_SF enabled 8741da177e4SLinus Torvalds * when there's still unlinking to be done (next frame). 8751da177e4SLinus Torvalds */ 8761da177e4SLinus Torvalds spin_lock (&ohci->lock); 8771da177e4SLinus Torvalds if (ohci->ed_rm_list) 8787d12e780SDavid Howells finish_unlinks (ohci, ohci_frame_no(ohci)); 87989a0fd18SMike Nuss if ((ints & OHCI_INTR_SF) != 0 88089a0fd18SMike Nuss && !ohci->ed_rm_list 88189a0fd18SMike Nuss && !ohci->ed_to_check 8821da177e4SLinus Torvalds && HC_IS_RUNNING(hcd->state)) 8831da177e4SLinus Torvalds ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable); 8841da177e4SLinus Torvalds spin_unlock (&ohci->lock); 8851da177e4SLinus Torvalds 8861da177e4SLinus Torvalds if (HC_IS_RUNNING(hcd->state)) { 8871da177e4SLinus Torvalds ohci_writel (ohci, ints, ®s->intrstatus); 8881da177e4SLinus Torvalds ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); 8891da177e4SLinus Torvalds // flush those writes 8901da177e4SLinus Torvalds (void) ohci_readl (ohci, &ohci->regs->control); 8911da177e4SLinus Torvalds } 8921da177e4SLinus Torvalds 8931da177e4SLinus Torvalds return IRQ_HANDLED; 8941da177e4SLinus Torvalds } 8951da177e4SLinus Torvalds 8961da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/ 8971da177e4SLinus Torvalds 8981da177e4SLinus Torvalds static void ohci_stop (struct usb_hcd *hcd) 8991da177e4SLinus Torvalds { 9001da177e4SLinus Torvalds struct ohci_hcd *ohci = hcd_to_ohci (hcd); 9011da177e4SLinus Torvalds 9021da177e4SLinus Torvalds ohci_dump (ohci, 1); 9031da177e4SLinus Torvalds 9041da177e4SLinus Torvalds flush_scheduled_work(); 9051da177e4SLinus Torvalds 9061da177e4SLinus Torvalds ohci_usb_reset (ohci); 9071da177e4SLinus Torvalds ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); 90871795c1dSPete Zaitcev free_irq(hcd->irq, hcd); 90971795c1dSPete Zaitcev hcd->irq = -1; 9101da177e4SLinus Torvalds 91189a0fd18SMike Nuss if (quirk_zfmicro(ohci)) 91289a0fd18SMike Nuss del_timer(&ohci->unlink_watchdog); 913ab1666c1SLibin Yang if (quirk_amdiso(ohci)) 914ab1666c1SLibin Yang amd_iso_dev_put(); 91589a0fd18SMike Nuss 9161da177e4SLinus Torvalds remove_debug_files (ohci); 9171da177e4SLinus Torvalds ohci_mem_cleanup (ohci); 9181da177e4SLinus Torvalds if (ohci->hcca) { 9191da177e4SLinus Torvalds dma_free_coherent (hcd->self.controller, 9201da177e4SLinus Torvalds sizeof *ohci->hcca, 9211da177e4SLinus Torvalds ohci->hcca, ohci->hcca_dma); 9221da177e4SLinus Torvalds ohci->hcca = NULL; 9231da177e4SLinus Torvalds ohci->hcca_dma = 0; 9241da177e4SLinus Torvalds } 9251da177e4SLinus Torvalds } 9261da177e4SLinus Torvalds 9271da177e4SLinus Torvalds /*-------------------------------------------------------------------------*/ 9281da177e4SLinus Torvalds 929da6fb570SDavid Brownell #if defined(CONFIG_PM) || defined(CONFIG_PCI) 930da6fb570SDavid Brownell 9311da177e4SLinus Torvalds /* must not be called from interrupt context */ 9321da177e4SLinus Torvalds static int ohci_restart (struct ohci_hcd *ohci) 9331da177e4SLinus Torvalds { 9341da177e4SLinus Torvalds int temp; 9351da177e4SLinus Torvalds int i; 9361da177e4SLinus Torvalds struct urb_priv *priv; 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds spin_lock_irq(&ohci->lock); 9391da177e4SLinus Torvalds disable (ohci); 940d576bb9fSMichael Hanselmann 941d576bb9fSMichael Hanselmann /* Recycle any "live" eds/tds (and urbs). */ 9421da177e4SLinus Torvalds if (!list_empty (&ohci->pending)) 9431da177e4SLinus Torvalds ohci_dbg(ohci, "abort schedule...\n"); 9441da177e4SLinus Torvalds list_for_each_entry (priv, &ohci->pending, pending) { 9451da177e4SLinus Torvalds struct urb *urb = priv->td[0]->urb; 9461da177e4SLinus Torvalds struct ed *ed = priv->ed; 9471da177e4SLinus Torvalds 9481da177e4SLinus Torvalds switch (ed->state) { 9491da177e4SLinus Torvalds case ED_OPER: 9501da177e4SLinus Torvalds ed->state = ED_UNLINK; 9511da177e4SLinus Torvalds ed->hwINFO |= cpu_to_hc32(ohci, ED_DEQUEUE); 9521da177e4SLinus Torvalds ed_deschedule (ohci, ed); 9531da177e4SLinus Torvalds 9541da177e4SLinus Torvalds ed->ed_next = ohci->ed_rm_list; 9551da177e4SLinus Torvalds ed->ed_prev = NULL; 9561da177e4SLinus Torvalds ohci->ed_rm_list = ed; 9571da177e4SLinus Torvalds /* FALLTHROUGH */ 9581da177e4SLinus Torvalds case ED_UNLINK: 9591da177e4SLinus Torvalds break; 9601da177e4SLinus Torvalds default: 9611da177e4SLinus Torvalds ohci_dbg(ohci, "bogus ed %p state %d\n", 9621da177e4SLinus Torvalds ed, ed->state); 9631da177e4SLinus Torvalds } 9641da177e4SLinus Torvalds 96555d84968SAlan Stern if (!urb->unlinked) 96655d84968SAlan Stern urb->unlinked = -ESHUTDOWN; 9671da177e4SLinus Torvalds } 9687d12e780SDavid Howells finish_unlinks (ohci, 0); 9691da177e4SLinus Torvalds spin_unlock_irq(&ohci->lock); 9701da177e4SLinus Torvalds 9711da177e4SLinus Torvalds /* paranoia, in case that didn't work: */ 9721da177e4SLinus Torvalds 9731da177e4SLinus Torvalds /* empty the interrupt branches */ 9741da177e4SLinus Torvalds for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0; 9751da177e4SLinus Torvalds for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0; 9761da177e4SLinus Torvalds 9771da177e4SLinus Torvalds /* no EDs to remove */ 9781da177e4SLinus Torvalds ohci->ed_rm_list = NULL; 9791da177e4SLinus Torvalds 9801da177e4SLinus Torvalds /* empty control and bulk lists */ 9811da177e4SLinus Torvalds ohci->ed_controltail = NULL; 9821da177e4SLinus Torvalds ohci->ed_bulktail = NULL; 9831da177e4SLinus Torvalds 9841da177e4SLinus Torvalds if ((temp = ohci_run (ohci)) < 0) { 9851da177e4SLinus Torvalds ohci_err (ohci, "can't restart, %d\n", temp); 9861da177e4SLinus Torvalds return temp; 9871da177e4SLinus Torvalds } 988383975d7SAlan Stern ohci_dbg(ohci, "restart complete\n"); 9891da177e4SLinus Torvalds return 0; 9901da177e4SLinus Torvalds } 991d576bb9fSMichael Hanselmann 992da6fb570SDavid Brownell #endif 993da6fb570SDavid Brownell 994d576bb9fSMichael Hanselmann /*-------------------------------------------------------------------------*/ 995d576bb9fSMichael Hanselmann 9961da177e4SLinus Torvalds MODULE_AUTHOR (DRIVER_AUTHOR); 9972b70f073SAlan Stern MODULE_DESCRIPTION(DRIVER_DESC); 9981da177e4SLinus Torvalds MODULE_LICENSE ("GPL"); 9991da177e4SLinus Torvalds 10001da177e4SLinus Torvalds #ifdef CONFIG_PCI 10011da177e4SLinus Torvalds #include "ohci-pci.c" 10025e16fabeSSylvain Munaut #define PCI_DRIVER ohci_pci_driver 10031da177e4SLinus Torvalds #endif 10041da177e4SLinus Torvalds 10056381fad7SEric Miao #if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111) 10061da177e4SLinus Torvalds #include "ohci-sa1111.c" 10075e16fabeSSylvain Munaut #define SA1111_DRIVER ohci_hcd_sa1111_driver 10081da177e4SLinus Torvalds #endif 10091da177e4SLinus Torvalds 10103ba5f38fSBen Dooks #if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX) 10113eb0c5f4SBen Dooks #include "ohci-s3c2410.c" 10125e16fabeSSylvain Munaut #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver 10133eb0c5f4SBen Dooks #endif 10143eb0c5f4SBen Dooks 1015968b448bSAnand Gadiyar #ifdef CONFIG_USB_OHCI_HCD_OMAP1 10161da177e4SLinus Torvalds #include "ohci-omap.c" 1017968b448bSAnand Gadiyar #define OMAP1_PLATFORM_DRIVER ohci_hcd_omap_driver 1018968b448bSAnand Gadiyar #endif 1019968b448bSAnand Gadiyar 1020968b448bSAnand Gadiyar #ifdef CONFIG_USB_OHCI_HCD_OMAP3 1021968b448bSAnand Gadiyar #include "ohci-omap3.c" 1022968b448bSAnand Gadiyar #define OMAP3_PLATFORM_DRIVER ohci_hcd_omap3_driver 10231da177e4SLinus Torvalds #endif 10241da177e4SLinus Torvalds 10251da177e4SLinus Torvalds #ifdef CONFIG_ARCH_LH7A404 10261da177e4SLinus Torvalds #include "ohci-lh7a404.c" 10275e16fabeSSylvain Munaut #define PLATFORM_DRIVER ohci_hcd_lh7a404_driver 10281da177e4SLinus Torvalds #endif 10291da177e4SLinus Torvalds 1030e77ec189Seric miao #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) 10311da177e4SLinus Torvalds #include "ohci-pxa27x.c" 10325e16fabeSSylvain Munaut #define PLATFORM_DRIVER ohci_hcd_pxa27x_driver 10331da177e4SLinus Torvalds #endif 10341da177e4SLinus Torvalds 1035a5b7474aSLennert Buytenhek #ifdef CONFIG_ARCH_EP93XX 1036a5b7474aSLennert Buytenhek #include "ohci-ep93xx.c" 10375e16fabeSSylvain Munaut #define PLATFORM_DRIVER ohci_hcd_ep93xx_driver 1038a5b7474aSLennert Buytenhek #endif 1039a5b7474aSLennert Buytenhek 104042a4f17dSManuel Lauss #ifdef CONFIG_MIPS_ALCHEMY 10411da177e4SLinus Torvalds #include "ohci-au1xxx.c" 10425e16fabeSSylvain Munaut #define PLATFORM_DRIVER ohci_hcd_au1xxx_driver 10431da177e4SLinus Torvalds #endif 10441da177e4SLinus Torvalds 10455151d040SVitaly Wool #ifdef CONFIG_PNX8550 10465151d040SVitaly Wool #include "ohci-pnx8550.c" 10475e16fabeSSylvain Munaut #define PLATFORM_DRIVER ohci_hcd_pnx8550_driver 10485151d040SVitaly Wool #endif 10495151d040SVitaly Wool 10501da177e4SLinus Torvalds #ifdef CONFIG_USB_OHCI_HCD_PPC_SOC 10511da177e4SLinus Torvalds #include "ohci-ppc-soc.c" 10525e16fabeSSylvain Munaut #define PLATFORM_DRIVER ohci_hcd_ppc_soc_driver 10531da177e4SLinus Torvalds #endif 10541da177e4SLinus Torvalds 105558a0cd78SAndrew Victor #ifdef CONFIG_ARCH_AT91 105639a269c0SAndrew Victor #include "ohci-at91.c" 10575e16fabeSSylvain Munaut #define PLATFORM_DRIVER ohci_hcd_at91_driver 105839a269c0SAndrew Victor #endif 105939a269c0SAndrew Victor 106060bbfc84SVitaly Wool #ifdef CONFIG_ARCH_PNX4008 106160bbfc84SVitaly Wool #include "ohci-pnx4008.c" 10625e16fabeSSylvain Munaut #define PLATFORM_DRIVER usb_hcd_pnx4008_driver 106360bbfc84SVitaly Wool #endif 106460bbfc84SVitaly Wool 1065efe7daf2SSergei Shtylyov #ifdef CONFIG_ARCH_DAVINCI_DA8XX 1066efe7daf2SSergei Shtylyov #include "ohci-da8xx.c" 1067efe7daf2SSergei Shtylyov #define PLATFORM_DRIVER ohci_hcd_da8xx_driver 1068efe7daf2SSergei Shtylyov #endif 1069efe7daf2SSergei Shtylyov 1070828d55c5SYoshihiro Shimoda #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ 1071828d55c5SYoshihiro Shimoda defined(CONFIG_CPU_SUBTYPE_SH7721) || \ 10724c3f450bSKuninori Morimoto defined(CONFIG_CPU_SUBTYPE_SH7763) || \ 10734c3f450bSKuninori Morimoto defined(CONFIG_CPU_SUBTYPE_SH7786) 1074828d55c5SYoshihiro Shimoda #include "ohci-sh.c" 1075828d55c5SYoshihiro Shimoda #define PLATFORM_DRIVER ohci_hcd_sh_driver 1076828d55c5SYoshihiro Shimoda #endif 1077828d55c5SYoshihiro Shimoda 10785e16fabeSSylvain Munaut 1079495a678fSSylvain Munaut #ifdef CONFIG_USB_OHCI_HCD_PPC_OF 1080495a678fSSylvain Munaut #include "ohci-ppc-of.c" 1081495a678fSSylvain Munaut #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver 1082495a678fSSylvain Munaut #endif 1083495a678fSSylvain Munaut 10846a6c957eSGeoff Levand #ifdef CONFIG_PPC_PS3 10856a6c957eSGeoff Levand #include "ohci-ps3.c" 10867a4eb7fdSGeoff Levand #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver 10876a6c957eSGeoff Levand #endif 10886a6c957eSGeoff Levand 1089c604e851SMichael Buesch #ifdef CONFIG_USB_OHCI_HCD_SSB 1090c604e851SMichael Buesch #include "ohci-ssb.c" 1091c604e851SMichael Buesch #define SSB_OHCI_DRIVER ssb_ohci_driver 1092c604e851SMichael Buesch #endif 1093c604e851SMichael Buesch 1094f54aab6eSMagnus Damm #ifdef CONFIG_MFD_SM501 1095f54aab6eSMagnus Damm #include "ohci-sm501.c" 10963ee38d8bSBen Dooks #define SM501_OHCI_DRIVER ohci_hcd_sm501_driver 1097f54aab6eSMagnus Damm #endif 1098f54aab6eSMagnus Damm 109978c73414SDmitry Baryshkov #ifdef CONFIG_MFD_TC6393XB 110078c73414SDmitry Baryshkov #include "ohci-tmio.c" 110178c73414SDmitry Baryshkov #define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver 110278c73414SDmitry Baryshkov #endif 110378c73414SDmitry Baryshkov 11042249071bSLars-Peter Clausen #ifdef CONFIG_MACH_JZ4740 11052249071bSLars-Peter Clausen #include "ohci-jz4740.c" 11062249071bSLars-Peter Clausen #define PLATFORM_DRIVER ohci_hcd_jz4740_driver 11072249071bSLars-Peter Clausen #endif 11082249071bSLars-Peter Clausen 1109*1643accdSDavid Daney #ifdef CONFIG_USB_OCTEON_OHCI 1110*1643accdSDavid Daney #include "ohci-octeon.c" 1111*1643accdSDavid Daney #define PLATFORM_DRIVER ohci_octeon_driver 1112*1643accdSDavid Daney #endif 1113*1643accdSDavid Daney 11145e16fabeSSylvain Munaut #if !defined(PCI_DRIVER) && \ 11155e16fabeSSylvain Munaut !defined(PLATFORM_DRIVER) && \ 1116968b448bSAnand Gadiyar !defined(OMAP1_PLATFORM_DRIVER) && \ 1117968b448bSAnand Gadiyar !defined(OMAP3_PLATFORM_DRIVER) && \ 1118495a678fSSylvain Munaut !defined(OF_PLATFORM_DRIVER) && \ 11196a6c957eSGeoff Levand !defined(SA1111_DRIVER) && \ 1120c604e851SMichael Buesch !defined(PS3_SYSTEM_BUS_DRIVER) && \ 11213ee38d8bSBen Dooks !defined(SM501_OHCI_DRIVER) && \ 112278c73414SDmitry Baryshkov !defined(TMIO_OHCI_DRIVER) && \ 1123c604e851SMichael Buesch !defined(SSB_OHCI_DRIVER) 11241da177e4SLinus Torvalds #error "missing bus glue for ohci-hcd" 11251da177e4SLinus Torvalds #endif 11265e16fabeSSylvain Munaut 11275e16fabeSSylvain Munaut static int __init ohci_hcd_mod_init(void) 11285e16fabeSSylvain Munaut { 11295e16fabeSSylvain Munaut int retval = 0; 11305e16fabeSSylvain Munaut 11315e16fabeSSylvain Munaut if (usb_disabled()) 11325e16fabeSSylvain Munaut return -ENODEV; 11335e16fabeSSylvain Munaut 11342b70f073SAlan Stern printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); 11355e16fabeSSylvain Munaut pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, 11365e16fabeSSylvain Munaut sizeof (struct ed), sizeof (struct td)); 11379beeee65SAlan Stern set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); 11385e16fabeSSylvain Munaut 1139684c19e0STony Jones #ifdef DEBUG 1140485f4f39SGreg Kroah-Hartman ohci_debug_root = debugfs_create_dir("ohci", usb_debug_root); 1141684c19e0STony Jones if (!ohci_debug_root) { 1142684c19e0STony Jones retval = -ENOENT; 1143684c19e0STony Jones goto error_debug; 1144684c19e0STony Jones } 1145684c19e0STony Jones #endif 1146684c19e0STony Jones 11476a6c957eSGeoff Levand #ifdef PS3_SYSTEM_BUS_DRIVER 11487a4eb7fdSGeoff Levand retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); 11496a6c957eSGeoff Levand if (retval < 0) 11506a6c957eSGeoff Levand goto error_ps3; 11516a6c957eSGeoff Levand #endif 11526a6c957eSGeoff Levand 11535e16fabeSSylvain Munaut #ifdef PLATFORM_DRIVER 11545e16fabeSSylvain Munaut retval = platform_driver_register(&PLATFORM_DRIVER); 11555e16fabeSSylvain Munaut if (retval < 0) 1156de44743bSBenjamin Herrenschmidt goto error_platform; 11575e16fabeSSylvain Munaut #endif 11585e16fabeSSylvain Munaut 1159968b448bSAnand Gadiyar #ifdef OMAP1_PLATFORM_DRIVER 1160968b448bSAnand Gadiyar retval = platform_driver_register(&OMAP1_PLATFORM_DRIVER); 1161968b448bSAnand Gadiyar if (retval < 0) 1162968b448bSAnand Gadiyar goto error_omap1_platform; 1163968b448bSAnand Gadiyar #endif 1164968b448bSAnand Gadiyar 1165968b448bSAnand Gadiyar #ifdef OMAP3_PLATFORM_DRIVER 1166968b448bSAnand Gadiyar retval = platform_driver_register(&OMAP3_PLATFORM_DRIVER); 1167968b448bSAnand Gadiyar if (retval < 0) 1168968b448bSAnand Gadiyar goto error_omap3_platform; 1169968b448bSAnand Gadiyar #endif 1170968b448bSAnand Gadiyar 1171495a678fSSylvain Munaut #ifdef OF_PLATFORM_DRIVER 1172495a678fSSylvain Munaut retval = of_register_platform_driver(&OF_PLATFORM_DRIVER); 1173495a678fSSylvain Munaut if (retval < 0) 1174de44743bSBenjamin Herrenschmidt goto error_of_platform; 1175495a678fSSylvain Munaut #endif 1176495a678fSSylvain Munaut 11775e16fabeSSylvain Munaut #ifdef SA1111_DRIVER 11785e16fabeSSylvain Munaut retval = sa1111_driver_register(&SA1111_DRIVER); 11795e16fabeSSylvain Munaut if (retval < 0) 1180de44743bSBenjamin Herrenschmidt goto error_sa1111; 11815e16fabeSSylvain Munaut #endif 11825e16fabeSSylvain Munaut 11835e16fabeSSylvain Munaut #ifdef PCI_DRIVER 11845e16fabeSSylvain Munaut retval = pci_register_driver(&PCI_DRIVER); 11855e16fabeSSylvain Munaut if (retval < 0) 1186de44743bSBenjamin Herrenschmidt goto error_pci; 11875e16fabeSSylvain Munaut #endif 11885e16fabeSSylvain Munaut 1189c604e851SMichael Buesch #ifdef SSB_OHCI_DRIVER 1190c604e851SMichael Buesch retval = ssb_driver_register(&SSB_OHCI_DRIVER); 1191c604e851SMichael Buesch if (retval) 1192c604e851SMichael Buesch goto error_ssb; 1193c604e851SMichael Buesch #endif 1194c604e851SMichael Buesch 11953ee38d8bSBen Dooks #ifdef SM501_OHCI_DRIVER 11963ee38d8bSBen Dooks retval = platform_driver_register(&SM501_OHCI_DRIVER); 11973ee38d8bSBen Dooks if (retval < 0) 11983ee38d8bSBen Dooks goto error_sm501; 11993ee38d8bSBen Dooks #endif 12003ee38d8bSBen Dooks 120178c73414SDmitry Baryshkov #ifdef TMIO_OHCI_DRIVER 120278c73414SDmitry Baryshkov retval = platform_driver_register(&TMIO_OHCI_DRIVER); 120378c73414SDmitry Baryshkov if (retval < 0) 120478c73414SDmitry Baryshkov goto error_tmio; 120578c73414SDmitry Baryshkov #endif 120678c73414SDmitry Baryshkov 12075e16fabeSSylvain Munaut return retval; 12085e16fabeSSylvain Munaut 12095e16fabeSSylvain Munaut /* Error path */ 121078c73414SDmitry Baryshkov #ifdef TMIO_OHCI_DRIVER 121178c73414SDmitry Baryshkov platform_driver_unregister(&TMIO_OHCI_DRIVER); 121278c73414SDmitry Baryshkov error_tmio: 121378c73414SDmitry Baryshkov #endif 12143ee38d8bSBen Dooks #ifdef SM501_OHCI_DRIVER 121578c73414SDmitry Baryshkov platform_driver_unregister(&SM501_OHCI_DRIVER); 12163ee38d8bSBen Dooks error_sm501: 12173ee38d8bSBen Dooks #endif 1218c604e851SMichael Buesch #ifdef SSB_OHCI_DRIVER 121978c73414SDmitry Baryshkov ssb_driver_unregister(&SSB_OHCI_DRIVER); 1220c604e851SMichael Buesch error_ssb: 1221c604e851SMichael Buesch #endif 1222de44743bSBenjamin Herrenschmidt #ifdef PCI_DRIVER 1223c604e851SMichael Buesch pci_unregister_driver(&PCI_DRIVER); 1224de44743bSBenjamin Herrenschmidt error_pci: 1225495a678fSSylvain Munaut #endif 12265e16fabeSSylvain Munaut #ifdef SA1111_DRIVER 12275e16fabeSSylvain Munaut sa1111_driver_unregister(&SA1111_DRIVER); 1228de44743bSBenjamin Herrenschmidt error_sa1111: 1229de44743bSBenjamin Herrenschmidt #endif 1230de44743bSBenjamin Herrenschmidt #ifdef OF_PLATFORM_DRIVER 1231de44743bSBenjamin Herrenschmidt of_unregister_platform_driver(&OF_PLATFORM_DRIVER); 1232de44743bSBenjamin Herrenschmidt error_of_platform: 1233de44743bSBenjamin Herrenschmidt #endif 1234de44743bSBenjamin Herrenschmidt #ifdef PLATFORM_DRIVER 1235de44743bSBenjamin Herrenschmidt platform_driver_unregister(&PLATFORM_DRIVER); 1236de44743bSBenjamin Herrenschmidt error_platform: 12375e16fabeSSylvain Munaut #endif 1238968b448bSAnand Gadiyar #ifdef OMAP1_PLATFORM_DRIVER 1239968b448bSAnand Gadiyar platform_driver_unregister(&OMAP1_PLATFORM_DRIVER); 1240968b448bSAnand Gadiyar error_omap1_platform: 1241968b448bSAnand Gadiyar #endif 1242968b448bSAnand Gadiyar #ifdef OMAP3_PLATFORM_DRIVER 1243968b448bSAnand Gadiyar platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); 1244968b448bSAnand Gadiyar error_omap3_platform: 1245968b448bSAnand Gadiyar #endif 12466a6c957eSGeoff Levand #ifdef PS3_SYSTEM_BUS_DRIVER 12477a4eb7fdSGeoff Levand ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); 12486a6c957eSGeoff Levand error_ps3: 12496a6c957eSGeoff Levand #endif 1250684c19e0STony Jones #ifdef DEBUG 1251684c19e0STony Jones debugfs_remove(ohci_debug_root); 1252684c19e0STony Jones ohci_debug_root = NULL; 1253684c19e0STony Jones error_debug: 1254684c19e0STony Jones #endif 1255684c19e0STony Jones 12569beeee65SAlan Stern clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); 12575e16fabeSSylvain Munaut return retval; 12585e16fabeSSylvain Munaut } 12595e16fabeSSylvain Munaut module_init(ohci_hcd_mod_init); 12605e16fabeSSylvain Munaut 12615e16fabeSSylvain Munaut static void __exit ohci_hcd_mod_exit(void) 12625e16fabeSSylvain Munaut { 126378c73414SDmitry Baryshkov #ifdef TMIO_OHCI_DRIVER 126478c73414SDmitry Baryshkov platform_driver_unregister(&TMIO_OHCI_DRIVER); 126578c73414SDmitry Baryshkov #endif 12663ee38d8bSBen Dooks #ifdef SM501_OHCI_DRIVER 12673ee38d8bSBen Dooks platform_driver_unregister(&SM501_OHCI_DRIVER); 12683ee38d8bSBen Dooks #endif 1269c604e851SMichael Buesch #ifdef SSB_OHCI_DRIVER 1270c604e851SMichael Buesch ssb_driver_unregister(&SSB_OHCI_DRIVER); 1271c604e851SMichael Buesch #endif 12725e16fabeSSylvain Munaut #ifdef PCI_DRIVER 12735e16fabeSSylvain Munaut pci_unregister_driver(&PCI_DRIVER); 12745e16fabeSSylvain Munaut #endif 12755e16fabeSSylvain Munaut #ifdef SA1111_DRIVER 12765e16fabeSSylvain Munaut sa1111_driver_unregister(&SA1111_DRIVER); 12775e16fabeSSylvain Munaut #endif 1278495a678fSSylvain Munaut #ifdef OF_PLATFORM_DRIVER 1279495a678fSSylvain Munaut of_unregister_platform_driver(&OF_PLATFORM_DRIVER); 1280495a678fSSylvain Munaut #endif 12815e16fabeSSylvain Munaut #ifdef PLATFORM_DRIVER 12825e16fabeSSylvain Munaut platform_driver_unregister(&PLATFORM_DRIVER); 12835e16fabeSSylvain Munaut #endif 1284ffb6748fSKeshava Munegowda #ifdef OMAP3_PLATFORM_DRIVER 1285ffb6748fSKeshava Munegowda platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); 1286ffb6748fSKeshava Munegowda #endif 12876a6c957eSGeoff Levand #ifdef PS3_SYSTEM_BUS_DRIVER 12887a4eb7fdSGeoff Levand ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); 12896a6c957eSGeoff Levand #endif 1290684c19e0STony Jones #ifdef DEBUG 1291684c19e0STony Jones debugfs_remove(ohci_debug_root); 1292684c19e0STony Jones #endif 12939beeee65SAlan Stern clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); 12945e16fabeSSylvain Munaut } 12955e16fabeSSylvain Munaut module_exit(ohci_hcd_mod_exit); 12965e16fabeSSylvain Munaut 1297