MTK OTG 流程
一、注册mt_usb驱动
kernel-3.18/drivers/misc/mediatek/usb20/mt6735/usb20.c
static int __init usb20_init(void)
{
DBG(, "usb20 init\n"); #ifdef CONFIG_MTK_USB2JTAG_SUPPORT
if (usb2jtag_mode()) {
pr_err("[USB2JTAG] in usb2jtag mode, not to initialize usb driver\n");
return ;
}
#endif #ifdef FPGA_PLATFORM
add_usb_i2c_driver();
#endif
platform_driver_register(&mt_usb_driver);
return platform_driver_register(&mt_usb_dts_driver);
}
fs_initcall(usb20_init);
mt_usb_driver定义如下:
static struct platform_driver mt_usb_driver = {
.remove = mt_usb_remove,
.probe = mt_usb_probe,
.driver = {
.name = "mt_usb",
},
};
mt_usb_probe负责初始化mt_usb设备,mt_usb_probe在mt_usb设备注册时会通过设备模型被调用
static int mt_usb_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct platform_device *musb;
struct mt_usb_glue *glue;
#ifdef CONFIG_OF
struct musb_hdrc_config *config;
struct device_node *np = pdev->dev.of_node;
#endif
#ifdef CONFIG_MTK_UART_USB_SWITCH
struct device_node *ap_uart0_node = NULL;
#endif
int ret = -ENOMEM; glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
/* dev_err(&pdev->dev, "failed to allocate glue context\n"); */
goto err0;
} musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1;
}
#ifdef CONFIG_OF
dts_np = pdev->dev.of_node; /* usb_irq_number1 = irq_of_parse_and_map(pdev->dev.of_node, 0); */
usb_phy_base = (unsigned long)of_iomap(pdev->dev.of_node, );
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev, "failed to allocate musb platform data\n");
goto err2;
} config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
if (!config) {
/* dev_err(&pdev->dev, "failed to allocate musb hdrc config\n"); */
goto err2;
}
#ifdef CONFIG_USB_MTK_OTG
pdata->mode = MUSB_OTG;
#else
of_property_read_u32(np, "mode", (u32 *) &pdata->mode);
#endif #ifdef CONFIG_MTK_UART_USB_SWITCH
ap_uart0_node = of_find_compatible_node(NULL, NULL, AP_UART0_COMPATIBLE_NAME); if (ap_uart0_node == NULL) {
dev_err(&pdev->dev, "USB get ap_uart0_node failed\n");
if (ap_uart0_base)
iounmap(ap_uart0_base);
ap_uart0_base = ;
} else {
ap_uart0_base = of_iomap(ap_uart0_node, );
}
#endif of_property_read_u32(np, "num_eps", (u32 *) &config->num_eps);
config->multipoint = of_property_read_bool(np, "multipoint"); /* deprecated on musb.h, mark it to reduce build warning */
#if 0
of_property_read_u32(np, "dma_channels", (u32 *) &config->dma_channels);
config->dyn_fifo = of_property_read_bool(np, "dyn_fifo");
config->soft_con = of_property_read_bool(np, "soft_con");
config->dma = of_property_read_bool(np, "dma");
#endif pdata->config = config;
#endif musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &mt_usb_dmamask;
musb->dev.coherent_dma_mask = mt_usb_dmamask;
#ifdef CONFIG_OF
pdev->dev.dma_mask = &mt_usb_dmamask;
pdev->dev.coherent_dma_mask = mt_usb_dmamask;
#endif glue->dev = &pdev->dev;
glue->musb = musb; pdata->platform_ops = &mt_usb_ops; platform_set_drvdata(pdev, glue); ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources);
if (ret) {
dev_err(&pdev->dev, "failed to add resources\n");
goto err2;
} ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n");
goto err2;
} ret = platform_device_add(musb); if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
goto err2;
} ret = device_create_file(&pdev->dev, &dev_attr_cmode);
ret = device_create_file(&pdev->dev, &dev_attr_saving);
#ifdef CONFIG_MTK_UART_USB_SWITCH
ret = device_create_file(&pdev->dev, &dev_attr_portmode);
ret = device_create_file(&pdev->dev, &dev_attr_tx);
ret = device_create_file(&pdev->dev, &dev_attr_rx);
ret = device_create_file(&pdev->dev, &dev_attr_uartpath);
#endif if (ret) {
dev_err(&pdev->dev, "failed to create musb device\n");
goto err2;
}
#ifdef CONFIG_OF
DBG(, "USB probe done!\n");
#endif #if defined(FPGA_PLATFORM) || defined(FOR_BRING_UP)
musb_force_on = ;
#endif
if (get_boot_mode() == META_BOOT) {
DBG(, "in special mode %d\n", get_boot_mode());
musb_force_on = ;
} return ; err2:
platform_device_put(musb); err1:
kfree(glue); err0:
return ret;
}
二、mt_usb设备在哪里注册
在usb20_init函数中mt_usb驱动注册之后,紧接着又注册了mt_usb_dts驱动
static struct platform_driver mt_usb_dts_driver = {
.remove = mt_usb_dts_remove,
.probe = mt_usb_dts_probe,
.driver = {
.name = "mt_dts_usb",
#ifdef CONFIG_OF
.of_match_table = apusb_of_ids,
#endif
},
};
当系统启动之后,解析设备树,当满足apusb_of_ids时候就会调用mt_usb_dts_probe函数
static int mt_usb_dts_probe(struct platform_device *pdev)
{
int retval = ; /* enable uart log */
musb_uart_debug = ; DBG(, "first_connect, check_delay_done to 0\n");
first_connect = ;
check_delay_done = ; DBG(, "set musb_connect_legacy to 0\n");
musb_connect_legacy = ;
DBG(, "init connection_work\n");
INIT_DELAYED_WORK(&connection_work, do_connection_work);
DBG(, "keep musb->power & mtk_usb_power in the samae value\n");
mtk_usb_power = false; #ifndef CONFIG_MTK_CLKMGR
musb_clk = devm_clk_get(&pdev->dev, "usb0");
if (IS_ERR(musb_clk)) {
DBG(, KERN_WARNING "cannot get musb clock\n");
return PTR_ERR(musb_clk);
}
DBG(, KERN_WARNING "get musb clock ok, prepare it\n");
retval = clk_prepare(musb_clk);
if (retval == ) {
DBG(, KERN_WARNING "prepare done\n");
} else {
DBG(, KERN_WARNING "prepare fail\n");
return retval;
}
#endif mt_usb_device.dev.of_node = pdev->dev.of_node;
retval = platform_device_register(&mt_usb_device);
if (retval != )
DBG(, "register musbfsh device fail!\n"); if (usb20_phy_init_debugfs())
DBG(, "usb20_phy_init_debugfs fail!\n");
return retval; }
三、初始化mt_usb设备
mt_usb_dts_probe函数中调用platform_device_register(&mt_usb_device); 根据Linux设备模型,此处会match到mt_usb_driver,调用mt_usb_probe函数
static int mt_usb_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
struct platform_device *musb;
struct mt_usb_glue *glue;
#ifdef CONFIG_OF
struct musb_hdrc_config *config;
struct device_node *np = pdev->dev.of_node;
#endif
#ifdef CONFIG_MTK_UART_USB_SWITCH
struct device_node *ap_uart0_node = NULL;
#endif
int ret = -ENOMEM; glue = kzalloc(sizeof(*glue), GFP_KERNEL);
if (!glue) {
/* dev_err(&pdev->dev, "failed to allocate glue context\n"); */
goto err0;
} musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
if (!musb) {
dev_err(&pdev->dev, "failed to allocate musb device\n");
goto err1;
}
#ifdef CONFIG_OF
dts_np = pdev->dev.of_node; /* usb_irq_number1 = irq_of_parse_and_map(pdev->dev.of_node, 0); */
usb_phy_base = (unsigned long)of_iomap(pdev->dev.of_node, );
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev, "failed to allocate musb platform data\n");
goto err2;
} config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
if (!config) {
/* dev_err(&pdev->dev, "failed to allocate musb hdrc config\n"); */
goto err2;
}
#ifdef CONFIG_USB_MTK_OTG
pdata->mode = MUSB_OTG;
#else
of_property_read_u32(np, "mode", (u32 *) &pdata->mode);
#endif #ifdef CONFIG_MTK_UART_USB_SWITCH
ap_uart0_node = of_find_compatible_node(NULL, NULL, AP_UART0_COMPATIBLE_NAME); if (ap_uart0_node == NULL) {
dev_err(&pdev->dev, "USB get ap_uart0_node failed\n");
if (ap_uart0_base)
iounmap(ap_uart0_base);
ap_uart0_base = ;
} else {
ap_uart0_base = of_iomap(ap_uart0_node, );
}
#endif of_property_read_u32(np, "num_eps", (u32 *) &config->num_eps);
config->multipoint = of_property_read_bool(np, "multipoint"); /* deprecated on musb.h, mark it to reduce build warning */
#if 0
of_property_read_u32(np, "dma_channels", (u32 *) &config->dma_channels);
config->dyn_fifo = of_property_read_bool(np, "dyn_fifo");
config->soft_con = of_property_read_bool(np, "soft_con");
config->dma = of_property_read_bool(np, "dma");
#endif pdata->config = config;
#endif musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &mt_usb_dmamask;
musb->dev.coherent_dma_mask = mt_usb_dmamask;
#ifdef CONFIG_OF
pdev->dev.dma_mask = &mt_usb_dmamask;
pdev->dev.coherent_dma_mask = mt_usb_dmamask;
#endif glue->dev = &pdev->dev;
glue->musb = musb; pdata->platform_ops = &mt_usb_ops; platform_set_drvdata(pdev, glue); ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources);
if (ret) {
dev_err(&pdev->dev, "failed to add resources\n");
goto err2;
} ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
if (ret) {
dev_err(&pdev->dev, "failed to add platform_data\n");
goto err2;
} ret = platform_device_add(musb); if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
goto err2;
} ret = device_create_file(&pdev->dev, &dev_attr_cmode);
ret = device_create_file(&pdev->dev, &dev_attr_saving);
#ifdef CONFIG_MTK_UART_USB_SWITCH
ret = device_create_file(&pdev->dev, &dev_attr_portmode);
ret = device_create_file(&pdev->dev, &dev_attr_tx);
ret = device_create_file(&pdev->dev, &dev_attr_rx);
ret = device_create_file(&pdev->dev, &dev_attr_uartpath);
#endif if (ret) {
dev_err(&pdev->dev, "failed to create musb device\n");
goto err2;
}
#ifdef CONFIG_OF
DBG(, "USB probe done!\n");
#endif #if defined(FPGA_PLATFORM) || defined(FOR_BRING_UP)
musb_force_on = ;
#endif
if (get_boot_mode() == META_BOOT) {
DBG(, "in special mode %d\n", get_boot_mode());
musb_force_on = ;
} return ; err2:
platform_device_put(musb); err1:
kfree(glue); err0:
return ret;
}
static const struct musb_platform_ops mt_usb_ops = {
.init = mt_usb_init,
.exit = mt_usb_exit,
/*.set_mode = mt_usb_set_mode, */
.try_idle = mt_usb_try_idle,
.enable = mt_usb_enable,
.disable = mt_usb_disable,
.set_vbus = mt_usb_set_vbus,
.vbus_status = mt_usb_get_vbus_status
};
四、mt_usb具体初始化过程
mt_usb设备被初始化成一个很大的数据机构struct musb,初始过程就是对该struct musb结构初始化
static int mt_usb_init(struct musb *musb)
{
#ifndef CONFIG_MTK_LEGACY
int ret;
#endif
DBG(, "mt_usb_init\n"); usb_phy_generic_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) {
DBG(, "[MUSB] usb_get_phy error!!\n");
return -EPROBE_DEFER;
}
#ifdef CONFIG_OF
/* musb->nIrq = usb_irq_number1; */
#else
musb->nIrq = USB_MCU_IRQ_BIT1_ID;
#endif
musb->dma_irq = (int)SHARE_IRQ;
musb->fifo_cfg = fifo_cfg;
musb->fifo_cfg_size = ARRAY_SIZE(fifo_cfg);
musb->dyn_fifo = true;
musb->power = false;
musb->is_host = false;
musb->fifo_size = * ; wake_lock_init(&musb->usb_lock, WAKE_LOCK_SUSPEND, "USB suspend lock"); #ifndef FPGA_PLATFORM
#ifdef CONFIG_ARCH_MT6735
INIT_WORK(&vcore_work, do_vcore_work);
vcore_wq = create_singlethread_workqueue("usb20_vcore_work");
INIT_LIST_HEAD(&vcore_req_free_pool);
INIT_LIST_HEAD(&vcore_req_execute_pool);
#endif
#endif #ifndef FPGA_PLATFORM
#ifdef CONFIG_MTK_LEGACY
hwPowerOn(MT6328_POWER_LDO_VUSB33, VOL_3300, "VUSB_LDO");
DBG(, "enable VBUS LDO\n");
#else
reg = regulator_get(musb->controller, "vusb33");
if (!IS_ERR(reg)) {
#define VUSB33_VOL_MIN 3300000
#define VUSB33_VOL_MAX 3300000
ret = regulator_set_voltage(reg, VUSB33_VOL_MIN, VUSB33_VOL_MAX);
if (ret < )
DBG(, "regulator set vol failed: %d\n", ret);
else
DBG(, "regulator set vol ok, <%d,%d>\n", VUSB33_VOL_MIN, VUSB33_VOL_MAX);
ret = regulator_enable(reg);
if (ret < ) {
DBG(, "regulator_enable failed: %d\n", ret);
regulator_put(reg);
} else {
DBG(, "enable USB regulator\n");
}
} else {
DBG(, "regulator_get failed\n");
}
#endif
#endif /* mt_usb_enable(musb); */ musb->isr = mt_usb_interrupt;
musb_writel(musb->mregs, MUSB_HSDMA_INTR, 0xff | (0xff << DMA_INTR_UNMASK_SET_OFFSET));
DBG(, "musb platform init %x\n", musb_readl(musb->mregs, MUSB_HSDMA_INTR)); #ifdef MUSB_QMU_SUPPORT
/* FIXME, workaround for device_qmu + host_dma */
musb_writel(musb->mregs, USB_L1INTM,
TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS | DMA_INT_STATUS |
QINT_STATUS);
#else
musb_writel(musb->mregs, USB_L1INTM,
TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS | DMA_INT_STATUS);
#endif setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long)musb); #ifdef CONFIG_USB_MTK_OTG
mt_usb_otg_init(musb);
#endif return ;
}
五、OTG设备初始化与OTG中断处理
1. OTG初始化
void mt_usb_otg_init(struct musb *musb)
{
/* BYPASS OTG function in special mode */
if (get_boot_mode() == META_BOOT
#ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING
|| get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT
|| get_boot_mode() == LOW_POWER_OFF_CHARGING_BOOT
#endif
) {
DBG(, "in special mode %d\n", get_boot_mode());
return;
} /* test */
host_plug_test_wq = create_singlethread_workqueue("host_plug_test_wq");
INIT_DELAYED_WORK(&host_plug_test_work, do_host_plug_test_work); #ifdef CONFIG_OF
usb_node = of_find_compatible_node(NULL, NULL, "mediatek,mt6735-usb20");
if (usb_node == NULL) {
pr_err("USB OTG - get USB0 node failed\n");
} else {
if (of_property_read_u32_index(usb_node, "iddig_gpio", , &iddig_pin)) {
iddig_if_config = ;
pr_err("get dtsi iddig_pin fail\n");
}
if (of_property_read_u32_index(usb_node, "iddig_gpio", , &iddig_pin_mode))
pr_err("get dtsi iddig_pin_mode fail\n");
} #if !defined(CONFIG_MTK_LEGACY)
pinctrl = devm_pinctrl_get(mtk_musb->controller);
if (IS_ERR(pinctrl)) {
dev_err(mtk_musb->controller, "Cannot find usb pinctrl!\n");
}
#endif
#endif /* init idpin interrupt */
ktime_start = ktime_get();
INIT_DELAYED_WORK(&musb->id_pin_work, musb_id_pin_work);
otg_int_init(); /* EP table */
musb->fifo_cfg_host = fifo_cfg_host;
musb->fifo_cfg_host_size = ARRAY_SIZE(fifo_cfg_host); otg_state.name = "otg_state";
otg_state.index = ;
otg_state.state = ; if (switch_dev_register(&otg_state))
pr_err("switch_dev_register fail\n");
else
pr_debug("switch_dev register success\n");
}
2. otg中断初始化
static void otg_int_init(void)
{
#ifdef ID_PIN_USE_EX_EINT
int ret = ;
#ifndef CONFIG_MTK_FPGA
#ifdef CONFIG_OF
#if defined(CONFIG_MTK_LEGACY)
mt_set_gpio_mode(iddig_pin, iddig_pin_mode);
mt_set_gpio_dir(iddig_pin, GPIO_DIR_IN);
mt_set_gpio_pull_enable(iddig_pin, GPIO_PULL_ENABLE);
mt_set_gpio_pull_select(iddig_pin, GPIO_PULL_UP);
#else
pr_debug("****%s:%d before Init IDDIG KS!!!!!\n", __func__, __LINE__); pinctrl_iddig = pinctrl_lookup_state(pinctrl, "iddig_irq_init");
if (IS_ERR(pinctrl_iddig)) {
ret = PTR_ERR(pinctrl_iddig);
dev_err(mtk_musb->controller, "Cannot find usb pinctrl iddig_irq_init\n");
} pinctrl_select_state(pinctrl, pinctrl_iddig); pr_debug("****%s:%d end Init IDDIG KS!!!!!\n", __func__, __LINE__);
#endif
#else
mt_set_gpio_mode(GPIO_OTG_IDDIG_EINT_PIN, GPIO_OTG_IDDIG_EINT_PIN_M_IDDIG);
mt_set_gpio_dir(GPIO_OTG_IDDIG_EINT_PIN, GPIO_DIR_IN);
mt_set_gpio_pull_enable(GPIO_OTG_IDDIG_EINT_PIN, GPIO_PULL_ENABLE);
mt_set_gpio_pull_select(GPIO_OTG_IDDIG_EINT_PIN, GPIO_PULL_UP);
#endif
#endif
#if defined(CONFIG_MTK_LEGACY)
mt_gpio_set_debounce(IDDIG_EINT_PIN, );
usb_iddig_number = mt_gpio_to_irq(IDDIG_EINT_PIN);
pr_debug("USB IDDIG IRQ LINE %d, %d!!\n", IDDIG_EINT_PIN, mt_gpio_to_irq(IDDIG_EINT_PIN));
ret = request_irq(usb_iddig_number, mt_usb_ext_iddig_int, IRQF_TRIGGER_LOW, "USB_IDDIG", NULL);
#else
/*gpio_request(iddig_pin, "USB_IDDIG");*/
gpio_direction_input(iddig_pin);
gpio_set_debounce(iddig_pin, ); //
usb_iddig_number = mt_gpio_to_irq(iddig_pin);
ret = request_irq(usb_iddig_number, mt_usb_ext_iddig_int, IRQF_TRIGGER_LOW, "USB_IDDIG", NULL);
#endif
if (ret > )
pr_err("USB IDDIG IRQ LINE not available!!\n");
else
pr_debug("USB IDDIG IRQ LINE available!!\n");
#else
u32 phy_id_pull = ; phy_id_pull = __raw_readl(U2PHYDTM1);
phy_id_pull |= ID_PULL_UP;
__raw_writel(phy_id_pull, U2PHYDTM1); musb_writel(mtk_musb->mregs, USB_L1INTM, IDDIG_INT_STATUS|musb_readl(mtk_musb->mregs, USB_L1INTM));
#endif
}
3. otg中断处理
当otg插入或拔出,产生中断时,会调用otg_int_init函数中注册的mt_usb_ext_iddig_int函数
static irqreturn_t mt_usb_ext_iddig_int(int irq, void *dev_id)
{
iddig_cnt++; queue_delayed_work(mtk_musb->st_wq, &mtk_musb->id_pin_work, msecs_to_jiffies(sw_deboun_time));
DBG(, "id pin interrupt assert\n");
disable_irq_nosync(usb_iddig_number);
return IRQ_HANDLED;
}
4. 中断处理函数唤醒之前注册的id_pin_work
mtk_musb->id_pin_work在mt_usb_otg_init函数中注册
INIT_DELAYED_WORK(&musb->id_pin_work, musb_id_pin_work);
static void musb_id_pin_work(struct work_struct *data)
{
u8 devctl = ;
int temp1,temp2;
unsigned long flags;
static int inited, timeout; /* default to 0 */
static DEFINE_RATELIMIT_STATE(ratelimit, * HZ, );
static s64 diff_time;
int val = -; /* kernel_init_done should be set in early-init stage through init.$platform.usb.rc */
if (!inited && !kernel_init_done && !mtk_musb->is_ready && !timeout) {
ktime_end = ktime_get();
diff_time = ktime_to_ms(ktime_sub(ktime_end, ktime_start));
if (__ratelimit(&ratelimit)) {
DBG(, "init_done:%d, is_ready:%d, inited:%d, TO:%d, diff:%lld\n",
kernel_init_done, mtk_musb->is_ready, inited, timeout,
diff_time);
} if (diff_time > ID_PIN_WORK_BLOCK_TIMEOUT) {
DBG(, "diff_time:%lld\n", diff_time);
timeout = ;
} queue_delayed_work(mtk_musb->st_wq, &mtk_musb->id_pin_work, msecs_to_jiffies(ID_PIN_WORK_RECHECK_TIME));
return;
} else if (!inited) {
DBG(, "PASS, init_done:%d, is_ready:%d, inited:%d, TO:%d\n",
kernel_init_done, mtk_musb->is_ready, inited, timeout);
} inited = ; spin_lock_irqsave(&mtk_musb->lock, flags);
musb_generic_disable(mtk_musb);
spin_unlock_irqrestore(&mtk_musb->lock, flags); down(&mtk_musb->musb_lock);
DBG(, "work start, is_host=%d\n", mtk_musb->is_host); if (mtk_musb->in_ipo_off) {
DBG(, "do nothing due to in_ipo_off\n");
goto out;
} while(){
mtk_musb->is_host = musb_is_host();
temp1 = mtk_musb->is_host;
msleep();
mtk_musb->is_host = musb_is_host();
temp2 = mtk_musb->is_host;
printk("temp1=%d; temp2=%d!!!\n", temp1, temp2); if(temp1 == temp2)
break;
}
DBG(, "musb is as %s\n", mtk_musb->is_host?"host":"device");
switch_set_state((struct switch_dev *)&otg_state, mtk_musb->is_host); if (mtk_musb->is_host) {
printk("#######################host!!!\n");
/* setup fifo for host mode */
ep_config_from_table_for_host(mtk_musb);
wake_lock(&mtk_musb->usb_lock); do{
mt_usb_set_vbus(mtk_musb, );
msleep();
val = fan5405_get_boost_status();
printk("lucky debug host boost state=%d!!!\n", val);
}while(val != ); //OTG mode should close red light
gpio_direction_output(red_led_en, );
gpio_direction_output(red_led_en1, );
/* for no VBUS sensing IP*/
#if 1
/* wait VBUS ready */
msleep();
/* clear session*/
devctl = musb_readb(mtk_musb->mregs, MUSB_DEVCTL);
musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, (devctl&(~MUSB_DEVCTL_SESSION)));
/* USB MAC OFF*/
/* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=X, IDPULLUP=1 */
USBPHY_SET8(0x6c, 0x11);
USBPHY_CLR8(0x6c, 0x2e);
USBPHY_SET8(0x6d, 0x3f);
DBG(, "force PHY to idle, 0x6d=%x, 0x6c=%x\n", USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
/* wait */
mdelay();
/* restart session */
devctl = musb_readb(mtk_musb->mregs, MUSB_DEVCTL);
musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, (devctl | MUSB_DEVCTL_SESSION));
/* USB MAC ONand Host Mode*/
/* VBUSVALID=1, AVALID=1, BVALID=1, SESSEND=0, IDDIG=0, IDPULLUP=1 */
USBPHY_CLR8(0x6c, 0x10);
USBPHY_SET8(0x6c, 0x2d);
USBPHY_SET8(0x6d, 0x3f);
DBG(, "force PHY to host mode, 0x6d=%x, 0x6c=%x\n", USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
#endif musb_start(mtk_musb);
MUSB_HST_MODE(mtk_musb);
switch_int_to_device(mtk_musb); if (host_plug_test_enable && !host_plug_test_triggered)
queue_delayed_work(host_plug_test_wq, &host_plug_test_work, );
} else {
/* for device no disconnect interrupt */
printk("#######################device!!!\n");
spin_lock_irqsave(&mtk_musb->lock, flags);
if (mtk_musb->is_active) {
DBG(, "for not receiving disconnect interrupt\n");
usb_hcd_resume_root_hub(musb_to_hcd(mtk_musb));
musb_root_disconnect(mtk_musb);
}
spin_unlock_irqrestore(&mtk_musb->lock, flags); DBG(, "devctl is %x\n", musb_readb(mtk_musb->mregs, MUSB_DEVCTL));
musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, );
if (wake_lock_active(&mtk_musb->usb_lock))
wake_unlock(&mtk_musb->usb_lock); do{
mt_usb_set_vbus(mtk_musb, );
msleep();
val = fan5405_get_boost_status();
printk("lucky debug dev boost state=%d!!!\n", val);
}while(val != ); //OTG out recover
//gpio_direction_output(red_led_en, 0);
//gpio_direction_output(red_led_en1, 0);
/* for no VBUS sensing IP */
#if 1
/* USB MAC OFF*/
/* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=X, IDPULLUP=1 */
USBPHY_SET8(0x6c, 0x11);
USBPHY_CLR8(0x6c, 0x2e);
USBPHY_SET8(0x6d, 0x3f);
DBG(, "force PHY to idle, 0x6d=%x, 0x6c=%x\n", USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
#endif musb_stop(mtk_musb);
mtk_musb->xceiv->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(mtk_musb);
switch_int_to_host(mtk_musb);
}
out:
DBG(, "work end, is_host=%d\n", mtk_musb->is_host);
up(&mtk_musb->musb_lock); }
MTK OTG 流程的更多相关文章
- MTK touchscreen 流程
1. kernel-3.18/drivers/input/touchscreen/mediatek/tpd_common_probe.c static int __init tpd_probe_ini ...
- MTK HDMI 流程
一.HDMI初始化 1. kernel-3.18/drivers/misc/mediatek/ext_disp/mtk_extd_mgr.c static int __init mtk_extd_mg ...
- android MTK驱动背光唤醒流程
在标准的android驱动中,睡眠唤醒流程非常清晰,能够较方便的更改lcd唤醒时间和led背光的点亮时间,但是也很容易出现问题,比如说闪屏,唤醒慢! 出现闪屏有两个原因 1. 开背光时间在唤醒lcd前 ...
- MTK Camera 开机启动流程(转载)
一.MTK平台Camera框架 MTK平台的Camera的架构见下图, 这里主要介绍kernel部分和HAL层部分. 1.Kernel 部分主要有两块: 1.1.image sensordriver, ...
- andorid之摄像头驱动流程--MTK平台
原文地址:andorid之摄像头驱动流程--MTK平台 作者:守候心田 camera成像原理: 景物通过镜头生产光学图像投射到sensor表面上,然后转为模拟电信号,经过数模变成数字图像信号,在经过D ...
- 居于mtk芯片安卓车机系统具体流程
一:车机系统框架 MCU 功能 电源控制 Radio 控制(RDS) 按键检测(Panel/Remote/SW) 常见信号检查(倒车/大灯/刹车) CAN 模块通讯 ARM- ...
- MTK camera 闪光灯Flashlight驱动调试流程
MTK camera 闪光灯Flashlight驱动调试流程 分类: MtkDev | 作者: topicdev 相关 | 发布日期 : 2014-09-26 | 热度 : 153° ...
- mtk lcm驱动加载流程 (转载)
平台:mt6582 + Android 4.4 前面就说过,在mtk代码中支持屏是可兼容的,通过调用驱动中的compare_id函数来匹配驱动和屏,这里来细看一下代码. 1. LK部分(mediate ...
- mtk 的conferrence call建立流程
(重点看main_log与) 抓mtk log: 1.*#*#82533284#*#* 进入抓log UI 2.*#*#825364#*#* 进入工程模式 3.进入"Lo ...
随机推荐
- PPAPI插件的动态创建、改动、删除
一旦你完毕了PPAPI插件的开发,实际使用时可能会有下列需求: 动态创建PPAPI插件 删除PPAPI插件 改变PPAPI插件的尺寸 实现起来非常easy,从JS里直接訪问DOM(BOM)就可以.以下 ...
- was系统错误日志大量出现标识符缺失
原创作品.出自 "深蓝的blog" 博客,深蓝的blog:http://blog.csdn.net/huangyanlong/article/details/46909941 近日 ...
- 【java读书笔记】——Collection集合之六大接口(Collection、Set、List、Map、Iterator和Comparable)
两个月之前准备软考时,简单的从理论上总结了最经常使用的数据结构和算法,比方:线性表,链表,图.在进行java开发时,jdk为我们提供了一系列对应的类来实现主要的数据结构.jdk所提供的容器API位于j ...
- Oracle 【to_number】【instr】
需求:对一个包含数字的字符串排序 search后参考了 http://www.cnblogs.com/m-cnblogs/archive/2012/03/30/2425938.html 截屏: (用 ...
- website link
error: template with C linkage http://blog.csdn.net/jiong_1988/article/details/7915420http://velep.c ...
- iOS移动开发周报-第17期
lhq iOS移动开发周报-第17期 前言 欢迎国内的iOS同行或技术作者向我提交周报线索,线索可以是新闻.教程.开发工具或开源项目,将相关文章的简介和链接在微博上发布并 @唐巧_boy 即可. [摘 ...
- Centos7-搭建hdfs启动时报java.net.BindException: Problem binding to [node01:9000] java.net.BindException异常
今天用阿里的服务器搭了个伪分布式的HDFS,格式化后启动hdfs,发现只有dataNode启动了,查看启动日志发现异常: 2019-01-22 15:54:50,507 FATAL org.apach ...
- 去除input框的值
onfocus="this.value=' ';" <input type="text" name="buynum" id=" ...
- 防止ViewPager中的Fragment被销毁
pager.setOffscreenPageLimit(2); 就可以让ViewPager多缓存一个页面
- 查看客户端java日志
通过 Java 控制面板启用 Java 控制台 Windows 8 使用搜索来查找控制面板 按 Windows 徽标键 + W 以打开搜索框来搜索设置,或者将鼠标指针拖动到屏幕的右下角,然后单击搜索图 ...