MAINTAINERS: Add Maximilian Brune to RISC-V
[coreboot.git] / util / autoport / lynxpoint.go
blob98a1ca8248d847cd5752f39e737101ff1881688c
1 package main
3 import "fmt"
5 type LPVariant int
7 const (
8 LYNX_POINT_MOBILE LPVariant = iota
9 LYNX_POINT_DESKTOP
10 LYNX_POINT_SERVER
11 LYNX_POINT_ULT
14 type lynxpoint struct {
15 variant LPVariant
16 node *DevTreeNode
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
33 ROMSizeKB = int(highflkb)
34 FlashROMSupport = "y"
38 func (b lynxpoint) GetGPIOHeader() string {
39 return "southbridge/intel/lynxpoint/pch.h"
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"
48 func (b lynxpoint) EncodeGPE(in int) int {
49 return in + 0x10
52 func (b lynxpoint) DecodeGPE(in int) int {
53 return in - 0x10
56 func (b lynxpoint) NeedRouteGPIOManually() {
57 b.node.Comment += ", FIXME: set gpiX_routing for EC support"
60 func GetLptDesktopEHCISetting(loc_param uint32, txamp uint32) (string, int) {
61 var port_pos string
62 var port_length int
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
73 } else {
74 port_pos = "USB_PORT_FLEX"
75 port_length = 0x40
77 return port_pos, port_length
80 func GetLptMobileEHCISetting(loc_param uint32, txamp uint32) (string, int) {
81 var port_pos string
82 var port_length int
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
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
99 } else {
100 port_pos = "USB_PORT_BACK_PANEL"
101 port_length = 0x40
103 return port_pos, port_length
106 func GetLptLPEHCISetting(loc_param uint32, txamp uint32) (string, int) {
107 var port_pos string
108 var port_length int
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
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
125 } else {
126 port_pos = "USB_PORT_BACK_PANEL"
127 port_length = 0x40
129 return port_pos, port_length
132 func (b lynxpoint) Scan(ctx Context, addr PCIDevData) {
134 SouthBridge = &b
136 inteltool := ctx.InfoSource.GetInteltool()
138 isULT := (b.variant == LYNX_POINT_ULT)
140 if isULT {
141 Lynxpoint_LP_GPIO(ctx, inteltool)
142 } else {
143 GPIO(ctx, inteltool)
146 KconfigBool["SOUTHBRIDGE_INTEL_LYNXPOINT"] = true
147 if isULT {
148 KconfigBool["INTEL_LYNXPOINT_LP"] = true
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"
158 if isULT {
159 lpPchGetFlashSize(ctx)
160 } else {
161 ich9GetFlashSize(ctx)
164 FADT := ctx.InfoSource.GetACPI()["FACP"]
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
171 if sp0dtle_data != sp0dtle_edge {
172 fmt.Printf("Different SATA Gen3 port0 DTLE data and edge values are used.\n")
175 if sp1dtle_data != sp1dtle_edge {
176 fmt.Printf("Different SATA Gen3 port1 DTLE data and edge values are used.\n")
179 cur := DevTreeNode{
180 Chip: "southbridge/intel/lynxpoint",
181 Comment: "Intel Series 8 Lynx Point PCH",
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),
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"},
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])
239 b.node = &cur
241 PutPCIChip(addr, cur)
242 PutPCIDevParent(addr, "", "lpc")
244 DSDTIncludes = append(DSDTIncludes, DSDTInclude{
245 File: "southbridge/intel/common/acpi/platform.asl",
247 DSDTIncludes = append(DSDTIncludes, DSDTInclude{
248 File: "southbridge/intel/lynxpoint/acpi/globalnvs.asl",
249 Comment: "global NVS and variables",
251 DSDTIncludes = append(DSDTIncludes, DSDTInclude{
252 File: "southbridge/intel/common/acpi/sleepstates.asl",
254 DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{
255 File: "southbridge/intel/lynxpoint/acpi/pch.asl",
258 AddBootBlockFile("bootblock.c", "")
259 bb := Create(ctx, "bootblock.c")
260 defer bb.Close()
261 Add_gpl(bb)
262 bb.WriteString(`#include <southbridge/intel/lynxpoint/pch.h>
264 /* FIXME: remove this if not needed */
265 void mainboard_config_superio(void)
270 sb := Create(ctx, "romstage.c")
271 defer sb.Close()
272 Add_gpl(sb)
273 sb.WriteString(`#include <stdint.h>
274 #include <northbridge/intel/haswell/haswell.h>
275 #include <northbridge/intel/haswell/raminit.h>
276 #include <southbridge/intel/lynxpoint/pch.h>
278 void mainboard_config_rcba(void)
282 /* FIXME: called after romstage_common, remove it if not used */
283 void mb_late_romstage_setup(void)
287 void mb_get_spd_map(struct spd_info *spdi)
289 /* FIXME: check this */
290 spdi->addresses[0] = 0x50;
291 spdi->addresses[1] = 0x51;
292 spdi->addresses[2] = 0x52;
293 spdi->addresses[3] = 0x53;
296 const struct usb2_port_config mainboard_usb2_ports[MAX_USB2_PORTS] = {
297 /* FIXME: Length and Location are computed from IOBP values, may be inaccurate */
298 /* Length, Enable, OCn#, Location */
301 pdo1 := PCIMap[PCIAddr{Bus: 0, Dev: 0x1d, Func: 0}].ConfigDump[0x64]
302 ocmap1 := PCIMap[PCIAddr{Bus: 0, Dev: 0x1d, Func: 0}].ConfigDump[0x74:0x78]
304 var pdo2 uint8
305 var ocmap2 []uint8
306 var nPorts uint
307 if isULT {
308 nPorts = 8
309 } else {
310 pdo2 = PCIMap[PCIAddr{Bus: 0, Dev: 0x1a, Func: 0}].ConfigDump[0x64]
311 ocmap2 = PCIMap[PCIAddr{Bus: 0, Dev: 0x1a, Func: 0}].ConfigDump[0x74:0x78]
312 nPorts = 14
315 xusb2pr := GetLE16(PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xd0:0xd4])
317 for port := uint(0); port < nPorts; port++ {
318 var port_oc int = -1
319 var port_pos string
320 var port_disable uint8
322 if port < 8 {
323 port_disable = ((pdo1 >> port) & (uint8(xusb2pr>>port) ^ 1)) & 1
324 for oc := 0; oc < 4; oc++ {
325 if (ocmap1[oc] & (1 << port)) != 0 {
326 port_oc = oc
327 break
330 } else {
331 port_disable = ((pdo2 >> (port - 8)) & (uint8(xusb2pr>>port) ^ 1)) & 1
332 for oc := 0; oc < 4; oc++ {
333 if (ocmap2[oc] & (1 << (port - 8))) != 0 {
334 port_oc = oc + 4
335 break
340 /* get USB2 port length and location from IOBP */
341 port_iobp := inteltool.IOBP[0xe5004100+uint32(port)*0x100]
342 loc_param := (port_iobp >> 8) & 7
343 txamp := (port_iobp >> 11) & 7
344 var port_length int
346 if isULT {
347 port_pos, port_length = GetLptLPEHCISetting(loc_param, txamp)
348 } else if b.variant == LYNX_POINT_MOBILE {
349 port_pos, port_length = GetLptMobileEHCISetting(loc_param, txamp)
350 } else { /* desktop or server */
351 port_pos, port_length = GetLptDesktopEHCISetting(loc_param, txamp)
354 if port_disable == 1 {
355 port_pos = "USB_PORT_SKIP"
358 if port_oc == -1 {
359 fmt.Fprintf(sb, "\t{ 0x%04x, %d, USB_OC_PIN_SKIP, %s },\n",
360 port_length, (port_disable ^ 1), port_pos)
361 } else {
362 fmt.Fprintf(sb, "\t{ 0x%04x, %d, %d, %s },\n",
363 port_length, (port_disable ^ 1), port_oc, port_pos)
367 sb.WriteString(`};
369 const struct usb3_port_config mainboard_usb3_ports[MAX_USB3_PORTS] = {
372 xpdo := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xe8]
373 u3ocm := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xc8:0xd0]
375 if !isULT {
376 nPorts = 6
377 } else {
378 nPorts = 4
381 for port := uint(0); port < nPorts; port++ {
382 var port_oc int = -1
383 port_disable := (xpdo >> port) & 1
384 for oc := 0; oc < 8; oc++ {
385 if (u3ocm[oc] & (1 << port)) != 0 {
386 port_oc = oc
387 break
390 if port_oc == -1 {
391 fmt.Fprintf(sb, "\t{ %d, USB_OC_PIN_SKIP },\n",
392 (port_disable ^ 1))
393 } else {
394 fmt.Fprintf(sb, "\t{ %d, %d },\n",
395 (port_disable ^ 1), port_oc)
399 sb.WriteString(`};
404 func init() {
405 for _, id := range []uint16{
406 0x8c41, 0x8c49, 0x8c4b, 0x8c4f,
408 RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_MOBILE})
411 for _, id := range []uint16{
412 0x8c42, 0x8c44, 0x8c46, 0x8c4a,
413 0x8c4c, 0x8c4e, 0x8c50, 0x8c5c,
415 RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_DESKTOP})
418 for _, id := range []uint16{
419 0x8c52, 0x8c54, 0x8c56,
421 RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_SERVER})
424 for _, id := range []uint16{
425 0x9c41, 0x9c43, 0x9c45,
427 RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_ULT})
430 /* PCIe bridge */
431 for _, id := range []uint16{
432 0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
433 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
435 RegisterPCI(0x8086, id, GenericPCI{})
438 /* SMBus controller */
439 RegisterPCI(0x8086, 0x8c22, GenericPCI{MissingParent: "smbus"})
440 RegisterPCI(0x8086, 0x9c22, GenericPCI{MissingParent: "smbus"})
442 /* SATA */
443 for _, id := range []uint16{
444 0x8c00, 0x8c02, 0x8c04, 0x8c06, 0x8c08, 0x8c0e,
445 0x8c01, 0x8c03, 0x8c05, 0x8c07, 0x8c09, 0x8c0f,
446 0x9c03, 0x9c05, 0x9c07, 0x9c0f,
448 RegisterPCI(0x8086, id, GenericPCI{})
451 /* EHCI */
452 for _, id := range []uint16{
453 0x9c26, 0x8c26, 0x8c2d,
455 RegisterPCI(0x8086, id, GenericPCI{})
458 /* XHCI */
459 RegisterPCI(0x8086, 0x8c31, GenericPCI{})
460 RegisterPCI(0x8086, 0x9c31, GenericPCI{})
462 /* ME and children */
463 for _, id := range []uint16{
464 0x8c3a, 0x8c3b, 0x8c3c, 0x8c3d,
465 0x9c3a, 0x9c3b, 0x9c3c, 0x9c3d,
467 RegisterPCI(0x8086, id, GenericPCI{})
470 /* Ethernet */
471 RegisterPCI(0x8086, 0x8c33, GenericPCI{})
473 /* Thermal */
474 RegisterPCI(0x8086, 0x8c24, GenericPCI{})
475 RegisterPCI(0x8086, 0x9c24, GenericPCI{})
477 /* LAN Controller on LP PCH (if EEPROM has 0x0000/0xffff in DID) */
478 RegisterPCI(0x8086, 0x155a, GenericPCI{})
480 /* SDIO */
481 RegisterPCI(0x8086, 0x9c35, GenericPCI{})
483 /* Smart Sound Technology Controller */
484 RegisterPCI(0x8086, 0x9c36, GenericPCI{})
486 /* Serial I/O */
487 for id := uint16(0x9c60); id <= 0x9c66; id++ {
488 RegisterPCI(0x8086, id, GenericPCI{})