代码路径:/kernel/msm-3.18/drivers/usb/phy/phy_msm_usb.c
msm_otg_probe
(1)工作队列初始化
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);充电器类型检测的work
INIT_DELAYED_WORK(&motg->id_status_work, msm_id_status_w);batt id状态的work
(2)注册power supply
motg->usb_psy.name = "usb";//文件节点/sys/class/power_supply/usb
motg->usb_psy.type = POWER_SUPPLY_TYPE_USB;
motg->usb_psy.supplied_to = otg_pm_power_supplied_to;
motg->usb_psy.num_supplicants = ARRAY_SIZE(otg_pm_power_supplied_to);
motg->usb_psy.properties = otg_pm_power_props_usb;//所有支持的property
motg->usb_psy.num_properties = ARRAY_SIZE(otg_pm_power_props_usb);
motg->usb_psy.get_property = otg_power_get_property_usb;
motg->usb_psy.set_property = otg_power_set_property_usb;
motg->usb_psy.property_is_writeable
= otg_power_property_is_writeable_usb;
if (!msm_otg_register_power_supply(pdev, motg))
psy = &motg->usb_psy;
下面来重点分析两个工作队列sm_work和chg_detected_work
msm_otg_sm_work
case OTG_STATE_B_IDLE:
switch (motg->chg_state) {
case USB_CHG_STATE_UNDEFINED://代码里面定义了USB chg detection涉及的多个状态
motg->chg_state = USB_CHG_STATE_IN_PROGRESS;//状态设置为检测中
msm_chg_detect_work(&motg->chg_work.work);//启动充电器类型检测的work
case USB_CHG_STATE_DETECTED://充电器类型检测完毕,也就是说上面的chg detect work
完毕后一定会设置该状态。
switch (motg->chg_type) {
case USB_DCP_CHARGER:
/* fall through */
case USB_PROPRIETARY_CHARGER:
msm_otg_notify_charger(motg,dcp_max_current);
if (!motg->is_ext_chg_dcp)
otg->phy->state =OTG_STATE_B_CHARGER;
break;
case USB_UNSUPPORTED_CHARGER:
msm_otg_notify_charger(motg, 0);
if (!motg->is_ext_chg_dcp)
otg->phy->state =OTG_STATE_B_CHARGER;
break;
case USB_CDP_CHARGER:
msm_otg_notify_charger(motg,IDEV_CHG_MAX);
/* fall through */
case USB_SDP_CHARGER:
msm_chg_check_dcd_flchg(motg);
msm_otg_start_peripheral(otg, 1);
otg->phy->state =OTG_STATE_B_PERIPHERAL;
mod_timer(&motg->chg_check_timer,CHG_RECHECK_DELAY);
break;
根据不同的充电器类型都调用了msm_otg_notify_charger函数,该函数一个参数为电流
msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
dev_dbg(motg->phy.dev, "Requested curr from USB = %u, max-type-c:%u\n",mA, motg->typec_current_max);//打印log信息
/* Save bc1.2 max_curr if type-c charger later moves to diff mode */
-> motg->bc1p2_current_max = mA;
-->if (msm_otg_notify_chg_type(motg))//通知PMIC充电器类型
dev_err(motg->phy.dev,"Failed notifying %d charger type to PMIC\n",motg->chg_type);
msm_otg_notify_power_supply(motg, mA);//设置其他property属性
msm_chg_detect_work:
switch (motg->chg_state) {
case USB_CHG_STATE_UNDEFINED:
case USB_CHG_STATE_IN_PROGRESS:
……
motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
break;
case USB_CHG_STATE_WAIT_FOR_DCD:
msm_chg_enable_primary_det(motg);
motg->chg_state = USB_CHG_STATE_DCD_DONE;
case USB_CHG_STATE_DCD_DONE:
vout = msm_chg_check_primary_det(motg);
if (vout && !dm_vlgc) { /* VDAT_REF < DM < VLGC */
if (line_state) { /* DP > VLGC */
motg->chg_type = USB_PROPRIETARY_CHARGER;//到这里检测出第一种充电器类型proprietary,具体是啥类型也不清楚。
motg->chg_state = USB_CHG_STATE_DETECTED;
delay = 0;
} else {
msm_chg_enable_secondary_det(motg);//再做进一步的类型检测
motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
}
else { /* DM < VDAT_REF || DM > VLGC */
if (line_state) /* DP > VLGC or/and DM > VLGC */
motg->chg_type = USB_PROPRIETARY_CHARGER;
else if (!dcd) {
if (motg->pdata->enable_floated_charger== FLOATING_AS_DCP)
motg->chg_type = USB_DCP_CHARGER;//根据配置设置这种情况下的充电器类型到底是DCP还是unsupported的,enable_floated_charger可以在dtsi中配置。
else if (motg->pdata->enable_floated_charger== FLOATING_AS_INVALID)
motg->chg_type =USB_UNSUPPORTED_CHARGER;
} else {
motg->chg_type = USB_SDP_CHARGER;//检测到SDP充电器
}
motg->chg_state = USB_CHG_STATE_DETECTED;//状态设置为检测完成。
delay = 0;
}
case USB_CHG_STATE_PRIMARY_DONE:
vout = msm_chg_check_secondary_det(motg);
if (vout)
motg->chg_type = USB_DCP_CHARGER;
else
motg->chg_type = USB_CDP_CHARGER;//在secondary检测阶段区分是DCP还是CDP
motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
case USB_CHG_STATE_SECONDARY_DONE:
motg->chg_state = USB_CHG_STATE_DETECTED;// secondary检测完毕整个类型检测完毕,状态设置为detected
case USB_CHG_STATE_DETECTED://下面看检测完毕后又做了哪些工作?看注释!!!
/* Notify the charger type to power supply owner as soon as we determine the charger.*/
msm_otg_notify_chg_type(motg);
queue_work(motg->otg_wq, &motg->sm_work);再次去调度sm_work