T60: handle EC events in SMM if ACPI is disabled
authorSven Schnelle <svens@stackframe.org>
Thu, 23 Jun 2011 17:12:25 +0000 (19:12 +0200)
committerSven Schnelle <svens@stackframe.org>
Thu, 7 Jul 2011 13:47:29 +0000 (15:47 +0200)
Change-Id: I6f9e90015cafef3da896453ef8e3588434ae3554
Signed-off-by: Sven Schnelle <svens@stackframe.org>
Reviewed-on: http://review.coreboot.org/89
Tested-by: build bot (Jenkins)
src/mainboard/lenovo/t60/acpi/video.asl
src/mainboard/lenovo/t60/devicetree.cb
src/mainboard/lenovo/t60/mainboard.c
src/mainboard/lenovo/t60/mainboard_smi.c
src/mainboard/lenovo/t60/smi.h

index c2f9dfb4590dcff4b01c60b925bdde6f1ae8bc9a..9a458e90f665478f6bec2cc8fc38e5b274b479d8 100644 (file)
@@ -19,6 +19,8 @@
  * MA 02110-1301 USA
  */
 
+#include "smi.h"
+
 Device (DSPC)
 {
        Name (_ADR, 0x00020001)
@@ -31,6 +33,7 @@ Device (DSPC)
 
        Method(BRTD, 0, NotSerialized)
        {
+               Trap(SMI_BRIGHTNESS_DOWN)
                Store(BRTC, Local0)
                if (LGreater (Local0, 15))
                {
@@ -41,6 +44,7 @@ Device (DSPC)
 
        Method(BRTU, 0, NotSerialized)
        {
+               Trap(SMI_BRIGHTNESS_UP)
                Store (BRTC, Local0)
                if (LLess(Local0, 0xff))
                {
index 9d7a414662f89a0b8fed0217bd4cec6bdb6f717b..3615e59eb7208083942d7f5cb0e7b2e11e00c2ea 100644 (file)
@@ -66,6 +66,7 @@ chip northbridge/intel/i945
                        register "sata_ahci" = "0x0"
 
                        register "gpe0_en" = "0x11000006"
+                       register "alt_gp_smi_en" = "0x1000"
 
                        device pci 1b.0 on # Audio Cnotroller
                                subsystemid 0x17aa 0x2010
index 371085bd49c4111483ad38d8e3b49d165ed827f5..2b8c5fe4b12f6e53ff1c1be702ab1d1d373d421d 100644 (file)
@@ -61,7 +61,8 @@ static void mainboard_enable(device_t dev)
        }
 
        /* set dock status led */
-       ec_write(0x0c, inb(0x164c) & 8 ? 0x88 : 0x08);
+       ec_write(0x0c, 0x08);
+       ec_write(0x0c, inb(0x164c) & 8 ? 0x89 : 0x09);
 
        if (get_option(&defaults_loaded, "cmos_defaults_loaded") < 0) {
                printk(BIOS_INFO, "failed to get cmos_defaults_loaded");
index 30c2420f9c6c597618ef06ec1b577e2b3fad9ad9..4a0b5062c9c6c3e3074d448c4b0f9d840bf60159 100644 (file)
 #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 LVTMA_BL_MOD_LEVEL 0x7af9 /* ATI Radeon backlight level */
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -38,7 +40,28 @@ 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);
+}
+
+static void mainboard_smi_brightness_down(void)
+{
+       u8 *bar;
+       if ((bar = (u8 *)pci_read_config32(PCI_DEV(1, 0, 0), 0x18))) {
+               printk(BIOS_DEBUG, "bar: %08X, level %02X\n",  (unsigned int)bar, *(bar+LVTMA_BL_MOD_LEVEL));
+               *(bar+LVTMA_BL_MOD_LEVEL) &= 0xf0;
+               if (*(bar+LVTMA_BL_MOD_LEVEL) > 0x10)
+                       *(bar+LVTMA_BL_MOD_LEVEL) -= 0x10;
+       }
+}
+
+static void mainboard_smi_brightness_up(void)
+{
+       u8 *bar;
+       if ((bar = (u8 *)pci_read_config32(PCI_DEV(1, 0, 0), 0x18))) {
+               printk(BIOS_DEBUG, "bar: %08X, level %02X\n",  (unsigned int )bar, *(bar+LVTMA_BL_MOD_LEVEL));
+               *(bar+LVTMA_BL_MOD_LEVEL) |= 0x0f;
+               if (*(bar+LVTMA_BL_MOD_LEVEL) < 0xf0)
+                       *(bar+LVTMA_BL_MOD_LEVEL) += 0x10;
+       }
 }
 
 int mainboard_io_trap_handler(int smif)
@@ -55,18 +78,29 @@ int mainboard_io_trap_handler(int smif)
                dlpc_init();
                if (!dock_connect()) {
                        /* set dock LED to indicate status */
-                       ec_write(0x0c, 0x88);
+                       ec_write(0x0c, 0x08);
+                       ec_write(0x0c, 0x89);
                } else {
                        /* blink dock LED to indicate failure */
                        ec_write(0x0c, 0xc8);
+                       ec_write(0x0c, 0x09);
                }
                break;
 
        case SMI_DOCK_DISCONNECT:
                dock_disconnect();
+               ec_write(0x0c, 0x09);
                ec_write(0x0c, 0x08);
                break;
 
+       case SMI_BRIGHTNESS_UP:
+               mainboard_smi_brightness_up();
+               break;
+
+       case SMI_BRIGHTNESS_DOWN:
+               mainboard_smi_brightness_down();
+               break;
+
        default:
                return 0;
        }
@@ -76,3 +110,84 @@ int mainboard_io_trap_handler(int smif)
        return 1;
 }
 
+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;
+               /* Fn-F9 Key */
+               case 0x18:
+               /* power loss */
+               case 0x27:
+               /* undock event */
+               case 0x50:
+                       mainboard_io_trap_handler(SMI_DOCK_DISCONNECT);
+                       break;
+               /* dock event */
+               case 0x37:
+                       mainboard_io_trap_handler(SMI_DOCK_CONNECT);
+                       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 APM_CNT_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 APM_CNT_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;
+}
+
index f89b6bd74f0718cc30f20f2d0bd0f3bd8ad3f668..f8e8a7ccfaeac2f0c4d2a9e80b4fc4277e4fccf8 100644 (file)
@@ -22,5 +22,7 @@
 
 #define SMI_DOCK_CONNECT 0x01
 #define SMI_DOCK_DISCONNECT 0x02
+#define SMI_BRIGHTNESS_UP 0x03
+#define SMI_BRIGHTNESS_DOWN 0x04
 
 #endif