/ util / autoport / ec_lenovo.go
ec_lenovo.go
  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  	Add_SPDX(ap, ASL, GPL2_only)
 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  
 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  
 61  	Add_SPDX(si, ASL, GPL2_only)
 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_SPDX(smi, C, GPL2_only)
 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(`
 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();
 98  	printk(BIOS_DEBUG, "EC event %#02x\n", event);
 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);
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_SPDX(ec, ASL, GPL2_only)
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  }