系统控制中断SCI

Peter 于 2021-03-21 发布

SCI全称是System Control Interrupt(系统控制中断)当硬件产生了一些ACPI事件的时候,它可以使用系统控制中断SCI来通知OS。SCI是一个低电平有效共享的中断信号。ACPI Spec说有2种类型的event会产生SCI,一种叫做Fixed-FeatureEvents,另外一种是General-PurposeEvents。Fixed-Feature Events 产生的SCI通常是由OS inbox driver去处理的。所以我们只需要关注GPE 。

SCI_EVENT

SCI中断的相关信息被记录在FADT table中,OS通过FADT获得SCI使用的中断号码,从而能够在SCI产生时处理该中断。

SCI_INT

通常情况下SCI_INT会被设置成IRQ9,但是它也不是固定的,我们也可以按照板子的设计修改SCI_INT。

FADT

芯片组的spec会有寄存器用来配置SCI IRQ number。下图是PCH上的一个寄存器描述。

ACPI_CNTL

芯片组的spec会有专门的寄存器用来控制GPE。下图是PCH上的一个寄存器描述。

GPE0_EN

为了客制化一些功能或者实现一些特殊的Feature,通常要配置一些GPIO让它能够在特定的条件下产生SCI,这时我们要把特定的GPIO配置成INPUT, SCI,把GPE0_EN对应的bit设置起来。然后需要在ACPI table中提供_Lxx的形式的method,至于xx则是和GPE_STS这个register相对应的,所以要特别注意的是通常情况下Intel PCH GPIO 都是从GPE_STS的bit16开始的,所以如果是GPIO0那么这个method应该是_L10。当系统中相关的GPIO status有变化就会触发SCI, _LXX(),就会被调用了。

EC的SCI虽然跟通常的GPE稍有差别, 但本质上它仍然是GPE。参考代码如下图所示:

Device (EC0)
{
	Name (_HID, EISAID ("PNP0C09"))
	Name (_UID, 1)
	Name (_GPE, Add(EC_SCI_GPI, 16)) // GPE for Runtime SCI
	
}

它跟普通的GPE的区别是,EC有一个叫做Q_EVENT的东西。所谓Q_EVENT指的是OS收到EC的SCI后,OS通过发84h command 给EC读取EC Ram中的值,这个值被称为Q_EVENT ID。这也是Q_EVENT得名的原因(Q是Query的缩写,而84h就是Query Embedded Controller)。然后OS中的asl code会根据该id去调用_QXX()如下面的code所示,这里的XX指的就是EVENT ID。每当电源插入,电池充电,屏幕开合的时候,通常EC就会产生Q_EVENT。

// AC Power Connected
Method (_Q26, 0, NotSerialized)
{
	Store (One, \PWRS)
	Notify (AC, 0x80)
	Notify (BATX, 0x80)
	\PNOT ()
}

参考:

- [1. ACPI Spec](https://www.uefi.org/sites/default/files/resources/ACPI_6_2.pdf)

- [2. EC.asl](https://github.com/roboard/coreboot/blob/master/src/ec/quanta/it8518/acpi/ec.asl)