Linux Superio Read CPU FAN RPM

​ 之前写了一篇Linux下利用Superio控制GPIO的教程,这次继续利用Superio读取CPU风扇转速,CPU风扇属于环境控制器(EC),内置在IT8786E-I中,包括五个电压输入,三个温度传感器输入,五个FAN转速计输入和五组先进的风扇控制器。 EC监控硬件环境,实现个人电脑的环境控制。

000

大致流程

  1. 进入MB PnP 模式(87h, 01h, 55h, 55h;)

  2. 使能 EC(LDN=04h, Index 30h=01)

  3. 得到EC Base Address

    基地址由逻辑设备寄存器确定(index=60h, 61h)

    数据端口(Base+05h);数据端口(Base+06h)

  4. 配置风扇转速寄存器(index=0Ch,default=00h)

  5. 计算出风扇转速(index=0Dh,18h)

    001

  6. 退出MB PnP 模式(index=02h,default=02h)

LInux实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include<stdio.h>
#include<sys/io.h>
#include<unistd.h>
#include<math.h>

#define REG 0x2e
#define VAL 0x2f
#define CHIPID 0x20
#define CHIPREV 0x22

static int superio_inw(int reg)
{
int val;
outb(reg++, REG);
val = inb(VAL) << 8;
outb(reg, REG);
val |= inb(VAL);
return val;
}

static void init_ec()
{
//Enter MB PnP Mode
outb(0x87, REG);
outb(0x01, REG);
outb(0x55, REG);
outb(0x55, REG);

//使能EC控制器
outb(0x07, REG);
outb(0x04, VAL);
outb(0x30,REG);
outb(0x01,VAL);
}

int main()
{
unsigned int ec_base,addr_port,data_port,fan_speed,fan_rpm;
int ret = iopl(3);
if(ret == -1)
{
printf("iopl error.\n");
return -1;
}
//初始化
init_ec();

//获取EC控制器基地址
ec_base = superio_inw(0x60);
printf("ec_base addr:0x%x\n", ec_base);
addr_port = ec_base+0x05;
data_port = ec_base+0x06;
printf("addr_port is 0x%x data_port is 0x%x\n",addr_port,data_port);

//配置风扇转速计控制寄存器
outb(0x0c, addr_port);
outb(0x00, data_port);

//一起有三组,这里使用的第一组,也就是CPU_FAN
//1:CPU_FAN 2:SYS_FAN 3:PWR_FAN
//1-3 Reading Registers[7:0] (Index=0Dh-0Fh)
outb(0x0d,addr_port);
int lval = inb(data_port);
//1-3 Extended Reading Registers [15:8] (Index=18h-1Ah)
outb(0x18,addr_port);
int mval = inb(data_port);
//每转的内部时钟计数,这里是16位
fan_speed = (mval<<8) | lval;
printf("mval:%02x lval:%02x fan_speed is %d\n",mval, lval, fan_speed);
//最后根据芯片手册的公式计算出风扇转速
fan_rpm = 1.35*pow(10,6)/(fan_speed*2);
printf("fan_rpm is %d\n",fan_rpm);

//读取tmp1温度寄存器
outb(0x29, addr_port);
float tmpin1 = inb(data_port);
printf("tmpin1 is %.1f °C\n",tmpin1);

//Exit MB PnP Mode
outb(0x02, REG);
outb(0x02, VAL);
iopl(0);
return 0;
}

代码执行结果

002

项目地址:https://github.com/huchanghui123/IT87-SUPERIO-FAN.git

------ 本文结束------