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