充电IC驱动调试----移植充电IC bq25601

2023-11-09

关键词: MTK android 充电IC
内核: linux3.18
系统: android7.0
作者: arunboy(欢迎转载,请注明作者)

在原有展讯平台下面的bq25601的基础上编写mtk平台下的bq25601代码,参考mtk平台下的.并进行相关调试.
充电IC的移植是在kernel和lk里面,lk里面是mt_battery.c中调用了以下几个函数

#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

首先参考两个代码新建了一个文件,把一些接口函数进行了替换.然后查看数据手册修改数组,寄存器的值.
截图
图中的数组都是查看数据手册然后进行填充,下面那些使用字母的因为在别的文件中定义了数字.

电池充电有三个阶段:预充电阶段,恒流充电,恒压充电.
预充电阶段:设置充电电流一般为500mA以下
恒流充电阶段:电压一般在3.2~4.1v左右,充电器的输入电压会越来越高
恒压充电阶段:4.2v左右,充电ic输出电压不变,电流逐渐减小.

驱动代码分析

1.bq25601.c

/**********************************************************
  *
  *   [I2C Slave Setting]
  *
  *********************************************************/
#define bq25601_SLAVE_ADDR_WRITE   0xD6//根据数据手册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

//充电的一些初始化的值,根据数据手册的某个寄存的的某位代表的什么意思进行设值.
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;
}

然后把这几个函数进行填充完整就行,根据项目需求,有的不需要.

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;

主要记录两个函数,i2c的读写数据的函数:

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里面,就是实现 bq25601_hw_init(),bq25601_charging_enable(bEnable),bq25601_dump_register()这三个函数,基本上和kernel里面的差不多.
4.参考数据手册几个有关充电IC的参数
Termination Current 截止电流,一般设置为200mA以下
Charge Voltage 充电IC的输出电压
Precharge current 预充电电流,一般设置为500mA以下
VAG OVP 最高电压,bq25601可以支持到14v
Absolute VINDPM Threshold 充电IC的最高输出

总结

编写调试驱动代码一定要认真,特别注意宏定义,加上了没,有没有把以前的宏定义注释掉,而且要查看一下有没有在Makefile,Kconfig中添加修改,报错的话要看错误提示,然后去查错误类型,有的报的这个地方的错误但是错误不在这个文件当中.
kernel-3.18/arch/arm64/boot/dts/project_bat_setting.dtsi可以配置电池曲线,充电属性等相关配置.注意还有一个电阻值的配置,如果与硬件不匹配,会导致误差较大.
这里写图片描述

问题

pmic检测充电器状态不对,改用了通过读取充电IC的寄存器的状态来判断是否在充电.查寻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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

充电IC驱动调试----移植充电IC bq25601 的相关文章

