/ util / autoport / lynxpoint.go
lynxpoint.go
  1  package main
  2  
  3  import "fmt"
  4  
  5  type LPVariant int
  6  
  7  const (
  8  	LYNX_POINT_MOBILE LPVariant = iota
  9  	LYNX_POINT_DESKTOP
 10  	LYNX_POINT_SERVER
 11  	LYNX_POINT_ULT
 12  )
 13  
 14  type lynxpoint struct {
 15  	variant LPVariant
 16  	node    *DevTreeNode
 17  }
 18  
 19  func lpPchGetFlashSize(ctx Context) {
 20  	inteltool := ctx.InfoSource.GetInteltool()
 21  	/* In LP PCH, Boot BIOS Straps field in GCS has only one bit.  */
 22  	switch (inteltool.RCBA[0x3410] >> 10) & 1 {
 23  	case 0:
 24  		ROMProtocol = "SPI"
 25  		highflkb := uint32(0)
 26  		for reg := uint16(0); reg < 5; reg++ {
 27  			fl := (inteltool.RCBA[0x3854+4*reg] >> 16) & 0x1fff
 28  			flkb := (fl + 1) << 2
 29  			if flkb > highflkb {
 30  				highflkb = flkb
 31  			}
 32  		}
 33  		ROMSizeKB = int(highflkb)
 34  		FlashROMSupport = "y"
 35  	}
 36  }
 37  
 38  func (b lynxpoint) GetGPIOHeader() string {
 39  	return "southbridge/intel/lynxpoint/pch.h"
 40  }
 41  
 42  func (b lynxpoint) EnableGPE(in int) {
 43  	if b.variant != LYNX_POINT_ULT {
 44  		b.node.Registers[fmt.Sprintf("gpi%d_routing", in)] = "2"
 45  	}
 46  }
 47  
 48  func (b lynxpoint) EncodeGPE(in int) int {
 49  	return in + 0x10
 50  }
 51  
 52  func (b lynxpoint) DecodeGPE(in int) int {
 53  	return in - 0x10
 54  }
 55  
 56  func (b lynxpoint) NeedRouteGPIOManually() {
 57  	b.node.Comment += ", FIXME: set gpiX_routing for EC support"
 58  }
 59  
 60  func GetLptDesktopEHCISetting(loc_param uint32, txamp uint32) (string, int) {
 61  	var port_pos string
 62  	var port_length int
 63  
 64  	if loc_param == 4 {
 65  		port_pos = "USB_PORT_BACK_PANEL"
 66  		if txamp <= 2 {
 67  			port_length = 0x40
 68  		} else if txamp >= 4 {
 69  			port_length = 0x140
 70  		} else {
 71  			port_length = 0x110
 72  		}
 73  	} else {
 74  		port_pos = "USB_PORT_FLEX"
 75  		port_length = 0x40
 76  	}
 77  	return port_pos, port_length
 78  }
 79  
 80  func GetLptMobileEHCISetting(loc_param uint32, txamp uint32) (string, int) {
 81  	var port_pos string
 82  	var port_length int
 83  
 84  	if loc_param == 4 {
 85  		port_pos = "USB_PORT_DOCK"
 86  		if txamp <= 1 {
 87  			port_length = 0x40
 88  		} else {
 89  			port_length = 0x80
 90  		}
 91  	} else if loc_param == 6 {
 92  		/* not internal, not dock, port_length >= 0x70 */
 93  		port_pos = "USB_PORT_BACK_PANEL"
 94  		if txamp <= 2 {
 95  			port_length = 0x80
 96  		} else {
 97  			port_length = 0x110
 98  		}
 99  	} else {
100  		port_pos = "USB_PORT_BACK_PANEL"
101  		port_length = 0x40
102  	}
103  	return port_pos, port_length
104  }
105  
106  func GetLptLPEHCISetting(loc_param uint32, txamp uint32) (string, int) {
107  	var port_pos string
108  	var port_length int
109  
110  	if loc_param == 6 {
111  		/* back panel or mini pcie, length >= 0x70 */
112  		port_pos = "USB_PORT_MINI_PCIE"
113  		if txamp <= 2 {
114  			port_length = 0x80
115  		} else {
116  			port_length = 0x110
117  		}
118  	} else if loc_param == 4 {
119  		port_pos = "USB_PORT_DOCK"
120  		if txamp <= 1 {
121  			port_length = 0x40
122  		} else {
123  			port_length = 0x80
124  		}
125  	} else {
126  		port_pos = "USB_PORT_BACK_PANEL"
127  		port_length = 0x40
128  	}
129  	return port_pos, port_length
130  }
131  
132  func (b lynxpoint) Scan(ctx Context, addr PCIDevData) {
133  
134  	SouthBridge = &b
135  
136  	inteltool := ctx.InfoSource.GetInteltool()
137  
138  	isULT := (b.variant == LYNX_POINT_ULT)
139  
140  	if isULT {
141  		Lynxpoint_LP_GPIO(ctx, inteltool)
142  	} else {
143  		GPIO(ctx, inteltool)
144  	}
145  
146  	KconfigBool["SOUTHBRIDGE_INTEL_LYNXPOINT"] = true
147  	if isULT {
148  		KconfigBool["INTEL_LYNXPOINT_LP"] = true
149  	}
150  	KconfigBool["SERIRQ_CONTINUOUS_MODE"] = true
151  	if isULT {
152  		KconfigInt["USBDEBUG_HCD_INDEX"] = 1
153  	} else {
154  		KconfigInt["USBDEBUG_HCD_INDEX"] = 2
155  		KconfigComment["USBDEBUG_HCD_INDEX"] = "FIXME: check this"
156  	}
157  
158  	if isULT {
159  		lpPchGetFlashSize(ctx)
160  	} else {
161  		ich9GetFlashSize(ctx)
162  	}
163  
164  	FADT := ctx.InfoSource.GetACPI()["FACP"]
165  
166  	sp0dtle_data := (inteltool.IOBP[0xea002750] >> 24) & 0xf
167  	sp0dtle_edge := (inteltool.IOBP[0xea002754] >> 16) & 0xf
168  	sp1dtle_data := (inteltool.IOBP[0xea002550] >> 24) & 0xf
169  	sp1dtle_edge := (inteltool.IOBP[0xea002554] >> 16) & 0xf
170  
171  	if sp0dtle_data != sp0dtle_edge {
172  		fmt.Printf("Different SATA Gen3 port0 DTLE data and edge values are used.\n")
173  	}
174  
175  	if sp1dtle_data != sp1dtle_edge {
176  		fmt.Printf("Different SATA Gen3 port1 DTLE data and edge values are used.\n")
177  	}
178  
179  	cur := DevTreeNode{
180  		Chip:    "southbridge/intel/lynxpoint",
181  		Comment: "Intel Series 8 Lynx Point PCH",
182  
183  		/* alt_gp_smi_en is not generated because coreboot doesn't use SMI like OEM firmware */
184  		Registers: map[string]string{
185  			"gen1_dec":             FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x84:0x88]),
186  			"gen2_dec":             FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x88:0x8c]),
187  			"gen3_dec":             FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x8c:0x90]),
188  			"gen4_dec":             FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x90:0x94]),
189  			"sata_port_map":        fmt.Sprintf("0x%x", PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 2}].ConfigDump[0x92]&0x3f),
190  			"docking_supported":    (FormatBool((FADT[113] & (1 << 1)) != 0)),
191  			"sata_port0_gen3_dtle": fmt.Sprintf("0x%x", sp0dtle_data),
192  			"sata_port1_gen3_dtle": fmt.Sprintf("0x%x", sp1dtle_data),
193  		},
194  		PCISlots: []PCISlot{
195  			PCISlot{PCIAddr: PCIAddr{Dev: 0x13, Func: 0}, writeEmpty: isULT, additionalComment: "Smart Sound Audio DSP"},
196  			PCISlot{PCIAddr: PCIAddr{Dev: 0x14, Func: 0}, writeEmpty: true, additionalComment: "xHCI Controller"},
197  			PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 0}, writeEmpty: isULT, additionalComment: "Serial I/O DMA"},
198  			PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 1}, writeEmpty: isULT, additionalComment: "I2C0"},
199  			PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 2}, writeEmpty: isULT, additionalComment: "I2C1"},
200  			PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 3}, writeEmpty: isULT, additionalComment: "GSPI0"},
201  			PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 4}, writeEmpty: isULT, additionalComment: "GSPI1"},
202  			PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 5}, writeEmpty: isULT, additionalComment: "UART0"},
203  			PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 6}, writeEmpty: isULT, additionalComment: "UART1"},
204  			PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 0}, writeEmpty: true, additionalComment: "Management Engine Interface 1"},
205  			PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 1}, writeEmpty: true, additionalComment: "Management Engine Interface 2"},
206  			PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 2}, writeEmpty: true, additionalComment: "Management Engine IDE-R"},
207  			PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 3}, writeEmpty: true, additionalComment: "Management Engine KT"},
208  			PCISlot{PCIAddr: PCIAddr{Dev: 0x17, Func: 0}, writeEmpty: isULT, additionalComment: "SDIO"},
209  			PCISlot{PCIAddr: PCIAddr{Dev: 0x19, Func: 0}, writeEmpty: true, additionalComment: "Intel Gigabit Ethernet"},
210  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1a, Func: 0}, writeEmpty: !isULT, additionalComment: "USB2 EHCI #2"},
211  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1b, Func: 0}, writeEmpty: true, additionalComment: "High Definition Audio"},
212  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 0}, writeEmpty: true, additionalComment: "PCIe Port #1"},
213  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 1}, writeEmpty: true, additionalComment: "PCIe Port #2"},
214  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 2}, writeEmpty: true, additionalComment: "PCIe Port #3"},
215  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 3}, writeEmpty: true, additionalComment: "PCIe Port #4"},
216  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 4}, writeEmpty: true, additionalComment: "PCIe Port #5"},
217  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 5}, writeEmpty: true, additionalComment: "PCIe Port #6"},
218  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 6}, writeEmpty: !isULT, additionalComment: "PCIe Port #7"},
219  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 7}, writeEmpty: !isULT, additionalComment: "PCIe Port #8"},
220  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 0}, writeEmpty: true, additionalComment: "USB2 EHCI #1"},
221  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 0}, writeEmpty: true, additionalComment: "LPC bridge"},
222  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 2}, writeEmpty: true, additionalComment: "SATA Controller (AHCI)"},
223  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 3}, writeEmpty: true, additionalComment: "SMBus"},
224  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 5}, writeEmpty: !isULT, additionalComment: "SATA Controller (Legacy)"},
225  			PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 6}, writeEmpty: true, additionalComment: "Thermal"},
226  		},
227  	}
228  
229  	if isULT {
230  		cur.Registers["gpe0_en_1"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x90])
231  		cur.Registers["gpe0_en_2"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x94])
232  		cur.Registers["gpe0_en_3"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x98])
233  		cur.Registers["gpe0_en_4"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x9c])
234  	} else {
235  		cur.Registers["gpe0_en_1"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x28])
236  		cur.Registers["gpe0_en_2"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x2c])
237  	}
238  
239  	b.node = &cur
240  
241  	PutPCIChip(addr, cur)
242  	PutPCIDevParent(addr, "", "lpc")
243  
244  	DSDTIncludes = append(DSDTIncludes, DSDTInclude{
245  		File: "southbridge/intel/common/acpi/platform.asl",
246  	})
247  	DSDTIncludes = append(DSDTIncludes, DSDTInclude{
248  		File:    "southbridge/intel/lynxpoint/acpi/globalnvs.asl",
249  		Comment: "global NVS and variables",
250  	})
251  	DSDTIncludes = append(DSDTIncludes, DSDTInclude{
252  		File: "southbridge/intel/common/acpi/sleepstates.asl",
253  	})
254  	DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{
255  		File: "southbridge/intel/lynxpoint/acpi/pch.asl",
256  	})
257  
258  	AddBootBlockFile("bootblock.c", "")
259  	bb := Create(ctx, "bootblock.c")
260  	defer bb.Close()
261  	Add_SPDX(bb, C, GPL2_only)
262  	bb.WriteString(`#include <southbridge/intel/lynxpoint/pch.h>
263  
264  /* FIXME: remove this if not needed */
265  void mainboard_config_superio(void)
266  {
267  }
268  `)
269  
270  	sb := Create(ctx, "romstage.c")
271  	defer sb.Close()
272  	Add_SPDX(sb, C, GPL2_only)
273  	sb.WriteString(`#include <stdint.h>
274  #include <northbridge/intel/haswell/haswell.h>
275  #include <southbridge/intel/lynxpoint/pch.h>
276  
277  void mainboard_config_rcba(void)
278  {
279  }
280  
281  /* FIXME: called after romstage_common, remove it if not used */
282  void mb_late_romstage_setup(void)
283  {
284  }
285  
286  const struct usb2_port_config mainboard_usb2_ports[MAX_USB2_PORTS] = {
287  	/* FIXME: Length and Location are computed from IOBP values, may be inaccurate */
288  	/* Length, Enable, OCn#, Location */
289  `)
290  
291  	pdo1 := PCIMap[PCIAddr{Bus: 0, Dev: 0x1d, Func: 0}].ConfigDump[0x64]
292  	ocmap1 := PCIMap[PCIAddr{Bus: 0, Dev: 0x1d, Func: 0}].ConfigDump[0x74:0x78]
293  
294  	var pdo2 uint8
295  	var ocmap2 []uint8
296  	var nPorts uint
297  	if isULT {
298  		nPorts = 8
299  	} else {
300  		pdo2 = PCIMap[PCIAddr{Bus: 0, Dev: 0x1a, Func: 0}].ConfigDump[0x64]
301  		ocmap2 = PCIMap[PCIAddr{Bus: 0, Dev: 0x1a, Func: 0}].ConfigDump[0x74:0x78]
302  		nPorts = 14
303  	}
304  
305  	xusb2pr := GetLE16(PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xd0:0xd4])
306  
307  	for port := uint(0); port < nPorts; port++ {
308  		var port_oc int = -1
309  		var port_pos string
310  		var port_disable uint8
311  
312  		if port < 8 {
313  			port_disable = ((pdo1 >> port) & (uint8(xusb2pr>>port) ^ 1)) & 1
314  			for oc := 0; oc < 4; oc++ {
315  				if (ocmap1[oc] & (1 << port)) != 0 {
316  					port_oc = oc
317  					break
318  				}
319  			}
320  		} else {
321  			port_disable = ((pdo2 >> (port - 8)) & (uint8(xusb2pr>>port) ^ 1)) & 1
322  			for oc := 0; oc < 4; oc++ {
323  				if (ocmap2[oc] & (1 << (port - 8))) != 0 {
324  					port_oc = oc + 4
325  					break
326  				}
327  			}
328  		}
329  
330  		/* get USB2 port length and location from IOBP */
331  		port_iobp := inteltool.IOBP[0xe5004100+uint32(port)*0x100]
332  		loc_param := (port_iobp >> 8) & 7
333  		txamp := (port_iobp >> 11) & 7
334  		var port_length int
335  
336  		if isULT {
337  			port_pos, port_length = GetLptLPEHCISetting(loc_param, txamp)
338  		} else if b.variant == LYNX_POINT_MOBILE {
339  			port_pos, port_length = GetLptMobileEHCISetting(loc_param, txamp)
340  		} else { /* desktop or server */
341  			port_pos, port_length = GetLptDesktopEHCISetting(loc_param, txamp)
342  		}
343  
344  		if port_disable == 1 {
345  			port_pos = "USB_PORT_SKIP"
346  		}
347  
348  		if port_oc == -1 {
349  			fmt.Fprintf(sb, "\t{ 0x%04x, %d, USB_OC_PIN_SKIP, %s },\n",
350  				port_length, (port_disable ^ 1), port_pos)
351  		} else {
352  			fmt.Fprintf(sb, "\t{ 0x%04x, %d, %d, %s },\n",
353  				port_length, (port_disable ^ 1), port_oc, port_pos)
354  		}
355  	}
356  
357  	sb.WriteString(`};
358  
359  const struct usb3_port_config mainboard_usb3_ports[MAX_USB3_PORTS] = {
360  `)
361  
362  	xpdo := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xe8]
363  	u3ocm := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xc8:0xd0]
364  
365  	if !isULT {
366  		nPorts = 6
367  	} else {
368  		nPorts = 4
369  	}
370  
371  	for port := uint(0); port < nPorts; port++ {
372  		var port_oc int = -1
373  		port_disable := (xpdo >> port) & 1
374  		for oc := 0; oc < 8; oc++ {
375  			if (u3ocm[oc] & (1 << port)) != 0 {
376  				port_oc = oc
377  				break
378  			}
379  		}
380  		if port_oc == -1 {
381  			fmt.Fprintf(sb, "\t{ %d, USB_OC_PIN_SKIP },\n",
382  				(port_disable ^ 1))
383  		} else {
384  			fmt.Fprintf(sb, "\t{ %d, %d },\n",
385  				(port_disable ^ 1), port_oc)
386  		}
387  	}
388  
389  	sb.WriteString(`};
390  `)
391  
392  }
393  
394  func init() {
395  	for _, id := range []uint16{
396  		0x8c41, 0x8c49, 0x8c4b, 0x8c4f,
397  	} {
398  		RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_MOBILE})
399  	}
400  
401  	for _, id := range []uint16{
402  		0x8c42, 0x8c44, 0x8c46, 0x8c4a,
403  		0x8c4c, 0x8c4e, 0x8c50, 0x8c5c,
404  	} {
405  		RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_DESKTOP})
406  	}
407  
408  	for _, id := range []uint16{
409  		0x8c52, 0x8c54, 0x8c56,
410  	} {
411  		RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_SERVER})
412  	}
413  
414  	for _, id := range []uint16{
415  		0x9c41, 0x9c43, 0x9c45,
416  	} {
417  		RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_ULT})
418  	}
419  
420  	/* PCIe bridge */
421  	for _, id := range []uint16{
422  		0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
423  		0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
424  	} {
425  		RegisterPCI(0x8086, id, GenericPCI{})
426  	}
427  
428  	/* SMBus controller  */
429  	RegisterPCI(0x8086, 0x8c22, GenericPCI{MissingParent: "smbus"})
430  	RegisterPCI(0x8086, 0x9c22, GenericPCI{MissingParent: "smbus"})
431  
432  	/* SATA */
433  	for _, id := range []uint16{
434  		0x8c00, 0x8c02, 0x8c04, 0x8c06, 0x8c08, 0x8c0e,
435  		0x8c01, 0x8c03, 0x8c05, 0x8c07, 0x8c09, 0x8c0f,
436  		0x9c03, 0x9c05, 0x9c07, 0x9c0f,
437  	} {
438  		RegisterPCI(0x8086, id, GenericPCI{})
439  	}
440  
441  	/* EHCI */
442  	for _, id := range []uint16{
443  		0x9c26, 0x8c26, 0x8c2d,
444  	} {
445  		RegisterPCI(0x8086, id, GenericPCI{})
446  	}
447  
448  	/* XHCI */
449  	RegisterPCI(0x8086, 0x8c31, GenericPCI{})
450  	RegisterPCI(0x8086, 0x9c31, GenericPCI{})
451  
452  	/* ME and children */
453  	for _, id := range []uint16{
454  		0x8c3a, 0x8c3b, 0x8c3c, 0x8c3d,
455  		0x9c3a, 0x9c3b, 0x9c3c, 0x9c3d,
456  	} {
457  		RegisterPCI(0x8086, id, GenericPCI{})
458  	}
459  
460  	/* Ethernet */
461  	RegisterPCI(0x8086, 0x8c33, GenericPCI{})
462  
463  	/* Thermal */
464  	RegisterPCI(0x8086, 0x8c24, GenericPCI{})
465  	RegisterPCI(0x8086, 0x9c24, GenericPCI{})
466  
467  	/* LAN Controller on LP PCH (if EEPROM has 0x0000/0xffff in DID) */
468  	RegisterPCI(0x8086, 0x155a, GenericPCI{})
469  
470  	/* SDIO */
471  	RegisterPCI(0x8086, 0x9c35, GenericPCI{})
472  
473  	/* Smart Sound Technology Controller */
474  	RegisterPCI(0x8086, 0x9c36, GenericPCI{})
475  
476  	/* Serial I/O */
477  	for id := uint16(0x9c60); id <= 0x9c66; id++ {
478  		RegisterPCI(0x8086, id, GenericPCI{})
479  	}
480  }