can't able to update the design capacity in bq27441-G1
/***************************************************************************
* can't able to update the design capacity in bq27441-G1
* 声明:
* 本文主要是记录分析bq27441-G1芯片无法修改一些参数的原因,主要是因为
* bq27x00_powersupply_init中绑定了bq27x00_battery_poll作为定时任务,之后
* 直接调用bq27x00_update获取电池信息,这个时候bq27x00_battery_poll还没有
* 执行,所以第一次bq27x00_update获取的是默认的bq27441-G1信息,而在此之后
* bq27x00_update中会对有些信息进行选择更新,所以造成了design capacity不
* 准确。
*
* 2016-2-22 深圳 南山平山村 曾剑锋
**************************************************************************/ /**
* 参考文章:
* Application of bq27441-g1 with 3.X Linux kernel
* http://e2e.ti.com/support/power_management/battery_management/f/180/p/471744/1701660
*/ static int __init bq27x00_powersupply_init(struct bq27x00_device_info *di)
{
int ret; di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
if (di->chip == BQ274XX) {
set_properties_array(di, bq274xx_battery_props,
ARRAY_SIZE(bq274xx_battery_props));
} else if (di->chip == BQ276XX) {
set_properties_array(di, bq276xx_battery_props,
ARRAY_SIZE(bq276xx_battery_props));
} else if (di->chip == BQ27520) {
set_properties_array(di, bq27520_battery_props,
ARRAY_SIZE(bq27520_battery_props));
} else if (di->chip == BQ2753X) {
set_properties_array(di, bq2753x_battery_props,
ARRAY_SIZE(bq2753x_battery_props));
} else {
set_properties_array(di, bq27x00_battery_props,
ARRAY_SIZE(bq27x00_battery_props));
}
di->bat.get_property = bq27x00_battery_get_property;
di->bat.external_power_changed = bq27x00_external_power_changed; INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll); ------------------+
mutex_init(&di->lock); |
|
ret = power_supply_register(di->dev, &di->bat); |
if (ret) { |
dev_err(di->dev, "failed to register battery: %d\n", ret); |
return ret; |
} |
|
dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION); |
|
bq27x00_update(di); ------------------*------+
| |
return ; | |
} | |
| |
static void bq27x00_battery_poll(struct work_struct *work) <------------+ |
{ |
struct bq27x00_device_info *di = |
container_of(work, struct bq27x00_device_info, work.work); |
|
if (((di->chip == BQ274XX) || (di->chip == BQ276XX)) && |
!rom_mode_gauge_dm_initialized(di)) { |
rom_mode_gauge_dm_init(di); -------------------+ |
} | |
| |
bq27x00_update(di); -------------------*-------+
| |
if (poll_interval > ) { | |
/* The timer does not have to be accurate. */ | |
set_timer_slack(&di->work.timer, poll_interval * HZ / ); | |
schedule_delayed_work(&di->work, poll_interval * HZ); | |
} | |
} | |
| |
#define INITCOMP_TIMEOUT_MS 10000 | |
static void rom_mode_gauge_dm_init(struct bq27x00_device_info *di) <----+ |
{ |
int i; |
int timeout = INITCOMP_TIMEOUT_MS; |
u8 subclass, offset; |
u32 blk_number; |
u32 blk_number_prev = ; |
u8 buf[]; |
bool buf_valid = false; |
struct dm_reg *dm_reg; |
|
dev_dbg(di->dev, "%s:\n", __func__); |
|
while (!rom_mode_gauge_init_completed(di) && timeout > ) { |
msleep(); |
timeout -= ; |
} |
|
if (timeout <= ) { |
dev_err(di->dev, "%s: INITCOMP not set after %d seconds\n", |
__func__, INITCOMP_TIMEOUT_MS/); |
return; |
} |
|
if (!di->dm_regs || !di->dm_regs_count) { |
dev_err(di->dev, "%s: Data not available for DM initialization\n", |
__func__); |
return; |
} |
|
enter_cfg_update_mode(di); |
for (i = ; i < di->dm_regs_count; i++) { |
dm_reg = &di->dm_regs[i]; |
subclass = dm_reg->subclass; |
offset = dm_reg->offset; |
|
/* |
* Create a composite block number to see if the subsequent |
* register also belongs to the same 32 btye block in the DM |
*/ |
blk_number = subclass << ; |
blk_number |= offset >> ; |
|
if (blk_number == blk_number_prev) { |
copy_to_dm_buf_big_endian(di, buf, offset, |
dm_reg->len, dm_reg->data); |
} else { |
|
if (buf_valid) |
update_dm_block(di, blk_number_prev >> , |
(blk_number_prev << ) & 0xFF , buf); |
else |
buf_valid = true; |
|
read_dm_block(di, dm_reg->subclass, dm_reg->offset, |
buf); |
copy_to_dm_buf_big_endian(di, buf, offset, |
dm_reg->len, dm_reg->data); |
} |
blk_number_prev = blk_number; |
} |
|
/* Last buffer to be written */ |
if (buf_valid) |
update_dm_block(di, subclass, offset, buf); |
|
exit_cfg_update_mode(di); |
} |
|
static void bq27x00_update(struct bq27x00_device_info *di) <----------------+
{
struct bq27x00_reg_cache cache = {, };
bool is_bq27200 = (di->chip == BQ27200);
bool is_bq27500 = (di->chip == BQ27500);
bool is_bq274xx = (di->chip == BQ274XX);
bool is_bq276xx = (di->chip == BQ276XX); cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, !is_bq27500);
if (cache.flags >= ) {
if (is_bq27200 && (cache.flags & BQ27200_FLAG_CI)) {
dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
cache.capacity = -ENODATA;
cache.energy = -ENODATA;
cache.time_to_empty = -ENODATA;
cache.time_to_empty_avg = -ENODATA;
cache.time_to_full = -ENODATA;
cache.charge_full = -ENODATA;
cache.health = -ENODATA;
} else {
cache.capacity = bq27x00_battery_read_soc(di);
if (!(is_bq274xx || is_bq276xx)) {
cache.energy = bq27x00_battery_read_energy(di);
cache.time_to_empty =
bq27x00_battery_read_time(di,
BQ27XXX_REG_TTE);
cache.time_to_empty_avg =
bq27x00_battery_read_time(di,
BQ27XXX_REG_TTECP);
cache.time_to_full =
bq27x00_battery_read_time(di,
BQ27XXX_REG_TTF);
}
cache.charge_full = bq27x00_battery_read_fcc(di);
cache.health = bq27x00_battery_read_health(di);
}
cache.temperature = bq27x00_battery_read_temperature(di);
if (!is_bq274xx)
cache.cycle_count = bq27x00_battery_read_cyct(di);
cache.power_avg =
bq27x00_battery_read_pwr_avg(di, BQ27XXX_POWER_AVG); /* We only have to read charge design full once */
if (di->charge_design_full <= ) // pay attention at here
di->charge_design_full = bq27x00_battery_read_dcap(di); printk("---------------------------------------\n");
printk("cache.capacity : %d\n", cache.capacity);
printk("cache.energy : %d\n", cache.energy);
printk("cache.time_to_empty : %d\n", cache.time_to_empty);
printk("cache.charge_full : %d\n", cache.charge_full);
printk("cache.health : %d\n", cache.health);
printk("cache.tmperature : %d\n", cache.temperature);
printk("cache.power_avg : %d\n", cache.power_avg);
printk("di->charge_design_full : %d\n", di->charge_design_full);
printk("---------------------------------------\n");
} if (memcmp(&di->cache, &cache, sizeof(cache)) != ) {
di->cache = cache;
power_supply_changed(&di->bat);
} di->last_update = jiffies;
}
can't able to update the design capacity in bq27441-G1的更多相关文章
- The The Garbage-First (G1) collector since Oracle JDK 7 update 4 and later releases
Refer to http://www.oracle.com/technetwork/tutorials/tutorials-1876574.html for detail. 一些内容复制到这儿 Th ...
- bq27441-G1 工作机制
/*************************************************************************** * bq27441-G1 工作机制 * 声明: ...
- usb.ids
# # List of USB ID's # # Maintained by Vojtech Pavlik <vojtech@suse.cz> # If you have any new ...
- TI单节电量计基本介绍及常见问题解答
电量计(gas gauge /fuel gauge)是用来计量显示电池电量,通常包括mAh剩余容量(RM),满充容量(FCC),百分比容量(SOC),电压,电流,温度等,部分电量计还包含放空,充满时间 ...
- LSI Storcli 工具使用
查看RAID卡ID 命令功能 查看LSI SAS3108RAID卡的ID. 命令格式 storcli64 show 使用实例 # 查看LSI SAS3108RAID卡的ID. [root@localh ...
- Java Hotspot G1 GC的一些关键技术
G1 GC,全称Garbage-First Garbage Collector,通过-XX:+UseG1GC参数来启用,作为体验版随着JDK 6u14版本面世,在JDK 7u4版本发行时被正式推出,相 ...
- I.MX6 bq27441 driver hacking
/************************************************************************* * I.MX6 bq27441 driver ha ...
- Win32_Battery class
wmi的Win32_Battery类实现 其中EstimatedChargeRemaining属性返回剩余电量的百分比,EstimatedRunTime属性返回剩余时间(分钟) 其他属性参考http: ...
- SQL 基础学习(1):下载DB Browser for SQLite. 下载graphviz(为了使用Rails ERD的前提)出现❌,已debug.
SQL is a standard language for storing, manipulating and retrieving data in databases. 关系型数据库:RDBMS( ...
随机推荐
- Python学习笔记2——模块的发布
1.为模块nester创建文件夹nester,其中包含:nester.py(模块文件): """这是"nester.py"模块,提供了一个名为prin ...
- (转)《深入理解java虚拟机》学习笔记1——Java内存结构
java虚拟机规范规定的java虚拟机内存其实就是java虚拟机运行时数据区,其架构如下: 其中方法区和堆是由所有线程共享的数据区. Java虚拟机栈,本地方法栈和程序计数器是线程隔离的数据区. (1 ...
- MVC5 Bundles发布到IIS失效问题解决方案
MVC中Bundles可以提高代码的可重用性 我每个页面都需要用到这十几个JS+CSS 当我把MVC发布到服务器以后,Bundles中的JS和CSS会失效的时候 宝宝的心里是崩溃的.... 查了很多资 ...
- 【linux程序设计4th】第三章1
makefile .PHONY:clean all CC=gcc CFLAGS=-Wall -g ###replace your bin BIN=simple_write simple_read co ...
- this.Invoke和this.BeginInvoke的区别
private void button1_Click(object sender, EventArgs e) { "; this.Invoke(new EventHandler(delega ...
- PAT-乙级-1020. 月饼 (25)
1020. 月饼 (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 月饼是中国人在中秋佳节时吃的一种传统食 ...
- sql不重复的查找统计数据(经典)
例表如下: 表名:MYTEST TID COL1 COL2 COL3 1 1 A A2 1 ...
- discuz云平台报调用远程接口失败的问题分析和解决
根据网络两篇文章整理 问题描述:当开通或关闭某个云平台服务的时候,报如下错误信息:调用远程接口失败.请检查您的服务器是否处于内网以及您服务器的防火墙设置. 云平台测试站点的接口文件正常,于是开始在文件 ...
- 线索二叉树Threaded binary tree
摘要 按照某种遍历方式对二叉树进行遍历,可以把二叉树中所有结点排序为一个线性序列.在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点:除最后一个结点外每一个结点有且仅有一个直接后继结点.这 ...
- C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
学C++的时候,这几个输入函数弄的有点迷糊:这里做个小结,为了自己复习,也希望对后来者能有所帮助,如果有差错的地方还请各位多多指教(本文所有程序均通过VC 6.0运行) 1.cin 2.cin.get ...