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; } |