作者: arunboy
在原有展訊平臺下面的bq25601的基礎(chǔ)上編寫mtk平臺下的bq25601代碼,參考mtk平臺下的.并進行相關(guān)調(diào)試.
充電IC的移植是在kernel和lk里面,lk里面是mt_battery.c中調(diào)用了以下幾個函數(shù)
#if?defined(MTK_BQ25601_SUPPORT) ????bq25601_hw_init(); ????bq25601_charging_enable(bEnable); ????bq25601_dump_register(); #endif
kernel里面在power/mt6735/Makefile中
ifeq?($(CONFIG_MTK_BQ25601_SUPPORT),y) ????????????????????obj-$(CONFIG_MTK_SMART_BATTERY)?+=?bq25601.o?charging_hw_bq25601.o
首先參考兩個代碼新建了一個文件,把一些接口函數(shù)進行了替換.然后查看數(shù)據(jù)手冊修改數(shù)組,寄存器的值.
圖中的數(shù)組都是查看數(shù)據(jù)手冊然后進行填充,下面那些使用字母的因為在別的文件中定義了數(shù)字.
電池充電有三個階段:預(yù)充電階段,恒流充電,恒壓充電.
預(yù)充電階段:設(shè)置充電電流一般為500mA以下
恒流充電階段:電壓一般在3.2~4.1v左右,充電器的輸入電壓會越來越高
恒壓充電階段:4.2v左右,充電ic輸出電壓不變,電流逐漸減小.
驅(qū)動代碼分析
1.bq25601.c
/**********************************************************
??*
??*???[I2C?Slave?Setting]
??*
??*********************************************************/
#define?bq25601_SLAVE_ADDR_WRITE???0xD6//根據(jù)數(shù)據(jù)手冊i2c的地址是0x6b,左移一位以后得到0xd6
#define?bq25601_SLAVE_ADDR_READ????0xD7
static?struct?i2c_client?*new_client;
static?const?struct?i2c_device_id?bq25601_i2c_id[]?=?{?{"bq25601",?0},?{}?};
kal_bool?chargin_hw_init_done?=?KAL_FALSE;
static?int?bq25601_driver_probe(struct?i2c_client?*client,?const?struct?i2c_device_id?*id);
#ifdef?CONFIG_OF
static?const?struct?of_device_id?bq25601_of_match[]?=?{
????{.compatible?=?"bq25601",},
????{},
};
MODULE_DEVICE_TABLE(of,?bq25601_of_match);
#endif
static?struct?i2c_driver?bq25601_driver?=?{
????.driver?=?{
???????????.name?=?"bq25601",
#ifdef?CONFIG_OF
???????????.of_match_table?=?bq25601_of_match,
#endif
???????????},
????.probe?=?bq25601_driver_probe,
????.id_table?=?bq25601_i2c_id,
};2.charging_hw_bq25601.c
//充電的一些初始化的值,根據(jù)數(shù)據(jù)手冊的某個寄存的的某位代表的什么意思進行設(shè)值.
static?unsigned?int?charging_hw_init(void?*data)
{
????unsigned?int?status?=?STATUS_OK;
????battery_log(BAT_LOG_CRTI,?"charging_hw_init!n");
????bq25601_set_en_hiz(0x0);
????bq25601_set_vindpm(0x8);????/*?VIN?DPM?check?4.70V?*/
????//bq25601_set_vindpm(0x0);
????bq25601_set_reg_rst(0x0);
????bq25601_set_wdt_rst(0x1);???/*?Kick?watchdog?*/
????bq25601_set_sys_min(0x5);???/*?Minimum?system?voltage?3.5V?*/
????bq25601_set_iprechg(0x7);???/*?Precharge?current?480mA?*/
????bq25601_set_iterm(0x1);?/*?Termination?current?120mA?*/
????bq25601_set_vreg(0x0B);?/*?VREG?4.208V?*/
????bq25601_set_min_vbat_sel(0x0);??/*?BATLOWV?2.8V?*/
????bq25601_set_vrechg(0x0);????/*?VRECHG?0.1V?(4.108V)?*/
????bq25601_set_en_term(0x1);???/*?Enable?termination?*/
????bq25601_set_watchdog(0x1);??/*?WDT?40s?*/
????bq25601_set_en_timer(0x0);??/*?Disable?charge?timer?*/
????bq25601_set_vindpm_int(0x0);????/*?Disable?fault?vindpm?interrupt?*/
????bq25601_set_iindpm_int(0x0);????/*?Disable?fault?iindpm?interrupt?*/
????bq25601_set_ovp(0x3);
????return?status;
}然后把這幾個函數(shù)進行填充完整就行,根據(jù)項目需求,有的不需要.
charging_func[CHARGING_CMD_INIT]?=?charging_hw_init; ????????charging_func[CHARGING_CMD_DUMP_REGISTER]?=?charging_dump_register; ????????charging_func[CHARGING_CMD_ENABLE]?=?charging_enable; ????????charging_func[CHARGING_CMD_SET_CV_VOLTAGE]?=?charging_set_cv_voltage; ????????charging_func[CHARGING_CMD_GET_CURRENT]?=?charging_get_current; ????????charging_func[CHARGING_CMD_SET_CURRENT]?=?charging_set_current; ????????charging_func[CHARGING_CMD_SET_INPUT_CURRENT]?=?charging_set_input_current; ????????charging_func[CHARGING_CMD_GET_CHARGING_STATUS]?=??charging_get_charging_status; ????????charging_func[CHARGING_CMD_RESET_WATCH_DOG_TIMER]?=?charging_reset_watch_dog_timer; ????????charging_func[CHARGING_CMD_SET_HV_THRESHOLD]?=?charging_set_hv_threshold; ????????charging_func[CHARGING_CMD_GET_HV_STATUS]?=?charging_get_hv_status; ????????charging_func[CHARGING_CMD_GET_BATTERY_STATUS]?=?charging_get_battery_status; ????????charging_func[CHARGING_CMD_GET_CHARGER_DET_STATUS]?=?charging_get_charger_det_status; ????????charging_func[CHARGING_CMD_GET_CHARGER_TYPE]?=?charging_get_charger_type; ????????charging_func[CHARGING_CMD_SET_PLATFORM_RESET]?=?charging_set_platform_reset; ????????charging_func[CHARGING_CMD_GET_PLATFORM_BOOT_MODE]?=?charging_get_platform_boot_mode; ????????charging_func[CHARGING_CMD_SET_POWER_OFF]?=?charging_set_power_off; ????????charging_func[CHARGING_CMD_SET_TA_CURRENT_PATTERN]?=?charging_set_ta_current_pattern; ????????charging_func[CHARGING_CMD_SET_ERROR_STATE]?=?charging_set_error_state; ????????charging_func[CHARGING_CMD_DISO_INIT]?=?charging_diso_init; ????????charging_func[CHARGING_CMD_GET_DISO_STATE]?=?charging_get_diso_state; ????????charging_func[CHARGING_CMD_SET_VBUS_OVP_EN]?=?charging_set_vbus_ovp_en; ????????charging_func[CHARGING_CMD_SET_VINDPM]?=?charging_set_vindpm;
主要記錄兩個函數(shù),i2c的讀寫數(shù)據(jù)的函數(shù):
int?bq25601_read_byte(unsigned?char?cmd,?unsigned?char?*returnData)
{
????char?cmd_buf[1]?=?{?0x00?};
????char?readData?=?0;
????int?ret?=?0;
????mutex_lock(&bq25601_i2c_access);
????/*?new_client->addr?=?((new_client->addr)?&?I2C_MASK_FLAG)?|?I2C_WR_FLAG;?*/
????new_client->ext_flag?=
????????((new_client->ext_flag)?&?I2C_MASK_FLAG)?|?I2C_WR_FLAG?|?I2C_DIRECTION_FLAG;
????cmd_buf[0]?=?cmd;
????ret?=?i2c_master_send(new_client,?&cmd_buf[0],?(1?<<?8?|?1));
????if?(ret?<?0)?{
????????/*?new_client->addr?=?new_client->addr?&?I2C_MASK_FLAG;?*/
????????new_client->ext_flag?=?0;
????????mutex_unlock(&bq25601_i2c_access);
????????return?0;
????}
????readData?=?cmd_buf[0];
????*returnData?=?readData;
????/*?new_client->addr?=?new_client->addr?&?I2C_MASK_FLAG;?*/
????new_client->ext_flag?=?0;
????mutex_unlock(&bq25601_i2c_access);
????return?1;
}
int?bq25601_write_byte(unsigned?char?cmd,?unsigned?char?writeData)
{
????char?write_data[2]?=?{?0?};
????int?ret?=?0;
????mutex_lock(&bq25601_i2c_access);
????write_data[0]?=?cmd;
????write_data[1]?=?writeData;
????new_client->ext_flag?=?((new_client->ext_flag)?&?I2C_MASK_FLAG)?|?I2C_DIRECTION_FLAG;
????ret?=?i2c_master_send(new_client,?write_data,?2);
????if?(ret?<?0)?{
????????new_client->ext_flag?=?0;
????????mutex_unlock(&bq25601_i2c_access);
????????return?0;
????}
????new_client->ext_flag?=?0;
????mutex_unlock(&bq25601_i2c_access);
????return?1;
}3.對于lk里面,就是實現(xiàn) ? bq25601_hw_init(),bq25601_charging_enable(bEnable),bq25601_dump_register()這三個函數(shù),基本上和kernel里面的差不多.
4.參考數(shù)據(jù)手冊幾個有關(guān)充電IC的參數(shù)
Termination Current ? ? 截止電流,一般設(shè)置為200mA以下
Charge Voltage ? ? ? ? ? ? ?充電IC的輸出電壓
Precharge current ? ? ? ? ?預(yù)充電電流,一般設(shè)置為500mA以下
VAG OVP 最高電壓,bq25601可以支持到14v
Absolute VINDPM Threshold 充電IC的最高輸出
總結(jié)
編寫調(diào)試驅(qū)動代碼一定要認真,特別注意宏定義,加上了沒,有沒有把以前的宏定義注釋掉,而且要查看一下有沒有在Makefile,Kconfig中添加修改,報錯的話要看錯誤提示,然后去查錯誤類型,有的報的這個地方的錯誤但是錯誤不在這個文件當中.
kernel-3.18/arch/arm64/boot/dts/project_bat_setting.dtsi可以配置電池曲線,充電屬性等相關(guān)配置.注意還有一個電阻值的配置,如果與硬件不匹配,會導(dǎo)致誤差較大.
問題
pmic檢測充電器狀態(tài)不對,改用了通過讀取充電IC的寄存器的狀態(tài)來判斷是否在充電.查尋datasheet后可以看到在REG08里面讀取.
添加如下檢測代碼:
????stat?=?bq25601_get_vbus_stat(); ????if?(stat?==?0x1?||?stat?==?0x2) ????????val?=?KAL_TRUE; ????else ????????val?=?KAL_FALSE;
充電IC的配置
1 device下面的配置
2 kernel 里面的config和dts(i2c地址) ? PS:盡量保證user版和debug版一塊修改.
3 lk里面的config
4 preloader里面的config ?
END





