博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MSM8260 EHCI-MSM72k主控制器的状态机迁移分析
阅读量:4214 次
发布时间:2019-05-26

本文共 6204 字,大约阅读时间需要 20 分钟。

本分析基于android4.0.4代码,高通8260平台
//插入usb a cable前的状态是 OTG_STATE_B_IDLE
static void msm_otg_sm_work(struct work_struct *w)
{
    switch (state) {
        case OTG_STATE_UNDEFINED:
             {
                if (!dev->otg.host || !is_host())
                    set_bit(ID, &dev->inputs);//什么都不插入,初始化时会设置该位
                if (dev->otg.gadget && is_b_sess_vld())
                    set_bit(B_SESS_VLD, &dev->inputs);
            }
            spin_lock_irqsave(&dev->lock, flags);
            if ((test_bit(ID, &dev->inputs)) &&
                    !test_bit(ID_A, &dev->inputs)) {
                dev->otg.state = OTG_STATE_B_IDLE;//什么都不插入,初始化时的状态
            }
            work = 1;
            break;
        case OTG_STATE_B_IDLE:
        dev->otg.default_a = 0;
        ..............    
         else {//初始时,会停留在OTG_STATE_B_IDLE状态并睡眠
            msm_otg_set_power(&dev->otg, 0);
            pr_debug("entering into lpm\n");
            pr_info("%s: -->>entering into lpm.\n",__func__);
            msm_otg_put_suspend(dev);
            if (dev->pdata->ldo_set_voltage)
                dev->pdata->ldo_set_voltage(3075);
        }
        break;
    }
    if (work)
        queue_work(dev->wq, &dev->sm_work);
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------
//插入usb a cable前的状态是 OTG_STATE_B_IDLE
static void msm_otg_sm_work(struct work_struct *w)
{
    switch (state) {
        case OTG_STATE_B_IDLE:
            dev->otg.default_a = 0;
            if (!test_bit(ID, &dev->inputs) || test_bit(ID_A, &dev->inputs)) {//此时的id=0
                pr_debug("!id || id_A\n");
                clear_bit(B_BUS_REQ, &dev->inputs);
                otg_reset(&dev->otg, 0);
                spin_lock_irqsave(&dev->lock, flags);
                dev->otg.state = OTG_STATE_A_IDLE;//状态迁移到OTG_STATE_A_IDLE,迁移到a idle
                spin_unlock_irqrestore(&dev->lock, flags);
                msm_otg_set_power(&dev->otg, 0);
                work = 1;
            }
            break;
        //继续调度work
        case OTG_STATE_A_IDLE:
            dev->otg.default_a = 1;
            if (!test_bit(A_BUS_DROP, &dev->inputs) &&
                    (test_bit(A_SRP_DET, &dev->inputs) ||
                     test_bit(A_BUS_REQ, &dev->inputs))) {//A_BUS_REQ = 1
                pr_debug("!a_bus_drop && (a_srp_det || a_bus_req)\n");
                clear_bit(A_SRP_DET, &dev->inputs);
                /* Disable SRP detection */
                writel((readl(USB_OTGSC) & ~OTGSC_INTR_STS_MASK) &
                        ~OTGSC_DPIE, USB_OTGSC);
                spin_lock_irqsave(&dev->lock, flags);
                dev->otg.state = OTG_STATE_A_WAIT_VRISE;//状态迁移到OTG_STATE_A_WAIT_VRISE,等待电压达到a的门限
                spin_unlock_irqrestore(&dev->lock, flags);
                /* ACA: ID_A: Stop charging untill enumeration */
                if (test_bit(ID_A, &dev->inputs))
                    msm_otg_set_power(&dev->otg, 0);
                else
                    dev->pdata->vbus_power(USB_PHY_INTEGRATED, 1);
                msm_otg_start_timer(dev, TA_WAIT_VRISE, A_WAIT_VRISE);
                /* no need to schedule work now */
            }
            break;
        case OTG_STATE_A_WAIT_VRISE:
            if (test_bit(A_VBUS_VLD, &dev->inputs)) {
                    pr_debug("a_vbus_vld\n");
                    spin_lock_irqsave(&dev->lock, flags);
                    dev->otg.state = OTG_STATE_A_WAIT_BCON;//状态迁移到OTG_STATE_A_WAIT_BCON,等待外围设备插入
                    spin_unlock_irqrestore(&dev->lock, flags);
                    if (TA_WAIT_BCON > 0)
                        msm_otg_start_timer(dev, TA_WAIT_BCON,
                            A_WAIT_BCON);
                    /* Start HCD to detect peripherals. */
                    pr_info("%s:----------->>>>>>>>%d.\n",__func__,__LINE__);
                    msm_otg_start_host(&dev->otg, REQUEST_START);//在这里启动主机控制器
                }
            break;
        //插入usb a cable时状态迁移到此,下面分析插入u盘的状态迁移
        case OTG_STATE_A_WAIT_BCON:
             if (test_bit(B_CONN, &dev->inputs)) {
                    pr_debug("b_conn\n");
                    msm_otg_del_timer(dev);
                    /* HCD is added already. just move to
                     * A_HOST state.
                     */
                    spin_lock_irqsave(&dev->lock, flags);
                    dev->otg.state = OTG_STATE_A_HOST;//状态迁移到OTG_STATE_A_HOST,作为主机开始工作
                    spin_unlock_irqrestore(&dev->lock, flags);
                    if (test_bit(ID_A, &dev->inputs)) {
                        atomic_set(&dev->chg_type, USB_CHG_TYPE__SDP);
                        msm_otg_set_power(&dev->otg,
                            USB_IDCHG_MIN - get_aca_bmaxpower(dev));
                    }
                }
            break;
        //拔出u盘时
        case OTG_STATE_A_HOST:
             if (!test_bit(B_CONN, &dev->inputs)) {
                    pr_debug("!b_conn\n");
                    spin_lock_irqsave(&dev->lock, flags);
                    dev->otg.state = OTG_STATE_A_WAIT_BCON;//状态迁移到等待外围设备插入
                    spin_unlock_irqrestore(&dev->lock, flags);
                    if (TA_WAIT_BCON > 0)
                        msm_otg_start_timer(dev, TA_WAIT_BCON, A_WAIT_BCON);
                }
            break;
        //其中插入,拔出u盘触发的条件是通知链
        static int usbdev_notify(struct notifier_block *self,
                    unsigned long action, void *device)
        {
            enum usb_otg_state state;
            struct msm_otg *dev = container_of(self, struct msm_otg, usbdev_nb);
            struct usb_device *udev = device;
            int work = 1;
            spin_lock_irqsave(&dev->lock, flags);
            state = dev->otg.state;//当前的状态机状态
            spin_unlock_irqrestore(&dev->lock, flags);
            switch (state) {
            case OTG_STATE_A_WAIT_BCON:
                if (action == USB_DEVICE_ADD) {//u盘插入时会设置dev->inputs相应的位
                    pr_debug("B_CONN set\n");
                    set_bit(B_CONN, &dev->inputs);
                    ...........
                }
                break;
            case OTG_STATE_A_HOST:
                if (action == USB_DEVICE_REMOVE) {//u盘拔出时会清除dev->inputs相应的位
                    pr_debug("B_CONN clear\n");
                    clear_bit(B_CONN, &dev->inputs);
                    set_aca_bmaxpower(dev, 0);
                }
                break;
            default:
                work = 0;
                break;
            }
        do_work:
            if (work) {
                wake_lock(&dev->wlock);
                queue_work(dev->wq, &dev->sm_work);//调度work,改变状态机的迁移状态
            }
        }
        //拔掉hub时的状态
        case OTG_STATE_A_WAIT_BCON:
            if ((test_bit(ID, &dev->inputs) &&//拔出时id =1
                    !test_bit(ID_A, &dev->inputs)) ||
                    test_bit(A_BUS_DROP, &dev->inputs) ||
                    test_bit(A_WAIT_BCON, &dev->tmouts)) {
                pr_debug("id_f/b/c || a_bus_drop ||"
                        "a_wait_bcon_tmout\n");
                if (test_bit(A_WAIT_BCON, &dev->tmouts))
                    msm_otg_send_event(&dev->otg,
                        OTG_EVENT_DEV_CONN_TMOUT);
                msm_otg_del_timer(dev);
                clear_bit(A_BUS_REQ, &dev->inputs);
                msm_otg_start_host(&dev->otg, REQUEST_STOP);
                /* Reset both phy and link */
                otg_reset(&dev->otg, 1);
                /* ACA: ID_A with NO accessory, just the A plug is
                 * attached to ACA: Use IDCHG_MAX for charging
                 */
                if (test_bit(ID_A, &dev->inputs))
                    msm_otg_set_power(&dev->otg, USB_IDCHG_MAX);
                else
                    dev->pdata->vbus_power(USB_PHY_INTEGRATED, 0);
                spin_lock_irqsave(&dev->lock, flags);
                dev->otg.state = OTG_STATE_A_WAIT_VFALL;//状态机迁移,等待a的电压门限降下
                spin_unlock_irqrestore(&dev->lock, flags);
                msm_otg_start_timer(dev, TA_WAIT_VFALL, A_WAIT_VFALL);
            }
            break;
        //等待电压将下来
        case OTG_STATE_A_WAIT_VFALL:
            if (test_bit(A_WAIT_VFALL, &dev->tmouts)) {
                clear_bit(A_VBUS_VLD, &dev->inputs);
                spin_lock_irqsave(&dev->lock, flags);
                dev->otg.state = OTG_STATE_A_IDLE;//继续迁移到a idle
                spin_unlock_irqrestore(&dev->lock, flags);
                work = 1;
            }
            break;
        //状态机继续迁移
        case OTG_STATE_A_IDLE:
            dev->otg.default_a = 1;
            if (test_bit(ID, &dev->inputs) &&//id = 1
                    !test_bit(ID_A, &dev->inputs)) {
                pr_debug("id && !id_a\n");
                dev->otg.default_a = 0;
                otg_reset(&dev->otg, 0);
                spin_lock_irqsave(&dev->lock, flags);
                dev->otg.state = OTG_STATE_B_IDLE;//迁移到b idle
                spin_unlock_irqrestore(&dev->lock, flags);
                msm_otg_set_power(&dev->otg, 0);
                work = 1;
            }
            break;
    }
    if (work)
        queue_work(dev->wq, &dev->sm_work);
}
 

转载地址:http://zrdmi.baihongyu.com/

你可能感兴趣的文章
【一天一道LeetCode】#56. Merge Intervals
查看>>
【一天一道LeetCode】#58. Length of Last Word
查看>>
【一天一道LeetCode】#59. Spiral Matrix II
查看>>
【一天一道LeetCode】#30. Substring with Concatenation of All Words
查看>>
【一天一道LeetCode】#60. Permutation Sequence.
查看>>
【一天一道LeetCode】#113. Path Sum II
查看>>
【一天一道LeetCode】#114. Flatten Binary Tree to Linked List
查看>>
【unix网络编程第三版】阅读笔记(二):套接字编程简介
查看>>
【一天一道LeetCode】#115. Distinct Subsequences
查看>>
【一天一道LeetCode】#116. Populating Next Right Pointers in Each Node
查看>>
【一天一道LeetCode】#118. Pascal's Triangle
查看>>
JNI简介及实例
查看>>
JAVA实现文件树
查看>>
ebay api - GetUserDisputes 函数
查看>>
ebay api GetMyMessages 函数
查看>>
手动12 - 安装php加速器 Zend OPcache
查看>>
set theme -yii2
查看>>
yii2 - 模块(modules)的view 映射到theme里面
查看>>
yii2 - controller
查看>>
yii2 - 增加actions
查看>>