?? ohci.h
字號:
*/struct ohci_hcd { spinlock_t lock; /* * I/O memory used to communicate with the HC (dma-consistent) */ struct ohci_regs __iomem *regs; /* * main memory used to communicate with the HC (dma-consistent). * hcd adds to schedule for a live hc any time, but removals finish * only at the start of the next frame. */ struct ohci_hcca *hcca; dma_addr_t hcca_dma; struct ed *ed_rm_list; /* to be removed */ struct ed *ed_bulktail; /* last in bulk list */ struct ed *ed_controltail; /* last in ctrl list */ struct ed *periodic [NUM_INTS]; /* shadow int_table */ /* * OTG controllers and transceivers need software interaction; * other external transceivers should be software-transparent */ struct otg_transceiver *transceiver; /* * memory management for queue data structures */ struct dma_pool *td_cache; struct dma_pool *ed_cache; struct td *td_hash [TD_HASH_SIZE]; struct list_head pending; /* * driver state */ int num_ports; int load [NUM_INTS]; u32 hc_control; /* copy of hc control reg */ unsigned long next_statechange; /* suspend/resume */ u32 fminterval; /* saved register */ unsigned autostop:1; /* rh auto stopping/stopped */ unsigned long flags; /* for HC bugs */#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */#define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */#define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */#define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ // there are also chip quirks/bugs in init logic};/* convert between an hcd pointer and the corresponding ohci_hcd */static inline struct ohci_hcd *hcd_to_ohci (struct usb_hcd *hcd){ return (struct ohci_hcd *) (hcd->hcd_priv);}static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci){ return container_of ((void *) ohci, struct usb_hcd, hcd_priv);}/*-------------------------------------------------------------------------*/#ifndef DEBUG#define STUB_DEBUG_FILES#endif /* DEBUG */#define ohci_dbg(ohci, fmt, args...) \ dev_dbg (ohci_to_hcd(ohci)->self.controller , fmt , ## args )#define ohci_err(ohci, fmt, args...) \ dev_err (ohci_to_hcd(ohci)->self.controller , fmt , ## args )#define ohci_info(ohci, fmt, args...) \ dev_info (ohci_to_hcd(ohci)->self.controller , fmt , ## args )#define ohci_warn(ohci, fmt, args...) \ dev_warn (ohci_to_hcd(ohci)->self.controller , fmt , ## args )#ifdef OHCI_VERBOSE_DEBUG# define ohci_vdbg ohci_dbg#else# define ohci_vdbg(ohci, fmt, args...) do { } while (0)#endif/*-------------------------------------------------------------------------*//* * While most USB host controllers implement their registers and * in-memory communication descriptors in little-endian format, * a minority (notably the IBM STB04XXX and the Motorola MPC5200 * processors) implement them in big endian format. * * In addition some more exotic implementations like the Toshiba * Spider (aka SCC) cell southbridge are "mixed" endian, that is, * they have a different endianness for registers vs. in-memory * descriptors. * * This attempts to support either format at compile time without a * runtime penalty, or both formats with the additional overhead * of checking a flag bit. * * That leads to some tricky Kconfig rules howevber. There are * different defaults based on some arch/ppc platforms, though * the basic rules are: * * Controller type Kconfig options needed * --------------- ---------------------- * little endian CONFIG_USB_OHCI_LITTLE_ENDIAN * * fully big endian CONFIG_USB_OHCI_BIG_ENDIAN_DESC _and_ * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO * * mixed endian CONFIG_USB_OHCI_LITTLE_ENDIAN _and_ * CONFIG_USB_OHCI_BIG_ENDIAN_{MMIO,DESC} * * (If you have a mixed endian controller, you -must- also define * CONFIG_USB_OHCI_LITTLE_ENDIAN or things will not work when building * both your mixed endian and a fully big endian controller support in * the same kernel image). */#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_DESC#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN#define big_endian_desc(ohci) (ohci->flags & OHCI_QUIRK_BE_DESC)#else#define big_endian_desc(ohci) 1 /* only big endian */#endif#else#define big_endian_desc(ohci) 0 /* only little endian */#endif#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN#define big_endian_mmio(ohci) (ohci->flags & OHCI_QUIRK_BE_MMIO)#else#define big_endian_mmio(ohci) 1 /* only big endian */#endif#else#define big_endian_mmio(ohci) 0 /* only little endian */#endif/* * Big-endian read/write functions are arch-specific. * Other arches can be added if/when they're needed. * * REVISIT: arch/powerpc now has readl/writel_be, so the * definition below can die once the STB04xxx support is * finally ported over. */#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE)#define readl_be(addr) in_be32((__force unsigned *)addr)#define writel_be(val, addr) out_be32((__force unsigned *)addr, val)#endifstatic inline unsigned int _ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs){#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO return big_endian_mmio(ohci) ? readl_be (regs) : readl (regs);#else return readl (regs);#endif}static inline void _ohci_writel (const struct ohci_hcd *ohci, const unsigned int val, __hc32 __iomem *regs){#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO big_endian_mmio(ohci) ? writel_be (val, regs) : writel (val, regs);#else writel (val, regs);#endif}#ifdef CONFIG_ARCH_LH7A404/* Marc Singer: at the time this code was written, the LH7A404 * had a problem reading the USB host registers. This * implementation of the ohci_readl function performs the read * twice as a work-around. */#define ohci_readl(o,r) (_ohci_readl(o,r),_ohci_readl(o,r))#define ohci_writel(o,v,r) _ohci_writel(o,v,r)#else#define ohci_readl(o,r) _ohci_readl(o,r)#define ohci_writel(o,v,r) _ohci_writel(o,v,r)#endif/*-------------------------------------------------------------------------*//* cpu to ohci */static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x){ return big_endian_desc(ohci) ? (__force __hc16)cpu_to_be16(x) : (__force __hc16)cpu_to_le16(x);}static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x){ return big_endian_desc(ohci) ? cpu_to_be16p(x) : cpu_to_le16p(x);}static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x){ return big_endian_desc(ohci) ? (__force __hc32)cpu_to_be32(x) : (__force __hc32)cpu_to_le32(x);}static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x){ return big_endian_desc(ohci) ? cpu_to_be32p(x) : cpu_to_le32p(x);}/* ohci to cpu */static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x){ return big_endian_desc(ohci) ? be16_to_cpu((__force __be16)x) : le16_to_cpu((__force __le16)x);}static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x){ return big_endian_desc(ohci) ? be16_to_cpup((__force __be16 *)x) : le16_to_cpup((__force __le16 *)x);}static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x){ return big_endian_desc(ohci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x);}static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x){ return big_endian_desc(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x);}/*-------------------------------------------------------------------------*//* HCCA frame number is 16 bits, but is accessed as 32 bits since not all * hardware handles 16 bit reads. That creates a different confusion on * some big-endian SOC implementations. Same thing happens with PSW access. * * FIXME: Deal with that as a runtime quirk when STB03xxx is ported over * to arch/powerpc */#ifdef CONFIG_STB03xxx#define OHCI_BE_FRAME_NO_SHIFT 16#else#define OHCI_BE_FRAME_NO_SHIFT 0#endifstatic inline u16 ohci_frame_no(const struct ohci_hcd *ohci){ u32 tmp; if (big_endian_desc(ohci)) { tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no); tmp >>= OHCI_BE_FRAME_NO_SHIFT; } else tmp = le32_to_cpup((__force __le32 *)&ohci->hcca->frame_no); return (u16)tmp;}static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci, const struct td *td, int index){ return (__hc16 *)(big_endian_desc(ohci) ? &td->hwPSW[index ^ 1] : &td->hwPSW[index]);}static inline u16 ohci_hwPSW(const struct ohci_hcd *ohci, const struct td *td, int index){ return hc16_to_cpup(ohci, ohci_hwPSWp(ohci, td, index));}/*-------------------------------------------------------------------------*/static inline void disable (struct ohci_hcd *ohci){ ohci_to_hcd(ohci)->state = HC_STATE_HALT;}#define FI 0x2edf /* 12000 bits per frame (-1) */#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))#define FIT (1 << 31)#define LSTHRESH 0x628 /* lowspeed bit threshold */static inline void periodic_reinit (struct ohci_hcd *ohci){ u32 fi = ohci->fminterval & 0x03fff; u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT; ohci_writel (ohci, (fit ^ FIT) | ohci->fminterval, &ohci->regs->fminterval); ohci_writel (ohci, ((9 * fi) / 10) & 0x3fff, &ohci->regs->periodicstart);}/* AMD-756 (D2 rev) reports corrupt register contents in some cases. * The erratum (#4) description is incorrect. AMD's workaround waits * till some bits (mostly reserved) are clear; ok for all revs. */#define read_roothub(hc, register, mask) ({ \ u32 temp = ohci_readl (hc, &hc->regs->roothub.register); \ if (temp == -1) \ disable (hc); \ else if (hc->flags & OHCI_QUIRK_AMD756) \ while (temp & mask) \ temp = ohci_readl (hc, &hc->regs->roothub.register); \ temp; })static inline u32 roothub_a (struct ohci_hcd *hc) { return read_roothub (hc, a, 0xfc0fe000); }static inline u32 roothub_b (struct ohci_hcd *hc) { return ohci_readl (hc, &hc->regs->roothub.b); }static inline u32 roothub_status (struct ohci_hcd *hc) { return ohci_readl (hc, &hc->regs->roothub.status); }static inline u32 roothub_portstatus (struct ohci_hcd *hc, int i) { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -