一、注册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);
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章