package main import "fmt" func LenovoEC(ctx Context) { ap := Create(ctx, "acpi/platform.asl") defer ap.Close() wakeGPE := 13 sbGPE := GuessECGPE(ctx) var GPE int var GPEUnsure bool if sbGPE < 0 { sbGPE = SouthBridge.EncodeGPE(1) GPE = 1 GPEUnsure = true SouthBridge.NeedRouteGPIOManually() } else { GPE = SouthBridge.DecodeGPE(sbGPE) GPEUnsure = false } SouthBridge.EnableGPE(wakeGPE) SouthBridge.EnableGPE(GPE) GPEDefine := DSDTDefine{ Key: "THINKPAD_EC_GPE", } GPEDefine.Value = fmt.Sprintf("%d", sbGPE) if GPEUnsure { GPEDefine.Comment = "FIXME: Check this" } DSDTDefines = append(DSDTDefines, DSDTDefine{ Key: "EC_LENOVO_H8_ME_WORKAROUND", Value: "1", }, GPEDefine) Add_SPDX(ap, ASL, GPL2_only) ap.WriteString( `Method(_WAK, 1) { /* ME may not be up yet. */ Store(0, \_TZ.MEB1) Store(0, \_TZ.MEB2) Return(Package() {0, 0}) } Method(_PTS,1) { \_SB.PCI0.LPCB.EC.RADI(0) } `) si := Create(ctx, "acpi/superio.asl") defer si.Close() Add_SPDX(si, ASL, GPL2_only) si.WriteString("#include \n") /* FIXME:XX Move this to ec/lenovo. */ smi := Create(ctx, "smihandler.c") defer smi.Close() AddSMMFile("smihandler.c", "") Add_SPDX(smi, C, GPL2_only) smi.WriteString( `#include #include #include #include #include #include #include <` + SouthBridge.GetGPIOHeader() + ">\n\n") if GPEUnsure { smi.WriteString("/* FIXME: check this */\n") } fmt.Fprintf(smi, "#define GPE_EC_SCI %d\n", GPE) smi.WriteString("/* FIXME: check this */\n") fmt.Fprintf(smi, "#define GPE_EC_WAKE %d\n", wakeGPE) smi.WriteString(` 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); } void mainboard_smi_gpi(u32 gpi_sts) { if (gpi_sts & (1 << GPE_EC_SCI)) mainboard_smi_handle_ec_sci(); } int mainboard_smi_apmc(u8 data) { switch (data) { case APM_CNT_ACPI_ENABLE: /* use 0x1600/0x1604 to prevent races with userspace */ ec_set_ports(0x1604, 0x1600); /* route EC_SCI to SCI */ gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SCI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); 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 EC_SCI to SMI */ gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; default: break; } return 0; } void mainboard_smi_sleep(u8 slp_typ) { if (slp_typ == 3) { u8 ec_wake = ec_read(0x32); /* If EC wake events are enabled, enable wake on EC WAKE GPE. */ if (ec_wake & 0x14) { /* Redirect EC WAKE GPE to SCI. */ gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI); } } } `) ec := Create(ctx, "acpi/ec.asl") defer ec.Close() Add_SPDX(ec, ASL, GPL2_only) ec.WriteString("#include \n") KconfigBool["EC_LENOVO_PMH7"] = true KconfigBool["EC_LENOVO_H8"] = true pmh := DevTreeNode{ Chip: "ec/lenovo/pmh7", Registers: map[string]string{ "backlight_enable": "true", "dock_event_enable": "true", }, Children: []DevTreeNode{ DevTreeNode{ Chip: "pnp", Comment: "dummy", Dev: 0xff, Func: 1, }, }, } PutChip("lpc", pmh) ecs := ctx.InfoSource.GetEC() h8 := DevTreeNode{ Chip: "ec/lenovo/h8", Children: []DevTreeNode{ DevTreeNode{ Chip: "pnp", Comment: "dummy", Dev: 0xff, Func: 2, IOs: map[uint16]uint16{ 0x60: 0x62, 0x62: 0x66, 0x64: 0x1600, 0x66: 0x1604, }, }, }, Comment: "FIXME: has_keyboard_backlight, has_power_management_beeps, has_uwb", Registers: map[string]string{ "config0": FormatHex8(ecs[0]), "config1": FormatHex8(ecs[1]), "config2": FormatHex8(ecs[2]), "config3": FormatHex8(ecs[3]), "beepmask0": FormatHex8(ecs[4]), "beepmask1": FormatHex8(ecs[5]), }, } for i := 0; i < 0x10; i++ { if ecs[0x10+i] != 0 { h8.Registers[fmt.Sprintf("event%x_enable", i)] = FormatHex8(ecs[0x10+i]) } } PutChip("lpc", h8) eeprom := DevTreeNode{ Chip: "drivers/i2c/at24rf08c", Comment: "eeprom, 8 virtual devices, same chip", Children: []DevTreeNode{ DevTreeNode{ Chip: "i2c", Dev: 0x54, }, DevTreeNode{ Chip: "i2c", Dev: 0x55, }, DevTreeNode{ Chip: "i2c", Dev: 0x56, }, DevTreeNode{ Chip: "i2c", Dev: 0x57, }, DevTreeNode{ Chip: "i2c", Dev: 0x5c, }, DevTreeNode{ Chip: "i2c", Dev: 0x5d, }, DevTreeNode{ Chip: "i2c", Dev: 0x5e, }, DevTreeNode{ Chip: "i2c", Dev: 0x5f, }, }, } PutChip("smbus", eeprom) }