motherboards can use this hook to get notified if someone writes to the APM_CNT port (0xb2). If the hook returns 1, the chipset specific hook is also skipped.
Signed-off-by: Sven Schnelle svens@stackframe.org --- src/include/cpu/x86/smm.h | 2 +- src/southbridge/intel/i82801gx/smihandler.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h index ad0984e..559b1b7 100644 --- a/src/include/cpu/x86/smm.h +++ b/src/include/cpu/x86/smm.h @@ -263,4 +263,4 @@ void __attribute__((weak)) northbridge_smi_handler(unsigned int node, smm_state_ void __attribute__((weak)) southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save);
void __attribute__((weak)) mainboard_smi_gpi(u16 gpi_sts); - +int __attribute__((weak)) mainboard_apm_cnt(u8 data); diff --git a/src/southbridge/intel/i82801gx/smihandler.c b/src/southbridge/intel/i82801gx/smihandler.c index aefa283..bccf6d5 100644 --- a/src/southbridge/intel/i82801gx/smihandler.c +++ b/src/southbridge/intel/i82801gx/smihandler.c @@ -362,6 +362,9 @@ static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state /* Emulate B2 register as the FADT / Linux expects it */
reg8 = inb(APM_CNT); + if (mainboard_apm_cnt && mainboard_apm_cnt(reg8)) + return; + switch (reg8) { case CST_CONTROL: /* Calling this function seems to cause
could be used for various things if the OS doesn't provide ACPI support, or has ACPI disabled. The current patch only uses this to enable operation of the backlight hotkeys.
As the Thinkpad EC doesn't support EC_QUERY on ports 0x1600/0x1604 and there are no event queue registers in the EC register space, we're using 0x62/0x66 as EC I/O ports as long as ACPI is disabled.
Signed-off-by: Sven Schnelle svens@stackframe.org --- src/mainboard/lenovo/x60/devicetree.cb | 4 +- src/mainboard/lenovo/x60/mainboard_smi.c | 89 +++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/src/mainboard/lenovo/x60/devicetree.cb b/src/mainboard/lenovo/x60/devicetree.cb index b708dce..42a45d1 100644 --- a/src/mainboard/lenovo/x60/devicetree.cb +++ b/src/mainboard/lenovo/x60/devicetree.cb @@ -53,13 +53,13 @@ chip northbridge/intel/i945 # 1 SMI# (if corresponding ALT_GPI_SMI_EN bit is also set) # 2 SCI (if corresponding GPIO_EN bit is also set) register "gpi13_routing" = "2" - register "gpi12_routing" = "2" + register "gpi12_routing" = "1" register "gpi8_routing" = "2"
register "sata_ahci" = "0x0"
register "gpe0_en" = "0x11000006" - + register "alt_gp_smi_en" = "0x1000" device pci 1b.0 on # Audio Cnotroller subsystemid 0x17aa 0x2010 end diff --git a/src/mainboard/lenovo/x60/mainboard_smi.c b/src/mainboard/lenovo/x60/mainboard_smi.c index 5e0f6a9..e45c774 100644 --- a/src/mainboard/lenovo/x60/mainboard_smi.c +++ b/src/mainboard/lenovo/x60/mainboard_smi.c @@ -24,10 +24,14 @@ #include <console/console.h> #include <cpu/x86/smm.h> #include "southbridge/intel/i82801gx/nvs.h" +#include "southbridge/intel/i82801gx/i82801gx.h" #include <ec/acpi/ec.h> #include "dock.h" #include "smi.h"
+#define ACPI_ENABLE 0xe1 +#define ACPI_DISABLE 0x1e + /* The southbridge SMI handler checks whether gnvs has a * valid pointer before calling the trap handler */ @@ -38,7 +42,6 @@ static void mainboard_smm_init(void) printk(BIOS_DEBUG, "initializing SMI\n"); /* Enable 0x1600/0x1600 register pair */ ec_set_bit(0x00, 0x05); - ec_set_ports(0x1604, 0x1600); }
int mainboard_io_trap_handler(int smif) @@ -76,3 +79,87 @@ int mainboard_io_trap_handler(int smif) return 0; }
+static void mainboard_smi_brightness_up(void) +{ + u8 value; + + if ((value = pci_read_config8(PCI_DEV(0, 2, 1), 0xf4)) < 0xf0) + pci_write_config8(PCI_DEV(0, 2, 1), 0xf4, (value + 0x10) | 0xf); +} + +static void mainboard_smi_brightness_down(void) +{ + u8 value; + + if ((value = pci_read_config8(PCI_DEV(0, 2, 1), 0xf4)) > 0x10) + pci_write_config8(PCI_DEV(0, 2, 1), 0xf4, (value - 0x10) & 0xf0); +} + +static void mainboard_smi_handle_ec_sci(void) +{ + u8 status = inb(EC_SC); + u8 event; + + if (!(status & EC_SCI_EVT)) + return; + + event = ec_query(); + printk(BIOS_DEBUG, "EC event %02x\n", event); + + switch(event) { + /* brightness up */ + case 0x14: + mainboard_smi_brightness_up(); + break; + /* brightness down */ + case 0x15: + mainboard_smi_brightness_down(); + break; + default: + break; + } +} + +void mainboard_smi_gpi(u16 gpi) +{ + if (gpi & (1 << 12)) + mainboard_smi_handle_ec_sci(); +} + +int mainboard_apm_cnt(u8 data) +{ + u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc; + u8 tmp; + + printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase, data); + + if (!pmbase) + return 0; + + switch(data) { + case ACPI_ENABLE: + /* use 0x1600/0x1604 to prevent races with userspace */ + ec_set_ports(0x1604, 0x1600); + /* route H8SCI to SCI */ + outw(inw(ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN); + tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb); + tmp &= ~0x03; + tmp |= 0x02; + pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp); + break; + case ACPI_DISABLE: + /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't + provide a EC query function */ + ec_set_ports(0x66, 0x62); + /* route H8SCI# to SMI */ + outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000, pmbase + ALT_GP_SMI_EN); + tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb); + tmp &= ~0x03; + tmp |= 0x01; + pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp); + break; + default: + break; + } + return 0; +}
On 6/4/11 10:47 AM, Sven Schnelle wrote:
could be used for various things if the OS doesn't provide ACPI support, or has ACPI disabled. The current patch only uses this to enable operation of the backlight hotkeys.
As the Thinkpad EC doesn't support EC_QUERY on ports 0x1600/0x1604 and there are no event queue registers in the EC register space, we're using 0x62/0x66 as EC I/O ports as long as ACPI is disabled.
Signed-off-by: Sven Schnellesvens@stackframe.org
Acked-by: Stefan Reinauer stefan.reinauer@coreboot.org
On 6/4/11 10:47 AM, Sven Schnelle wrote:
motherboards can use this hook to get notified if someone writes to the APM_CNT port (0xb2). If the hook returns 1, the chipset specific hook is also skipped.
Signed-off-by: Sven Schnellesvens@stackframe.org
Acked-by: Stefan Reinauer stefan.reinauer@coreboot.org
src/include/cpu/x86/smm.h | 2 +- src/southbridge/intel/i82801gx/smihandler.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h index ad0984e..559b1b7 100644 --- a/src/include/cpu/x86/smm.h +++ b/src/include/cpu/x86/smm.h @@ -263,4 +263,4 @@ void __attribute__((weak)) northbridge_smi_handler(unsigned int node, smm_state_ void __attribute__((weak)) southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save);
void __attribute__((weak)) mainboard_smi_gpi(u16 gpi_sts);
+int __attribute__((weak)) mainboard_apm_cnt(u8 data); diff --git a/src/southbridge/intel/i82801gx/smihandler.c b/src/southbridge/intel/i82801gx/smihandler.c index aefa283..bccf6d5 100644 --- a/src/southbridge/intel/i82801gx/smihandler.c +++ b/src/southbridge/intel/i82801gx/smihandler.c @@ -362,6 +362,9 @@ static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state /* Emulate B2 register as the FADT / Linux expects it */
reg8 = inb(APM_CNT);
- if (mainboard_apm_cnt&& mainboard_apm_cnt(reg8))
return;
Is it on purpose that the mainboard_apm_cnt function can prevent the generic 82801gx code (including the not implemented C state coordination) from running?
- switch (reg8) { case CST_CONTROL: /* Calling this function seems to cause
Stefan Reinauer stefan.reinauer@coreboot.org writes:
--- a/src/southbridge/intel/i82801gx/smihandler.c +++ b/src/southbridge/intel/i82801gx/smihandler.c @@ -362,6 +362,9 @@ static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t *state /* Emulate B2 register as the FADT / Linux expects it */
reg8 = inb(APM_CNT);
- if (mainboard_apm_cnt&& mainboard_apm_cnt(reg8))
return;
Is it on purpose that the mainboard_apm_cnt function can prevent the generic 82801gx code (including the not implemented C state coordination) from running?
Yes, that's intentional. If one mainboard doesn't like the way how the i82801gx handles some APM_CNT, it could say so and does it's own implementation. Most callbacks will probably simply return 0, but's IMHO it's nice to have this option.
Sven