目录
- 背景
- 一、芯片介绍
- 二、手册
- 三、内核驱动配置
- 3.1 设备树配置
- 3.2 修改内核配置文件
- 3.3 编译
- 四、内核驱动分析
- 1、初始化流程
- 2、属性文件/解释
- 五、调试和计算
背景
最近调试了一款德州仪器的带有I2C控制接口的可以实现电压、电流、功率监测,并可以进行报警设置的芯片INA226;
本文主要总结在linux 5.10下怎么配置内核将此芯片用起来,并总结内核中此芯片的驱动实现;
一、芯片介绍
INA226 是具有 I2C™ 或 SMBUS 兼容接口的电流分流
器和功率监测器。该器件同时监控分流压降和总线电源
电压。可编程校准值、转换时间、和均值计算,与一个
内部乘法器相组合,实现电流值(安培)和功率值
(瓦)的直接读取。
INA226 可在 0V 至 36V 的共模总线电压范围内感测电
流,与电源电压无关。 该器件由一个 2.7V 至 5.5V 的
单电源供电,汲取 330μA 的典型电源电流。该器件的
额定工作温度范围为 –40°C 至 125°C,I2C 兼容接口
上具有多达 16 个可编程地址。
二、手册
https://www.ti.com.cn/product/cn/INA226/part-details/INA226AIDGST
详细描述和硬件参考设计等见手册;
三、内核驱动配置
3.1 设备树配置
&i2cXXX {
status = “okay”;
ina226@xx {
compatible = “ti,ina226”;
reg = <0xXX>; //器件地址结合手册和硬件配置定义
shunt-resistor = <1000>; //采样电阻值单位是: micro-ohm 微欧姆,如果是1毫欧就乘以1000
};
};
3.2 修改内核配置文件
修改内核源码/arch/arm64/configs/xxxxxxx_defconfg配置文件,添加编译选项
CONFIG_SENSORS_INA2XX=y 编译到内核 或者
CONFIG_SENSORS_INA2XX=m 编译成模块
3.3 编译
配置成模块时,查看是否生成ina2xx.o 和 ina2xx.ko;
配置编译到内核时,查看是否生成ina2xx.o;
四、内核驱动分析
1、初始化流程
驱动和设备树表示的设备match后 -> ina2xx_probe 执行
static int ina2xx_probe(struct i2c_client *client)
{struct device *dev = &client->dev;struct ina2xx_data *data;struct device *hwmon_dev;u32 val;int ret, group = 0;enum ina2xx_ids chip;if (client->dev.of_node)chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev);//获取设备与驱动匹配后的of_device_id 结构里的数据,这的data为驱动不同芯片自定义的索引 ina219 为0 ,ina226为1elsechip = i2c_match_id(ina2xx_id, client)->driver_data;data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); //分配data结构的内存if (!data)return -ENOMEM;/* set the device type */data->config = &ina2xx_config[chip]; //结构ina2xx_config 的结构体赋值mutex_init(&data->config_lock);if (of_property_read_u32(dev->of_node, "shunt-resistor", &val) < 0) {struct ina2xx_platform_data *pdata = dev_get_platdata(dev); //读取设备树中定义的采样电阻值if (pdata)val = pdata->shunt_uohms; //得到采样电阻的阻值微欧姆elseval = INA2XX_RSHUNT_DEFAULT;}ina2xx_set_shunt(data, val);// struct ina2xx_data结构成员初始化ina2xx_regmap_config.max_register = data->config->registers; //芯片寄存器的个数data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config);//寄存器地址和值的位宽定义if (IS_ERR(data->regmap)) {dev_err(dev, "failed to allocate register map\n");return PTR_ERR(data->regmap);}ret = ina2xx_init(data);//初始化将默认值配置给配置寄存器,校准值配置给校准寄存器if (ret < 0) {dev_err(dev, "error configuring the device: %d\n", ret);return -ENODEV;}data->groups[group++] = &ina2xx_group;//通用属性组if (chip == ina226)data->groups[group++] = &ina226_group; //ina226 属性组hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,data, data->groups); //注册成硬件监控设备类if (IS_ERR(hwmon_dev))return PTR_ERR(hwmon_dev);dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",client->name, data->rshunt);return 0;
}
2、属性文件/解释
1、会生成如下属性文件和目录
2、举例解释
//属性文件in0_input ,ina2xx_value 属性只读对应 ina2xx_value_show 函数,INA2XX_SHUNT_VOLTAGE 采样电阻分压寄存器
static SENSOR_DEVICE_ATTR_RO(in0_input, ina2xx_value, INA2XX_SHUNT_VOLTAGE);//属性文件in1_input ,ina2xx_value 属性只读对应ina2xx_value_show 函数,INA2XX_BUS_VOLTAGE总线电压寄存器
static SENSOR_DEVICE_ATTR_RO(in1_input, ina2xx_value, INA2XX_BUS_VOLTAGE);
五、调试和计算
1、安装模块 或者编译进内核启动;
2、查看板卡/设备内属性目录
ls /sys/class/hwmon/hwmonX
3、以上属性文件内的数据为数字值,根据表示的数据内容的含义乘以分辨率,并结合具体的单位即可计算测量值,也可以与一期测量结果进行对比;