背景
最近公司某产品用到了TI的电量计芯片
看了下代码,比较简单,连Makefile都没写,不过这也挺好,说明对编译环境没有要求。自己编写好Makefile后编译,出现3个编译错误:
bq40z50_fg.c:609:2: error: 'POWER_SUPPLY_PROP_RESISTANCE_ID' undeclared here (not in a function); did you mean 'POWER_SUPPLY_PROP_VOLTAGE_MIN'? 609 | POWER_SUPPLY_PROP_RESISTANCE_ID, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | POWER_SUPPLY_PROP_VOLTAGE_MIN bq40z50_fg.c:610:2: error: 'POWER_SUPPLY_PROP_UPDATE_NOW' undeclared here (not in a function); did you mean 'POWER_SUPPLY_PROP_CHARGE_NOW'? 610 | POWER_SUPPLY_PROP_UPDATE_NOW, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ | POWER_SUPPLY_PROP_CHARGE_NOW bq40z50_fg.c:777:22: error: 'POWER_SUPPLY_TYPE_BMS' undeclared (first use in this function); did you mean 'POWER_SUPPLY_TYPE_UPS'? 777 | bq->fg_psy_d.type = POWER_SUPPLY_TYPE_BMS; | ^~~~~~~~~~~~~~~~~~~~~ | POWER_SUPPLY_TYPE_UPS
分析一番发现,是因为我们产品是基于5.10内核的,而TI的开源驱动是基于4.4内核的,有些宏定义在5.10内核找不到。
解决过程
首先检查出错的宏是不是改名了,一番对比后确认,不是改名,就是删掉了,估计是觉得跟其他相关宏定义重合度太高。
移植POWER_SUPPLY_TYPE_BMS
先检查
再看4.4内核
移植POWER_SUPPLY_PROP_RESISTANCE_ID
该属性没有对应的替代,不过查看TI对该属性的实现,发现get是固定返回0,set没实现,那还有什么意义?直接删除了事。
移植POWER_SUPPLY_PROP_UPDATE_NOW
该属性也没有对应的替代,不过查看TI对该属性的实现,发现get也是固定返回0,set是dump所有I2C寄存器,只是方便调试,删了也没啥影响。
加载运行效果
做了前述修改后,代码在5.10内核上编译通过,加载成功,在
最终代码补丁
Index: bq40z50_fg.c =================================================================== --- bq40z50_fg.c (版本 418) +++ bq40z50_fg.c (版本 419) @@ -606,8 +593,6 @@ /*POWER_SUPPLY_PROP_HEALTH,*//*implement it in battery power_supply*/ POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_RESISTANCE_ID, - POWER_SUPPLY_PROP_UPDATE_NOW, }; static int fg_get_property(struct power_supply *psy, enum power_supply_property psp, @@ -710,13 +695,6 @@ val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; break; - case POWER_SUPPLY_PROP_RESISTANCE_ID: - val->intval = 0; - break; - case POWER_SUPPLY_PROP_UPDATE_NOW: - val->intval = 0; - break; - default: return -EINVAL; } @@ -738,9 +716,6 @@ bq->fake_soc = val->intval; power_supply_changed(bq->fg_psy); break; - case POWER_SUPPLY_PROP_UPDATE_NOW: - fg_dump_registers(bq); - break; default: return -EINVAL; } @@ -757,7 +732,6 @@ switch (prop) { case POWER_SUPPLY_PROP_TEMP: case POWER_SUPPLY_PROP_CAPACITY: - case POWER_SUPPLY_PROP_UPDATE_NOW: ret = 1; break; default: @@ -774,7 +748,7 @@ struct power_supply_config fg_psy_cfg = {}; bq->fg_psy_d.name = "bms"; - bq->fg_psy_d.type = POWER_SUPPLY_TYPE_BMS; + bq->fg_psy_d.type = POWER_SUPPLY_TYPE_BATTERY; bq->fg_psy_d.properties = fg_props; bq->fg_psy_d.num_properties = ARRAY_SIZE(fg_props); bq->fg_psy_d.get_property = fg_get_property;
总结
芯片厂商开发Linux驱动时,为了节省人力,一般会选择一个内核版本进行开发,开发完毕后一般不会随Linux大版本的发布而更新,因为人家的驱动代码主要是做演示用的,版本发布导致的内核接口变更需要工程师自己去适配。