diff options
Diffstat (limited to 'drivers/usb/host/ehci.h')
| -rw-r--r-- | drivers/usb/host/ehci.h | 110 | 
1 files changed, 89 insertions, 21 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 291db7d09f2..eee228a26a0 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -38,7 +38,7 @@ typedef __u16 __bitwise __hc16;  #endif  /* statistics can be kept for tuning/monitoring */ -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG  #define EHCI_STATS  #endif @@ -54,6 +54,28 @@ struct ehci_stats {  	unsigned long		unlink;  }; +/* + * Scheduling and budgeting information for periodic transfers, for both + * high-speed devices and full/low-speed devices lying behind a TT. + */ +struct ehci_per_sched { +	struct usb_device	*udev;		/* access to the TT */ +	struct usb_host_endpoint *ep; +	struct list_head	ps_list;	/* node on ehci_tt's ps_list */ +	u16			tt_usecs;	/* time on the FS/LS bus */ +	u16			cs_mask;	/* C-mask and S-mask bytes */ +	u16			period;		/* actual period in frames */ +	u16			phase;		/* actual phase, frame part */ +	u8			bw_phase;	/* same, for bandwidth +						   reservation */ +	u8			phase_uf;	/* uframe part of the phase */ +	u8			usecs, c_usecs;	/* times on the HS bus */ +	u8			bw_uperiod;	/* period in microframes, for +						   bandwidth reservation */ +	u8			bw_period;	/* same, in frames */ +}; +#define NO_FRAME	29999			/* frame not assigned yet */ +  /* ehci_hcd->lock guards shared data against other CPUs:   *   ehci_hcd:	async, unlink, periodic (and shadow), ...   *   usb_host_endpoint: hcpriv @@ -203,6 +225,7 @@ struct ehci_hcd {			/* one per controller */  	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */  	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */  	unsigned		need_oc_pp_cycle:1; /* MPC834X port power */ +	unsigned		imx28_write_fix:1; /* For Freescale i.MX28 */  	/* required for usb32 quirk */  	#define OHCI_CTRL_HCFS          (3 << 6) @@ -226,10 +249,19 @@ struct ehci_hcd {			/* one per controller */  #endif  	/* debug files */ -#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) +#ifdef CONFIG_DYNAMIC_DEBUG  	struct dentry		*debug_dir;  #endif +	/* bandwidth usage */ +#define EHCI_BANDWIDTH_SIZE	64 +#define EHCI_BANDWIDTH_FRAMES	(EHCI_BANDWIDTH_SIZE >> 3) +	u8			bandwidth[EHCI_BANDWIDTH_SIZE]; +						/* us allocated per uframe */ +	u8			tt_budget[EHCI_BANDWIDTH_SIZE]; +						/* us budgeted per uframe */ +	struct list_head	tt_list; +  	/* platform-specific data -- must come last */  	unsigned long		priv[0] __aligned(sizeof(s64));  }; @@ -385,6 +417,7 @@ struct ehci_qh {  	struct list_head	intr_node;	/* list of intr QHs */  	struct ehci_qtd		*dummy;  	struct list_head	unlink_node; +	struct ehci_per_sched	ps;		/* scheduling info */  	unsigned		unlink_cycle; @@ -398,16 +431,8 @@ struct ehci_qh {  	u8			xacterrs;	/* XactErr retry counter */  #define	QH_XACTERR_MAX		32		/* XactErr retry limit */ -	/* periodic schedule info */ -	u8			usecs;		/* intr bandwidth */  	u8			gap_uf;		/* uframes split/csplit gap */ -	u8			c_usecs;	/* ... split completion bw */ -	u16			tt_usecs;	/* tt downstream bandwidth */ -	unsigned short		period;		/* polling interval */ -	unsigned short		start;		/* where polling starts */ -#define NO_FRAME ((unsigned short)~0)			/* pick new start */ -	struct usb_device	*dev;		/* access to TT */  	unsigned		is_out:1;	/* bulk or intr OUT */  	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */  	unsigned		dequeue_during_giveback:1; @@ -434,6 +459,7 @@ struct ehci_iso_packet {  struct ehci_iso_sched {  	struct list_head	td_list;  	unsigned		span; +	unsigned		first_packet;  	struct ehci_iso_packet	packet [0];  }; @@ -449,22 +475,17 @@ struct ehci_iso_stream {  	u8			highspeed;  	struct list_head	td_list;	/* queued itds/sitds */  	struct list_head	free_list;	/* list of unused itds/sitds */ -	struct usb_device	*udev; -	struct usb_host_endpoint *ep;  	/* output of (re)scheduling */ -	int			next_uframe; +	struct ehci_per_sched	ps;		/* scheduling info */ +	unsigned		next_uframe;  	__hc32			splits;  	/* the rest is derived from the endpoint descriptor, -	 * trusting urb->interval == f(epdesc->bInterval) and  	 * including the extra info for hw_bufp[0..2]  	 */ -	u8			usecs, c_usecs; -	u16			interval; -	u16			tt_usecs; +	u16			uperiod;	/* period in uframes */  	u16			maxp; -	u16			raw_mask;  	unsigned		bandwidth;  	/* This is used to initialize iTD's hw_bufp fields */ @@ -579,6 +600,35 @@ struct ehci_fstn {  /*-------------------------------------------------------------------------*/ +/* + * USB-2.0 Specification Sections 11.14 and 11.18 + * Scheduling and budgeting split transactions using TTs + * + * A hub can have a single TT for all its ports, or multiple TTs (one for each + * port).  The bandwidth and budgeting information for the full/low-speed bus + * below each TT is self-contained and independent of the other TTs or the + * high-speed bus. + * + * "Bandwidth" refers to the number of microseconds on the FS/LS bus allocated + * to an interrupt or isochronous endpoint for each frame.  "Budget" refers to + * the best-case estimate of the number of full-speed bytes allocated to an + * endpoint for each microframe within an allocated frame. + * + * Removal of an endpoint invalidates a TT's budget.  Instead of trying to + * keep an up-to-date record, we recompute the budget when it is needed. + */ + +struct ehci_tt { +	u16			bandwidth[EHCI_BANDWIDTH_FRAMES]; + +	struct list_head	tt_list;	/* List of all ehci_tt's */ +	struct list_head	ps_list;	/* Items using this TT */ +	struct usb_tt		*usb_tt; +	int			tt_port;	/* TT port number */ +}; + +/*-------------------------------------------------------------------------*/ +  /* Prepare the PORTSC wakeup flags during controller suspend/resume */  #define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup)	\ @@ -679,6 +729,18 @@ static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,  #endif  } +#ifdef CONFIG_SOC_IMX28 +static inline void imx28_ehci_writel(const unsigned int val, +		volatile __u32 __iomem *addr) +{ +	__asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr)); +} +#else +static inline void imx28_ehci_writel(const unsigned int val, +		volatile __u32 __iomem *addr) +{ +} +#endif  static inline void ehci_writel(const struct ehci_hcd *ehci,  		const unsigned int val, __u32 __iomem *regs)  { @@ -687,7 +749,10 @@ static inline void ehci_writel(const struct ehci_hcd *ehci,  		writel_be(val, regs) :  		writel(val, regs);  #else -	writel(val, regs); +	if (ehci->imx28_write_fix) +		imx28_ehci_writel(val, regs); +	else +		writel(val, regs);  #endif  } @@ -783,9 +848,9 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)  	dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) -#if !defined(DEBUG) && !defined(CONFIG_DYNAMIC_DEBUG) +#ifndef CONFIG_DYNAMIC_DEBUG  #define STUB_DEBUG_FILES -#endif	/* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ +#endif  /*-------------------------------------------------------------------------*/ @@ -807,4 +872,7 @@ extern int	ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);  extern int	ehci_resume(struct usb_hcd *hcd, bool hibernated);  #endif	/* CONFIG_PM */ +extern int	ehci_hub_control(struct usb_hcd	*hcd, u16 typeReq, u16 wValue, +				 u16 wIndex, char *buf, u16 wLength); +  #endif /* __LINUX_EHCI_HCD_H */  | 
