EC与BIOS&OS的通信

62/66 端口介绍

HOST可以通过62/66 IO端口或者MMIO访问EC共享的RAM,62/66端口不像CMOS端口可以直接读写,在读写之前还要判断端口数据是否准备好了以及端口是否为空。

EC端口寄存器

在这里插入图片描述
读66端口,相当于读EC的状态,写66端口相当于给EC写命令,数据端口为62端口

状态寄存器

在这里插入图片描述
状态寄存器大小为一个字节,BIT0和BIT1可以用于HOST判断EC端口是否可写,或者是否有数据可以读取。而BIT3可用于EC端判断HOST下发的是数据还是命令

EC命令

在这里插入图片描述
这些命令是HOST端下发给EC的,0x80命令代表HOST要读EC RAM,0x81命令代表HOST要写EC RAM,0x82和0x83则表示是否要开启快速访问。0x84则表示HOST之前收到了EC的中断通知,要读取Q event。

读写EC RAM实例

1.判断端口状态函数

#define EC_TIME_OUT		    10000
#define EC_S_IBF            0x02    // Input buffer is full/empty
#define EC_S_OBF            0x01    // Output buffer is full/empty
#define STATE_SUCCESS       0x00
#define STATE_ERROR         0x01
#define EC_D_PORT           0x62
#define EC_C_PORT           0x66
#define EC_C_READ_MEM       0x80    // Read the EC memory
#define EC_C_WRITE_MEM      0x81    // Write the EC memory

uint8_t WaitECIbe (
  uint8_t              CommandState
  )
{
  uint8_t                 ECCmdState = 0;
  uint8_t                 Index;

  for (Index = 0; Index < EC_TIME_OUT; Index++) {
    ECCmdState = (uint8_t)ioread8 (CommandState);
    if (!(ECCmdState & EC_S_IBF)) {
      return STATE_SUCCESS;
    } else{
      usleep(15); 
    }
  }
  return STATE_ERROR;
}

uint8_t WaitECObf (
  uint8_t              CommandState
)
{
  uint8_t                 ECCmdState = 0;
  uint8_t                 Index;

  for (Index = 0; Index < EC_TIME_OUT; Index++) {
    ECCmdState = (uint8_t)ioread8 (CommandState);
    if (ECCmdState & EC_S_OBF) {
      return STATE_SUCCESS;
    } else{
      usleep(15);
    }
  }

  return STATE_ERROR;
}

WaitECIbe 用于判断端口是否为空,WaitECObf 用于判断是否准备好数据。

2.发送命令以及读写数据

void SendDataToEc (
  uint8_t                               Port,
  uint8_t                               Data
  )
{
  WaitECIbe (Port);                   // Wait Input Buffer Empty
  iowrite8 (Port - 4, Data);
  WaitECIbe (Port);                   // Wait Input Buffer Empty
}

void SendCmdToEc (
  uint8_t                               Port,
  uint8_t                               Cmd
  )
{

  WaitECIbe (Port);                   // Wait Input Buffer Empty
  iowrite8 (Port, Cmd);
  WaitECIbe (Port);                   // Wait Input Buffer Empty

}


uint8_t GetDataFromEc (
  uint8_t                               Port
  )
{
  uint8_t         Data;

  WaitECIbe (Port);                   // Wait Input Buffer Empty
  WaitECObf (Port);                   // Wait Output Buffer Full
  Data = ioread8 (Port - 4);

  return Data;
}

以上三个函数分别用于发送数据和命令以及读取数据。有了上面三个函数之后就可以操作EC了。
3.读写EC函数

void ECWrite(
  uint8_t    Index,
  uint8_t    Value
  )
{
  //
  // Write Command
  //
  SendCmdToEc (EC_C_PORT, EC_C_WRITE_MEM);

  //
  // send ECRAM offset to DATA port
  //
  SendDataToEc (EC_C_PORT, Index);

  //
  // Write DATA to EC ram
  //
  SendDataToEc (EC_C_PORT, Value);
}

首先发送0x81命令给EC告诉EC要写EC RAM,然后发送要写的index,最后把数据写入。
而读函数的话则需要把命令换为0x80。

uint8_t ECRead(
  uint8_t    Index
  )
{
  SendCmdToEc (EC_C_PORT, EC_C_READ_MEM);

  //
  // send ECRAM offset to DATA port
  //
  SendDataToEc (EC_C_PORT, Index);

  //
  // get DATA from EC
  //
  return GetDataFromEc (EC_C_PORT);
}

4.在BIOS下IoLib里面有IoRead8和IoWrite8函数调用,而在linux下可以实现如下

#include <stdint.h>
#include <stdbool.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
static int fd;
bool port_dev_init(void)
{
    fd = open("/dev/port", O_RDWR);
    if (fd < 0) {
        return false;
    }  
    return true;
}
void port_dev_exit(void)
{
    close(fd);
}
uint8_t ioread8(uint16_t port)
{
    uint8_t buf[2] = { 0 };
    lseek(fd, port, SEEK_SET);
    read(fd, buf, 1);
    return buf[0];
}
void iowrite8(uint16_t port, uint8_t data)
{
    uint8_t buf[2] = { 0 };
    lseek(fd, port, SEEK_SET);
    buf[0] = data;
    write(fd, buf, 1);
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值