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; +}