diff options
Diffstat (limited to 'target/linux/adm5120/files/drivers/usb/host/adm5120.h')
-rw-r--r-- | target/linux/adm5120/files/drivers/usb/host/adm5120.h | 114 |
1 files changed, 80 insertions, 34 deletions
diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120.h b/target/linux/adm5120/files/drivers/usb/host/adm5120.h index 95616f27a8..370722547e 100644 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120.h +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120.h @@ -56,7 +56,8 @@ struct ed { dma_addr_t dma; /* addr of ED */ struct td *dummy; /* next TD to activate */ - struct list_head urb_list; /* list of our URBs */ + struct urb_priv *urb_active; /* active URB */ + struct list_head urb_pending; /* pending URBs */ struct list_head ed_list; /* list of all EDs*/ struct list_head rm_list; /* for remove list */ @@ -65,16 +66,15 @@ struct ed { struct ed *ed_next; /* on schedule list */ struct ed *ed_prev; /* for non-interrupt EDs */ struct ed *ed_rm_next; /* on rm list */ - struct ed *ed_soft_list; /* on software int list */ - struct list_head td_list; /* "shadow list" of our TDs */ /* create --> IDLE --> OPER --> ... --> IDLE --> destroy * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... */ - u8 state; /* ED_{IDLE,UNLINK,OPER} */ -#define ED_IDLE 0x00 /* NOT linked to HC */ -#define ED_UNLINK 0x01 /* being unlinked from hc */ -#define ED_OPER 0x02 /* IS linked to hc */ + u8 state; +#define ED_NEW 0x00 /* just allocated */ +#define ED_IDLE 0x01 /* linked into HC, but not running */ +#define ED_OPER 0x02 /* linked into HC and running */ +#define ED_UNLINK 0x03 /* being unlinked from HC */ u8 type; /* PIPE_{BULK,...} */ @@ -115,16 +115,17 @@ struct td { #define TD_T_SHIFT 23 /* data toggle state */ #define TD_T_MASK 0x3 #define TD_T (TD_T_MASK << TD_T_SHIFT) -#define TD_T_DATA0 (0x2 << TD_T_SHIFT) /* DATA0 */ -#define TD_T_DATA1 (0x3 << TD_T_SHIFT) /* DATA1 */ -#define TD_T_CARRY (0x0 << TD_T_SHIFT) /* uses ED_C */ +#define TD_T_DATA0 (0x2 << TD_T_SHIFT) /* DATA0 */ +#define TD_T_DATA1 (0x3 << TD_T_SHIFT) /* DATA1 */ +#define TD_T_CARRY (0x0 << TD_T_SHIFT) /* uses ED_C */ #define TD_T_GET(x) (((x) >> TD_T_SHIFT) & TD_T_MASK) #define TD_DP_SHIFT 21 /* direction/pid */ #define TD_DP_MASK 0x3 #define TD_DP (TD_DP_MASK << TD_DP_SHIFT) -#define TD_DP_SETUP (0x0 << TD_DP_SHIFT) /* SETUP pid */ -#define TD_DP_OUT (0x1 << TD_DP_SHIFT) /* OUT pid */ -#define TD_DP_IN (0x2 << TD_DP_SHIFT) /* IN pid */ +#define TD_DP_SETUP (0x0 << TD_DP_SHIFT) /* SETUP pid */ +#define TD_DP_OUT (0x1 << TD_DP_SHIFT) /* OUT pid */ +#define TD_DP_IN (0x2 << TD_DP_SHIFT) /* IN pid */ +#define TD_DP_GET(x) (((x) >> TD_DP_SHIFT) & TD_DP_MASK) #define TD_ISI_SHIFT 8 /* Interrupt Service Interval */ #define TD_ISI_MASK 0x3f #define TD_ISI_GET(x) (((x) >> TD_ISI_SHIFT) & TD_ISI_MASK) @@ -142,19 +143,12 @@ struct td { /* rest are purely for the driver's use */ __u8 index; - struct ed *ed; - struct td *td_hash; /* dma-->td hashtable */ - struct td *next_dl_td; +/* struct ed *ed;*/ struct urb *urb; dma_addr_t td_dma; /* addr of this TD */ dma_addr_t data_dma; /* addr of data it points to */ - struct list_head td_list; /* "shadow list", TDs on same ED */ - - u32 flags; -#define TD_FLAG_DONE (1 << 17) /* retired to done list */ -#define TD_FLAG_ISO (1 << 16) /* copy of ED_ISO */ } __attribute__ ((aligned(TD_ALIGN))); /* c/b/i need 16; only iso needs 32 */ /* @@ -354,6 +348,7 @@ struct admhcd_regs { /* hcd-private per-urb state */ struct urb_priv { struct ed *ed; + struct urb *urb; struct list_head pending; /* URBs on the same ED */ u32 td_cnt; /* # tds in this request */ @@ -374,6 +369,8 @@ struct urb_priv { struct admhcd { spinlock_t lock; + spinlock_t dma_lock; + u32 dma_state; /* * I/O memory used to communicate with the HC (dma-consistent) @@ -384,14 +381,10 @@ struct admhcd { * hcd adds to schedule for a live hc any time, but removals finish * only at the start of the next frame. */ - struct ed *ed_head; struct ed *ed_tails[4]; struct ed *ed_rm_list; /* to be removed */ - struct ed *ed_halt_list; /* halted due to an error */ - struct ed *ed_soft_list; /* for software interrupt processing */ - struct ed *periodic[NUM_INTS]; /* shadow int_table */ #if 0 /* TODO: remove? */ @@ -408,7 +401,6 @@ struct admhcd { struct dma_pool *td_cache; struct dma_pool *ed_cache; struct td *td_hash[TD_HASH_SIZE]; - struct list_head pending; /* * driver state @@ -446,6 +438,7 @@ static inline struct usb_hcd *admhcd_to_hcd(const struct admhcd *ahcd) #define STUB_DEBUG_FILES #endif /* DEBUG */ +#if 0 #define admhc_dbg(ahcd, fmt, args...) \ dev_dbg(admhcd_to_hcd(ahcd)->self.controller , fmt , ## args ) #define admhc_err(ahcd, fmt, args...) \ @@ -460,6 +453,22 @@ static inline struct usb_hcd *admhcd_to_hcd(const struct admhcd *ahcd) #else # define admhc_vdbg(ahcd, fmt, args...) do { } while (0) #endif +#else +#define admhc_dbg(ahcd, fmt, args...) \ + printk(KERN_DEBUG "adm5120-hcd: " fmt , ## args ) +#define admhc_err(ahcd, fmt, args...) \ + printk(KERN_ERR "adm5120-hcd: " fmt , ## args ) +#define ahcd_info(ahcd, fmt, args...) \ + printk(KERN_INFO "adm5120-hcd: " fmt , ## args ) +#define admhc_warn(ahcd, fmt, args...) \ + printk(KERN_WARNING "adm5120-hcd: " fmt , ## args ) + +#ifdef ADMHC_VERBOSE_DEBUG +# define admhc_vdbg admhc_dbg +#else +# define admhc_vdbg(ahcd, fmt, args...) do { } while (0) +#endif +#endif /*-------------------------------------------------------------------------*/ @@ -633,6 +642,15 @@ static inline u16 admhc_frame_no(const struct admhcd *ahcd) return (u16)t; } +static inline u16 admhc_frame_remain(const struct admhcd *ahcd) +{ + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->fmnumber) >> ADMHC_SFN_FR_SHIFT; + t &= ADMHC_SFN_FR_MASK; + return (u16)t; +} + /*-------------------------------------------------------------------------*/ static inline void admhc_disable(struct admhcd *ahcd) @@ -652,7 +670,7 @@ static inline void periodic_reinit(struct admhcd *ahcd) /* TODO: adjust FSLargestDataPacket value too? */ admhc_writel(ahcd, (fit ^ FIT) | ahcd->fminterval, - &ahcd->regs->fminterval); + &ahcd->regs->fminterval); } static inline u32 admhc_get_rhdesc(struct admhcd *ahcd) @@ -698,17 +716,45 @@ static inline void admhc_intr_ack(struct admhcd *ahcd, u32 ints) static inline void admhc_dma_enable(struct admhcd *ahcd) { - ahcd->host_control = admhc_readl(ahcd, &ahcd->regs->host_control); - if (ahcd->host_control & ADMHC_HC_DMAE) + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->host_control); + if (t & ADMHC_HC_DMAE) return; - ahcd->host_control |= ADMHC_HC_DMAE; - admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); + t |= ADMHC_HC_DMAE; + admhc_writel(ahcd, t, &ahcd->regs->host_control); + admhc_dbg(ahcd,"DMA enabled\n"); } static inline void admhc_dma_disable(struct admhcd *ahcd) { - ahcd->host_control = admhc_readl(ahcd, &ahcd->regs->host_control); - ahcd->host_control &= ~ADMHC_HC_DMAE; - admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->host_control); + if (!(t & ADMHC_HC_DMAE)) + return; + + t &= ~ADMHC_HC_DMAE; + admhc_writel(ahcd, t, &ahcd->regs->host_control); + admhc_dbg(ahcd,"DMA disabled\n"); +} + +static inline void admhc_dma_lock(struct admhcd *ahcd) +{ + spin_lock(ahcd->dma_lock); + + ahcd->dma_state = admhc_readl(ahcd, &ahcd->regs->host_control); + admhc_writel(ahcd, 0, &ahcd->regs->hosthead); + admhc_writel(ahcd, ahcd->dma_state & ~ADMHC_HC_DMAE, + &ahcd->regs->host_control); + admhc_dbg(ahcd,"DMA locked\n"); +} + +static inline void admhc_dma_unlock(struct admhcd *ahcd) +{ + admhc_writel(ahcd, (u32)ahcd->ed_head->dma, &ahcd->regs->hosthead); + admhc_writel(ahcd, ahcd->dma_state, &ahcd->regs->host_control); + admhc_dbg(ahcd,"DMA unlocked\n"); + spin_unlock(ahcd->dma_lock); } |