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 | |
Iru Cai | 16f213a | 2020-09-16 16:23:46 +0800 | [diff] [blame] | 42 | Add_gpl(ap) |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 43 | ap.WriteString( |
Paul Menzel | 56258ff | 2020-01-15 14:28:58 +0100 | [diff] [blame] | 44 | `Method(_WAK, 1) |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 45 | { |
Peter Lemenkov | 71a7ca7 | 2020-01-22 11:48:55 +0100 | [diff] [blame] | 46 | /* ME may not be up yet. */ |
Paul Menzel | 56258ff | 2020-01-15 14:28:58 +0100 | [diff] [blame] | 47 | Store(0, \_TZ.MEB1) |
| 48 | Store(0, \_TZ.MEB2) |
| 49 | Return(Package() {0, 0}) |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | Method(_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 | |
Iru Cai | 16f213a | 2020-09-16 16:23:46 +0800 | [diff] [blame] | 61 | Add_gpl(si) |
Stefan Reinauer | 86ddd73 | 2016-03-11 20:22:28 -0800 | [diff] [blame] | 62 | si.WriteString("#include <drivers/pc80/pc/ps2_controller.asl>\n") |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 63 | |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 64 | /* FIXME:XX Move this to ec/lenovo. */ |
| 65 | smi := Create(ctx, "smihandler.c") |
| 66 | defer smi.Close() |
| 67 | |
| 68 | AddSMMFile("smihandler.c", "") |
| 69 | |
Arthur Heymans | 5930285 | 2017-05-01 10:33:56 +0200 | [diff] [blame] | 70 | Add_gpl(smi) |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 71 | smi.WriteString( |
Arthur Heymans | 5930285 | 2017-05-01 10:33:56 +0200 | [diff] [blame] | 72 | `#include <arch/io.h> |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 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(` |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 89 | static 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(); |
Paul Menzel | 5664293 | 2020-07-19 09:42:53 +0200 | [diff] [blame] | 98 | printk(BIOS_DEBUG, "EC event %#02x\n", event); |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 99 | } |
| 100 | |
| 101 | void mainboard_smi_gpi(u32 gpi_sts) |
| 102 | { |
| 103 | if (gpi_sts & (1 << GPE_EC_SCI)) |
| 104 | mainboard_smi_handle_ec_sci(); |
| 105 | } |
| 106 | |
| 107 | int 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 | |
| 133 | void mainboard_smi_sleep(u8 slp_typ) |
| 134 | { |
| 135 | if (slp_typ == 3) { |
| 136 | u8 ec_wake = ec_read(0x32); |
Peter Lemenkov | 71a7ca7 | 2020-01-22 11:48:55 +0100 | [diff] [blame] | 137 | /* If EC wake events are enabled, enable wake on EC WAKE GPE. */ |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 138 | if (ec_wake & 0x14) { |
Peter Lemenkov | 71a7ca7 | 2020-01-22 11:48:55 +0100 | [diff] [blame] | 139 | /* Redirect EC WAKE GPE to SCI. */ |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 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 | |
Iru Cai | 16f213a | 2020-09-16 16:23:46 +0800 | [diff] [blame] | 149 | Add_gpl(ec) |
Vladimir Serbinenko | 3129f79 | 2014-10-15 21:51:47 +0200 | [diff] [blame] | 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": "0x01", |
| 159 | "dock_event_enable": "0x01", |
| 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 | } |