1package main 2 3import "fmt" 4 5func LenovoEC(ctx Context) { 6 ap := Create(ctx, "acpi/platform.asl") 7 defer ap.Close() 8 9 wakeGPE := 13 10 11 sbGPE := GuessECGPE(ctx) 12 var GPE int 13 var GPEUnsure bool 14 if sbGPE < 0 { 15 sbGPE = SouthBridge.EncodeGPE(1) 16 GPE = 1 17 GPEUnsure = true 18 SouthBridge.NeedRouteGPIOManually() 19 } else { 20 GPE = SouthBridge.DecodeGPE(sbGPE) 21 GPEUnsure = false 22 } 23 24 SouthBridge.EnableGPE(wakeGPE) 25 SouthBridge.EnableGPE(GPE) 26 27 GPEDefine := DSDTDefine{ 28 Key: "THINKPAD_EC_GPE", 29 } 30 31 GPEDefine.Value = fmt.Sprintf("%d", sbGPE) 32 if GPEUnsure { 33 GPEDefine.Comment = "FIXME: Check this" 34 } 35 36 DSDTDefines = append(DSDTDefines, 37 DSDTDefine{ 38 Key: "EC_LENOVO_H8_ME_WORKAROUND", 39 Value: "1", 40 }, GPEDefine) 41 42 Add_gpl(ap) 43 ap.WriteString( 44 `Method(_WAK, 1) 45{ 46 /* ME may not be up yet. */ 47 Store(0, \_TZ.MEB1) 48 Store(0, \_TZ.MEB2) 49 Return(Package() {0, 0}) 50} 51 52Method(_PTS,1) 53{ 54 \_SB.PCI0.LPCB.EC.RADI(0) 55} 56`) 57 58 si := Create(ctx, "acpi/superio.asl") 59 defer si.Close() 60 61 Add_gpl(si) 62 si.WriteString("#include <drivers/pc80/pc/ps2_controller.asl>\n") 63 64 /* FIXME:XX Move this to ec/lenovo. */ 65 smi := Create(ctx, "smihandler.c") 66 defer smi.Close() 67 68 AddSMMFile("smihandler.c", "") 69 70 Add_gpl(smi) 71 smi.WriteString( 72 `#include <arch/io.h> 73#include <console/console.h> 74#include <cpu/x86/smm.h> 75#include <ec/acpi/ec.h> 76#include <ec/lenovo/h8/h8.h> 77#include <delay.h> 78#include <` + SouthBridge.GetGPIOHeader() + ">\n\n") 79 80 if GPEUnsure { 81 smi.WriteString("/* FIXME: check this */\n") 82 } 83 fmt.Fprintf(smi, "#define GPE_EC_SCI %d\n", GPE) 84 85 smi.WriteString("/* FIXME: check this */\n") 86 fmt.Fprintf(smi, "#define GPE_EC_WAKE %d\n", wakeGPE) 87 88 smi.WriteString(` 89static void mainboard_smi_handle_ec_sci(void) 90{ 91 u8 status = inb(EC_SC); 92 u8 event; 93 94 if (!(status & EC_SCI_EVT)) 95 return; 96 97 event = ec_query(); 98 printk(BIOS_DEBUG, "EC event %#02x\n", event); 99} 100 101void mainboard_smi_gpi(u32 gpi_sts) 102{ 103 if (gpi_sts & (1 << GPE_EC_SCI)) 104 mainboard_smi_handle_ec_sci(); 105} 106 107int mainboard_smi_apmc(u8 data) 108{ 109 switch (data) { 110 case APM_CNT_ACPI_ENABLE: 111 /* use 0x1600/0x1604 to prevent races with userspace */ 112 ec_set_ports(0x1604, 0x1600); 113 /* route EC_SCI to SCI */ 114 gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SCI); 115 /* discard all events, and enable attention */ 116 ec_write(0x80, 0x01); 117 break; 118 case APM_CNT_ACPI_DISABLE: 119 /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't 120 provide a EC query function */ 121 ec_set_ports(0x66, 0x62); 122 /* route EC_SCI to SMI */ 123 gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI); 124 /* discard all events, and enable attention */ 125 ec_write(0x80, 0x01); 126 break; 127 default: 128 break; 129 } 130 return 0; 131} 132 133void mainboard_smi_sleep(u8 slp_typ) 134{ 135 if (slp_typ == 3) { 136 u8 ec_wake = ec_read(0x32); 137 /* If EC wake events are enabled, enable wake on EC WAKE GPE. */ 138 if (ec_wake & 0x14) { 139 /* Redirect EC WAKE GPE to SCI. */ 140 gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI); 141 } 142 } 143} 144`) 145 146 ec := Create(ctx, "acpi/ec.asl") 147 defer ec.Close() 148 149 Add_gpl(ec) 150 ec.WriteString("#include <ec/lenovo/h8/acpi/ec.asl>\n") 151 152 KconfigBool["EC_LENOVO_PMH7"] = true 153 KconfigBool["EC_LENOVO_H8"] = true 154 155 pmh := DevTreeNode{ 156 Chip: "ec/lenovo/pmh7", 157 Registers: map[string]string{ 158 "backlight_enable": "true", 159 "dock_event_enable": "true", 160 }, 161 Children: []DevTreeNode{ 162 DevTreeNode{ 163 Chip: "pnp", 164 Comment: "dummy", 165 Dev: 0xff, 166 Func: 1, 167 }, 168 }, 169 } 170 PutChip("lpc", pmh) 171 172 ecs := ctx.InfoSource.GetEC() 173 h8 := DevTreeNode{ 174 Chip: "ec/lenovo/h8", 175 Children: []DevTreeNode{ 176 DevTreeNode{ 177 Chip: "pnp", 178 Comment: "dummy", 179 Dev: 0xff, 180 Func: 2, 181 IOs: map[uint16]uint16{ 182 0x60: 0x62, 183 0x62: 0x66, 184 0x64: 0x1600, 185 0x66: 0x1604, 186 }, 187 }, 188 }, 189 Comment: "FIXME: has_keyboard_backlight, has_power_management_beeps, has_uwb", 190 Registers: map[string]string{ 191 "config0": FormatHex8(ecs[0]), 192 "config1": FormatHex8(ecs[1]), 193 "config2": FormatHex8(ecs[2]), 194 "config3": FormatHex8(ecs[3]), 195 "beepmask0": FormatHex8(ecs[4]), 196 "beepmask1": FormatHex8(ecs[5]), 197 }, 198 } 199 for i := 0; i < 0x10; i++ { 200 if ecs[0x10+i] != 0 { 201 h8.Registers[fmt.Sprintf("event%x_enable", i)] = FormatHex8(ecs[0x10+i]) 202 } 203 } 204 PutChip("lpc", h8) 205 206 eeprom := DevTreeNode{ 207 Chip: "drivers/i2c/at24rf08c", 208 Comment: "eeprom, 8 virtual devices, same chip", 209 Children: []DevTreeNode{ 210 DevTreeNode{ 211 Chip: "i2c", 212 Dev: 0x54, 213 }, 214 DevTreeNode{ 215 Chip: "i2c", 216 Dev: 0x55, 217 }, 218 DevTreeNode{ 219 Chip: "i2c", 220 Dev: 0x56, 221 }, 222 DevTreeNode{ 223 Chip: "i2c", 224 Dev: 0x57, 225 }, 226 DevTreeNode{ 227 Chip: "i2c", 228 Dev: 0x5c, 229 }, 230 DevTreeNode{ 231 Chip: "i2c", 232 Dev: 0x5d, 233 }, 234 DevTreeNode{ 235 Chip: "i2c", 236 Dev: 0x5e, 237 }, 238 DevTreeNode{ 239 Chip: "i2c", 240 Dev: 0x5f, 241 }, 242 }, 243 } 244 PutChip("smbus", eeprom) 245} 246