coreboot/util/autoport/lynxpoint.go
Angel Pons 1f20a947c5 util/autoport: Fix newly-added Kconfig select
Commit 4a09db75d9 ("util/autoport: Add
support for 9 Series PCHs (Lynx Point Refresh)") got submitted after
commit 01d82febb2 ("util/autoport:
Separate handling of Kconfig selects").

The latter commit was specifically made so that the former commit could
properly express a Kconfig select with a condition. However, the former
commit did not get updated, and got submitted as-is since there was no
unresolved review comment to keep track of this TODO. As a result, what
should have been a conditional Kconfig select but with the condition in
a comment to work around limitations of the original system accidentally
became a bool option override.

So, simply use the new system to express a conditional Kconfig select.
This fixes the wrongly-generated Kconfig as well as the original issue.

Even though this would still have worked, the `USE_BROADWELL_MRC` option
must be selected for boards with a Lynx Point Refresh PCH, since Haswell
MRC will not work on those PCHs. Still, this can be caught and corrected
during review, in case any board ports are made before this fix lands.

Change-Id: I98f032283e9e5bb5ec13dbff382304b7abfec07e
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91027
Reviewed-by: Nicholas <nic.c3.14@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
2026-02-02 13:57:38 +00:00

513 lines
16 KiB
Go

package main
import "fmt"
type LPVariant int
const (
LYNX_POINT_MOBILE LPVariant = iota
LYNX_POINT_DESKTOP
LYNX_POINT_SERVER
LYNX_POINT_ULT
LYNX_POINT_REFRESH
)
type lynxpoint struct {
variant LPVariant
node *DevTreeNode
}
func lpPchGetFlashSize(ctx Context) {
inteltool := ctx.InfoSource.GetInteltool()
/* In LP PCH, Boot BIOS Straps field in GCS has only one bit. */
switch (inteltool.RCBA[0x3410] >> 10) & 1 {
case 0:
ROMProtocol = "SPI"
highflkb := uint32(0)
for reg := uint16(0); reg < 5; reg++ {
fl := (inteltool.RCBA[0x3854+4*reg] >> 16) & 0x1fff
flkb := (fl + 1) << 2
if flkb > highflkb {
highflkb = flkb
}
}
ROMSizeKB = int(highflkb)
FlashROMSupport = "y"
}
}
func (b lynxpoint) GetGPIOHeader() string {
return "southbridge/intel/lynxpoint/pch.h"
}
func (b lynxpoint) EnableGPE(in int) {
if b.variant != LYNX_POINT_ULT {
b.node.Registers[fmt.Sprintf("gpi%d_routing", in)] = "2"
}
}
func (b lynxpoint) EncodeGPE(in int) int {
return in + 0x10
}
func (b lynxpoint) DecodeGPE(in int) int {
return in - 0x10
}
func (b lynxpoint) NeedRouteGPIOManually() {
b.node.Comment += ", FIXME: set gpiX_routing for EC support"
}
func GetLptDesktopEHCISetting(loc_param uint32, txamp uint32) (string, int) {
var port_pos string
var port_length int
if loc_param == 4 {
port_pos = "USB_PORT_BACK_PANEL"
if txamp <= 2 {
port_length = 0x40
} else if txamp >= 4 {
port_length = 0x140
} else {
port_length = 0x110
}
} else {
port_pos = "USB_PORT_FLEX"
port_length = 0x40
}
return port_pos, port_length
}
func GetLptMobileEHCISetting(loc_param uint32, txamp uint32) (string, int) {
var port_pos string
var port_length int
if loc_param == 4 {
port_pos = "USB_PORT_DOCK"
if txamp <= 1 {
port_length = 0x40
} else {
port_length = 0x80
}
} else if loc_param == 6 {
/* not internal, not dock, port_length >= 0x70 */
port_pos = "USB_PORT_BACK_PANEL"
if txamp <= 2 {
port_length = 0x80
} else {
port_length = 0x110
}
} else {
port_pos = "USB_PORT_BACK_PANEL"
port_length = 0x40
}
return port_pos, port_length
}
func GetLptLPEHCISetting(loc_param uint32, txamp uint32) (string, int) {
var port_pos string
var port_length int
if loc_param == 6 {
/* back panel or mini pcie, length >= 0x70 */
port_pos = "USB_PORT_MINI_PCIE"
if txamp <= 2 {
port_length = 0x80
} else {
port_length = 0x110
}
} else if loc_param == 4 {
port_pos = "USB_PORT_DOCK"
if txamp <= 1 {
port_length = 0x40
} else {
port_length = 0x80
}
} else {
port_pos = "USB_PORT_BACK_PANEL"
port_length = 0x40
}
return port_pos, port_length
}
func (b lynxpoint) Scan(ctx Context, addr PCIDevData) {
SouthBridge = &b
inteltool := ctx.InfoSource.GetInteltool()
isULT := (b.variant == LYNX_POINT_ULT)
if isULT {
Lynxpoint_LP_GPIO(ctx, inteltool)
} else {
GPIO(ctx, inteltool)
}
KconfigSelect["SOUTHBRIDGE_INTEL_LYNXPOINT"] = ""
if isULT {
KconfigSelect["INTEL_LYNXPOINT_LP"] = ""
}
KconfigSelect["SERIRQ_CONTINUOUS_MODE"] = ""
if isULT {
KconfigInt["USBDEBUG_HCD_INDEX"] = 1
} else {
KconfigInt["USBDEBUG_HCD_INDEX"] = 2
KconfigComment["USBDEBUG_HCD_INDEX"] = "FIXME: check this"
}
if isULT {
lpPchGetFlashSize(ctx)
} else {
ich9GetFlashSize(ctx)
}
if (b.variant == LYNX_POINT_REFRESH) {
KconfigSelect["USE_BROADWELL_MRC"] = "!USE_NATIVE_RAMINIT"
}
FADT := ctx.InfoSource.GetACPI()["FACP"]
sp0dtle_data := (inteltool.IOBP[0xea002750] >> 24) & 0xf
sp0dtle_edge := (inteltool.IOBP[0xea002754] >> 16) & 0xf
sp1dtle_data := (inteltool.IOBP[0xea002550] >> 24) & 0xf
sp1dtle_edge := (inteltool.IOBP[0xea002554] >> 16) & 0xf
if sp0dtle_data != sp0dtle_edge {
fmt.Printf("Different SATA Gen3 port0 DTLE data and edge values are used.\n")
}
if sp1dtle_data != sp1dtle_edge {
fmt.Printf("Different SATA Gen3 port1 DTLE data and edge values are used.\n")
}
cur := DevTreeNode{
Chip: "southbridge/intel/lynxpoint",
Comment: "Intel Series 8 Lynx Point PCH",
/* alt_gp_smi_en is not generated because coreboot doesn't use SMI like OEM firmware */
Registers: map[string]string{
"gen1_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x84:0x88]),
"gen2_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x88:0x8c]),
"gen3_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x8c:0x90]),
"gen4_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x90:0x94]),
"sata_port_map": fmt.Sprintf("0x%x", PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 2}].ConfigDump[0x92]&0x3f),
"docking_supported": (FormatBool((FADT[113] & (1 << 1)) != 0)),
"sata_port0_gen3_dtle": fmt.Sprintf("0x%x", sp0dtle_data),
"sata_port1_gen3_dtle": fmt.Sprintf("0x%x", sp1dtle_data),
},
PCISlots: []PCISlot{
PCISlot{PCIAddr: PCIAddr{Dev: 0x13, Func: 0}, writeEmpty: isULT, additionalComment: "Smart Sound Audio DSP"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x14, Func: 0}, writeEmpty: true, additionalComment: "xHCI Controller"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 0}, writeEmpty: isULT, additionalComment: "Serial I/O DMA"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 1}, writeEmpty: isULT, additionalComment: "I2C0"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 2}, writeEmpty: isULT, additionalComment: "I2C1"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 3}, writeEmpty: isULT, additionalComment: "GSPI0"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 4}, writeEmpty: isULT, additionalComment: "GSPI1"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 5}, writeEmpty: isULT, additionalComment: "UART0"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 6}, writeEmpty: isULT, additionalComment: "UART1"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 0}, writeEmpty: true, additionalComment: "Management Engine Interface 1"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 1}, writeEmpty: true, additionalComment: "Management Engine Interface 2"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 2}, writeEmpty: true, additionalComment: "Management Engine IDE-R"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 3}, writeEmpty: true, additionalComment: "Management Engine KT"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x17, Func: 0}, writeEmpty: isULT, additionalComment: "SDIO"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x19, Func: 0}, writeEmpty: true, additionalComment: "Intel Gigabit Ethernet"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1a, Func: 0}, writeEmpty: !isULT, additionalComment: "USB2 EHCI #2"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1b, Func: 0}, writeEmpty: true, additionalComment: "High Definition Audio"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 0}, writeEmpty: true, additionalComment: "PCIe Port #1"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 1}, writeEmpty: true, additionalComment: "PCIe Port #2"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 2}, writeEmpty: true, additionalComment: "PCIe Port #3"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 3}, writeEmpty: true, additionalComment: "PCIe Port #4"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 4}, writeEmpty: true, additionalComment: "PCIe Port #5"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 5}, writeEmpty: true, additionalComment: "PCIe Port #6"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 6}, writeEmpty: !isULT, additionalComment: "PCIe Port #7"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 7}, writeEmpty: !isULT, additionalComment: "PCIe Port #8"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 0}, writeEmpty: true, additionalComment: "USB2 EHCI #1"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 0}, writeEmpty: true, additionalComment: "LPC bridge"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 2}, writeEmpty: true, additionalComment: "SATA Controller (AHCI)"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 3}, writeEmpty: true, additionalComment: "SMBus"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 5}, writeEmpty: !isULT, additionalComment: "SATA Controller (Legacy)"},
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 6}, writeEmpty: true, additionalComment: "Thermal"},
},
}
if isULT {
cur.Registers["gpe0_en_1"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x90])
cur.Registers["gpe0_en_2"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x94])
cur.Registers["gpe0_en_3"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x98])
cur.Registers["gpe0_en_4"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x9c])
} else {
cur.Registers["gpe0_en_1"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x28])
cur.Registers["gpe0_en_2"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x2c])
}
b.node = &cur
PutPCIChip(addr, cur)
PutPCIDevParent(addr, "", "lpc")
DSDTIncludes = append(DSDTIncludes, DSDTInclude{
File: "southbridge/intel/common/acpi/platform.asl",
})
DSDTIncludes = append(DSDTIncludes, DSDTInclude{
File: "southbridge/intel/lynxpoint/acpi/globalnvs.asl",
Comment: "global NVS and variables",
})
DSDTIncludes = append(DSDTIncludes, DSDTInclude{
File: "southbridge/intel/common/acpi/sleepstates.asl",
})
DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{
File: "southbridge/intel/lynxpoint/acpi/pch.asl",
})
AddBootBlockFile("bootblock.c", "")
bb := Create(ctx, "bootblock.c")
defer bb.Close()
Add_SPDX(bb, C, GPL2_only)
bb.WriteString(`#include <southbridge/intel/lynxpoint/pch.h>
/* FIXME: remove this if not needed */
void mainboard_config_superio(void)
{
}
`)
sb := Create(ctx, "romstage.c")
defer sb.Close()
Add_SPDX(sb, C, GPL2_only)
sb.WriteString(`#include <stdint.h>
#include <northbridge/intel/haswell/haswell.h>
#include <southbridge/intel/lynxpoint/pch.h>
void mainboard_config_rcba(void)
{
}
/* FIXME: called after romstage_common, remove it if not used */
void mb_late_romstage_setup(void)
{
}
const struct usb2_port_config mainboard_usb2_ports[MAX_USB2_PORTS] = {
/* FIXME: Length and Location are computed from IOBP values, may be inaccurate */
/* Length, Enable, OCn#, Location */
`)
pdo1 := PCIMap[PCIAddr{Bus: 0, Dev: 0x1d, Func: 0}].ConfigDump[0x64]
ocmap1 := PCIMap[PCIAddr{Bus: 0, Dev: 0x1d, Func: 0}].ConfigDump[0x74:0x78]
var pdo2 uint8
var ocmap2 []uint8
var nPorts uint
if isULT {
nPorts = 8
} else {
pdo2 = PCIMap[PCIAddr{Bus: 0, Dev: 0x1a, Func: 0}].ConfigDump[0x64]
ocmap2 = PCIMap[PCIAddr{Bus: 0, Dev: 0x1a, Func: 0}].ConfigDump[0x74:0x78]
nPorts = 14
}
xusb2pr := GetLE16(PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xd0:0xd4])
for port := uint(0); port < nPorts; port++ {
var port_oc int = -1
var port_pos string
var port_disable uint8
if port < 8 {
port_disable = ((pdo1 >> port) & (uint8(xusb2pr>>port) ^ 1)) & 1
for oc := 0; oc < 4; oc++ {
if (ocmap1[oc] & (1 << port)) != 0 {
port_oc = oc
break
}
}
} else {
port_disable = ((pdo2 >> (port - 8)) & (uint8(xusb2pr>>port) ^ 1)) & 1
for oc := 0; oc < 4; oc++ {
if (ocmap2[oc] & (1 << (port - 8))) != 0 {
port_oc = oc + 4
break
}
}
}
/* get USB2 port length and location from IOBP */
port_iobp := inteltool.IOBP[0xe5004100+uint32(port)*0x100]
loc_param := (port_iobp >> 8) & 7
txamp := (port_iobp >> 11) & 7
var port_length int
if isULT {
port_pos, port_length = GetLptLPEHCISetting(loc_param, txamp)
} else if b.variant == LYNX_POINT_MOBILE {
port_pos, port_length = GetLptMobileEHCISetting(loc_param, txamp)
} else { /* desktop or server */
port_pos, port_length = GetLptDesktopEHCISetting(loc_param, txamp)
}
if port_disable == 1 {
port_pos = "USB_PORT_SKIP"
}
if port_oc == -1 {
fmt.Fprintf(sb, "\t{ 0x%04x, %d, USB_OC_PIN_SKIP, %s },\n",
port_length, (port_disable ^ 1), port_pos)
} else {
fmt.Fprintf(sb, "\t{ 0x%04x, %d, %d, %s },\n",
port_length, (port_disable ^ 1), port_oc, port_pos)
}
}
sb.WriteString(`};
const struct usb3_port_config mainboard_usb3_ports[MAX_USB3_PORTS] = {
`)
xpdo := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xe8]
u3ocm := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xc8:0xd0]
if !isULT {
nPorts = 6
} else {
nPorts = 4
}
for port := uint(0); port < nPorts; port++ {
var port_oc int = -1
port_disable := (xpdo >> port) & 1
for oc := 0; oc < 8; oc++ {
if (u3ocm[oc] & (1 << port)) != 0 {
port_oc = oc
break
}
}
if port_oc == -1 {
fmt.Fprintf(sb, "\t{ %d, USB_OC_PIN_SKIP },\n",
(port_disable ^ 1))
} else {
fmt.Fprintf(sb, "\t{ %d, %d },\n",
(port_disable ^ 1), port_oc)
}
}
sb.WriteString(`};
`)
}
func init() {
for _, id := range []uint16{
/* Lynx Point (8 Series PCH) */
0x8c41, 0x8c49, 0x8c4b, 0x8c4f,
} {
RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_MOBILE})
}
for _, id := range []uint16{
/* Lynx Point (8 Series PCH) */
0x8c42, 0x8c44, 0x8c46, 0x8c4a,
0x8c4c, 0x8c4e, 0x8c50, 0x8c5c,
} {
RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_DESKTOP})
}
for _, id := range []uint16{
0x8c52, 0x8c54, 0x8c56,
} {
RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_SERVER})
}
for _, id := range []uint16{
0x9c41, 0x9c43, 0x9c45,
} {
RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_ULT})
}
for _, id := range []uint16{
/* Lynx Point Refresh (9 Series PCH) */
0x8cc1, 0x8cc2, 0x8cc3, 0x8cc4, 0x8cc6,
} {
RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_REFRESH})
}
/* PCIe bridge */
for _, id := range []uint16{
/* Lynx Point (8 Series PCH) */
0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
/* Lynx Point LP */
0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
/* Lynx Point Refresh (9 Series PCH) */
0x8c90, 0x8c92, 0x8c94, 0x8c96, 0x8c98, 0x8c9a, 0x8c9c, 0x8c9e,
} {
RegisterPCI(0x8086, id, GenericPCI{})
}
/* SMBus controller */
RegisterPCI(0x8086, 0x8c22, GenericPCI{MissingParent: "smbus"}) /* Lynx Point (8 Series PCH) */
RegisterPCI(0x8086, 0x9c22, GenericPCI{MissingParent: "smbus"}) /* Lynx Point LP */
RegisterPCI(0x8086, 0x8ca2, GenericPCI{MissingParent: "smbus"}) /* Lynx Point Refresh (9 Series PCH) */
/* SATA */
for _, id := range []uint16{
/* Lynx Point (8 Series PCH) */
0x8c00, 0x8c02, 0x8c04, 0x8c06, 0x8c08, 0x8c0e,
0x8c01, 0x8c03, 0x8c05, 0x8c07, 0x8c09, 0x8c0f,
/* Lynx Point LP */
0x9c03, 0x9c05, 0x9c07, 0x9c0f,
/* Lynx Point Refresh (9 Series PCH) */
0x8c80, 0x8c82, 0x8c84, 0x8c86, 0x8c88, 0x8c8e,
0x8c81, 0x8c83, 0x8c85, 0x8c87, 0x8c89, 0x8c8f,
} {
RegisterPCI(0x8086, id, GenericPCI{})
}
/* EHCI */
for _, id := range []uint16{
0x8c26, 0x8c2d, /* Lynx Point (8 Series PCH) */
0x9c26, /* Lynx Point LP */
0x8ca6, 0x8cad, /* Lynx Point Refresh (9 Series PCH) */
} {
RegisterPCI(0x8086, id, GenericPCI{})
}
/* XHCI */
RegisterPCI(0x8086, 0x8c31, GenericPCI{}) /* Lynx Point (8 Series PCH) */
RegisterPCI(0x8086, 0x9c31, GenericPCI{}) /* Lynx Point LP */
RegisterPCI(0x8086, 0x8cb1, GenericPCI{}) /* Lynx Point Refresh (9 Series PCH) */
/* ME and children */
for _, id := range []uint16{
/* Lynx Point (8 Series PCH) */
0x8c3a, 0x8c3b, 0x8c3c, 0x8c3d,
/* Lynx Point LP */
0x9c3a, 0x9c3b, 0x9c3c, 0x9c3d,
/* Lynx Point Refresh (9 Series PCH) */
0x8cba, 0x8cbb, 0x8cbc, 0x8cbd,
} {
RegisterPCI(0x8086, id, GenericPCI{})
}
/* Ethernet */
RegisterPCI(0x8086, 0x8c33, GenericPCI{}) /* Lynx Point (8 Series PCH) */
RegisterPCI(0x8086, 0x8cb3, GenericPCI{}) /* Lynx Point Refresh (9 Series PCH) */
/* Thermal */
RegisterPCI(0x8086, 0x8c24, GenericPCI{}) /* Lynx Point (8 Series PCH) */
RegisterPCI(0x8086, 0x9c24, GenericPCI{}) /* Lynx Point LP */
RegisterPCI(0x8086, 0x8ca4, GenericPCI{}) /* Lynx Point Refresh (9 Series PCH) */
/* LAN Controller on LP PCH (if EEPROM has 0x0000/0xffff in DID) */
RegisterPCI(0x8086, 0x155a, GenericPCI{})
/* SDIO */
RegisterPCI(0x8086, 0x9c35, GenericPCI{})
/* Smart Sound Technology Controller */
RegisterPCI(0x8086, 0x9c36, GenericPCI{})
/* Serial I/O */
for id := uint16(0x9c60); id <= 0x9c66; id++ {
RegisterPCI(0x8086, id, GenericPCI{})
}
}