coreboot-kgpe-d16/util/autoport/ec_lenovo.go

296 lines
5.9 KiB
Go

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)
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()
si.WriteString("#include <drivers/pc80/ps2_controller.asl>\n")
dock := Create(ctx, "dock.c")
defer dock.Close()
AddRAMStageFile("dock.c", "")
dock.WriteString(
`#include <ec/lenovo/h8/h8.h>
void h8_mainboard_init_dock (void)
{
/* FIXME: fill this if needed. */
}
`)
/* FIXME:XX Move this to ec/lenovo. */
smi := Create(ctx, "smihandler.c")
defer smi.Close()
AddSMMFile("smihandler.c", "")
smi.WriteString(
`/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
* Copyright (C) 2014 Vladimir Serbinenko
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc.
*/
#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_smm_init(void)
{
printk(BIOS_DEBUG, "initializing SMI\n");
/* Enable 0x1600/0x1600 register pair */
ec_set_bit(0x00, 0x05);
}
int mainboard_io_trap_handler(int smif)
{
static int smm_initialized;
if (!smm_initialized) {
mainboard_smm_init();
smm_initialized = 1;
}
return 0;
}
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()
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": "0x01",
"dock_event_enable": "0x01",
},
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)
}