// SPDX-License-Identifier: GPL-1.0+ /* * Open Host Controller Interface (OHCI) driver for USB. * * Maintainer: Alan Stern <[email protected]> * * (C) Copyright 1999 Roman Weissgaerber <[email protected]> * (C) Copyright 2000-2004 David Brownell <[email protected]> * * [ Initialisation is based on Linus' ] * [ uhci code and gregs ohci fragments ] * [ (C) Copyright 1999 Linus Torvalds ] * [ (C) Copyright 1999 Gregory P. Smith] * * * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller * interfaces (though some non-x86 Intel chips use it). It supports * smarter hardware than UHCI. A download link for the spec available * through the https://www.usb.org website. * * This file is licenced under the GPL. */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/pci.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ioport.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/timer.h> #include <linux/list.h> #include <linux/usb.h> #include <linux/usb/otg.h> #include <linux/usb/hcd.h> #include <linux/dma-mapping.h> #include <linux/dmapool.h> #include <linux/workqueue.h> #include <linux/debugfs.h> #include <linux/genalloc.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/unaligned.h> #include <asm/byteorder.h> #define DRIVER_AUTHOR … #define DRIVER_DESC … /*-------------------------------------------------------------------------*/ /* For initializing controller (mask in an HCFS mode too) */ #define OHCI_CONTROL_INIT … #define OHCI_INTR_INIT … #ifdef __hppa__ /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ #define IR_DISABLE #endif #ifdef CONFIG_ARCH_OMAP /* OMAP doesn't support IR (no SMM; not needed) */ #define IR_DISABLE #endif /*-------------------------------------------------------------------------*/ static const char hcd_name [] = …; #define STATECHANGE_DELAY … #define IO_WATCHDOG_DELAY … #define IO_WATCHDOG_OFF … #include "ohci.h" #include "pci-quirks.h" static void ohci_dump(struct ohci_hcd *ohci); static void ohci_stop(struct usb_hcd *hcd); static void io_watchdog_func(struct timer_list *t); #include "ohci-hub.c" #include "ohci-dbg.c" #include "ohci-mem.c" #include "ohci-q.c" /* * On architectures with edge-triggered interrupts we must never return * IRQ_NONE. */ #if defined(CONFIG_SA1111) /* ... or other edge-triggered systems */ #define IRQ_NOTMINE … #else #define IRQ_NOTMINE … #endif /* Some boards misreport power switching/overcurrent */ static bool distrust_firmware; module_param (distrust_firmware, bool, 0); MODULE_PARM_DESC(…) …; /* Some boards leave IR set wrongly, since they fail BIOS/SMM handshakes */ static bool no_handshake; module_param (no_handshake, bool, 0); MODULE_PARM_DESC(…) …; /*-------------------------------------------------------------------------*/ static int number_of_tds(struct urb *urb) { … } /* * queue up an urb for anything except the root hub */ static int ohci_urb_enqueue ( struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags ) { … } /* * decouple the URB from the HC queues (TDs, urb_priv). * reporting is always done * asynchronously, and we might be dealing with an urb that's * partially transferred, or an ED with other urbs being unlinked. */ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { … } /*-------------------------------------------------------------------------*/ /* frees config/altsetting state for endpoints, * including ED memory, dummy TD, and bulk/intr data toggle */ static void ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) { … } static int ohci_get_frame (struct usb_hcd *hcd) { … } static void ohci_usb_reset (struct ohci_hcd *ohci) { … } /* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and * other cases where the next software may expect clean state from the * "firmware". this is bus-neutral, unlike shutdown() methods. */ static void _ohci_shutdown(struct usb_hcd *hcd) { … } static void ohci_shutdown(struct usb_hcd *hcd) { … } /*-------------------------------------------------------------------------* * HC functions *-------------------------------------------------------------------------*/ /* init memory, and kick BIOS/SMM off */ static int ohci_init (struct ohci_hcd *ohci) { … } /*-------------------------------------------------------------------------*/ /* Start an OHCI controller, set the BUS operational * resets USB and controller * enable interrupts */ static int ohci_run (struct ohci_hcd *ohci) { … } /* ohci_setup routine for generic controller initialization */ int ohci_setup(struct usb_hcd *hcd) { … } EXPORT_SYMBOL_GPL(…); /* ohci_start routine for generic controller start of all OHCI bus glue */ static int ohci_start(struct usb_hcd *hcd) { … } /*-------------------------------------------------------------------------*/ /* * Some OHCI controllers are known to lose track of completed TDs. They * don't add the TDs to the hardware done queue, which means we never see * them as being completed. * * This watchdog routine checks for such problems. Without some way to * tell when those TDs have completed, we would never take their EDs off * the unlink list. As a result, URBs could never be dequeued and * endpoints could never be released. */ static void io_watchdog_func(struct timer_list *t) { … } /* an interrupt happens */ static irqreturn_t ohci_irq (struct usb_hcd *hcd) { … } /*-------------------------------------------------------------------------*/ static void ohci_stop (struct usb_hcd *hcd) { … } /*-------------------------------------------------------------------------*/ #if defined(CONFIG_PM) || defined(CONFIG_USB_PCI) /* must not be called from interrupt context */ int ohci_restart(struct ohci_hcd *ohci) { … } EXPORT_SYMBOL_GPL(…); #endif #ifdef CONFIG_PM int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) { … } EXPORT_SYMBOL_GPL(…); int ohci_resume(struct usb_hcd *hcd, bool hibernated) { … } EXPORT_SYMBOL_GPL(…); #endif /*-------------------------------------------------------------------------*/ /* * Generic structure: This gets copied for platform drivers so that * individual entries can be overridden as needed. */ static const struct hc_driver ohci_hc_driver = …; void ohci_init_driver(struct hc_driver *drv, const struct ohci_driver_overrides *over) { … } EXPORT_SYMBOL_GPL(…); /*-------------------------------------------------------------------------*/ MODULE_AUTHOR(…); MODULE_DESCRIPTION(…); MODULE_LICENSE(…) …; #if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111) #include "ohci-sa1111.c" #define SA1111_DRIVER … #endif #ifdef CONFIG_USB_OHCI_HCD_PPC_OF #include "ohci-ppc-of.c" #define OF_PLATFORM_DRIVER … #endif #ifdef CONFIG_PPC_PS3 #include "ohci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER … #endif #ifdef CONFIG_MFD_SM501 #include "ohci-sm501.c" #define SM501_OHCI_DRIVER … #endif static int __init ohci_hcd_mod_init(void) { … } module_init(…) …; static void __exit ohci_hcd_mod_exit(void) { … } module_exit(ohci_hcd_mod_exit);