hisi3516dv300芯片基于hwmon驱动框架的温度获取驱动源码分析
Posted 正在起飞的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hisi3516dv300芯片基于hwmon驱动框架的温度获取驱动源码分析相关的知识,希望对你有一定的参考价值。
1、内核hwmon驱动框架
2、驱动实现的效果
/sys/devices/virtual/hwmon/hwmon0 # pwd
/sys/class/hwmon/hwmon0
/sys/devices/virtual/hwmon/hwmon0 # ls
power subsystem temp1_input uevent
/sys/devices/virtual/hwmon/hwmon0 # cat temp1_input
41
/sys/devices/virtual/hwmon/hwmon0 #
(1)在sysfs中可以看到/sys/class/hwmon/hwmon0文件夹,里面有temp1_input文件;
(2)读取temp1_input文件,里面是芯片的温度值;
(3)文件夹名字不一定是hwmon0,如果你注册了不止一个hwmon设备,文件夹名字有可能是hwmon0或者hwmon1,看你注册hwmon设备的先后顺序;
3、获取芯片温度驱动的思路分析
(1)向内核hwmon驱动框架注册我们的驱动,在hwmon类下面创建相应的设备;
(2)填充创建的hwmon类设备的设备属性,创建保存温度值的文件,指定文件的show方法;
(3)对海思芯片温度传感器相关的寄存器进行动态映射;
(4)初始化海思芯片温度相关的寄存器,包括设置温度检测模式为循环模式、循环检测周期、使能等;
(5)应用通过读取temp1_input文件获取温度,实际就是执行temp1_input文件的show方法;
(6)在show方法中,读取温度记录值寄存器的值,计算出温度值并返回;
4、芯片自带的温度传感器
地址偏移量 | 寄存器编号 | 寄存器名字 |
---|---|---|
0x00B4 | MISC_CTRL45 | Tsensor控制寄存器 |
0x00B8 | MISC_CTRL46 | Tsensor 状态寄存器 |
0x00BC | MISC_CTRL47 | Tsensor 温度记录值寄存器 0 |
0x00C0 | MISC_CTRL48 | Tsensor 温度记录值寄存器 1 |
0x00C4 | MISC_CTRL49 | Tsensor 温度记录值寄存器 2 |
0x00C8 | MISC_CTRL50 | Tsensor 温度记录值寄存器 3 |
5、寄存器功能描述
5.1、Tsensor控制寄存器
(1)温度检测模式:一般选择循环检测模式,不停的去检测温度;
(2)循环检测周期:当设置为循环检测模式时要设置,就是每隔多长时间去检测一次温度,注意单位是2ms;
(3)温度上/下溢值:往寄存器写入值,表示芯片温度超过这个值时会触发Tsensor 状态寄存器的温度上/下溢报警位。这几个寄存器的位不是直接写温度值,有换算关系,hisi3516dv300的数据手册没有明确写出,但是按照海思其他芯片推测,应该是(tsensor_uplimit -136)/793*165-40
;
5.2、Tsensor 状态寄存器
(1)如果在Tsensor控制寄存器寄存器中设置了温度上/下溢值,则需要检测温度下溢告警位;
(2)其他的位不用也没什么影响,不设置也是可以正常工作;
5.3、Tsensor温度记录值寄存器
(1)总共有4个温度记录值寄存器,每个寄存器的bit位含义都是一样的;
(2)每个温度记录值寄存器都保存了两个温度值,分别保存在[9:0]和[25:16]bit位;
(3)Soc在4个温度记录值寄存器中保存了8个温度值,我们需要读出8个温度值来计算一个平均的温度值;
(4)温度计算公式:Temprature=(tsensor_result[0:1] -136)/793*165-40(单位:度);
6、芯片内部温度检测流程
步骤 1:设置 T-Sensor 采集模式 MISC_CTRL45[30]。
步骤 2:如果设置为循环采集模式,需设置循环采集周期 MISC_CTRL45[27:20];如果设置为单次采集模式,可略过此步骤。循环采集周期计算公式为: T = N × 2(ms),其中 N=MISC_CTRL45[27:20]。
步骤 3:使能 T-Sensor MISC_CTRL45[31],开始温度采集
步骤 4:软件读取T-Sensor采集到的温度码(十六进制值)。单次采集模式下,只有 MISC_CTRL47[9:0]中记录的温度记录码0有效。
循环采集模式下,MISC_CTRL47[31:0]~MISC_CTRL50[31:0]记录了最近八次温度记录码 0~7,其中最新的温度记录值为温度记录码 0。
步骤 5:根据温度记录码计算出对应的温度值。Temprature=(T-Senso -136)/793*165-40(单位:度);
7、驱动源码分析
7.1、驱动的注册函数
static int hisi3516d_hwmon_init(void)
int ret;
//向hwmon驱动框架注册我们的驱动
hisi3516d_hwmon_dev = hwmon_device_register(NULL);
if(IS_ERR(hisi3516d_hwmon_dev))
printk(KERN_ERR "hwmod device register faild\\n");
ret = PTR_ERR((void *)hisi3516d_hwmon_dev);
goto err_exit_3;
//填充hwmon驱动框架返回的设备,也就是创建设备下面的文件以及show、store方法
ret = sysfs_create_group(&hisi3516d_hwmon_dev->kobj,
&hisi3516d_hwmon_attribute_group);
if(ret)
printk(KERN_ERR "create sysfs group faild\\n");
goto err_exit_2;
//映射芯片温度相关寄存器的地址
ret = reg_remap();
if(ret)
printk(KERN_ERR "hi3559a hwmon ioremap faild\\n");
goto err_exit_1;
//初始化海思芯片的Tsensor寄存器
hisi3516d_temp_init();
return 0;
err_exit_1:
sysfs_remove_group(&hisi3516d_hwmon_dev->kobj,&hisi3516d_hwmon_attribute_group);
err_exit_2:
hwmon_device_unregister(hisi3516d_hwmon_dev);
err_exit_3:
return ret;
module_init(hisi3516d_hwmon_init);
(1)向hwmon驱动框架注册我们的驱动,得到一个设备结构体;
(2)填充设备结构体,给设备创建文件以及show、store方法;
(3)映射芯片温度相关寄存器的地址,这里采用的动态映射;
(4)初始化海思芯片的Tsensor寄存器,设置温度检测模式为循环模式、循环检测周期、使能等;
7.2、驱动的卸载函数
static void hisi3516d_hwmon_exit(void)
//解除寄存器的映射
reg_unmap();
//注销设备下的文件
sysfs_remove_group(&hisi3516d_hwmon_dev->kobj,&hisi3516d_hwmon_attribute_group);
//从hwmon驱动框架中注销驱动
hwmon_device_unregister(hisi3516d_hwmon_dev);
module_exit(hisi3516d_hwmon_exit);
就是注册函数的逆过程,释放资源,删除sysfs中创建的文件,从hwmon驱动框架中注销驱动;
7.3、创建temp1_input文件
struct device *hisi3516d_hwmon_dev;
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL, 0);
static struct attribute *hisi3516d_hwmon_attributes[] =
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL,
;
static struct attribute_group hisi3516d_hwmon_attribute_group =
.attrs = hisi3516d_hwmon_attributes,
;
(1)hisi3516d_hwmon_attribute_group变量是用来创建设备下的文件以及文件show、store方法的;
(2)文件名字是temp1_input,show方法是show_temp1_input()函数;
(3)SENSOR_DEVICE_ATTR宏的分析参考博客:https://blog.csdn.net/weixin_42031299/article/details/124890370;
7.4、读取Tsensor寄存器温度的函数
static ssize_t show_temp1_input(struct device *dev,
struct device_attribute *da, char *buf)
volatile unsigned int reg_val = 0;
unsigned int tmp_val = 0;
int32_t temperature_val = 0;
int32_t i = 0;
//获取温度记录值寄存器0寄存器中保存的两个温度值
reg_val = ioread32((void __iomem *)tsensorviraddr + T_SENSOR_RESULT0);
for(i = 0; i < 2; i++)
tmp_val = (reg_val >> (16*i)) & 0x3ff;
temperature_val += (tmp_val - 136)/793*165 - 40;
//获取温度记录值寄存器1寄存器中保存的两个温度值
reg_val = ioread32((void __iomem *)tsensorviraddr + T_SENSOR_RESULT1);
for(i = 0; i < 2; i++)
tmp_val = (reg_val >> (16*i)) & 0x3ff;
temperature_val += (tmp_val - 136)/793*165 - 40;
//获取温度记录值寄存器2寄存器中保存的两个温度值
reg_val = ioread32((void __iomem *)tsensorviraddr + T_SENSOR_RESULT2);
for(i = 0; i < 2; i++)
tmp_val = (reg_val >> (16*i)) & 0x3ff;
temperature_val += (tmp_val - 136)/793*165 - 40;
//获取温度记录值寄存器3寄存器中保存的两个温度值
reg_val = ioread32((void __iomem *)tsensorviraddr + T_SENSOR_RESULT3);
for(i = 0; i < 2; i++)
tmp_val = (reg_val >> (16*i)) & 0x3ff;
temperature_val += (tmp_val - 136)/793*165 - 40;
//温度值除以8,获取平均值
temperature_val = temperature_val >> 3;
sprintf(buf, "%d", temperature_val);
return strlen(buf);
(1)tsensorviraddr:温度相关寄存器动态映射后得到的基地址;
(2)获取8个温度值,然后再返回温度的平均值;
(3)当我们用"cat /sys/class/hwmon/hwmon0/temp1_input"命令读取temp1_input文件时,驱动里就调用show_temp1_input()函数,这是temp1_input文件的show方法;
以上是关于hisi3516dv300芯片基于hwmon驱动框架的温度获取驱动源码分析的主要内容,如果未能解决你的问题,请参考以下文章
Hi3516开发笔记:海思HI3516DV300芯片介绍,入手开发板以及Demo测试
#物联网征文#FFHHi3516DV300驱动开发——编写LED灯控制程序