static int __init udc_init( void ) {
printk( KERN_INFO "%s (%s)/n" , driver_desc, DRIVER_VERSION) ;
return platform_driver_register( & udc_driver) ;//驅動註冊進系統 }
發現設備後調用PROBE函數 static int __init fsl_udc_probe( struct platform_device * pdev) {
struct resource * res;
struct fsl_usb2_platform_data * pdata = pdev- > dev. platform_data;
int ret = - ENODEV;
unsigned int i;
u32 dccparams, portsc;
if ( strcmp ( pdev- > name, driver_name) ) {
VDBG( "Wrong device/n" ) ;
return - ENODEV;
}
/********************************************************/
static struct fsl_udc *udc_controller;
全局變量定義
/*******************************************************/
udc_controller = kzalloc( sizeof ( struct fsl_udc) , GFP_KERNEL) ;
if ( udc_controller = = NULL ) {
ERR( "malloc udc failed/n" ) ;
return - ENOMEM;
}
udc_controller- > pdata = pdata; //私有變量賦值
# ifdef CONFIG_USB_OTG
/* Memory and interrupt resources will be passed from OTG */
udc_controller- > transceiver = otg_get_transceiver( ) ;//在OTG功能中已經通過otg_set_transceiver
設置了transceiver結構,這裏面就可以GET
if ( ! udc_controller- > transceiver) {
printk( KERN_ERR "Can't find OTG driver!/n" ) ;
ret = - ENODEV;
goto err1a;
}
res = otg_get_resources( ) ; //獲得資源
if ( ! res) {
DBG( "resource not registered!/n" ) ;
return - ENODEV;
} # else
if ( ( pdev- > dev. parent) & &
( to_platform_device( pdev- > dev. parent) - > resource) ) {
pdev- > resource =
to_platform_device( pdev- > dev. parent) - > resource;
pdev- > num_resources =
to_platform_device( pdev- > dev. parent) - > num_resources;
}
res = platform_get_resource( pdev, IORESOURCE_MEM, 0) ;
if ( ! res) {
ret = - ENXIO;
goto err1a;
}
if ( ! request_mem_region( res- > start, resource_size( res) ,
driver_name) ) {
ERR( "request mem region for %s failed /n" , pdev- > name) ;
ret = - EBUSY;
goto err1a;
} # endif
/*將物理地址映射爲驅動可以訪問的虛擬地址*/
dr_regs = ioremap( res- > start, resource_size( res) ) ;
if ( ! dr_regs) {
ret = - ENOMEM;
goto err1;
}
pdata- > regs = ( void * ) dr_regs;
//私有數據接收映射地址
/*
* do platform specific init: check the clock, grab/config pins, etc.
*/
/*調用私有數據的初始化函數,關於初始化函數下面分析*/
if ( pdata- > platform_init & & pdata- > platform_init( pdev) ) {
ret = - ENODEV;
goto err2a;
}
if ( pdata- > have_sysif_regs)
usb_sys_regs = ( struct usb_sys_interface * )
( ( u32) dr_regs + USB_DR_SYS_OFFSET) ;
/* Read Device Controller Capability Parameters register */
dccparams = fsl_readl( & dr_regs- > dccparams) ;
if ( ! ( dccparams & DCCPARAMS_DC) ) {
ERR( "This SOC doesn't support device role/n" ) ;
ret = - ENODEV;
goto err2;
}
/* Get max device endpoints */
/* DEN is bidirectional ep number, max_ep doubles the number */
udc_controller- > max_ep = ( dccparams & DCCPARAMS_DEN_MASK) * 2;
# ifdef CONFIG_USB_OTG
res+ + ;
udc_controller- > irq = res- > start; # else
udc_controller- > irq = platform_get_irq( pdev, 0) ; # endif
if ( ! udc_controller- > irq) {
ret = - ENODEV;
goto err2;
}
/*註冊中斷,該中斷和OTG的中斷共享一個*/
ret = request_irq( udc_controller- > irq, fsl_udc_irq, IRQF_SHARED,
driver_name, udc_controller) ;
if ( ret ! = 0) {
ERR( "cannot request irq %d err %d /n" ,
udc_controller- > irq, ret) ;
goto err2;
}
/* Initialize the udc structure including QH member and other member */
/*對一些資源進行空間開闢等初始化操作*/
if ( struct_udc_setup( udc_controller, pdev) ) {
ERR( "Can't initialize udc data structure/n" ) ;
ret = - ENOMEM;
goto err3;
}
if ( ! udc_controller- > transceiver) {
/* initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched */
dr_controller_setup( udc_controller) ;
}
/* Setup gadget structure */
udc_controller- > gadget. ops = & fsl_gadget_ops;
udc_controller- > gadget. is_dualspeed = 1;
udc_controller- > gadget. ep0 = & udc_controller- > eps[ 0] . ep;
INIT_LIST_HEAD( & udc_controller- > gadget. ep_list) ;
udc_controller- > gadget. speed = USB_SPEED_UNKNOWN;
udc_controller- > gadget. name = driver_name;
/* Setup gadget.dev and register with kernel */
dev_set_name( & udc_controller- > gadget. dev, "gadget" ) ;
udc_controller- > gadget. dev. release = fsl_udc_release;
udc_controller- > gadget. dev. parent = & pdev- > dev;
ret = device_register( & udc_controller- > gadget. dev) ;
if ( ret < 0)
goto err3;
if ( udc_controller- > transceiver) {
udc_controller- > gadget. is_otg = 1;
/* now didn't support lpm in OTG mode*/
device_set_wakeup_capable( & pdev- > dev, 0) ;
}
/* setup QH and epctrl for ep0 */
ep0_setup( udc_controller) ;
/* setup udc->eps[] for ep0 */
struct_ep_setup( udc_controller, 0, "ep0" , 0) ;
/* for ep0: the desc defined here;
* for other eps, gadget layer called ep_enable with defined desc
*/
udc_controller- > eps[ 0] . desc = & fsl_ep0_desc;
udc_controller- > eps[ 0] . ep. maxpacket = USB_MAX_CTRL_PAYLOAD;
/* setup the udc->eps[] for non-control endpoints and link
* to gadget.ep_list */
for ( i = 1; i < ( int ) ( udc_controller- > max_ep / 2) ; i+ + ) {
char name[ 14] ;
sprintf ( name, "ep%dout" , i) ;
struct_ep_setup( udc_controller, i * 2, name, 1) ;
sprintf ( name, "ep%din" , i) ;
struct_ep_setup( udc_controller, i * 2 + 1, name, 1) ;
}
/* use dma_pool for TD management */
udc_controller- > td_pool = dma_pool_create( "udc_td" , & pdev- > dev,
sizeof ( struct ep_td_struct) ,
DTD_ALIGNMENT, UDC_DMA_BOUNDARY) ;
if ( udc_controller- > td_pool = = NULL ) {
ret = - ENOMEM;
goto err4;
}
if ( g_iram_size) {
for ( i = 0; i < IRAM_PPH_NTD; i+ + ) {
udc_controller- > iram_buffer[ i] =
USB_IRAM_BASE_ADDR + i * g_iram_size;
udc_controller- > iram_buffer_v[ i] =
IO_ADDRESS( udc_controller- > iram_buffer[ i] ) ;
}
} # ifdef POSTPONE_FREE_LAST_DTD
last_free_td = NULL ; # endif
/* disable all INTR */
fsl_writel( 0, & dr_regs- > usbintr) ;
dr_wake_up_enable( udc_controller, false ) ;
udc_controller- > stopped = 1;
portsc = fsl_readl( & dr_regs- > portsc1) ;
portsc | = PORTSCX_PHY_LOW_POWER_SPD;
fsl_writel( portsc, & dr_regs- > portsc1) ;
if ( udc_controller- > pdata- > usb_clock_for_pm)
udc_controller- > pdata- > usb_clock_for_pm( false ) ;
create_proc_file( ) ;
return 0;
err4:
device_unregister( & udc_controller- > gadget. dev) ;
err3:
free_irq( udc_controller- > irq, udc_controller) ;
err2:
if ( pdata- > platform_uninit)
pdata- > platform_uninit( pdata) ;
err2a:
iounmap( ( u8 __iomem * ) dr_regs) ;
err1:
if ( ! udc_controller- > transceiver)
release_mem_region( res- > start, resource_size( res) ) ;
err1a:
kfree( udc_controller) ;
udc_controller = NULL ;
return ret; }
|