int usb_otg_start( struct platform_device pdev) { struct fsl_otg p_otg; /获得otg_transceiver结构 / struct otg_transceiver otg_trans = otg_get_transceiver( ) ; struct otg_fsm fsm; volatile unsigned long p; int status; struct resource res; u32 temp; /获得设备的私有数据/ struct fsl_usb2_platform_data pdata = pdev- > dev. platform_data; / 使用container_of宏定义可以通过结构中一个变量的指针获得该结构首地址 / p_otg = container_of( otg_trans, struct fsl_otg, otg) ; fsm = & p_otg- > fsm; / Initialize the state machine structure with default values / SET_OTG_STATE( otg_trans, OTG_STATE_UNDEFINED) ; fsm- > transceiver = & p_otg- > otg; / We don’t require predefined MEM/IRQ resource index / / 获得设备的资源,是在设备注册时结构体里面的内容/ res = platform_get_resource( pdev, IORESOURCE_MEM, 0) ; if ( ! res) return - ENXIO; / We don’t request_mem_region here to enable resource sharing with host/device / /通过资源中 获得的物理地址映射一个可以被驱动访问的虚拟地址指针/ usb_dr_regs = ioremap( res- > start, sizeof ( struct usb_dr_mmap) ) ; /将该指针保存到p_otg - > dr_mem_map中 / p_otg- > dr_mem_map = ( struct usb_dr_mmap ) usb_dr_regs; pdata- > regs = ( void ) usb_dr_regs; / request irq / /获得设备注册时候的中断并注册,在 OTG ID发生变化时触发中断,然后调用注册的中断例程函数,函数后面分析/ p_otg- > irq = platform_get_irq( pdev, 0) ; status = request_irq( p_otg- > irq, fsl_otg_isr, IRQF_SHARED, driver_name, p_otg) ; if ( status) { dev_dbg( p_otg- > otg. dev, “can’t get IRQ %d, error %d/n” , p_otg- > irq, status) ; iounmap( p_otg- > dr_mem_map) ; kfree( p_otg) ; return status; } if ( pdata- > platform_init & & pdata- > platform_init( pdev) ! = 0) return - EINVAL; / Export DR controller resources / /**/ int otg_set_resources(struct resource resources) { otg_resources = resources; return 0; } 和otg_set_transceiver功能类似将设备资源保存到一个全局变量中 /**/ otg_set_resources( pdev- > resource) ; / 开始配置USB寄存器/ / stop the controller / temp = readl( & p_otg- > dr_mem_map- > usbcmd) ; temp & = ~ USB_CMD_RUN_STOP; writel( temp, & p_otg- > dr_mem_map- > usbcmd) ; / reset the controller / temp = readl( & p_otg- > dr_mem_map- > usbcmd) ; temp | = USB_CMD_CTRL_RESET; writel( temp, & p_otg- > dr_mem_map- > usbcmd) ; / wait reset completed / while ( readl( & p_otg- > dr_mem_map- > usbcmd) & USB_CMD_CTRL_RESET) ; / configure the VBUSHS as IDLE(both host and device) / temp = USB_MODE_STREAM_DISABLE | ( pdata- > es ? USB_MODE_ES : 0) ; writel( temp, & p_otg- > dr_mem_map- > usbmode) ; / configure PHY interface / temp = readl( & p_otg- > dr_mem_map- > portsc) ; temp & = ~ ( PORTSC_PHY_TYPE_SEL | PORTSC_PTW) ; switch ( pdata- > phy_mode) { case FSL_USB2_PHY_ULPI: temp | = PORTSC_PTS_ULPI; break ; case FSL_USB2_PHY_UTMI_WIDE: temp | = PORTSC_PTW_16BIT; / fall through / case FSL_USB2_PHY_UTMI: temp | = PORTSC_PTS_UTMI; / fall through / default : break ; } writel( temp, & p_otg- > dr_mem_map- > portsc) ; if ( pdata- > have_sysif_regs) { / configure control enable IO output, big endian register / p = ( volatile unsigned long ) ( & p_otg- > dr_mem_map- > control) ; temp = p; temp | = USB_CTRL_IOENB; p = temp; } / disable all interrupt and clear all OTGSC status / temp = readl( & p_otg- > dr_mem_map- > otgsc) ; temp & = ~ OTGSC_INTERRUPT_ENABLE_BITS_MASK; temp | = OTGSC_INTERRUPT_STATUS_BITS_MASK | OTGSC_CTRL_VBUS_DISCHARGE; writel( temp, & p_otg- > dr_mem_map- > otgsc) ; / The identification (id) input is FALSE when a Mini-A plug is inserted in the devices Mini-AB receptacle. Otherwise, this input is TRUE. Also: record initial state of ID pin / if ( le32_to_cpu( p_otg- > dr_mem_map- > otgsc) & OTGSC_STS_USB_ID) { p_otg- > otg. state = OTG_STATE_UNDEFINED; p_otg- > fsm. id = 1; } else { p_otg- > otg. state = OTG_STATE_A_IDLE; p_otg- > fsm. id = 0; } DBG( “initial ID pin=%d/n” , p_otg- > fsm. id) ; / enable OTG ID pin interrupt */ temp = readl( & p_otg- > dr_mem_map- > otgsc) ; temp | = OTGSC_INTR_USB_ID_EN; temp & = ~ ( OTGSC_CTRL_VBUS_DISCHARGE | OTGSC_INTR_1MS_TIMER_EN) ; writel( temp, & p_otg- > dr_mem_map- > otgsc) ; return 0; } |
还没有评论,来说两句吧...