根据上一篇文章中的结论:如果在xbl阶段希望修改pmic相关的gpio,可以查看这个gpio是否已经有功能对其进行初始化。那么需要考虑一种情况:如果这个gpio从未被用过呢?因此本篇就是从根本上解决这个问题
根据高通文档可以得到的信息:
1.本平台最终是通过解析pm.dtsi这个设备树来进行gpio的初始化的
2.该设备树中的节点,在pm_sbl_boot_oem.c中进行解析
代码分析:
根据示例PM_CLK_ENABLE PM_BUSID_0 PMIC_A PM_CLK_RF_1 PM_TRUE,可以知道在pm.dtsi内要如何添加一个gpio的信息
sw-config {
compatible = "qcom,pm-sw";
// verbose: Set to TRUE will output verbose PON reason into uart log.
// Set to 2 will output verbose PON reason and raw data into uart log
// By default setting to FALSE to avoid impacting boot performance
verbose = <PM_FALSE>;
driver-post-init = <
// PM_CLK_ENABLE PM_BUSID_0 PMIC_A PM_CLK_RF_1 PM_TRUE
...
/*Delay*/
PM_DELAY(10)
> ;
apply-rsns-trim = <PM_FALSE>;
rsns-trim-value = <0>;
};
再查看pm_sbl_boot_oem.c内是如何解析这个设备树内的节点信息的
static pm_err_flag_type
pm_post_driver_init_dt_config( void )
{
pm_err_flag_type err_flag = PM_ERR_FLAG_SUCCESS;
uint16 spmi_clk_data_cfg = 0;
uint32 pmic_index = 0;
uint32 periph_id = 0;
uint32 value = 0;
uint32 operation = 0;
uint32 bus_id = 0;
int i = 0;
pm_model_type model = PMIC_IS_INVALID;
pm_dt_sw_config *sw_dt_config = NULL;
sw_dt_config = pm_dt_get_node( PMIC_DT_NODE_PM_SW_CONFIG );
if((sw_dt_config != NULL) && (sw_dt_config->post_driver_init != NULL) && (sw_dt_config->post_driver_init_count > 0))
{
for(i = 0; i < sw_dt_config->post_driver_init_count; i++)
{
operation = sw_dt_config->post_driver_init[i * 5];
bus_id = sw_dt_config->post_driver_init[(i * 5) + 1];
pmic_index = sw_dt_config->post_driver_init[(i * 5) + 2];
periph_id = sw_dt_config->post_driver_init[(i * 5) + 3];
value = sw_dt_config->post_driver_init[(i * 5) + 4];
...
switch( operation )
{
case PM_LDO_SET_ENABLE:
err_flag |= pm_ldo_sw_enable(pmic_index, periph_id, value, TRUE);
break;
case PM_LDO_SET_VOLT:
err_flag |= pm_ldo_volt_level(pmic_index, periph_id, value * 1000, TRUE); // *1000 to change to uv
break;
case PM_LDO_SET_MODE:
err_flag |= pm_ldo_sw_mode(pmic_index, periph_id, value);
break;
...
}
}
}
}
解析设备树的时候,会根据post_driver_init内的5个属性进行解析,分别为operation、bus_id、pmic_index、periph_id、value。再跟一下代码,可以看到operation就是就是作为选择项去调用各个对应的api,对剩余的4个参数进行修改。再看看哪里定义了这些operation,从而找到我们想要使用的
//GPIO
#define PM_GPIO_SET_ENABLE 60
#define PM_GPIO_SET_CFG_MODE 61
#define PM_GPIO_SET_OUTPUT_LVL 62
#define PM_GPIO_SET_VOLT_SRC 63
#define PM_GPIO_SET_OUT_BUFF_CONFIG 64
#define PM_GPIO_SET_OUT_DRV_STR 65
#define PM_GPIO_SET_OUT_SRC_CFG 66
#define PM_GPIO_SET_PULL_SEL 67
根据我们的需求,我们需要先将这个gpio设置为IN模式,将这个gpio默认变为拉低状态,接收从mcu传来拉低的状态再去做我们的功能
那么我们的pm.dtsi内要如何设置也可以得出结论了:
sw-config {
compatible = "qcom,pm-sw";
// verbose: Set to TRUE will output verbose PON reason into uart log.
// Set to 2 will output verbose PON reason and raw data into uart log
// By default setting to FALSE to avoid impacting boot performance
verbose = <PM_FALSE>;
driver-post-init = <
// PM_CLK_ENABLE PM_BUSID_0 PMIC_A PM_CLK_RF_1 PM_TRUE
PM_GPIO_SET_ENABLE PM_BUSID_0 PMIC_B PM_GPIO_06 TRUE
PM_GPIO_SET_CFG_MODE PM_BUSID_0 PMIC_B PM_GPIO_06 TRUE
PM_GPIO_SET_PULL_SEL PM_BUSID_0 PMIC_B PM_GPIO_06 PM_GPIO_PULL_UP_30UA
...
/*Delay*/
PM_DELAY(10)
> ;
apply-rsns-trim = <PM_FALSE>;
rsns-trim-value = <0>;
};
至此结束。编译后使用示波器进行量取对应的GPIO波形,修改之前为高电平,修改之后为低电平,并且abl内能判断逻辑也pass。
如有不对,麻烦大佬指点,谢谢