12.9. 通过嵌入式控制器的 SMBus 主控制器接口
本节规定了 ACPI 兼容 OS 可用于与基于嵌入式控制器的 SMBus 主控制器(EC-SMB-HC)通信的标准接口。该接口允许主机处理器(在 OSPM 控制下)管理 SMBus 上的设备。通常驻留在 SMBus 上的设备包括智能电池、智能电池充电器、对比度/背光控制器和温度传感器。
EC-SMB-HC 接口由一组驻留在嵌入式控制器空间中的寄存器块组成。软件使用这些寄存器来发起 SMBus 事务并接收 SMBus 通知。通过使用定义良好的寄存器集,OS 软件可以被编写为适用于任何供应商的嵌入式控制器硬件。
某些 SMBus 段具有特殊要求,即主控制器需过滤某些 SMBus 命令(例如,为防止失控的应用程序或病毒可能损坏电池子系统)。最容易实现这一点的方法,是通过嵌入式控制器来实现主机接口控制器——因为嵌入式控制器可以轻松过滤掉可能有问题的命令。
请注意,如果非 OS 代码会对设备资源执行可能存在争用的访问,则 EC-SMB-HC 接口将需要在其 ACPI 命名空间中包含 GLK 方法。有关使用 _GLK 方法的详细信息,请参见_GLK(全局锁)。
12.9.1. 寄存器说明
EC-SMBus 主机接口是一个平坦的寄存器数组,这些寄存器在嵌入式控制器地址空间中按顺序排列。
12.9.1.1. 状态寄存器,SMB_STS
该寄存器指示 SMBus 上的一般状态。这包括 SMB-HC 命令完成状态、已接收告警状态以及错误检测状态(错误码将在本节后面定义)。每当通过写入协议(SMB_PRTCL)寄存器发出新命令时,该寄存器都会被清零(ALRM 位除外)。在清除协议寄存器之前,始终先将错误代码写入该寄存器。SMB-HC 查询事件(即 SMB-HC 中断)会在协议寄存器清除之后被触发。
注意
OSPM 在对 ALRM 位完成服务后,必须通过向 SMB_STS 寄存器写入“00”来确保 ALRM 位被清除。
表 12.9 状态寄存器,SMB_STS
| Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
|---|---|---|---|---|---|---|---|
| Done | ALRM | RES | STATUS |
其中:
| DONE: | 表示上一条命令已完成且没有错误。 |
|---|---|
| ALRM: | 表示已接收到 SMBus 告警消息。 |
| RES: | 保留 |
| STATUS: | 表示 SMBus 通信状态,原因之一列于下表中。 |
表 12.10 SMBus 状态代码
| 状态代码 | 名称 | 描述 |
|---|---|---|
| 00h | SMBus 正常 | 表示事务已成功完成。 |
| 07h | SMBus 未知故障 | 表示由于未知的 SMBus 错误而失败。 |
| 10h | SMBus 设备地址未应答 | 表示事务失败,因为从设备地址未被应答。 |
| 11h | 检测到 SMBus 设备错误 | 表示事务失败,因为从设备发出了错误条件信号。 |
| 12h | SMBus 设备命令访问被拒绝 | 表示事务失败,因为 SMBus 主机不允许对所寻址设备执行特定命令。例如,SMBus 主机可能不允许调用方调整智能电池充电器的输出。 |
| 13h | SMBus 未知错误 | 表示事务失败,因为 SMBus 主机遇到了未知错误。 |
| 17h | SMBus 设备访问被拒绝 | 表示事务失败,因为 SMBus 主机不允许访问所寻址的设备。例如,SMBus 主机可能不允许调用方直接与控制系统电源平面的 SMBus 设备通信。 |
| 18h | SMBus 超时 | 表示事务失败,因为 SMBus 主机检测到总线上发生超时。 |
| 19h | SMBus 主机不支持的协议 | 表示事务失败,因为 SMBus 主机不支持所请求的协议。 |
| 1Ah | SMBus 忙 | 表示事务失败,因为 SMBus 主机报告 SMBus 当前正忙于其他某个事务。例如,智能电池可能正在向智能电池充电器发送充电信息。 |
| 1Fh | SMBus PEC (CRC-8) 错误 | 表示在上一笔事务期间发生了分组错误检查(PEC)错误。 |
所有其他错误代码均保留。
12.9.1.2. 协议寄存器,SMB_PRTCL
该寄存器决定在 SMBus 上生成的 SMBus 事务类型。除了向 SMB-HC 指示协议类型外,对该寄存器的写入还会在 SMBus 上发起该事务。请注意,协议值的第 7 位用于指示是否应采用分组错误检查。该位的值为 1(一个)表示指定协议应使用 PEC 格式,该位的值为 0(零)表示应使用标准(非 PEC)格式。
表 12.11 协议寄存器,SMB_PRTCL
| Bit7 | Bit6 to Bit0 |
|---|---|
| PEC | PROTOCOL |
其中 PROTOCOL 的值如下:
| 0x00 | 控制器未使用 |
|---|---|
| 0x01 | 保留 |
| 0x02 | 写快速命令 |
| 0x03 | 读快速命令 |
| 0x04 | 发送字节 |
| 0x05 | 接收字节 |
| 0x06 | 写字节 |
| 0x07 | 读字节 |
| 0x08 | 写字 |
| 0x09 | 读字 |
| 0x0A | 写块 |
| 0x0B | 读块 |
| 0x0C | 过程调用 |
| 0x0D | 块写-块读过程调用 |
例如,协议值 0x09 将用于与支持标准读字协议的设备通信。如果该设备也支持该协议的分组错误检查,则还可以选择使用值 0x89(带 PEC 的读字)。有关分组错误检查的更多信息,请参见 SMBus 规范。
当 OSPM 发起一个新命令,例如写入 SMB_PRTCL 寄存器时,SMBus 控制器首先更新 SMB_STS 寄存器,然后清除 SMB_PRTCL 寄存器。在 SMB_PRTCL 寄存器被清除之后,主控制器查询值会被触发。
所有其他协议值均保留。
12.9.1.3. 地址寄存器,SMB_ADDR
该寄存器包含要在 SMBus 上生成的 7 位地址。对于所有不同的协议,这是要在 SMBus 上发送的第一个字节。
表 12.12 地址寄存器,SMB_ADDR
| Bit7 to Bit1 | Bit0 |
|---|---|
| ADDRESS (A6:A0) | RES |
其中:
| RES: | 保留 |
|---|---|
| ADDRESS: | 7 位 SMBus 地址。该地址不是零对齐的(换句话说,它只是一个从位 1-7 对齐的 7 位地址(A6:A0))。 |
12.9.1.4. 命令寄存器,SMB_CMD
该寄存器包含将发送到 SMBus 上目标设备的命令字节,并用于以下协议:发送字节、写字节、写字、读字节、读字、处理调用、块读和块写。它不用于快速命令或接收字节协议,因此对于这些命令,其值为“无关”。
表 12.13 命令寄存器,SMB_CMD
| Bit7 到 Bit0 | COMMAND |
|---|
其中:
| COMMAND | 要发送到 SMBus 设备的命令字节。 |
|---|
12.9.1.5. 数据寄存器数组,SMB_DATA[i],i=0-31
这组寄存器包含在可于 SMBus 上运行的各种不同协议中要发送或接收的其余字节。SMB_DATA[i] 寄存器按每种协议定义,因此能够高效利用寄存器空间。
表 12.14 数据寄存器数组,SMB_DATA[i],i=0-31
| Bit7 到 Bit0 | DATA |
|---|
其中:
| DATA | 要发送或接收的一个数据字节(取决于协议)。 |
|---|
12.9.1.6. 块计数寄存器,SMB_BCNT
该寄存器包含在任何写块之前以及任何读块事务之后,SMB_DATA[i] 寄存器中存在的数据字节数。数据大小按每种协议定义。
表 12.15 块计数寄存器,SMB_BCNT
| Bit7 到 Bit5 | Bit4 到 Bit0 |
|---|---|
| RES | BCNT |
12.9.1.7. 告警地址寄存器,SMB_ALRM_ADDR
该寄存器包含主控制器在从地址 0x8 处接收到的告警消息地址,该消息来自发起该告警的 SMBus 主设备。该地址指示 SMBus 上发起该告警消息的设备的从地址。告警消息的状态包含在 SMB_ALRM_DATAx 寄存器中。一旦接收到告警消息,SMB-HC 将不会接收额外的告警消息,直到 ALRM 状态位被清除。
表 12.16 告警地址寄存器,SMB_ALRM_ADDR
| Bit7 到 Bit1 | Bit0 |
|---|---|
| ADDRESS (A6:A0) | RES |
其中:
| RES: | 保留 |
|---|---|
| ADDRESS: | 发起 SMBus 告警消息的 SMBus 设备的从地址(A6:A0)。 |
12.9.1.8. 告警数据寄存器,SMB_ALRM_DATA[0],SMB_ALRM_DATA[1]
这些寄存器包含主控制器在从地址 0x8 处接收到的告警消息的两个数据字节,该消息来自发起该告警的 SMBus 主设备。这些数据字节指示告警消息的具体原因,以便 OSPM 可以采取相应操作。一旦接收到告警消息,SMB-HC 将不会接收额外的告警消息,直到 ALRM 状态位被清除。
表 12.17 告警数据寄存器,SMB_ALRM_DATA[0],SMB_ALRM_DATA[1]
| Bit7 到 Bit0 | DATA (D7:D0) |
|---|
其中:
| DATA | 在告警消息中接收到的数据字节。 |
|---|
在告警状态位被置位之前,OSPM 不会读取告警地址和告警数据寄存器。随后 OSPM 驱动程序读取这 3 个字节,并清除告警状态位,以指示这些告警寄存器现在可用于下一次事件。
12.9.2. 协议说明
本节描述如何通过“寄存器说明”中描述的接口在 SMBus 上发起不同的协议。在写入启动 SMBus 事务的协议值之前,应先将所有寄存器写入适当的值。所有事务都可以一次完成。
12.9.2.1. 写快速
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_PRTCL: | 写入 0x02 以发起写快速协议。 |
返回的数据:
| SMB_STS: | 事务的状态码。 |
|---|---|
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.2. 读快速
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_PRTCL: | 写入 0x03 以发起读快速协议。 |
返回的数据:
| SMB_STS: | 事务的状态码。 |
|---|---|
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.3. 发送字节
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_PRTCL: | 写入 0x04 以发起发送字节协议,或写入 0x84 以发起带 PEC 的发送字节协议。 |
返回的数据:
| SMB_STS: | 事务的状态码。 |
|---|---|
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.4. 接收字节
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_PRTCL: | 写入 0x05 以发起接收字节协议,或写入 0x85 以发起带 PEC 的接收字节协议。 |
返回的数据:
| SMB_DATA[0]: | 接收到的数据字节。 |
|---|---|
| SMB_STS: | 事务的状态码。 |
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.5. 写字节
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_DATA[0]: | 要发送的数据字节。 |
| SMB_PRTCL: | 写入 0x06 以发起写字节协议,或写入 0x86 以发起带 PEC 的写字节协议。 |
返回的数据:
| SMB_STS: | 事务的状态码。 |
|---|---|
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.6. 读字节
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_PRTCL: | 写入 0x07 以发起读字节协议,或写入 0x87 以发起带 PEC 的读字节协议。 |
返回的数据:
| SMB_DATA[0]: | 接收到的数据字节。 |
|---|---|
| SMB_STS: | 事务的状态码。 |
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.7. 写字
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_DATA[0]: | 要发送的低数据字节。 |
| SMB_DATA[1]: | 要发送的高数据字节。 |
| SMB_PRTCL: | 写入 0x08 以发起写字协议,或写入 0x88 以发起带 PEC 的写字协议。 |
返回的数据:
| SMB_STS: | 事务的状态码。 |
|---|---|
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.8. 读字
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_PRTCL: | 写入 0x09 以发起读字协议,或写入 0x89 以发起带 PEC 的读字协议。 |
返回的数据:
| SMB_DATA[0]: | 接收到的低数据字节。 |
|---|---|
| SMB_DATA[1]: | 接收到的高数据字节。 |
| SMB_STS: | 事务的状态码。 |
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.9. 写块
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_DATA[0-31]: | 要写入的数据字节(1-32)。 |
| SMB_BCNT: | 要发送的数据字节数(1-32)。 |
| SMB_PRTCL: | 写入 0x0A 以发起写块协议,或写入 0x8A 以发起带 PEC 的写块协议。 |
返回的数据:
| SMB_PRTCL: | 0x00,表示命令完成。 |
|---|---|
| SMB_STS: | 事务的状态码。 |
12.9.2.10. 读块
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_PRTCL: | 写入 0x0B 以发起读块协议,或写入 0x8B 以发起带 PEC 的读块协议。 |
返回的数据:
| SMB_BCNT: | 接收到的数据字节数(1-32)。 |
|---|---|
| SMB_DATA[0-31]: | 接收到的数据字节(1-32)。 |
| SMB_STS: | 事务的状态码。 |
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.11. 处理调用
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_DATA[0]: | 要发送的低数据字节。 |
| SMB_DATA[1]: | 要发送的高数据字节。 |
| SMB_PRTCL: | 写入 0x0C 以发起处理调用协议,或写入 0x8C 以发起带 PEC 的处理调用协议。 |
返回的数据:
| SMB_DATA[0]: | 接收到的低数据字节。 |
|---|---|
| SMB_DATA[1]: | 接收到的高数据字节。 |
| SMB_STS: | 事务的状态码。 |
| SMB_PRTCL: | 0x00,表示命令完成。 |
12.9.2.12. 块写-块读处理调用
发送的数据:
| SMB_ADDR: | SMBus 设备的地址。 |
|---|---|
| SMB_CMD: | 要发送的命令字节。 |
| SMB_DATA[0-31]: | 要写入的数据字节(1-31)。 |
| SMB_BCNT: | 要发送的数据字节数(1-31)。 |
| SMB_PRTCL: | 写入 0x0D 以发起块写-块读处理调用协议,或写入 0x8D 以发起带 PEC 的块写-块读处理调用协议。 |
返回的数据:
| SMB_BCNT: | 接收到的数据字节数(1-31)。 |
|---|---|
| SMB_DATA[0-31]: | 接收到的数据字节(1-31)。 |
| SMB_STS: | 事务的状态码。 |
| SMB_PRTCL: | 0x00,表示命令完成。 |
注意
上述内容适用以下限制:写块和读块的总数据长度不得超过 32 字节,并且每个块(写和读)必须至少包含 1 个字节的数据。
12.9.2.13. SMBus 寄存器集
SMB-HC 的寄存器集具有以下格式。所有寄存器均为 8 位。
表 12.18 SMB EC 接口
| 位置 | 寄存器名称 | 说明 |
|---|---|---|
| BASE+0 | SMB_PRTCL | 协议寄存器 |
| BASE+1 | SMB_STS | 状态寄存器 |
| BASE+2 | SMB_ADDR | 地址寄存器 |
| BASE+3 | SMB_CMD | 命令寄存器 |
| BASE+4 | SMB_DATA[0] | 数据寄存器零 |
| BASE+5 | SMB_DATA[1] | 数据寄存器一 |
| BASE+6 | SMB_DATA[2] | 数据寄存器二 |
| BASE+7 | SMB_DATA[3] | 数据寄存器三 |
| BASE+8 | SMB_DATA[4] | 数据寄存器四 |
| BASE+9 | SMB_DATA[5] | 数据寄存器五 |
| BASE+10 | SMB_DATA[6] | 数据寄存器六 |
| BASE+11 | SMB_DATA[7] | 数据寄存器七 |
| BASE+12 | SMB_DATA[8] | 数据寄存器八 |
| BASE+13 | SMB_DATA[9] | 数据寄存器九 |
| BASE+14 | SMB_DATA[10] | 数据寄存器十 |
| BASE+15 | SMB_DATA[11] | 数据寄存器十一 |
| BASE+16 | SMB_DATA[12] | 数据寄存器十二 |
| BASE+17 | SMB_DATA[13] | 数据寄存器十三 |
| BASE+18 | SMB_DATA[14] | 数据寄存器十四 |
| BASE+19 | SMB_DATA[15] | 数据寄存器十五 |
| BASE+20 | SMB_DATA[16] | 数据寄存器十六 |
| BASE+21 | SMB_DATA[17] | 数据寄存器十七 |
| BASE+22 | SMB_DATA[18] | 数据寄存器十八 |
| BASE+23 | SMB_DATA[19] | 数据寄存器十九 |
| BASE+24 | SMB_DATA[20] | 数据寄存器二十 |
| BASE+25 | SMB_DATA[21] | 数据寄存器二十一 |
| BASE+26 | SMB_DATA[22] | 数据寄存器二十二 |
| BASE+27 | SMB_DATA[23] | 数据寄存器二十三 |
| BASE+28 | SMB_DATA[24] | 数据寄存器二十四 |
| BASE+29 | SMB_DATA[25] | 数据寄存器二十五 |
| BASE+30 | SMB_DATA[26] | 数据寄存器二十六 |
| BASE+31 | SMB_DATA[27] | 数据寄存器二十七 |
| BASE+32 | SMB_DATA[28] | 数据寄存器二十八 |
| BASE+33 | SMB_DATA[29] | 数据寄存器二十九 |
| BASE+34 | SMB_DATA[30] | 数据寄存器三十 |
| BASE+35 | SMB_DATA[31] | 数据寄存器三十一 |
| BASE+36 | SMB_BCNT | 块计数寄存器 |
| BASE+37 | SMB_ALRM_ADDR | 告警地址 |
| BASE+38 | SMB_ALRM_DATA[0] | 告警数据寄存器零 |
| BASE+39 | SMB_ALRM_DATA[1] | 告警数据寄存器一 |