diff options
author | Nicholas Chin <nic.c3.14@gmail.com> | 2024-03-18 10:45:05 -0600 |
---|---|---|
committer | Nicholas Chin <nic.c3.14@gmail.com> | 2024-03-18 10:45:05 -0600 |
commit | 8cba237086dfbb312a5913bb75eef4f6046aeae5 (patch) | |
tree | a208e8ff3e8b628b1615918cbb55b6ce351cfe54 /util/autoport/ec_lenovo.go | |
parent | c578fe56c36f94af5c51a1be27a1a1c4b57a4289 (diff) |
util: Import autoport with Haswell patches
This is a copy of coreboot's autoport utility, with a patch applied to
support Haswell/Lynx Point platforms. That patch is currently in review
on coreboot's Gerrit.
https://review.coreboot.org/c/coreboot/+/30890
Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com>
Diffstat (limited to 'util/autoport/ec_lenovo.go')
-rw-r--r-- | util/autoport/ec_lenovo.go | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/util/autoport/ec_lenovo.go b/util/autoport/ec_lenovo.go new file mode 100644 index 00000000..a34960ff --- /dev/null +++ b/util/autoport/ec_lenovo.go @@ -0,0 +1,245 @@ +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_gpl(ap) + 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_gpl(si) + si.WriteString("#include <drivers/pc80/pc/ps2_controller.asl>\n") + + /* FIXME:XX Move this to ec/lenovo. */ + smi := Create(ctx, "smihandler.c") + defer smi.Close() + + AddSMMFile("smihandler.c", "") + + Add_gpl(smi) + smi.WriteString( + `#include <arch/io.h> +#include <console/console.h> +#include <cpu/x86/smm.h> +#include <ec/acpi/ec.h> +#include <ec/lenovo/h8/h8.h> +#include <delay.h> +#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_gpl(ec) + ec.WriteString("#include <ec/lenovo/h8/acpi/ec.asl>\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) +} |