bq24735 linux 驱动详解 AC检测

bq24735是TI推出的一款充电芯片,工作中刚好,使用该芯片进行设计工作。

首先简单了解一下bq24735的寄存器介绍

bq24735寄存器比较简单,程序编写过程中,都会用到这些寄存器。

首先驱动使用i2c_driver类型,驱动采用传统的模式,在board中注册,这里需要注意的是bq24735地址

	{
		.type = "bq24735",
		.platform_data=	&bq24735_exchg_data,
		.addr = 0x09,
	},

这里bq24735_exchg_data可以定义一些私有数据,一般把bq24735初始化设置充电电压、充电电流、输入电流配置放进去,根据个人偏好处理吧,我个人基本上会把这个参数置空,因为不想每次都改动board文件了,有需求的话就直接修改bq24735驱动。

bq24735的驱动文件也很简单了,主要步骤就是

1.进入probe

2.读取bq24735 ID

    		ret = bq24735_read_word(client, BQ24735_MANUFACTURER_ID);
		if (ret < 0) {
			dev_err(&client->dev, "Failed to read manufacturer id : %d\n",
				ret);
			return ret;
		} else if (ret != 0x0040) {
			dev_err(&client->dev,
				"manufacturer id mismatch. 0x0040 != 0x%04x\n", ret);
			return -ENODEV;
		}
		/* Sleep at least 525ns to allow the reset to complete */
	        msleep(500);
	        ret = bq24735_read_word(client, BQ24735_DEVICE_ID);
	        if (ret < 0) {
		    dev_err(&client->dev, "Failed to read device id : %d\n", ret);
		    return ret;
	        } else if (ret != 0x000B) {
		    dev_err(&client->dev,
			"device id mismatch. 0x000b != 0x%04x\n", ret);
		    return -ENODEV;
	        }

3.配置bq24735的充电电压、充电电流、输入电流。这里需要注意的是,配置的值不是随便写的,需要到bq24735手册上查询,确定每个bit的配置含义,然后计算出自己想要配置的数值,然后写入对应的寄存器。

		ret = bq24735_write_word(charger->client,
					 BQ24735_CHARGE_CURRENT, value);
		if (ret < 0) {
		    dev_err(&charger->client->dev,
			"Failed to write charger current : %d\n",ret);
		    return ret;
                }

		ret = bq24735_write_word(charger->client,
					 BQ24735_CHARGE_VOLTAGE, value);
		if (ret < 0) {
		    dev_err(&charger->client->dev,
			"Failed to write charger voltage : %d\n",ret);
		    return ret;
		}
		ret = bq24735_write_word(charger->client,
					 BQ24735_INPUT_CURRENT, value);
		if (ret < 0) {
		    dev_err(&charger->client->dev,
		    "Failed to write input current : %d\n",ret);
		    return ret;
                }

4.关于AC插入检测

bq24735是可以检测是否有外部适配器插入检测,然后通过进行是否充电控制。检测的方法最好通过bq24735的ACDET管教进行,那要在驱动中实现一个GPIO的中断检测,这里我没有那样处理,而是在内核开启一个定时器,每秒钟读取bq24735的状态寄存器,查看是否有AC插入,如果有就使能充电,如果没有就关闭充电。

init_timer(&bq24735_timer);
bq24735_timer.function = bq24735_scan;
bq24735_timer.data = 0;
bq24735_timer.expires = jiffies + HZ;
add_timer(&bq24735_timer);


void bq24735_scan()
{
    if (bq24735_charger_is_present(charger))
	bq24735_enable_charging(charger);
    else
	bq24735_disable_charging(charger);
    bq24735_timer.expires = jiffies + HZ;
    add_timer(&bq24735_timer);
}

这样处理响应的实时性虽说差不多(凑合能用),但是比较占用CPU资源,最好还是采用GPIO中断的方式,来进行AC插入检测。等我调试了GPIO中断方式,再写一篇帖子来细说吧,当前任务先把项目交付。

5.使用到的一些关键宏函数,手动做了一点改动,基本上意思能表示清楚了,要借鉴的话,还是需要自己做点处理。

#define BQ24735_CHG_OPT			0x12
#define BQ24735_CHG_OPT_CHARGE_DISABLE	(1 << 0)
#define BQ24735_CHG_OPT_AC_PRESENT	(1 << 4)
#define BQ24735_CHARGE_CURRENT		0x14
#define BQ24735_CHARGE_CURRENT_MASK	0x1fc0
#define BQ24735_CHARGE_VOLTAGE		0x15
#define BQ24735_CHARGE_VOLTAGE_MASK	0x7ff0
#define BQ24735_INPUT_CURRENT		0x3f
#define BQ24735_INPUT_CURRENT_MASK	0x1f80
#define BQ24735_MANUFACTURER_ID		0xfe
#define BQ24735_DEVICE_ID		0xff



static inline int bq24735_write_word(struct i2c_client *client, u8 reg,
				     u16 value)
{
	return i2c_smbus_write_word_data(client, reg, le16_to_cpu(value));
}

static inline int bq24735_read_word(struct i2c_client *client, u8 reg)
{
	s32 ret = i2c_smbus_read_word_data(client, reg);

	return ret < 0 ? ret : le16_to_cpu(ret);
}

static int bq24735_update_word(struct i2c_client *client, u8 reg,
			       u16 mask, u16 value)
{
	unsigned int tmp;
	int ret;

	ret = bq24735_read_word(client, reg);
	if (ret < 0)
		return ret;

	tmp = ret & ~mask;
	tmp |= value & mask;

	return bq24735_write_word(client, reg, tmp);
}

static inline int bq24735_enable_charging(struct bq24735 *charger)
{
	return bq24735_update_word(charger->client, BQ24735_CHG_OPT,
				   BQ24735_CHG_OPT_CHARGE_DISABLE,
				   ~BQ24735_CHG_OPT_CHARGE_DISABLE);
	
}

static inline int bq24735_disable_charging(struct bq24735 *charger)
{
	return bq24735_update_word(charger->client, BQ24735_CHG_OPT,
				   BQ24735_CHG_OPT_CHARGE_DISABLE,
				   BQ24735_CHG_OPT_CHARGE_DISABLE);
}



static bool bq24735_charger_is_present(struct bq24735 *charger)
{

	int ac = 0;

	ac = bq24735_read_word(charger->client, BQ24735_CHG_OPT);
	if (ac < 0) {
		dev_err(&charger->client->dev,
		"Failed to read charger options : %d\n",ac);
		return false;
	}
	bq24735_write_word(charger->client,
					 BQ24735_CHG_OPT, /*0xf912*/0x9912);
	return (ac & BQ24735_CHG_OPT_AC_PRESENT) ? true : false;
}

针对上述表述上传一个参考代码

https://download.csdn.net/download/li171049/12665363

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大牛攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值