📄 ohci-sl811.h
字号:
/* * SL811HS OHCI HCD (Host Controller Driver) for USB. * * linux/drivers/usb/host/ohci-sl811.h * * Copyright (C) 2004 by Lothar Wassmann <LW at KARO-electronics.de> * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * * HW access macros and HW specific definitions * *///#include <asm/arch/karo.h>//#define USE_DMA //Can't use DMA because of SL811 register address alignment :(#define FLIP_BUFFERS 1#define USB_RESET_WIDTH 50#define DATA0_WR 0x07 // (Arm+Enable+tranmist to Host+DATA0)#define DATA1_WR 0x47 // (Arm+Enable+tranmist to Host on DATA1)#define ZDATA0_WR 0x05 // (Arm+Transaction Ignored+tranmist to Host+DATA0)#define ZDATA1_WR 0x45 // (Arm+Transaction Ignored+tranmist to Host+DATA1)#define DATA0_RD 0x03 // (Arm+Enable+received from Host+DATA0)#define DATA1_RD 0x43 // (Arm+Enable+received from Host+DATA1)#define PID_SETUP 0x2d // USB Specification 1.1 Standard Definition#define PID_SOF 0xA5#define PID_IN 0x69#define PID_OUT 0xe1#define SL11H_HOSTCTLREG 0x00#define SL11H_BUFADDRREG 0x01#define SL11H_BUFLNTHREG 0x02#define SL11H_PKTSTATREG 0x03 /* read */#define SL11H_PIDEPREG 0x03 /* write */#define SL11H_XFERCNTREG 0x04 /* read */#define SL11H_DEVADDRREG 0x04 /* write */#define SL11H_CTLREG1 0x05#define SL11H_INTENBLREG 0x06#define SL11H_HOSTCTLREG_B 0x08#define SL11H_BUFADDRREG_B 0x09#define SL11H_BUFLNTHREG_B 0x0A#define SL11H_PKTSTATREG_B 0x0B /* read */#define SL11H_PIDEPREG_B 0x0B /* write */#define SL11H_XFERCNTREG_B 0x0C /* read */#define SL11H_DEVADDRREG_B 0x0C /* write */#define SL11H_INTSTATREG 0x0D /* write clears bitwise */#define SL11H_HWREVREG 0x0E /* read */#define SL11H_SOFLOWREG 0x0E /* write */#define SL11H_SOFTMRREG 0x0F /* read */#define SL11H_CTLREG2 0x0F /* write */#define SL11H_DATA_START 0x10/* Host control register bits (addr 0) */#define SL11H_HCTLMASK_ARM 0x01#define SL11H_HCTLMASK_ENBLEP 0x02#define SL11H_HCTLMASK_WRITE 0x04#define SL11H_HCTLMASK_ISOCH 0x10#define SL11H_HCTLMASK_AFTERSOF 0x20#define SL11H_HCTLMASK_SEQ 0x40#define SL11H_HCTLMASK_PREAMBLE 0x80/* Packet status register bits (addr 3) */#define SL11H_STATMASK_ACK 0x01#define SL11H_STATMASK_ERROR 0x02#define SL11H_STATMASK_TMOUT 0x04#define SL11H_STATMASK_SEQ 0x08#define SL11H_STATMASK_SETUP 0x10#define SL11H_STATMASK_OVF 0x20#define SL11H_STATMASK_NAK 0x40#define SL11H_STATMASK_STALL 0x80#define SL811_PKT_ERR_MASK (SL11H_STATMASK_ERROR | \ SL11H_STATMASK_TMOUT | \ SL11H_STATMASK_OVF | \ SL11H_STATMASK_NAK | \ SL11H_STATMASK_STALL | \ SL11H_STATMASK_SEQ)/* Control register 1 bits (addr 5) */#define SL11H_CTL1MASK_SOFENA (1 << 0)#define SL11H_CTL1MASK_NOTXEOF2 (1 << 2) /* ??? */#define SL11H_CTL1MASK_DSTATE 0x18#define SL11H_CTL1MASK_NSPD 0x20#define SL11H_CTL1MASK_SUSPEND 0x40#define SL11H_CTL1MASK_CLK12 0x80#define SL11H_CTL1VAL_NORMAL 0x00#define SL11H_CTL1VAL_RESET 0x08#define SL11H_CTL1VAL_FORCE_J 0x10#define SL11H_CTL1VAL_FORCE_K 0x18/* Interrupt enable (addr 6) and interrupt status register bits (addr 0xD) */#define SL11H_INTMASK_XFERDONE 0x01#define SL11H_INTMASK_XFERDONE_B 0x02#define SL11H_INTMASK_SOFINTR 0x10#define SL11H_INTMASK_INSRMV 0x20#define SL11H_INTMASK_RESUME 0x40#define SL11H_INTMASK_DSTATE 0x80 /* only in status reg */#define SL811_INT_MASK (SL11H_INTMASK_SOFINTR | SL11H_INTMASK_INSRMV)/* HW rev and SOF lo register bits (addr 0xE) */#define SL11H_HWRMASK_HWREV 0xF0/* SOF counter and control reg 2 (addr 0xF) */#define SL11H_CTL2MASK_SOFHI 0x3F#define SL11H_CTL2MASK_DSWAP 0x40#define SL11H_CTL2MASK_HOSTMODE 0x80#define SL811_MAP_SIZE 256#define SL811_BUF_SIZE (SL811_MAP_SIZE - SL11H_DATA_START)#define ohci_to_hcd(ohci) (&(ohci)->hcd)typedef enum { DEV_IDLE = 0x00, DEV_LOW_SPEED = 0x01, DEV_FULL_SPEED = 0x02, DEV_ACTIVE = 0x04, DEV_CHECK = 0x08, DEV_SOF = 0x10, DEV_SLEEP = 0x20, DEV_OHCI_IRQ = 0x40, DEV_CONN_CHK = 0x80,} dev_state_t;#define DEV_CONNECTED (DEV_FULL_SPEED | DEV_LOW_SPEED)#define DEV_TRIGGERED (DEV_CONN_CHK | DEV_OHCI_IRQ)struct xfer_buf { void *buf_addr; int buf_len; struct td *td; union { u8 send_data[3]; struct { u8 len; u8 pid_ep; u8 dev_addr; } __attribute__((packed)); } __attribute__((packed)); u8 hc; union { u8 rcv_data[2]; struct { u8 pkt_stat; u8 count; } __attribute__((packed)); } __attribute__((packed));};struct hc_sl811_dev { struct device dev; void *addr_reg; void *data_reg; int irq; struct timer_list int_timer; unsigned int last_sof; struct tasklet_struct usb_reset_bh; struct xfer_buf xfer_buf[FLIP_BUFFERS]; unsigned int flip; void *buf_addr; int buf_len; unsigned int num_bufs; unsigned int buf_map; struct td *current_td; int dev_state; u32 pm_state; u8 cbc; u8 intrdelay; u8 hw_rev;};struct hc_sl811_driver { struct device_driver drv; unsigned int devid; int (*probe)(struct hc_sl811_dev *dev); int (*remove)(struct hc_sl811_dev *dev); int (*suspend)(struct hc_sl811_dev *dev, u32 state); int (*resume)(struct hc_sl811_dev *dev);};#define SL811_DRV(_d) container_of((_d), struct hc_sl811_driver, drv)/* * SL811 HW Interface */#define hc_sl811_addr_reg (dev->addr_reg)#define hc_sl811_data_reg (dev->data_reg)static inline void HC_SL811_WRITE_ADDR(struct hc_sl811_dev *dev, int reg){ writeb(reg, hc_sl811_addr_reg);}static inline void HC_SL811_WRITE_DATA(struct hc_sl811_dev *dev, int val){ writeb(val, hc_sl811_data_reg);}static inline u8 HC_SL811_READ_DATA(struct hc_sl811_dev *dev){ u8 val; val = readb(hc_sl811_data_reg); return val;}static inline u8 __hc_sl811_read_reg(struct hc_sl811_dev *dev, int reg){ u8 val; HC_SL811_WRITE_ADDR(dev, reg); val = HC_SL811_READ_DATA(dev); return val;}static inline u8 hc_sl811_read_reg(struct hc_sl811_dev *dev, int reg){ u8 val; unsigned long flags; local_irq_save(flags); val = __hc_sl811_read_reg(dev, reg); local_irq_restore(flags); return val;}static inline void __hc_sl811_write_reg(struct hc_sl811_dev *dev, int reg, u8 val){ HC_SL811_WRITE_ADDR(dev, reg); HC_SL811_WRITE_DATA(dev, val);}static inline void hc_sl811_write_reg(struct hc_sl811_dev *dev, int reg, u8 val){ unsigned long flags; local_irq_save(flags); __hc_sl811_write_reg(dev, reg, val); local_irq_restore(flags);}static inline void __hc_sl811_set_mask(struct hc_sl811_dev *dev, int reg, u8 mask){ u8 val; val = __hc_sl811_read_reg(dev, reg); val |= mask; __hc_sl811_write_reg(dev, reg, val);}static inline void hc_sl811_set_mask(struct hc_sl811_dev *dev, int reg, u8 mask){ unsigned long flags; local_irq_save(flags); __hc_sl811_set_mask(dev, reg, mask); local_irq_restore(flags);}static inline void __hc_sl811_clr_mask(struct hc_sl811_dev *dev, int reg, u8 mask){ u8 val; val = __hc_sl811_read_reg(dev, reg); val &= ~mask; __hc_sl811_write_reg(dev, reg, val);}static inline void hc_sl811_clr_mask(struct hc_sl811_dev *dev, int reg, u8 mask){ unsigned long flags; local_irq_save(flags); __hc_sl811_clr_mask(dev, reg, mask); local_irq_restore(flags);}static void __hc_sl811_write_regs(struct hc_sl811_dev *dev, u8 reg, const void *buf, int count){ int i; const u8 *data = buf; HC_SL811_WRITE_ADDR(dev, reg); for (i = 0; i < count; i++) { HC_SL811_WRITE_DATA(dev, data[i]); }}static void __hc_sl811_read_regs(struct hc_sl811_dev *dev, u8 reg, void *buf, int count){ int i; u8 *data = buf; HC_SL811_WRITE_ADDR(dev, reg); for (i = 0; i < count; i++) { data[i] = HC_SL811_READ_DATA(dev); }}static void hc_sl811_dump_regs(struct hc_sl811_dev *dev){ u8 reg; for (reg = SL11H_HOSTCTLREG; reg <= SL11H_CTLREG2; reg++) { u8 val; unsigned long flags; if (reg == 7) continue; local_irq_save(flags); val = __hc_sl811_read_reg(dev, reg); local_irq_restore(flags); printk(KERN_DEBUG "%s: reg[%02x]=%02x\n", __FUNCTION__, reg, val); }}#if defined(CONFIG_ARCH_KARO)static void sl811_set_hw_reset(void){ if (karo_pcf8574_clr(FMsk(KARO_PCF8574_USBRST)) < 0) { printk(KERN_ERR "%s: failed to assert reset via PCF8574\n", __FUNCTION__); }}static void sl811_clr_hw_reset(void){ if (karo_pcf8574_set(FMsk(KARO_PCF8574_USBRST)) < 0) { printk(KERN_ERR "%s: failed to deassert reset via PCF8574\n", __FUNCTION__); }}#else//#error Define your hardware specific functions herestatic void sl811_set_hw_reset(void){}static void sl811_clr_hw_reset(void){}#endif// function prototypesstatic int hc_sl811_detect_device(struct usb_hcd *hcd);static void hc_sl811_usb_reset(struct usb_hcd *hcd, int assert);static void hc_sl811_start_sof(struct usb_hcd *hcd, int lowspeed);static void ohci_sl811_bh(unsigned long data);static u32 retire_td(struct usb_hcd *hcd, struct td *td, struct ed *ed, u32 cc);static u32 kill_current_td(struct usb_hcd *hcd, struct hc_sl811_dev *dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -