博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
can't able to update the design capacity in bq27441-G1
阅读量:7104 次
发布时间:2019-06-28

本文共 12927 字,大约阅读时间需要 43 分钟。

/*************************************************************************** *       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 0;                                                             |      |}                                                                         |      |                                                                          |      |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 > 0) {                                             |       |        /* The timer does not have to be accurate. */                    |       |        set_timer_slack(&di->work.timer, poll_interval * HZ / 4);        |       |        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 = 0;                                                     |    u8 buf[32];                                                                  |    bool buf_valid = false;                                                      |    struct dm_reg *dm_reg;                                                       |                                                                                 |    dev_dbg(di->dev, "%s:\n", __func__);                                         |                                                                                 |    while (!rom_mode_gauge_init_completed(di) && timeout > 0) {                  |        msleep(100);                                                             |        timeout -= 100;                                                          |    }                                                                            |                                                                                 |    if (timeout <= 0) {                                                          |        dev_err(di->dev, "%s: INITCOMP not set after %d seconds\n",              |            __func__, INITCOMP_TIMEOUT_MS/100);                                  |        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 = 0; 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 << 8;                                              |        blk_number |= offset >> 5;                                               |                                                                                 |        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 >> 8,                        |                    (blk_number_prev << 5) & 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 = {
0, }; 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 >= 0) { 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 <= 0) // 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)) != 0) { di->cache = cache; power_supply_changed(&di->bat); } di->last_update = jiffies;}

 

转载地址:http://zvjhl.baihongyu.com/

你可能感兴趣的文章
FreeBSD8.2系统安装Salt
查看>>
HP 380G7安装 WIN2008 R2 SP1提示找不到系统分区
查看>>
1.2方程求根之不定点迭代法
查看>>
C#.NET通用权限管理系统组件中让系统按代码生成器的方式运行的方法
查看>>
Mysql主从复制 (suse 11 sp2)
查看>>
jQuery最佳实践
查看>>
gnome-terminal技巧
查看>>
jQuery插件开发全解析
查看>>
Visual Studio 2012/2010/2008 远程调试
查看>>
jsp页面传值的乱码问题总结
查看>>
名不副实的女解说员
查看>>
cacti批量添加主机和图形
查看>>
源代码安装
查看>>
dhcp在企业网的应用
查看>>
thinkphp U方法生成链接没有host
查看>>
ElasticSearch入门介绍之安装部署(二)
查看>>
continue与break的理解
查看>>
我的友情链接
查看>>
date用法示例_shell脚本
查看>>
Ubuntu命令行中文乱码的解决方法
查看>>