X86 Linux SuperIO 读取CPU风扇转速

硬件:工控主板K4005UP6
系统:Ubuntu 18.04LTS

k4005up6.png

CPU风扇属于环境控制器(EC),内置在IT8786E-I中,包括五个电压输入,三个温度传感器输入,五个FAN转速计输入和五组先进的风扇控制器。 EC监控硬件环境,实现个人电脑的环境控制。


000.png

流程

  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.png
  1. 退出MB PnP 模式(index=02h,default=02h)

Linux代码

#include
#include
#include
#include

#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.png

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

你可能感兴趣的:(X86 Linux SuperIO 读取CPU风扇转速)