2009-06-04 11:34:49 +04:00
/*
* Intel Langwell USB Device Controller driver
* Copyright ( C ) 2008 - 2009 , Intel Corporation .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*/
# include <linux/usb/langwell_udc.h>
/*-------------------------------------------------------------------------*/
/* driver data structures and utilities */
/*
* dTD : Device Endpoint Transfer Descriptor
* describe to the device controller the location and quantity of
* data to be send / received for given transfer
*/
struct langwell_dtd {
u32 dtd_next ;
/* bits 31:5, next transfer element pointer */
# define DTD_NEXT(d) (((d)>>5)&0x7ffffff)
# define DTD_NEXT_MASK (0x7ffffff << 5)
/* terminate */
# define DTD_TERM BIT(0)
/* bits 7:0, execution back states */
u32 dtd_status : 8 ;
# define DTD_STATUS(d) (((d)>>0)&0xff)
# define DTD_STS_ACTIVE BIT(7) /* active */
# define DTD_STS_HALTED BIT(6) /* halted */
# define DTD_STS_DBE BIT(5) /* data buffer error */
# define DTD_STS_TRE BIT(3) /* transaction error */
/* bits 9:8 */
u32 dtd_res0 : 2 ;
/* bits 11:10, multipier override */
u32 dtd_multo : 2 ;
# define DTD_MULTO (BIT(11) | BIT(10))
/* bits 14:12 */
u32 dtd_res1 : 3 ;
/* bit 15, interrupt on complete */
u32 dtd_ioc : 1 ;
# define DTD_IOC BIT(15)
/* bits 30:16, total bytes */
u32 dtd_total : 15 ;
# define DTD_TOTAL(d) (((d)>>16)&0x7fff)
# define DTD_MAX_TRANSFER_LENGTH 0x4000
/* bit 31 */
u32 dtd_res2 : 1 ;
/* dTD buffer pointer page 0 to 4 */
u32 dtd_buf [ 5 ] ;
# define DTD_OFFSET_MASK 0xfff
/* bits 31:12, buffer pointer */
# define DTD_BUFFER(d) (((d)>>12)&0x3ff)
/* bits 11:0, current offset */
# define DTD_C_OFFSET(d) (((d)>>0)&0xfff)
/* bits 10:0, frame number */
# define DTD_FRAME(d) (((d)>>0)&0x7ff)
/* driver-private parts */
/* dtd dma address */
dma_addr_t dtd_dma ;
/* next dtd virtual address */
struct langwell_dtd * next_dtd_virt ;
} ;
/*
* dQH : Device Endpoint Queue Head
* describe where all transfers are managed
* 48 - byte data structure , aligned on 64 - byte boundary
*
* These are associated with dTD structure
*/
struct langwell_dqh {
/* endpoint capabilities and characteristics */
u32 dqh_res0 : 15 ; /* bits 14:0 */
u32 dqh_ios : 1 ; /* bit 15, interrupt on setup */
# define DQH_IOS BIT(15)
u32 dqh_mpl : 11 ; /* bits 26:16, maximum packet length */
# define DQH_MPL (0x7ff << 16)
u32 dqh_res1 : 2 ; /* bits 28:27 */
u32 dqh_zlt : 1 ; /* bit 29, zero length termination */
# define DQH_ZLT BIT(29)
u32 dqh_mult : 2 ; /* bits 31:30 */
# define DQH_MULT (BIT(30) | BIT(31))
/* current dTD pointer */
u32 dqh_current ; /* locate the transfer in progress */
# define DQH_C_DTD(e) \
( ( ( e ) > > 5 ) & 0x7ffffff ) /* bits 31:5, current dTD pointer */
/* transfer overlay, hardware parts of a struct langwell_dtd */
u32 dtd_next ;
u32 dtd_status : 8 ; /* bits 7:0, execution back states */
u32 dtd_res0 : 2 ; /* bits 9:8 */
u32 dtd_multo : 2 ; /* bits 11:10, multipier override */
u32 dtd_res1 : 3 ; /* bits 14:12 */
u32 dtd_ioc : 1 ; /* bit 15, interrupt on complete */
u32 dtd_total : 15 ; /* bits 30:16, total bytes */
u32 dtd_res2 : 1 ; /* bit 31 */
u32 dtd_buf [ 5 ] ; /* dTD buffer pointer page 0 to 4 */
u32 dqh_res2 ;
struct usb_ctrlrequest dqh_setup ; /* setup packet buffer */
} __attribute__ ( ( aligned ( 64 ) ) ) ;
/* endpoint data structure */
struct langwell_ep {
struct usb_ep ep ;
dma_addr_t dma ;
struct langwell_udc * dev ;
unsigned long irqs ;
struct list_head queue ;
struct langwell_dqh * dqh ;
const struct usb_endpoint_descriptor * desc ;
char name [ 14 ] ;
unsigned stopped : 1 ,
ep_type : 2 ,
ep_num : 8 ;
} ;
/* request data structure */
struct langwell_request {
struct usb_request req ;
struct langwell_dtd * dtd , * head , * tail ;
struct langwell_ep * ep ;
dma_addr_t dtd_dma ;
struct list_head queue ;
unsigned dtd_count ;
unsigned mapped : 1 ;
} ;
/* ep0 transfer state */
enum ep0_state {
WAIT_FOR_SETUP ,
DATA_STATE_XMIT ,
DATA_STATE_NEED_ZLP ,
WAIT_FOR_OUT_STATUS ,
DATA_STATE_RECV ,
} ;
/* device suspend state */
enum lpm_state {
LPM_L0 , /* on */
LPM_L1 , /* LPM L1 sleep */
LPM_L2 , /* suspend */
LPM_L3 , /* off */
} ;
/* device data structure */
struct langwell_udc {
/* each pci device provides one gadget, several endpoints */
struct usb_gadget gadget ;
spinlock_t lock ; /* device lock */
struct langwell_ep * ep ;
struct usb_gadget_driver * driver ;
2012-02-13 15:24:02 +04:00
struct usb_phy * transceiver ;
2009-06-04 11:34:49 +04:00
u8 dev_addr ;
u32 usb_state ;
u32 resume_state ;
u32 bus_reset ;
enum lpm_state lpm_state ;
enum ep0_state ep0_state ;
u32 ep0_dir ;
u16 dciversion ;
unsigned ep_max ;
unsigned devcap : 1 ,
enabled : 1 ,
region : 1 ,
got_irq : 1 ,
powered : 1 ,
remote_wakeup : 1 ,
rate : 1 ,
is_reset : 1 ,
softconnected : 1 ,
vbus_active : 1 ,
suspended : 1 ,
stopped : 1 ,
2010-08-05 17:18:29 +04:00
lpm : 1 , /* LPM capability */
has_sram : 1 , /* SRAM caching */
got_sram : 1 ;
2009-06-04 11:34:49 +04:00
/* pci state used to access those endpoints */
struct pci_dev * pdev ;
/* Langwell otg transceiver */
struct langwell_otg * lotg ;
/* control registers */
struct langwell_cap_regs __iomem * cap_regs ;
struct langwell_op_regs __iomem * op_regs ;
struct usb_ctrlrequest local_setup_buff ;
struct langwell_dqh * ep_dqh ;
size_t ep_dqh_size ;
dma_addr_t ep_dqh_dma ;
/* ep0 status request */
struct langwell_request * status_req ;
/* dma pool */
struct dma_pool * dtd_pool ;
/* make sure release() is done */
struct completion * done ;
2010-08-05 17:18:21 +04:00
2010-08-05 17:18:29 +04:00
/* for private SRAM caching */
unsigned int sram_addr ;
unsigned int sram_size ;
2010-08-05 17:18:21 +04:00
/* device status data for get_status request */
u16 dev_status ;
2009-06-04 11:34:49 +04:00
} ;
2011-10-08 14:17:34 +04:00
# define gadget_to_langwell(g) container_of((g), struct langwell_udc, gadget)