高通的某些平台将电源管理移植到了ADSP Subsystem, 分析一下其中比较关心的部分
Architecture
—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —
| Generic TypeC Drvier PowerSupply Framework |
| GlinkClient-UCSI GlinkClient-BM |
| PMIC Glink(Linux kernel) |
—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —
| PMIC GLink(ADSP) |
| Charger Thread BM Thread |
—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —
BM (Battery Manager)
SSDEV (Sink/Source devices)
BCS (Battery Charging Status)
ICM (Intelligent Charging Module)
APSD (Automatic power source detection)
AICL (automatic input current limiting)
UCSI (USB Type-C Connector System Software Interface driver)
Charge Detection
不同于之前是先运行BC1.2再运行APSD,这里是直接运行APSD其中兼容BC1.2
BattMngrDevice_InitContext (既然ChgConfigData没有初始化 usb_connector_type,但检测的时候需要判断类型)
//CHARGER_CONFIG_DATA -> CHARGER_DETECTION_CONFIG_DATA usb_connector_type + NoofInputs 检测时有用
//charget_cfg.NoOfInputs = 2; (Input0 Type-C port or microUSB port + Input1 Wireless charging)
ssdev_initialize(0, (usb_connector_type == CONNECTOR_TYPE_MICRO_USB) ? SSDEV_MODULE_USB : SSDEV_MODULE_TYPEC);
ssdev_initialize(1, SSDEV_MODULE_WLS);
PmSchgAdcCmn2_GetUSBConnectorType(&usb_connector_type) (battmngrconfig_props.c CONNCfg定义的属性 0:microB 1:typec)
从这里我们可以得知,如果没有定义属性或者属性置为0,则默认是 SSDEV_MODULE_TYPEC,否则则需要通过PMIC内部来进行判断
charger初始化的时候通过BattMngr_Thread_Create创建了线程charger_main,
while的循环执行charger_events (CHARGER_EVENT_TYPE 包含CHARGER_EVENT_CHGTYPE_CHANGE 角色电压电流等)
charger_process_events
charger_detection_event_handler
ssdev_detect_partner
SSDEV_MODULE_TYPEC -> ssdev_typec_detect_partner
SSDEV_MODULE_USB -> ssdev_usb_detect_partner
break
charger_detection_evaluate_charger
SSDEV_MODULE_TYPEC -> charger_detection_evaluate_typec_charger
break
SSDEV_MODULE_USB -> charger_detection_evaluate_usb_charger
break
SSDEV_PARTNER_TYPE
SSDEV_PARTNER_SNK_USB_SDP SSDEV_PARTNER_SNK_USB_OCP, SSDEV_PARTNER_SNK_USB_CDP,
SSDEV_PARTNER_SNK_USB_DCP, SSDEV_PARTNER_SNK_USB_FLOAT,...
SSDEV_PARTNER_TYPE跟之前平台类似 Android Qcom USB Driver学习(二)
需要注意在SSDEV_MODULE_TYPEC中ssdev_typec_detect_partner 和 ssdev_usb_detect_partner之间是没有break的,
也就是说无论是Typec还是usb都要通过ssdev_usb_detect_partner来调用PmSchgUsb_GetApsdResultStatus (APSD算法兼容BC1.2)返回
UsbPartnerType (充电类型),并且在charger_detection_evaluate_charger中应用,只执行一个来进行Input Current Limit的配置,
charger_detection_evaluate_typec_charger与charger_detection_evaluate_usb_charger 中就有break,
那时什么情况下会去触发detect呢? 中断 BATTMNGR_INTERRUPT_TYPE
battmngr_plat_irq_schgp_qg_apsd_done
在APSD运行的结束的中断后charger_notify(CHARGER_EVENT_DETECTION_UPDATE)通知到Charger Thread
battmngr_plat_irq_schgp_qg_plug_in
在插入的时候会发送BATTMNGR_DRV_USB_PLUGIN_EVENT,再通过charger_notify通知到Charger Thread
那时什么情况下会去触发detect呢? 中断 BATTMNGR_INTERRUPT_TYPE
battmngr_plat_irq_schgp_qg_apsd_done
在APSD运行的结束的中断后charger_notify(CHARGER_EVENT_DETECTION_UPDATE)通知到Charger Thread
battmngr_plat_irq_schgp_qg_plug_in
在插入的时候会发送BATTMNGR_DRV_USB_PLUGIN_EVENT,再通过charger_notify通知到Charger Thread
Kernel communication with ADSP
Battery Charging
battery_chg_write -> pmic_glink_write + wait_for_completion_timeout(等待ADSP的ack)
pmic_glink_process_rx_data -> pmic_glink_tx
处理数据并且回调给Kernel,返回响应,使得上面发送时的wait_for_completion_timeout等待结束
pmic_glink_rx_callback -> client->msg_cb
battery_chg_callback -> handle_message -> completion ack
battery_dock_charger_notify_msg(通信的message由两部分组成)
(1)PMIC Glink message header
#define MSG_OWNER_BC 32778 (kernel)
#define MSG_TYPE_REQ_RESP 1
req_msg.hdr.owner = MSG_OWNER_BC;
req_msg.hdr.type = MSG_TYPE_REQ_RESP;
req_msg.hdr.opcode = (opcode for battery charger)
(2)req_msg.value + req_msg.property_id
注意Kernle和ADSP定义的名称不同
#define PMIC_GLINK_MSG_OWNER_CHARGER 32778 (ADSP)
#define PMIC_GLINK_MSG_TYPE_REQ_RESP 1
Type-C Role
#define MSG_OWNER_UC 32779 (kernel)
#define PMIC_GLINK_MSG_OWNER_USB_TYPE_C 32779 (ADSP)
ucsi_acknowledge_connector_change
ucsi_qti_async_write -> ucsi_qti_glink_write -> pmic_glink_write
UCSI最终还是通过PMIC GLink的API来实现,并且同样会产生回调,会通过msg head中的owner来区分Client
pmic_glink_rx_callback->client->msg_cb
ucsi_callback -> handle_ucsi_notify -> ucsi_connector_change
typedef enum _PM_TYPEC_PORT_ROLE_TYPE typedef enum _PM_TYPEC_EXIT_CONTROL_TYPE
{ {
TYPEC_PORT_ROLE_DRP, //Source还是Sink由CC决定 TYPEC_EXIT_CONTROL_SNK,
TYPEC_PORT_ROLE_SNK, //Source 供电 TYPEC_EXIT_CONTROL_SRC,
TYPEC_PORT_ROLE_SRC, //Sink接受供电 } PM_TYPEC_EXIT_CONTROL_TYPE;
TYPEC_PORT_ROLE_DISABLE,
TYPEC_PORT_ROLE_INVALID
} PM_TYPEC_PORT_ROLE_TYPE;
这个还是跟之前如果需要转变则需要kernel调用两个API(1)typec_set_data_role (2)usb_role_switch_set_role
enum typec_data_role { enum typec_role {
TYPEC_DEVICE, TYPEC_SINK,
TYPEC_HOST, TYPEC_SOURCE,
};
Battery Status
BM Thread -> battmngr_platform_charger_update
BattMngrPlatformFuncs.BattMngrPlat_Charger_Update_FuncPtr -> battmngr_plat_scpqchg_qbg_update_charger_power_supply
将propery都存到到对应的属性中,例如usb_power_supply_properties
pmic_glink_send_power_supply_notification (msg.notifcation == USB_POWER_SUPPLY_GET_REQ == BC_USB_STATUS_GET)
pmic_glink_tx(msg.hdr.opcode = BATT_MNGR_NOTIFY_IND == BC_NOTIFY_IND)
根据opcode在callback回kernel中调用handle_notification发生变化,再去将ADSP返回的值更新到powersupply properties
最后还是调用到power_supply_changed就跟原先的上报流程一样了,通过uevent上报各上层的healthd
标签:USB,charger,Driver,TYPEC,SSDEV,Qcom,Android,TYPE,usb
From: https://www.cnblogs.com/linhaostudy/p/18379309