2008-11-12 13:38:31 -08:00
/*
* Copyright ( C ) 2005 Mike Lee ( eemike @ gmail . com )
*
* This udc driver is now under testing and code is based on pxa2xx_udc . h
* Please use it with your own risk !
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# ifndef __LINUX_USB_GADGET_IMX_H
# define __LINUX_USB_GADGET_IMX_H
# include <linux/types.h>
/* Helper macros */
# define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */
# define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0)
# define IMX_USB_NB_EP 6
/* Driver structures */
struct imx_request {
struct usb_request req ;
struct list_head queue ;
unsigned int in_use ;
} ;
enum ep0_state {
EP0_IDLE ,
EP0_IN_DATA_PHASE ,
EP0_OUT_DATA_PHASE ,
EP0_CONFIG ,
EP0_STALL ,
} ;
struct imx_ep_struct {
struct usb_ep ep ;
struct imx_udc_struct * imx_usb ;
struct list_head queue ;
unsigned char stopped ;
unsigned char fifosize ;
unsigned char bEndpointAddress ;
unsigned char bmAttributes ;
} ;
struct imx_udc_struct {
struct usb_gadget gadget ;
struct usb_gadget_driver * driver ;
struct device * dev ;
struct imx_ep_struct imx_ep [ IMX_USB_NB_EP ] ;
struct clk * clk ;
2009-01-21 15:19:19 +02:00
struct timer_list timer ;
2008-11-12 13:38:31 -08:00
enum ep0_state ep0state ;
struct resource * res ;
void __iomem * base ;
unsigned char set_config ;
int cfg ,
intf ,
alt ,
usbd_int [ 7 ] ;
} ;
/* USB registers */
# define USB_FRAME (0x00) /* USB frame */
# define USB_SPEC (0x04) /* USB Spec */
# define USB_STAT (0x08) /* USB Status */
# define USB_CTRL (0x0C) /* USB Control */
# define USB_DADR (0x10) /* USB Desc RAM addr */
# define USB_DDAT (0x14) /* USB Desc RAM/EP buffer data */
# define USB_INTR (0x18) /* USB interrupt */
# define USB_MASK (0x1C) /* USB Mask */
# define USB_ENAB (0x24) /* USB Enable */
# define USB_EP_STAT(x) (0x30 + (x*0x30)) /* USB status/control */
# define USB_EP_INTR(x) (0x34 + (x*0x30)) /* USB interrupt */
# define USB_EP_MASK(x) (0x38 + (x*0x30)) /* USB mask */
# define USB_EP_FDAT(x) (0x3C + (x*0x30)) /* USB FIFO data */
# define USB_EP_FDAT0(x) (0x3C + (x*0x30)) /* USB FIFO data */
# define USB_EP_FDAT1(x) (0x3D + (x*0x30)) /* USB FIFO data */
# define USB_EP_FDAT2(x) (0x3E + (x*0x30)) /* USB FIFO data */
# define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */
# define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */
# define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */
2009-01-21 15:17:55 +02:00
# define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last rd f. pointer */
# define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last wr f. pointer */
2008-11-12 13:38:31 -08:00
# define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */
# define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */
# define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */
/* USB Control Register Bit Fields.*/
# define CTRL_CMDOVER (1<<6) /* UDC status */
# define CTRL_CMDERROR (1<<5) /* UDC status */
# define CTRL_FE_ENA (1<<3) /* Enable Font End logic */
# define CTRL_UDC_RST (1<<2) /* UDC reset */
# define CTRL_AFE_ENA (1<<1) /* Analog Font end enable */
# define CTRL_RESUME (1<<0) /* UDC resume */
/* USB Status Register Bit Fields.*/
# define STAT_RST (1<<8)
# define STAT_SUSP (1<<7)
# define STAT_CFG (3<<5)
# define STAT_INTF (3<<3)
# define STAT_ALTSET (7<<0)
/* USB Interrupt Status/Mask Registers Bit fields */
# define INTR_WAKEUP (1<<31) /* Wake up Interrupt */
# define INTR_MSOF (1<<7) /* Missed Start of Frame */
# define INTR_SOF (1<<6) /* Start of Frame */
# define INTR_RESET_STOP (1<<5) /* Reset Signaling stop */
# define INTR_RESET_START (1<<4) /* Reset Signaling start */
# define INTR_RESUME (1<<3) /* Suspend to resume */
# define INTR_SUSPEND (1<<2) /* Active to suspend */
# define INTR_FRAME_MATCH (1<<1) /* Frame matched */
# define INTR_CFG_CHG (1<<0) /* Configuration change occurred */
/* USB Enable Register Bit Fields.*/
# define ENAB_RST (1<<31) /* Reset USB modules */
# define ENAB_ENAB (1<<30) /* Enable USB modules*/
# define ENAB_SUSPEND (1<<29) /* Suspend USB modules */
# define ENAB_ENDIAN (1<<28) /* Endian of USB modules */
# define ENAB_PWRMD (1<<0) /* Power mode of USB modules */
/* USB Descriptor Ram Address Register bit fields */
# define DADR_CFG (1<<31) /* Configuration */
# define DADR_BSY (1<<30) /* Busy status */
# define DADR_DADR (0x1FF) /* Descriptor Ram Address */
/* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */
# define DDAT_DDAT (0xFF) /* Descriptor Endpoint Buffer */
/* USB Endpoint Status Register bit fields */
# define EPSTAT_BCOUNT (0x7F<<16) /* Endpoint FIFO byte count */
# define EPSTAT_SIP (1<<8) /* Endpoint setup in progress */
# define EPSTAT_DIR (1<<7) /* Endpoint transfer direction */
# define EPSTAT_MAX (3<<5) /* Endpoint Max packet size */
# define EPSTAT_TYP (3<<3) /* Endpoint type */
# define EPSTAT_ZLPS (1<<2) /* Send zero length packet */
# define EPSTAT_FLUSH (1<<1) /* Endpoint FIFO Flush */
# define EPSTAT_STALL (1<<0) /* Force stall */
/* USB Endpoint FIFO Status Register bit fields */
# define FSTAT_FRAME_STAT (0xF<<24) /* Frame status bit [0-3] */
# define FSTAT_ERR (1<<22) /* FIFO error */
# define FSTAT_UF (1<<21) /* FIFO underflow */
# define FSTAT_OF (1<<20) /* FIFO overflow */
# define FSTAT_FR (1<<19) /* FIFO frame ready */
# define FSTAT_FULL (1<<18) /* FIFO full */
# define FSTAT_ALRM (1<<17) /* FIFO alarm */
# define FSTAT_EMPTY (1<<16) /* FIFO empty */
/* USB Endpoint FIFO Control Register bit fields */
# define FCTRL_WFR (1<<29) /* Write frame end */
/* USB Endpoint Interrupt Status Regsiter bit fields */
# define EPINTR_FIFO_FULL (1<<8) /* fifo full */
# define EPINTR_FIFO_EMPTY (1<<7) /* fifo empty */
# define EPINTR_FIFO_ERROR (1<<6) /* fifo error */
# define EPINTR_FIFO_HIGH (1<<5) /* fifo high */
# define EPINTR_FIFO_LOW (1<<4) /* fifo low */
# define EPINTR_MDEVREQ (1<<3) /* multi Device request */
# define EPINTR_EOT (1<<2) /* fifo end of transfer */
# define EPINTR_DEVREQ (1<<1) /* Device request */
# define EPINTR_EOF (1<<0) /* fifo end of frame */
/* Debug macros */
# ifdef DEBUG
/* #define DEBUG_REQ */
/* #define DEBUG_TRX */
/* #define DEBUG_INIT */
/* #define DEBUG_EP0 */
/* #define DEBUG_EPX */
/* #define DEBUG_IRQ */
/* #define DEBUG_EPIRQ */
/* #define DEBUG_DUMP */
2009-01-21 15:17:25 +02:00
/* #define DEBUG_ERR */
2008-11-12 13:38:31 -08:00
# ifdef DEBUG_REQ
# define D_REQ(dev, args...) dev_dbg(dev, ## args)
# else
# define D_REQ(dev, args...) do {} while (0)
# endif /* DEBUG_REQ */
# ifdef DEBUG_TRX
# define D_TRX(dev, args...) dev_dbg(dev, ## args)
# else
# define D_TRX(dev, args...) do {} while (0)
# endif /* DEBUG_TRX */
# ifdef DEBUG_INIT
# define D_INI(dev, args...) dev_dbg(dev, ## args)
# else
# define D_INI(dev, args...) do {} while (0)
# endif /* DEBUG_INIT */
# ifdef DEBUG_EP0
static const char * state_name [ ] = {
" EP0_IDLE " ,
" EP0_IN_DATA_PHASE " ,
" EP0_OUT_DATA_PHASE " ,
" EP0_CONFIG " ,
" EP0_STALL "
} ;
# define D_EP0(dev, args...) dev_dbg(dev, ## args)
# else
# define D_EP0(dev, args...) do {} while (0)
# endif /* DEBUG_EP0 */
# ifdef DEBUG_EPX
# define D_EPX(dev, args...) dev_dbg(dev, ## args)
# else
# define D_EPX(dev, args...) do {} while (0)
# endif /* DEBUG_EP0 */
# ifdef DEBUG_IRQ
static void dump_intr ( const char * label , int irqreg , struct device * dev )
{
dev_dbg ( dev , " <%s> USB_INTR=[%s%s%s%s%s%s%s%s%s] \n " , label ,
( irqreg & INTR_WAKEUP ) ? " wake " : " " ,
( irqreg & INTR_MSOF ) ? " msof " : " " ,
( irqreg & INTR_SOF ) ? " sof " : " " ,
( irqreg & INTR_RESUME ) ? " resume " : " " ,
( irqreg & INTR_SUSPEND ) ? " suspend " : " " ,
( irqreg & INTR_RESET_STOP ) ? " noreset " : " " ,
( irqreg & INTR_RESET_START ) ? " reset " : " " ,
( irqreg & INTR_FRAME_MATCH ) ? " fmatch " : " " ,
( irqreg & INTR_CFG_CHG ) ? " config " : " " ) ;
}
# else
# define dump_intr(x, y, z) do {} while (0)
# endif /* DEBUG_IRQ */
# ifdef DEBUG_EPIRQ
2009-01-21 15:17:55 +02:00
static void dump_ep_intr ( const char * label , int nr , int irqreg ,
struct device * dev )
2008-11-12 13:38:31 -08:00
{
dev_dbg ( dev , " <%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s] \n " , label , nr ,
( irqreg & EPINTR_FIFO_FULL ) ? " full " : " " ,
( irqreg & EPINTR_FIFO_EMPTY ) ? " fempty " : " " ,
( irqreg & EPINTR_FIFO_ERROR ) ? " ferr " : " " ,
( irqreg & EPINTR_FIFO_HIGH ) ? " fhigh " : " " ,
( irqreg & EPINTR_FIFO_LOW ) ? " flow " : " " ,
( irqreg & EPINTR_MDEVREQ ) ? " mreq " : " " ,
( irqreg & EPINTR_EOF ) ? " eof " : " " ,
( irqreg & EPINTR_DEVREQ ) ? " devreq " : " " ,
( irqreg & EPINTR_EOT ) ? " eot " : " " ) ;
}
# else
# define dump_ep_intr(x, y, z, i) do {} while (0)
# endif /* DEBUG_IRQ */
# ifdef DEBUG_DUMP
2009-01-21 15:17:55 +02:00
static void dump_usb_stat ( const char * label ,
struct imx_udc_struct * imx_usb )
2008-11-12 13:38:31 -08:00
{
int temp = __raw_readl ( imx_usb - > base + USB_STAT ) ;
dev_dbg ( imx_usb - > dev ,
" <%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d] \n " , label ,
( temp & STAT_RST ) ? " reset " : " " ,
( temp & STAT_SUSP ) ? " suspend " : " " ,
( temp & STAT_CFG ) > > 5 ,
( temp & STAT_INTF ) > > 3 ,
( temp & STAT_ALTSET ) ) ;
}
2009-01-21 15:17:55 +02:00
static void dump_ep_stat ( const char * label ,
struct imx_ep_struct * imx_ep )
2008-11-12 13:38:31 -08:00
{
2009-01-21 15:17:55 +02:00
int temp = __raw_readl ( imx_ep - > imx_usb - > base
+ USB_EP_INTR ( EP_NO ( imx_ep ) ) ) ;
2008-11-12 13:38:31 -08:00
dev_dbg ( imx_ep - > imx_usb - > dev ,
2009-01-21 15:17:55 +02:00
" <%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s] \n " ,
label , EP_NO ( imx_ep ) ,
2008-11-12 13:38:31 -08:00
( temp & EPINTR_FIFO_FULL ) ? " full " : " " ,
( temp & EPINTR_FIFO_EMPTY ) ? " fempty " : " " ,
( temp & EPINTR_FIFO_ERROR ) ? " ferr " : " " ,
( temp & EPINTR_FIFO_HIGH ) ? " fhigh " : " " ,
( temp & EPINTR_FIFO_LOW ) ? " flow " : " " ,
( temp & EPINTR_MDEVREQ ) ? " mreq " : " " ,
( temp & EPINTR_EOF ) ? " eof " : " " ,
( temp & EPINTR_DEVREQ ) ? " devreq " : " " ,
( temp & EPINTR_EOT ) ? " eot " : " " ) ;
2009-01-21 15:17:55 +02:00
temp = __raw_readl ( imx_ep - > imx_usb - > base
+ USB_EP_STAT ( EP_NO ( imx_ep ) ) ) ;
2008-11-12 13:38:31 -08:00
dev_dbg ( imx_ep - > imx_usb - > dev ,
2009-01-21 15:17:55 +02:00
" <%s> EP%d_STAT=[%s%s bcount=%d] \n " ,
label , EP_NO ( imx_ep ) ,
2008-11-12 13:38:31 -08:00
( temp & EPSTAT_SIP ) ? " sip " : " " ,
( temp & EPSTAT_STALL ) ? " stall " : " " ,
( temp & EPSTAT_BCOUNT ) > > 16 ) ;
2009-01-21 15:17:55 +02:00
temp = __raw_readl ( imx_ep - > imx_usb - > base
+ USB_EP_FSTAT ( EP_NO ( imx_ep ) ) ) ;
2008-11-12 13:38:31 -08:00
dev_dbg ( imx_ep - > imx_usb - > dev ,
2009-01-21 15:17:55 +02:00
" <%s> EP%d_FSTAT=[%s%s%s%s%s%s%s] \n " ,
label , EP_NO ( imx_ep ) ,
2008-11-12 13:38:31 -08:00
( temp & FSTAT_ERR ) ? " ferr " : " " ,
( temp & FSTAT_UF ) ? " funder " : " " ,
( temp & FSTAT_OF ) ? " fover " : " " ,
( temp & FSTAT_FR ) ? " fready " : " " ,
( temp & FSTAT_FULL ) ? " ffull " : " " ,
( temp & FSTAT_ALRM ) ? " falarm " : " " ,
( temp & FSTAT_EMPTY ) ? " fempty " : " " ) ;
}
2009-01-21 15:17:55 +02:00
static void dump_req ( const char * label , struct imx_ep_struct * imx_ep ,
struct usb_request * req )
2008-11-12 13:38:31 -08:00
{
int i ;
if ( ! req | | ! req - > buf ) {
2009-01-21 15:17:55 +02:00
dev_dbg ( imx_ep - > imx_usb - > dev ,
" <%s> req or req buf is free \n " , label ) ;
2008-11-12 13:38:31 -08:00
return ;
}
2009-01-21 15:17:55 +02:00
if ( ( ! EP_NO ( imx_ep ) & & imx_ep - > imx_usb - > ep0state
= = EP0_IN_DATA_PHASE )
2008-11-12 13:38:31 -08:00
| | ( EP_NO ( imx_ep ) & & EP_DIR ( imx_ep ) ) ) {
2009-01-21 15:17:55 +02:00
dev_dbg ( imx_ep - > imx_usb - > dev ,
" <%s> request dump < " , label ) ;
2008-11-12 13:38:31 -08:00
for ( i = 0 ; i < req - > length ; i + + )
printk ( " %02x- " , * ( ( u8 * ) req - > buf + i ) ) ;
printk ( " > \n " ) ;
}
}
# else
# define dump_ep_stat(x, y) do {} while (0)
# define dump_usb_stat(x, y) do {} while (0)
# define dump_req(x, y, z) do {} while (0)
# endif /* DEBUG_DUMP */
# ifdef DEBUG_ERR
# define D_ERR(dev, args...) dev_dbg(dev, ## args)
# else
# define D_ERR(dev, args...) do {} while (0)
# endif
# else
# define D_REQ(dev, args...) do {} while (0)
# define D_TRX(dev, args...) do {} while (0)
# define D_INI(dev, args...) do {} while (0)
# define D_EP0(dev, args...) do {} while (0)
# define D_EPX(dev, args...) do {} while (0)
# define dump_ep_intr(x, y, z, i) do {} while (0)
# define dump_intr(x, y, z) do {} while (0)
# define dump_ep_stat(x, y) do {} while (0)
# define dump_usb_stat(x, y) do {} while (0)
# define dump_req(x, y, z) do {} while (0)
# define D_ERR(dev, args...) do {} while (0)
# endif /* DEBUG */
# endif /* __LINUX_USB_GADGET_IMX_H */