//插入usb b 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;
}
//插入usb b cable的时候,状态机迁移如下
case OTG_STATE_B_IDLE:
dev->otg.default_a = 0;
if (test_bit(B_SESS_VLD, &dev->inputs) &&
!test_bit(ID_B, &dev->inputs)) {
pr_debug("b_sess_vld\n");
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_B_PERIPHERAL;//状态机迁移到OTG_STATE_B_PERIPHERAL
spin_unlock_irqrestore(&dev->lock, flags);
msm_otg_set_power(&dev->otg, 0);
msm_otg_start_peripheral(&dev->otg, 1);
}
break;
case OTG_STATE_B_PERIPHERAL:
//下面的if-else条件都不满足,状态机停留在OTG_STATE_B_PERIPHERAL状态
break;
//拔出usb b cable的时候,状态机迁移如下
case OTG_STATE_B_PERIPHERAL:
if (!test_bit(ID, &dev->inputs) || test_bit(ID_A, &dev->inputs) || test_bit(ID_B, &dev->inputs) ||
!test_bit(B_SESS_VLD, &dev->inputs)) { //B_SESS_VLD为0
pr_debug("!id || id_a/b || !b_sess_vld\n");
clear_bit(B_BUS_REQ, &dev->inputs);
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_B_IDLE; //状态机迁移到OTG_STATE_B_IDLE
spin_unlock_irqrestore(&dev->lock, flags);
msm_otg_start_peripheral(&dev->otg, 0);
dev->b_last_se0_sess = jiffies;
/* Workaround: Reset phy after session */
otg_reset(&dev->otg, 1);
work = 1;
}
break;
case OTG_STATE_B_IDLE:
dev->otg.default_a = 0;
else{
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;
//驱动该状态机的状态如下
1、在中断中
static irqreturn_t msm_otg_irq(int irq, void *data)
{
struct msm_otg *dev = data;
int work = 0;
enum usb_otg_state state;
unsigned long flags;
if (atomic_read(&dev->in_lpm)) {
queue_work(dev->wq, &dev->otg_resume_work);
goto out;
}
/*读出状态寄存器的值*/
otgsc = readl(USB_OTGSC);
sts = readl(USB_USBSTS);
state = dev->otg.state;//状态机的当前状态
if ((otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) {
if (otgsc & OTGSC_ID) {//拔出a cable时的触发状态
pr_debug("Id set\n");
set_bit(ID, &dev->inputs);
} else {
pr_debug("Id clear\n");//插入a cable时的触发状态
set_bit(A_BUS_REQ, &dev->inputs);
clear_bit(ID, &dev->inputs);
}
writel(otgsc, USB_OTGSC);
work = 1;//调度work,驱动状态机状态迁移
} else if (otgsc & OTGSC_BSVIS) {
writel(otgsc, USB_OTGSC);
if ((state >= OTG_STATE_A_IDLE) &&
!test_bit(ID_A, &dev->inputs))
goto out;
if (otgsc & OTGSC_BSV) {//插入b cable时候,所触发的条件
pr_debug("BSV set\n");
set_bit(B_SESS_VLD, &dev->inputs);
} else {//拔出b cable的时候,所触发的条件
pr_debug("BSV clear\n");
clear_bit(B_SESS_VLD, &dev->inputs);
}
work = 1;//调度work,驱动状态机状态迁移
} if (sts & STS_PCI) {
pc = readl(USB_PORTSC);
pr_debug("portsc = %x\n", pc);
work = 1;
switch (state) {
.............
default:
work = 0;
break;
}
}
if (work) {
wake_lock(&dev->wlock);
queue_work(dev->wq, &dev->sm_work);//调度驱动状态机
}
}
阅读(801) | 评论(0) | 转发(0) |