随机推荐

  • vcs编译vivado原语:

    使用vcs verdi问题较少 使用vlogan vcs verdi三步编译 vlogan vlogan V sverilgo ignore unique checks libext sv vp vlib svh l vlogan comp
  • include_directories和find_package

    通过一个自己要写的工程文件 终于弄明白了CMakeLists中的include directories和find package是什么意思了 简单而言 cmake本身不提供任何搜索库的便捷方法 所有搜索库并给变量赋值的操作必须由cmake代
  • Typora 语法说明

    Markdown介绍 Markdown 是一种轻量级标记语言 它允许人们使用易读易写的纯文本格式编写文档 Markdown 语言在 2004 由约翰 格鲁伯 英语 John Gruber 创建 Markdown 编写的文档可以导出 HTML
  • Docker Desktop 如何运行容器

    第一次使用windows环境下的DockerDesktop记录下使用方法 1 配置镜像源 虽然配置了镜像源 但是在界面你还是搜索不到镜像 应该默认使用的是官方dockerhub的原因 后面可以手动创建避开这个问题 2 运行系统的window
  • IntelliJ IDEA里Maven默认情况下编译版本为JDK1.5

    2019独角兽企业重金招聘Python工程师标准 gt gt gt IntelliJ IDEA里面Maven插件 如果pom xml里面没有设置编译版本 便采用默认的1 5版本 即便安装的JDK是jdk1 7 jdk1 8也是采用1 5版本
  • flutter中TextField光标偏移处理

    在flutter中当使用localizationsDelegates国际化之后 TextField输入框的光标出现了偏移错位的情况 只需要在style中加入textBaseline TextBaseline alphabetic就可以解决光
  • Java(变量+int+double+String+boolean四种数据类型)

    JavaDAY2 变量 int double String boolean四种数据类型 1 变量 表示变化的量 2 变量的简单运算 3 整数int与小数double 4 字符串String 5 布尔boolean 非此即彼 1 变量 表示变
  • Docker基本操作

    镜像命名规范 镜像名称一般分两部分组成 repository tag 如 mysql 8 1 在没有指定tag时 默认是latest 代表最新版本的镜像 Docker常用操作 在docker官网中输入你要的镜像名称 https hub do
  • 宋浩高等数学笔记(十)重积分

    本章更新第10章重积分 关于三重积分的应用部分暂时略过 本部分在考察的时候不会很难 困难在于对重积分本质的理解 以及极坐标下相关公式的计算 类比普通的定积分 如果对一个宽度不均匀的函数 求积分分后相当于计算总的面积 而对1积分则是相当于这段
  • HTML页面添加自定义水印(watermark)

    在需要引入HTML页面添加方法 document ready function 开启水印 watermark set 雨天路滑 小心驾驶 关闭水印 watermark del 页面添加水印效果 页面添加水印效果 method set 设置水
  • vue elmentui 日期选择器 多段时间 不可选

    日期选择器 实现动态的多段时间禁用
  • dijikstra 旅行商问题_『数学建模』TSP和MTSP问题

    2020 7 14更新 补充一下后续获奖情况 这次比赛我们小队获得了三等奖 为本次比赛中唯一获奖的大一学生队伍 完整问题及详细地参赛论文地址 2019 12 02 校内数模新手赛 blog csdn net 数模问题梗概 先给出一张地铁路线
  • 基于pygame的消消乐小游戏开发

    1 简介 今天向大家介绍一个帮助往届学生完成的毕业设计项目 基于pygame的消消乐小游戏开发 计算机毕业生设计 课程设计需要帮助的可以找我 2 设计概要 21世纪是信息化时代 随着信息技术和网络技术的发展 信息化已经渗透到人们日常生活的各
  • 用引用函数找出包含20个元素的整型数组中的最大值最小值以及其平均值(使用随机数初始化数组)#C++

    用引用函数找出包含20个元素的整型数组中的最大值最小值以及其平均值 使用随机数初始化数组 利用选择排序法 代码如下 include
  • 磁盘一把锁一个感叹号_硬盘上面一个感叹号是什么东西。求高手帮忙解决下。谢谢(下图)...

    出现这个提示是我隔热觉得是系统临时文件太多了 或是磁盘坏道出了问题引起的 看看下面的方法 不过还是要看看你的D盘 能不能进去读取数据 1 任务栏右下角出现这种提示 某文件损坏 请运行运用chkdsk工具修复 一般是系统垃圾文件太多导致的 主
  • 个人安装Ubuntu20.04和修复BIOS引导的过程(2022年5月)

    记录一下我个人安装Ubuntu20 04和修复BIOS引导的过程 不建议全部按照我的方法做 步骤9建议按照这个链接 https askubuntu com questions 1314321 select device boot insta
  • 一个完整的产品设计都要哪些设计流程

    设计理念是抽象的 它描述了一个产品从概念到完成的一般过程 然而 真正的产品设计过程要复杂得多 也要具体得多 因此 我们将分解这个过程中最重要的部分 并给实践中使用的建议 1 设计前期 通常 设计过程的第一步在产品设计之前就已经开始了 这是因
  • 如何利用数组实现高精度算法

    目录 引言 原理介绍 数据的输入 数字对齐的格式 以加法为例 小细节tips 代码如下 代码分析与书写过程 第一段 书写结构体 第二段 将字符串转化为数字输入数组 第三段 进行高精度数据的运算 以加法为例 最后一步 输出 引言 在C C 语
  • 分区容错性是什么意思_一篇文章搞清楚什么是分布式系统 CAP 定理

    专注于Java领域优质技术号 欢迎关注 来自 小旋锋 CAP定理是分布系统中的一个基本定理 它指出任何分布系统最多可以具有以下三个属性中的两个 一致性 Consistency 可用性 Availability 分区容错性 Partition
  • 充电IC驱动调试----移植充电IC bq25601

    关键词 MTK android 充电IC 内核 linux3 18 系统 android7 0 作者 arunboy 欢迎转载 请注明作者 在原有展讯平台下面的bq25601的基础上编写mtk平台下的bq25601代码 参考mtk平台下的