Linux SuperIO CPU FAN转速读取

By | 2019-09-27

上一篇文章介绍了在Linux用户空间使用outb接口,直接访问Superio芯片,操作GPIO寄存器的教程,这次继续利用Superio读取CPU风扇转速。
CPU风扇属于环境控制器(EC),内置在IT8786E-I中,包括五个电压输入,三个温度传感器输入,五个FAN转速计输入和五组先进的风扇控制器。 EC监控硬件环境,实现个人电脑的环境控制。

先查看芯片手册找到EC控制器接口总线地址

IT9896E-I

大致流程

  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)

CPU风扇转速计算公式如下:

风扇转速计算公式

代码如下:

#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;
}

执行结果

CPU RPM

One thought on “Linux SuperIO CPU FAN转速读取

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注