MTK OTG 流程
阅读原文时间:2021年06月02日阅读:1

一、注册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);

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章