zoukankan      html  css  js  c++  java
  • MTK OTG 流程

    一、注册mt_usb驱动

    kernel-3.18/drivers/misc/mediatek/usb20/mt6735/usb20.c

    static int __init usb20_init(void)
    {
        DBG(0, "usb20 init
    ");
    
    #ifdef CONFIG_MTK_USB2JTAG_SUPPORT
        if (usb2jtag_mode()) {
            pr_err("[USB2JTAG] in usb2jtag mode, not to initialize usb driver
    ");
            return 0;
        }
    #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
    "); */
            goto err0;
        }
    
        musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
            dev_err(&pdev->dev, "failed to allocate musb device
    ");
            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, 1);
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata) {
            dev_err(&pdev->dev, "failed to allocate musb platform data
    ");
            goto err2;
        }
    
        config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
        if (!config) {
            /* dev_err(&pdev->dev, "failed to allocate musb hdrc config
    "); */
            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
    ");
            if (ap_uart0_base)
                iounmap(ap_uart0_base);
            ap_uart0_base = 0;
        } else {
            ap_uart0_base = of_iomap(ap_uart0_node, 0);
        }
    #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
    ");
            goto err2;
        }
    
        ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
        if (ret) {
            dev_err(&pdev->dev, "failed to add platform_data
    ");
            goto err2;
        }
    
        ret = platform_device_add(musb);
    
        if (ret) {
            dev_err(&pdev->dev, "failed to register musb device
    ");
            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
    ");
            goto err2;
        }
    #ifdef CONFIG_OF
        DBG(0, "USB probe done!
    ");
    #endif
    
    #if defined(FPGA_PLATFORM) || defined(FOR_BRING_UP)
        musb_force_on = 1;
    #endif
        if (get_boot_mode() == META_BOOT) {
            DBG(0, "in special mode %d
    ", get_boot_mode());
            musb_force_on = 1;
        }
    
        return 0;
    
    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 = 0;
    
        /* enable uart log */
        musb_uart_debug = 1;
    
        DBG(0, "first_connect, check_delay_done to 0
    ");
        first_connect = 0;
        check_delay_done = 0;
    
        DBG(0, "set musb_connect_legacy to 0
    ");
        musb_connect_legacy = 0;
        DBG(0, "init connection_work
    ");
        INIT_DELAYED_WORK(&connection_work, do_connection_work);
        DBG(0, "keep musb->power & mtk_usb_power in the samae value
    ");
        mtk_usb_power = false;
    
    #ifndef CONFIG_MTK_CLKMGR
        musb_clk = devm_clk_get(&pdev->dev, "usb0");
        if (IS_ERR(musb_clk)) {
            DBG(0, KERN_WARNING "cannot get musb clock
    ");
            return PTR_ERR(musb_clk);
        }
        DBG(0, KERN_WARNING "get musb clock ok, prepare it
    ");
        retval = clk_prepare(musb_clk);
        if (retval == 0) {
            DBG(0, KERN_WARNING "prepare done
    ");
        } else {
            DBG(0, KERN_WARNING "prepare fail
    ");
            return retval;
        }
    #endif
    
        mt_usb_device.dev.of_node = pdev->dev.of_node;
        retval = platform_device_register(&mt_usb_device);
        if (retval != 0)
            DBG(0, "register musbfsh device fail!
    ");
    
        if (usb20_phy_init_debugfs())
            DBG(0, "usb20_phy_init_debugfs fail!
    ");
        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
    "); */
            goto err0;
        }
    
        musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
        if (!musb) {
            dev_err(&pdev->dev, "failed to allocate musb device
    ");
            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, 1);
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata) {
            dev_err(&pdev->dev, "failed to allocate musb platform data
    ");
            goto err2;
        }
    
        config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
        if (!config) {
            /* dev_err(&pdev->dev, "failed to allocate musb hdrc config
    "); */
            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
    ");
            if (ap_uart0_base)
                iounmap(ap_uart0_base);
            ap_uart0_base = 0;
        } else {
            ap_uart0_base = of_iomap(ap_uart0_node, 0);
        }
    #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
    ");
            goto err2;
        }
    
        ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
        if (ret) {
            dev_err(&pdev->dev, "failed to add platform_data
    ");
            goto err2;
        }
    
        ret = platform_device_add(musb);
    
        if (ret) {
            dev_err(&pdev->dev, "failed to register musb device
    ");
            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
    ");
            goto err2;
        }
    #ifdef CONFIG_OF
        DBG(0, "USB probe done!
    ");
    #endif
    
    #if defined(FPGA_PLATFORM) || defined(FOR_BRING_UP)
        musb_force_on = 1;
    #endif
        if (get_boot_mode() == META_BOOT) {
            DBG(0, "in special mode %d
    ", get_boot_mode());
            musb_force_on = 1;
        }
    
        return 0;
    
    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(0, "mt_usb_init
    ");
    
        usb_phy_generic_register();
        musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
    
        if (IS_ERR_OR_NULL(musb->xceiv)) {
            DBG(0, "[MUSB] usb_get_phy error!!
    ");
            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 = 8 * 1024;
    
        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(0, "enable VBUS LDO
    ");
    #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 < 0)
                DBG(0, "regulator set vol failed: %d
    ", ret);
            else
                DBG(0, "regulator set vol ok, <%d,%d>
    ", VUSB33_VOL_MIN, VUSB33_VOL_MAX);
            ret = regulator_enable(reg);
            if (ret < 0) {
                DBG(0, "regulator_enable failed: %d
    ", ret);
                regulator_put(reg);
            } else {
                DBG(0, "enable USB regulator
    ");
            }
        } else {
            DBG(0, "regulator_get failed
    ");
        }
    #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(0, "musb platform init %x
    ", 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 0;
    }

    五、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(0, "in special mode %d
    ", 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
    ");
        } else {
            if (of_property_read_u32_index(usb_node, "iddig_gpio", 0, &iddig_pin)) {
                iddig_if_config = 0;
                pr_err("get dtsi iddig_pin fail
    ");
            }
            if (of_property_read_u32_index(usb_node, "iddig_gpio", 1, &iddig_pin_mode))
                pr_err("get dtsi iddig_pin_mode fail
    ");
            }
    
        #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!
    ");
        }
        #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 = 0;
        otg_state.state = 0;
    
        if (switch_dev_register(&otg_state))
            pr_err("switch_dev_register fail
    ");
        else
            pr_debug("switch_dev register success
    ");
    }

    2. otg中断初始化

    static void otg_int_init(void)
    {
    #ifdef ID_PIN_USE_EX_EINT
        int    ret = 0;
    #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!!!!!
    ", __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
    ");
        }
    
        pinctrl_select_state(pinctrl, pinctrl_iddig);
    
        pr_debug("****%s:%d end Init IDDIG KS!!!!!
    ", __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, 64000);
        usb_iddig_number = mt_gpio_to_irq(IDDIG_EINT_PIN);
        pr_debug("USB IDDIG IRQ LINE %d, %d!!
    ", 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, 4000);    //64000
        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 > 0)
            pr_err("USB IDDIG IRQ LINE not available!!
    ");
        else
            pr_debug("USB IDDIG IRQ LINE available!!
    ");
    #else
        u32 phy_id_pull = 0;
    
        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(0, "id pin interrupt assert
    ");
        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 = 0;
        int temp1,temp2;
        unsigned long flags;
        static int inited, timeout; /* default to 0 */
        static DEFINE_RATELIMIT_STATE(ratelimit, 1 * HZ, 3);
        static s64 diff_time;
        int val = -1;
    
        /* 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(0, "init_done:%d, is_ready:%d, inited:%d, TO:%d, diff:%lld
    ",
                        kernel_init_done, mtk_musb->is_ready, inited, timeout,
                        diff_time);
            }
    
            if (diff_time > ID_PIN_WORK_BLOCK_TIMEOUT) {
                DBG(0, "diff_time:%lld
    ", diff_time);
                timeout = 1;
            }
    
            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(0, "PASS, init_done:%d, is_ready:%d, inited:%d, TO:%d
    ",
                    kernel_init_done,  mtk_musb->is_ready, inited, timeout);
        }
    
        inited = 1;
    
        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(0, "work start, is_host=%d
    ", mtk_musb->is_host);
    
        if (mtk_musb->in_ipo_off) {
            DBG(0, "do nothing due to in_ipo_off
    ");
            goto out;
        }
    
        while(1){
            mtk_musb->is_host = musb_is_host();
            temp1 = mtk_musb->is_host;
            msleep(5);
            mtk_musb->is_host = musb_is_host();
            temp2 = mtk_musb->is_host;
            printk("temp1=%d; temp2=%d!!!
    ", temp1, temp2);
    
            if(temp1 == temp2)
                break;
            }
        DBG(0, "musb is as %s
    ", 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!!!
    ");
            /* 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, 1);
                msleep(1);
                val = fan5405_get_boost_status();
                printk("lucky debug host boost state=%d!!!
    ", val);
            }while(val != 1);
            
            //OTG mode should close red light
            gpio_direction_output(red_led_en, 1);
            gpio_direction_output(red_led_en1, 0);
        /* for no VBUS sensing IP*/
        #if 1
            /* wait VBUS ready */
            msleep(100);
            /* 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(0, "force PHY to idle, 0x6d=%x, 0x6c=%x
    ", USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
            /* wait */
            mdelay(5);
            /* 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(0, "force PHY to host mode, 0x6d=%x, 0x6c=%x
    ", 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, 0);
        } else {
            /* for device no disconnect interrupt */
            printk("#######################device!!!
    ");
            spin_lock_irqsave(&mtk_musb->lock, flags);
            if (mtk_musb->is_active) {
                DBG(0, "for not receiving disconnect interrupt
    ");
                usb_hcd_resume_root_hub(musb_to_hcd(mtk_musb));
                musb_root_disconnect(mtk_musb);
            }
            spin_unlock_irqrestore(&mtk_musb->lock, flags);
    
            DBG(0, "devctl is %x
    ", musb_readb(mtk_musb->mregs, MUSB_DEVCTL));
            musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);
            if (wake_lock_active(&mtk_musb->usb_lock))
                wake_unlock(&mtk_musb->usb_lock);
            
            do{
                mt_usb_set_vbus(mtk_musb, 0);
                msleep(1);
                val = fan5405_get_boost_status();
                printk("lucky debug dev boost state=%d!!!
    ", val);
            }while(val != 0);
            
            //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(0, "force PHY to idle, 0x6d=%x, 0x6c=%x
    ", 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(0, "work end, is_host=%d
    ", mtk_musb->is_host);
        up(&mtk_musb->musb_lock);
    
    }
  • 相关阅读:
    tomcat 乱码问题
    mongo获取lbs数据
    sping mvc+uploadify 上传文件大小控制3部曲
    jstack 查看线程状态
    nginx 限流配置
    查找占用CPU高线程
    redis sentinel无法启动问题
    GC垃圾回收机制
    ASP.NET 生命周期
    Javascript验证手机号码正则表达式
  • 原文地址:https://www.cnblogs.com/jiangjh/p/10195928.html
Copyright © 2011-2022 走看看