Update usb host driver as in Axis SDK2.20
SVN-Revision: 14409
This commit is contained in:
		
							
								
								
									
										4985
									
								
								target/linux/etrax/files/drivers/usb/host/hc-crisv10.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4985
									
								
								target/linux/etrax/files/drivers/usb/host/hc-crisv10.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -4,131 +4,175 @@
 | 
				
			|||||||
#include <linux/types.h>
 | 
					#include <linux/types.h>
 | 
				
			||||||
#include <linux/list.h>
 | 
					#include <linux/list.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct USB_IN_Desc {
 | 
					struct USB_IN_Desc {
 | 
				
			||||||
	volatile __u16 sw_len;
 | 
					  volatile __u16 sw_len;
 | 
				
			||||||
	volatile __u16 command;
 | 
					  volatile __u16 command;
 | 
				
			||||||
	volatile unsigned long next;
 | 
					  volatile unsigned long next;
 | 
				
			||||||
	volatile unsigned long buf;
 | 
					  volatile unsigned long buf;
 | 
				
			||||||
	volatile __u16 hw_len;
 | 
					  volatile __u16 hw_len;
 | 
				
			||||||
	volatile __u16 status;
 | 
					  volatile __u16 status;
 | 
				
			||||||
} USB_IN_Desc_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct USB_SB_Desc {
 | 
					 | 
				
			||||||
	volatile __u16 sw_len;
 | 
					 | 
				
			||||||
	volatile __u16 command;
 | 
					 | 
				
			||||||
	volatile unsigned long next;
 | 
					 | 
				
			||||||
	volatile unsigned long buf;
 | 
					 | 
				
			||||||
	__u32 dummy;
 | 
					 | 
				
			||||||
} USB_SB_Desc_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct USB_EP_Desc {
 | 
					 | 
				
			||||||
	volatile __u16 hw_len;
 | 
					 | 
				
			||||||
	volatile __u16 command;
 | 
					 | 
				
			||||||
	volatile unsigned long sub;
 | 
					 | 
				
			||||||
	volatile unsigned long next;
 | 
					 | 
				
			||||||
	__u32 dummy;
 | 
					 | 
				
			||||||
} USB_EP_Desc_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct virt_root_hub {
 | 
					 | 
				
			||||||
	int devnum;
 | 
					 | 
				
			||||||
	void *urb;
 | 
					 | 
				
			||||||
	void *int_addr;
 | 
					 | 
				
			||||||
	int send;
 | 
					 | 
				
			||||||
	int interval;
 | 
					 | 
				
			||||||
	int numports;
 | 
					 | 
				
			||||||
	struct timer_list rh_int_timer;
 | 
					 | 
				
			||||||
	volatile __u16 wPortChange_1;
 | 
					 | 
				
			||||||
	volatile __u16 wPortChange_2;
 | 
					 | 
				
			||||||
	volatile __u16 prev_wPortStatus_1;
 | 
					 | 
				
			||||||
	volatile __u16 prev_wPortStatus_2;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct etrax_usb_intr_traffic {
 | 
					struct USB_SB_Desc {
 | 
				
			||||||
	int sleeping;
 | 
					  volatile __u16 sw_len;
 | 
				
			||||||
	int error;
 | 
					  volatile __u16 command;
 | 
				
			||||||
	struct wait_queue *wq;
 | 
					  volatile unsigned long next;
 | 
				
			||||||
 | 
					  volatile unsigned long buf;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct USB_EP_Desc {
 | 
				
			||||||
 | 
					  volatile __u16 hw_len;
 | 
				
			||||||
 | 
					  volatile __u16 command;
 | 
				
			||||||
 | 
					  volatile unsigned long sub;
 | 
				
			||||||
 | 
					  volatile unsigned long next;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Root Hub port status struct */
 | 
				
			||||||
 | 
					struct crisv10_rh {
 | 
				
			||||||
 | 
					  volatile __u16 wPortChange[2];
 | 
				
			||||||
 | 
					  volatile __u16 wPortStatusPrev[2];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* HCD description */
 | 
				
			||||||
 | 
					struct crisv10_hcd {
 | 
				
			||||||
 | 
					  spinlock_t		lock;
 | 
				
			||||||
 | 
					  __u8			num_ports;
 | 
				
			||||||
 | 
					  __u8                  running;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Endpoint HC private data description */
 | 
				
			||||||
 | 
					struct crisv10_ep_priv {
 | 
				
			||||||
 | 
					  int epid;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Additional software state info for a USB Controller epid */
 | 
				
			||||||
 | 
					struct etrax_epid {
 | 
				
			||||||
 | 
					  __u8 inuse;       /* !0 = setup in Etrax and used for a endpoint */
 | 
				
			||||||
 | 
					  __u8 disabled;    /* !0 = Temporarly disabled to avoid resubmission */
 | 
				
			||||||
 | 
					  __u8 type;        /* Setup as: PIPE_BULK, PIPE_CONTROL ... */
 | 
				
			||||||
 | 
					  __u8 out_traffic; /* !0 = This epid is for out traffic */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Struct to hold information of scheduled later URB completion */
 | 
				
			||||||
 | 
					struct urb_later_data {
 | 
				
			||||||
 | 
					  struct delayed_work dws;
 | 
				
			||||||
 | 
					  struct usb_hcd *hcd;
 | 
				
			||||||
 | 
					  struct urb *urb;
 | 
				
			||||||
 | 
					  int urb_num;
 | 
				
			||||||
 | 
					  int status;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct etrax_usb_hc {
 | 
					 | 
				
			||||||
	struct usb_bus *bus;
 | 
					 | 
				
			||||||
	struct virt_root_hub rh;
 | 
					 | 
				
			||||||
	struct etrax_usb_intr_traffic intr;
 | 
					 | 
				
			||||||
} etrax_hc_t;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
	STARTED,
 | 
					  STARTED,
 | 
				
			||||||
	NOT_STARTED,
 | 
					  NOT_STARTED,
 | 
				
			||||||
	UNLINK,
 | 
					  UNLINK,
 | 
				
			||||||
	TRANSFER_DONE,
 | 
					} crisv10_urb_state_t;
 | 
				
			||||||
	WAITING_FOR_DESCR_INTR
 | 
					 | 
				
			||||||
} etrax_usb_urb_state_t;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct crisv10_urb_priv {
 | 
				
			||||||
 | 
					  /* Sequence number for this URB. Every new submited URB gets this from
 | 
				
			||||||
 | 
					     a incrementing counter. Used when a URB is scheduled for later finish to
 | 
				
			||||||
 | 
					     be sure that the intended URB hasn't already been completed (device
 | 
				
			||||||
 | 
					     drivers has a tendency to reuse URBs once they are completed, causing us
 | 
				
			||||||
 | 
					     to not be able to single old ones out only based on the URB pointer.) */
 | 
				
			||||||
 | 
					  __u32 urb_num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct etrax_usb_urb_priv {
 | 
					  /* The first_sb field is used for freeing all SB descriptors belonging
 | 
				
			||||||
	/* The first_sb field is used for freeing all SB descriptors belonging
 | 
					     to an urb. The corresponding ep descriptor's sub pointer cannot be
 | 
				
			||||||
	   to an urb. The corresponding ep descriptor's sub pointer cannot be
 | 
					     used for this since the DMA advances the sub pointer as it processes
 | 
				
			||||||
	   used for this since the DMA advances the sub pointer as it processes
 | 
					     the sb list. */
 | 
				
			||||||
	   the sb list. */
 | 
					  struct USB_SB_Desc *first_sb;
 | 
				
			||||||
	USB_SB_Desc_t *first_sb;
 | 
					 | 
				
			||||||
	/* The last_sb field referes to the last SB descriptor that belongs to
 | 
					 | 
				
			||||||
	   this urb. This is important to know so we can free the SB descriptors
 | 
					 | 
				
			||||||
	   that ranges between first_sb and last_sb. */
 | 
					 | 
				
			||||||
	USB_SB_Desc_t *last_sb;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* The rx_offset field is used in ctrl and bulk traffic to keep track
 | 
					  /* The last_sb field referes to the last SB descriptor that belongs to
 | 
				
			||||||
	   of the offset in the urb's transfer_buffer where incoming data should be
 | 
					     this urb. This is important to know so we can free the SB descriptors
 | 
				
			||||||
	   copied to. */
 | 
					     that ranges between first_sb and last_sb. */
 | 
				
			||||||
	__u32 rx_offset;
 | 
					  struct USB_SB_Desc *last_sb;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
	/* Counter used in isochronous transfers to keep track of the
 | 
					  /* The rx_offset field is used in ctrl and bulk traffic to keep track
 | 
				
			||||||
	   number of packets received/transmitted.  */
 | 
					     of the offset in the urb's transfer_buffer where incoming data should be
 | 
				
			||||||
	__u32 isoc_packet_counter;
 | 
					     copied to. */
 | 
				
			||||||
 | 
					  __u32 rx_offset;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
	/* This field is used to pass information about the urb's current state between
 | 
					  /* Counter used in isochronous transfers to keep track of the
 | 
				
			||||||
	   the various interrupt handlers (thus marked volatile). */
 | 
					     number of packets received/transmitted.  */
 | 
				
			||||||
	volatile etrax_usb_urb_state_t urb_state;
 | 
					  __u32 isoc_packet_counter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Connection between the submitted urb and ETRAX epid number */
 | 
					  /* Flag that marks if this Isoc Out URB has finished it's transfer. Used
 | 
				
			||||||
	__u8 epid;
 | 
					     because several URBs can be finished before list is processed */
 | 
				
			||||||
 | 
					  __u8  isoc_out_done;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
	/* The rx_data_list field is used for periodic traffic, to hold
 | 
					  /* This field is used to pass information about the urb's current state
 | 
				
			||||||
	   received data for later processing in the the complete_urb functions,
 | 
					     between the various interrupt handlers (thus marked volatile). */
 | 
				
			||||||
	   where the data us copied to the urb's transfer_buffer. Basically, we
 | 
					  volatile crisv10_urb_state_t urb_state;
 | 
				
			||||||
	   use this intermediate storage because we don't know when it's safe to
 | 
					 | 
				
			||||||
	   reuse the transfer_buffer (FIXME?). */
 | 
					 | 
				
			||||||
	struct list_head rx_data_list;
 | 
					 | 
				
			||||||
} etrax_urb_priv_t;
 | 
					 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
/* This struct is for passing data from the top half to the bottom half. */
 | 
					  /* In Ctrl transfers consist of (at least) 3 packets: SETUP, IN and ZOUT.
 | 
				
			||||||
typedef struct usb_interrupt_registers
 | 
					     When DMA8 sub-channel 2 has processed the SB list for this sequence we
 | 
				
			||||||
{
 | 
					     get a interrupt. We also get a interrupt for In transfers and which
 | 
				
			||||||
	etrax_hc_t *hc;
 | 
					     one of these interrupts that comes first depends of data size and device.
 | 
				
			||||||
	__u32 r_usb_epid_attn;
 | 
					     To be sure that we have got both interrupts before we complete the URB
 | 
				
			||||||
	__u8 r_usb_status;
 | 
					     we have these to flags that shows which part that has completed.
 | 
				
			||||||
	__u16 r_usb_rh_port_status_1;
 | 
					     We can then check when we get one of the interrupts that if the other has
 | 
				
			||||||
	__u16 r_usb_rh_port_status_2;
 | 
					     occured it's safe for us to complete the URB, otherwise we set appropriate
 | 
				
			||||||
	__u32 r_usb_irq_mask_read;
 | 
					     flag and do the completion when we get the other interrupt. */
 | 
				
			||||||
	__u32 r_usb_fm_number;
 | 
					  volatile unsigned char ctrl_zout_done;
 | 
				
			||||||
	struct work_struct usb_bh;
 | 
					  volatile unsigned char ctrl_rx_done;
 | 
				
			||||||
} usb_interrupt_registers_t;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This struct is for passing data from the isoc top half to the isoc bottom half. */
 | 
					  /* Connection between the submitted urb and ETRAX epid number */
 | 
				
			||||||
typedef struct usb_isoc_complete_data
 | 
					  __u8 epid;
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct urb *urb;
 | 
					 | 
				
			||||||
	struct work_struct usb_bh;
 | 
					 | 
				
			||||||
} usb_isoc_complete_data_t;
 | 
					 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
/* This struct holds data we get from the rx descriptors for DMA channel 9
 | 
					  /* The rx_data_list field is used for periodic traffic, to hold
 | 
				
			||||||
   for periodic traffic (intr and isoc). */
 | 
					     received data for later processing in the the complete_urb functions,
 | 
				
			||||||
typedef struct rx_data
 | 
					     where the data us copied to the urb's transfer_buffer. Basically, we
 | 
				
			||||||
{
 | 
					     use this intermediate storage because we don't know when it's safe to
 | 
				
			||||||
	void *data;
 | 
					     reuse the transfer_buffer (FIXME?). */
 | 
				
			||||||
	int length;
 | 
					  struct list_head rx_data_list;
 | 
				
			||||||
	struct list_head list;
 | 
					 | 
				
			||||||
} rx_data_t;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* The interval time rounded up to closest 2^N */
 | 
				
			||||||
 | 
					  int interval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Pool of EP descriptors needed if it's a INTR transfer.
 | 
				
			||||||
 | 
					     Amount of EPs in pool correspons to how many INTR that should
 | 
				
			||||||
 | 
					     be inserted in TxIntrEPList (max 128, defined by MAX_INTR_INTERVAL) */
 | 
				
			||||||
 | 
					  struct USB_EP_Desc* intr_ep_pool[128];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* The mount of EPs allocated for this INTR URB */
 | 
				
			||||||
 | 
					  int intr_ep_pool_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Pointer to info struct if URB is scheduled to be finished later */
 | 
				
			||||||
 | 
					  struct urb_later_data* later_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Allocated bandwidth for isochronous and interrupt traffic */
 | 
				
			||||||
 | 
					  int bandwidth;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This struct is for passing data from the top half to the bottom half irq
 | 
				
			||||||
 | 
					   handlers */
 | 
				
			||||||
 | 
					struct crisv10_irq_reg {
 | 
				
			||||||
 | 
					  struct usb_hcd* hcd;
 | 
				
			||||||
 | 
					  __u32 r_usb_epid_attn;
 | 
				
			||||||
 | 
					  __u8 r_usb_status;
 | 
				
			||||||
 | 
					  __u16 r_usb_rh_port_status_1;
 | 
				
			||||||
 | 
					  __u16 r_usb_rh_port_status_2;
 | 
				
			||||||
 | 
					  __u32 r_usb_irq_mask_read;
 | 
				
			||||||
 | 
					  __u32 r_usb_fm_number;
 | 
				
			||||||
 | 
					  struct work_struct usb_bh;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This struct is for passing data from the isoc top half to the isoc bottom
 | 
				
			||||||
 | 
					   half. */
 | 
				
			||||||
 | 
					struct crisv10_isoc_complete_data {
 | 
				
			||||||
 | 
					  struct usb_hcd *hcd;
 | 
				
			||||||
 | 
					  struct urb *urb;
 | 
				
			||||||
 | 
					  struct work_struct usb_bh;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Entry item for URB lists for each endpint */
 | 
				
			||||||
typedef struct urb_entry
 | 
					typedef struct urb_entry
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct urb *urb;
 | 
						struct urb *urb;
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user