remove util/autoport
upstream has merged all of the changes that it contained, so we don't need this anymore. we'll have the newer upstream changes on the next general revision updates for coreboot, within config/coreboot/ Signed-off-by: Leah Rowe <leah@libreboot.org>audit6
parent
373c2eb23d
commit
f367afabc1
|
@ -118,6 +118,7 @@ configure_project()
|
||||||
{
|
{
|
||||||
eval `setvars "" xarch xlang build_depend autoconfargs xtree postmake \
|
eval `setvars "" xarch xlang build_depend autoconfargs xtree postmake \
|
||||||
tree_depend makeargs btype mkhelper bootstrapargs premake release`
|
tree_depend makeargs btype mkhelper bootstrapargs premake release`
|
||||||
|
|
||||||
[ -f "$1/target.cfg" ] || btype="auto"
|
[ -f "$1/target.cfg" ] || btype="auto"
|
||||||
[ -f "$datadir/mkhelper.cfg" ] && eval `setcfg "$datadir/mkhelper.cfg"`
|
[ -f "$datadir/mkhelper.cfg" ] && eval `setcfg "$datadir/mkhelper.cfg"`
|
||||||
|
|
||||||
|
@ -143,6 +144,7 @@ configure_project()
|
||||||
|
|
||||||
[ "$mode" = "fetch" ] || x_ ./update trees -f "$project" $target
|
[ "$mode" = "fetch" ] || x_ ./update trees -f "$project" $target
|
||||||
[ "$mode" = "fetch" ] || return 0
|
[ "$mode" = "fetch" ] || return 0
|
||||||
|
|
||||||
[ -f "CHANGELOG" ] && return 1; fetch_${cmd#build_}; return 1
|
[ -f "CHANGELOG" ] && return 1; fetch_${cmd#build_}; return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
type azalia struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i azalia) Scan(ctx Context, addr PCIDevData) {
|
|
||||||
az := Create(ctx, "hda_verb.c")
|
|
||||||
defer az.Close()
|
|
||||||
|
|
||||||
Add_gpl(az)
|
|
||||||
az.WriteString(
|
|
||||||
`#include <device/azalia_device.h>
|
|
||||||
|
|
||||||
const u32 cim_verb_data[] = {
|
|
||||||
`)
|
|
||||||
|
|
||||||
for _, codec := range ctx.InfoSource.GetAzaliaCodecs() {
|
|
||||||
fmt.Fprintf(az, "\t0x%08x,\t/* Codec Vendor / Device ID: %s */\n",
|
|
||||||
codec.VendorID, codec.Name)
|
|
||||||
fmt.Fprintf(az, "\t0x%08x,\t/* Subsystem ID */\n",
|
|
||||||
codec.SubsystemID)
|
|
||||||
fmt.Fprintf(az, "\t%d,\t\t/* Number of 4 dword sets */\n",
|
|
||||||
len(codec.PinConfig)+1)
|
|
||||||
fmt.Fprintf(az, "\tAZALIA_SUBVENDOR(%d, 0x%08x),\n",
|
|
||||||
codec.CodecNo, codec.SubsystemID)
|
|
||||||
|
|
||||||
keys := []int{}
|
|
||||||
for nid, _ := range codec.PinConfig {
|
|
||||||
keys = append(keys, nid)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Ints(keys)
|
|
||||||
|
|
||||||
for _, nid := range keys {
|
|
||||||
fmt.Fprintf(az, "\tAZALIA_PIN_CFG(%d, 0x%02x, 0x%08x),\n",
|
|
||||||
codec.CodecNo, nid, codec.PinConfig[nid])
|
|
||||||
}
|
|
||||||
az.WriteString("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
az.WriteString(
|
|
||||||
`};
|
|
||||||
|
|
||||||
const u32 pc_beep_verbs[0] = {};
|
|
||||||
|
|
||||||
AZALIA_ARRAY_SIZES;
|
|
||||||
`)
|
|
||||||
|
|
||||||
PutPCIDev(addr, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
/* I82801GX/I945 */
|
|
||||||
RegisterPCI(0x8086, 0x27d8, azalia{})
|
|
||||||
/* BD82X6X/sandybridge */
|
|
||||||
RegisterPCI(0x8086, 0x1c20, azalia{})
|
|
||||||
/* C216/ivybridge */
|
|
||||||
RegisterPCI(0x8086, 0x1e20, azalia{})
|
|
||||||
/* Lynx Point */
|
|
||||||
RegisterPCI(0x8086, 0x8c20, azalia{})
|
|
||||||
RegisterPCI(0x8086, 0x9c20, azalia{})
|
|
||||||
}
|
|
|
@ -1,337 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type bd82x6x struct {
|
|
||||||
variant string
|
|
||||||
node *DevTreeNode
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsPCIeHotplug(ctx Context, port int) bool {
|
|
||||||
portDev, ok := PCIMap[PCIAddr{Bus: 0, Dev: 0x1c, Func: port}]
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return (portDev.ConfigDump[0xdb] & (1 << 6)) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func ich9GetFlashSize(ctx Context) {
|
|
||||||
inteltool := ctx.InfoSource.GetInteltool()
|
|
||||||
switch (inteltool.RCBA[0x3410] >> 10) & 3 {
|
|
||||||
/* SPI. All boards I've seen with sandy/ivy use SPI. */
|
|
||||||
case 3:
|
|
||||||
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)
|
|
||||||
/* Shared with ME. Flashrom is unable to handle it. */
|
|
||||||
FlashROMSupport = "n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b bd82x6x) GetGPIOHeader() string {
|
|
||||||
return "southbridge/intel/bd82x6x/pch.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b bd82x6x) EnableGPE(in int) {
|
|
||||||
b.node.Registers[fmt.Sprintf("gpi%d_routing", in)] = "2"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b bd82x6x) EncodeGPE(in int) int {
|
|
||||||
return in + 0x10
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b bd82x6x) DecodeGPE(in int) int {
|
|
||||||
return in - 0x10
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b bd82x6x) NeedRouteGPIOManually() {
|
|
||||||
b.node.Comment += ", FIXME: set gpiX_routing for EC support"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b bd82x6x) Scan(ctx Context, addr PCIDevData) {
|
|
||||||
|
|
||||||
SouthBridge = &b
|
|
||||||
|
|
||||||
inteltool := ctx.InfoSource.GetInteltool()
|
|
||||||
GPIO(ctx, inteltool)
|
|
||||||
|
|
||||||
KconfigBool["SOUTHBRIDGE_INTEL_"+b.variant] = true
|
|
||||||
KconfigBool["SERIRQ_CONTINUOUS_MODE"] = true
|
|
||||||
KconfigInt["USBDEBUG_HCD_INDEX"] = 2
|
|
||||||
KconfigComment["USBDEBUG_HCD_INDEX"] = "FIXME: check this"
|
|
||||||
dmi := ctx.InfoSource.GetDMI()
|
|
||||||
if dmi.Vendor == "LENOVO" {
|
|
||||||
KconfigInt["DRAM_RESET_GATE_GPIO"] = 10
|
|
||||||
} else {
|
|
||||||
KconfigInt["DRAM_RESET_GATE_GPIO"] = 60
|
|
||||||
}
|
|
||||||
KconfigComment["DRAM_RESET_GATE_GPIO"] = "FIXME: check this"
|
|
||||||
|
|
||||||
ich9GetFlashSize(ctx)
|
|
||||||
|
|
||||||
DSDTDefines = append(DSDTDefines,
|
|
||||||
DSDTDefine{
|
|
||||||
Key: "BRIGHTNESS_UP",
|
|
||||||
Value: "\\_SB.PCI0.GFX0.INCB",
|
|
||||||
},
|
|
||||||
DSDTDefine{
|
|
||||||
Key: "BRIGHTNESS_DOWN",
|
|
||||||
Value: "\\_SB.PCI0.GFX0.DECB",
|
|
||||||
})
|
|
||||||
|
|
||||||
/* SPI init */
|
|
||||||
MainboardIncludes = append(MainboardIncludes, "southbridge/intel/bd82x6x/pch.h")
|
|
||||||
|
|
||||||
FADT := ctx.InfoSource.GetACPI()["FACP"]
|
|
||||||
|
|
||||||
pcieHotplugMap := "{ "
|
|
||||||
|
|
||||||
for port := 0; port < 7; port++ {
|
|
||||||
if IsPCIeHotplug(ctx, port) {
|
|
||||||
pcieHotplugMap += "1, "
|
|
||||||
} else {
|
|
||||||
pcieHotplugMap += "0, "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if IsPCIeHotplug(ctx, 7) {
|
|
||||||
pcieHotplugMap += "1 }"
|
|
||||||
} else {
|
|
||||||
pcieHotplugMap += "0 }"
|
|
||||||
}
|
|
||||||
|
|
||||||
cur := DevTreeNode{
|
|
||||||
Chip: "southbridge/intel/bd82x6x",
|
|
||||||
Comment: "Intel Series 6 Cougar Point PCH",
|
|
||||||
|
|
||||||
Registers: map[string]string{
|
|
||||||
"sata_interface_speed_support": "0x3",
|
|
||||||
"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]),
|
|
||||||
"pcie_port_coalesce": "1",
|
|
||||||
"pcie_hotplug_map": pcieHotplugMap,
|
|
||||||
|
|
||||||
"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)),
|
|
||||||
"spi_uvscc": fmt.Sprintf("0x%x", inteltool.RCBA[0x38c8]),
|
|
||||||
"spi_lvscc": fmt.Sprintf("0x%x", inteltool.RCBA[0x38c4]&^(1<<23)),
|
|
||||||
},
|
|
||||||
PCISlots: []PCISlot{
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x14, Func: 0}, writeEmpty: false, alias: "xhci", additionalComment: "USB 3.0 Controller"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 0}, writeEmpty: true, alias: "mei1", additionalComment: "Management Engine Interface 1"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 1}, writeEmpty: true, alias: "mei2", additionalComment: "Management Engine Interface 2"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 2}, writeEmpty: true, alias: "me_ide_r", additionalComment: "Management Engine IDE-R"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 3}, writeEmpty: true, alias: "me_kt", additionalComment: "Management Engine KT"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x19, Func: 0}, writeEmpty: true, alias: "gbe", additionalComment: "Intel Gigabit Ethernet"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1a, Func: 0}, writeEmpty: true, alias: "ehci2", additionalComment: "USB2 EHCI #2"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1b, Func: 0}, writeEmpty: true, alias: "hda", additionalComment: "High Definition Audio"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 0}, writeEmpty: true, alias: "pcie_rp1", additionalComment: "PCIe Port #1"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 1}, writeEmpty: true, alias: "pcie_rp2", additionalComment: "PCIe Port #2"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 2}, writeEmpty: true, alias: "pcie_rp3", additionalComment: "PCIe Port #3"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 3}, writeEmpty: true, alias: "pcie_rp4", additionalComment: "PCIe Port #4"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 4}, writeEmpty: true, alias: "pcie_rp5", additionalComment: "PCIe Port #5"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 5}, writeEmpty: true, alias: "pcie_rp6", additionalComment: "PCIe Port #6"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 6}, writeEmpty: true, alias: "pcie_rp7", additionalComment: "PCIe Port #7"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 7}, writeEmpty: true, alias: "pcie_rp8", additionalComment: "PCIe Port #8"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 0}, writeEmpty: true, alias: "ehci1", additionalComment: "USB2 EHCI #1"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1e, Func: 0}, writeEmpty: true, alias: "pci_bridge", additionalComment: "PCI bridge"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 0}, writeEmpty: true, alias: "lpc", additionalComment: "LPC bridge"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 2}, writeEmpty: true, alias: "sata1", additionalComment: "SATA Controller 1"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 3}, writeEmpty: true, alias: "smbus", additionalComment: "SMBus"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 5}, writeEmpty: true, alias: "sata2", additionalComment: "SATA Controller 2"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 6}, writeEmpty: true, alias: "thermal", additionalComment: "Thermal"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
b.node = &cur
|
|
||||||
|
|
||||||
xhciDev, ok := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}]
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
cur.Registers["xhci_switchable_ports"] = FormatHexLE32(xhciDev.ConfigDump[0xd4:0xd8])
|
|
||||||
cur.Registers["superspeed_capable_ports"] = FormatHexLE32(xhciDev.ConfigDump[0xdc:0xe0])
|
|
||||||
cur.Registers["xhci_overcurrent_mapping"] = FormatHexLE32(xhciDev.ConfigDump[0xc0:0xc4])
|
|
||||||
}
|
|
||||||
|
|
||||||
PutPCIChip(addr, cur)
|
|
||||||
PutPCIDevParent(addr, "", "lpc")
|
|
||||||
|
|
||||||
DSDTIncludes = append(DSDTIncludes, DSDTInclude{
|
|
||||||
File: "southbridge/intel/common/acpi/platform.asl",
|
|
||||||
})
|
|
||||||
DSDTIncludes = append(DSDTIncludes, DSDTInclude{
|
|
||||||
File: "southbridge/intel/bd82x6x/acpi/globalnvs.asl",
|
|
||||||
})
|
|
||||||
DSDTIncludes = append(DSDTIncludes, DSDTInclude{
|
|
||||||
File: "southbridge/intel/common/acpi/sleepstates.asl",
|
|
||||||
})
|
|
||||||
DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{
|
|
||||||
File: "southbridge/intel/bd82x6x/acpi/pch.asl",
|
|
||||||
})
|
|
||||||
|
|
||||||
AddBootBlockFile("early_init.c", "")
|
|
||||||
AddROMStageFile("early_init.c", "")
|
|
||||||
|
|
||||||
sb := Create(ctx, "early_init.c")
|
|
||||||
defer sb.Close()
|
|
||||||
Add_gpl(sb)
|
|
||||||
|
|
||||||
sb.WriteString(`
|
|
||||||
#include <bootblock_common.h>
|
|
||||||
#include <device/pci_ops.h>
|
|
||||||
#include <northbridge/intel/sandybridge/raminit_native.h>
|
|
||||||
#include <southbridge/intel/bd82x6x/pch.h>
|
|
||||||
|
|
||||||
`)
|
|
||||||
sb.WriteString("const struct southbridge_usb_port mainboard_usb_ports[] = {\n")
|
|
||||||
|
|
||||||
currentMap := map[uint32]int{
|
|
||||||
0x20000153: 0,
|
|
||||||
0x20000f57: 1,
|
|
||||||
0x2000055b: 2,
|
|
||||||
0x20000f51: 3,
|
|
||||||
0x2000094a: 4,
|
|
||||||
0x2000035f: 5,
|
|
||||||
0x20000f53: 6,
|
|
||||||
0x20000357: 7,
|
|
||||||
0x20000353: 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
for port := uint(0); port < 14; port++ {
|
|
||||||
var pinmask uint32
|
|
||||||
OCPin := -1
|
|
||||||
if port < 8 {
|
|
||||||
pinmask = inteltool.RCBA[0x35a0]
|
|
||||||
} else {
|
|
||||||
pinmask = inteltool.RCBA[0x35a4]
|
|
||||||
}
|
|
||||||
for pin := uint(0); pin < 4; pin++ {
|
|
||||||
if ((pinmask >> ((port % 8) + 8*pin)) & 1) != 0 {
|
|
||||||
OCPin = int(pin)
|
|
||||||
if port >= 8 {
|
|
||||||
OCPin += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current, ok := currentMap[inteltool.RCBA[uint16(0x3500+4*port)]]
|
|
||||||
comment := ""
|
|
||||||
if !ok {
|
|
||||||
comment = fmt.Sprintf("// FIXME: Unknown current: RCBA(0x%x)=0x%x", 0x3500+4*port, uint16(0x3500+4*port))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(sb, "\t{ %d, %d, %d }, %s\n",
|
|
||||||
((inteltool.RCBA[0x359c]>>port)&1)^1,
|
|
||||||
current,
|
|
||||||
OCPin,
|
|
||||||
comment)
|
|
||||||
}
|
|
||||||
sb.WriteString("};\n")
|
|
||||||
|
|
||||||
guessedMap := GuessSPDMap(ctx)
|
|
||||||
|
|
||||||
sb.WriteString(`
|
|
||||||
void bootblock_mainboard_early_init(void)
|
|
||||||
{
|
|
||||||
`)
|
|
||||||
RestorePCI16Simple(sb, addr, 0x82)
|
|
||||||
|
|
||||||
RestorePCI16Simple(sb, addr, 0x80)
|
|
||||||
|
|
||||||
sb.WriteString(`}
|
|
||||||
|
|
||||||
/* FIXME: Put proper SPD map here. */
|
|
||||||
void mainboard_get_spd(spd_raw_data *spd, bool id_only)
|
|
||||||
{
|
|
||||||
`)
|
|
||||||
for i, spd := range guessedMap {
|
|
||||||
fmt.Fprintf(sb, "\tread_spd(&spd[%d], 0x%02x, id_only);\n", i, spd)
|
|
||||||
}
|
|
||||||
sb.WriteString("}\n")
|
|
||||||
|
|
||||||
gnvs := Create(ctx, "acpi_tables.c")
|
|
||||||
defer gnvs.Close()
|
|
||||||
|
|
||||||
Add_gpl(gnvs)
|
|
||||||
gnvs.WriteString(`#include <acpi/acpi_gnvs.h>
|
|
||||||
#include <soc/nvs.h>
|
|
||||||
|
|
||||||
/* FIXME: check this function. */
|
|
||||||
void mainboard_fill_gnvs(struct global_nvs *gnvs)
|
|
||||||
{
|
|
||||||
/* The lid is open by default. */
|
|
||||||
gnvs->lids = 1;
|
|
||||||
|
|
||||||
/* Temperature at which OS will shutdown */
|
|
||||||
gnvs->tcrt = 100;
|
|
||||||
/* Temperature at which OS will throttle CPU */
|
|
||||||
gnvs->tpsv = 90;
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
/* BD82X6X LPC */
|
|
||||||
for id := 0x1c40; id <= 0x1c5f; id++ {
|
|
||||||
RegisterPCI(0x8086, uint16(id), bd82x6x{variant: "BD82X6X"})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* C216 LPC */
|
|
||||||
for id := 0x1e41; id <= 0x1e5f; id++ {
|
|
||||||
RegisterPCI(0x8086, uint16(id), bd82x6x{variant: "C216"})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PCIe bridge */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x1c10, 0x1c12, 0x1c14, 0x1c16,
|
|
||||||
0x1c18, 0x1c1a, 0x1c1c, 0x1c1e,
|
|
||||||
0x1e10, 0x1e12, 0x1e14, 0x1e16,
|
|
||||||
0x1e18, 0x1e1a, 0x1e1c, 0x1e1e,
|
|
||||||
0x1e25, 0x244e, 0x2448,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SMBus controller */
|
|
||||||
RegisterPCI(0x8086, 0x1c22, GenericPCI{MissingParent: "smbus"})
|
|
||||||
RegisterPCI(0x8086, 0x1e22, GenericPCI{MissingParent: "smbus"})
|
|
||||||
|
|
||||||
/* SATA */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x1c00, 0x1c01, 0x1c02, 0x1c03,
|
|
||||||
0x1e00, 0x1e01, 0x1e02, 0x1e03,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EHCI */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x1c26, 0x1c2d, 0x1e26, 0x1e2d,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XHCI */
|
|
||||||
RegisterPCI(0x8086, 0x1e31, GenericPCI{})
|
|
||||||
|
|
||||||
/* ME and children */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x1c3a, 0x1c3b, 0x1c3c, 0x1c3d,
|
|
||||||
0x1e3a, 0x1e3b, 0x1e3c, 0x1e3d,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ethernet */
|
|
||||||
RegisterPCI(0x8086, 0x1502, GenericPCI{})
|
|
||||||
RegisterPCI(0x8086, 0x1503, GenericPCI{})
|
|
||||||
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
Automated porting coreboot to Sandy Bridge/Ivy Bridge platforms `Go`
|
|
|
@ -1,91 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func FIXMEEC(ctx Context) {
|
|
||||||
ap := Create(ctx, "acpi/platform.asl")
|
|
||||||
defer ap.Close()
|
|
||||||
|
|
||||||
hasKeyboard := ctx.InfoSource.HasPS2()
|
|
||||||
|
|
||||||
sbGPE := GuessECGPE(ctx)
|
|
||||||
var GPEUnsure bool
|
|
||||||
if sbGPE < 0 {
|
|
||||||
sbGPE = SouthBridge.EncodeGPE(1)
|
|
||||||
GPEUnsure = true
|
|
||||||
SouthBridge.NeedRouteGPIOManually()
|
|
||||||
} else {
|
|
||||||
GPEUnsure = false
|
|
||||||
SouthBridge.EnableGPE(SouthBridge.DecodeGPE(sbGPE))
|
|
||||||
}
|
|
||||||
|
|
||||||
Add_gpl(ap)
|
|
||||||
ap.WriteString(
|
|
||||||
`Method(_WAK, 1)
|
|
||||||
{
|
|
||||||
/* FIXME: EC support */
|
|
||||||
Return(Package() {0, 0})
|
|
||||||
}
|
|
||||||
|
|
||||||
Method(_PTS,1)
|
|
||||||
{
|
|
||||||
/* FIXME: EC support */
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
ecs := ctx.InfoSource.GetEC()
|
|
||||||
MainboardIncludes = append(MainboardIncludes, "ec/acpi/ec.h")
|
|
||||||
MainboardIncludes = append(MainboardIncludes, "console/console.h")
|
|
||||||
|
|
||||||
MainboardInit +=
|
|
||||||
` /* FIXME: trim this down or remove if necessary */
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const u8 dmp[256] = {`
|
|
||||||
for i := 0; i < 0x100; i++ {
|
|
||||||
if (i & 0xf) == 0 {
|
|
||||||
MainboardInit += fmt.Sprintf("\n\t\t\t/* %02x */ ", i)
|
|
||||||
}
|
|
||||||
MainboardInit += fmt.Sprintf("0x%02x,", ecs[i])
|
|
||||||
if (i & 0xf) != 0xf {
|
|
||||||
MainboardInit += " "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MainboardInit += "\n\t\t};\n"
|
|
||||||
MainboardInit += `
|
|
||||||
printk(BIOS_DEBUG, "Replaying EC dump ...");
|
|
||||||
for (i = 0; i < 256; i++)
|
|
||||||
ec_write (i, dmp[i]);
|
|
||||||
printk(BIOS_DEBUG, "done\n");
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
KconfigBool["EC_ACPI"] = true
|
|
||||||
si := Create(ctx, "acpi/superio.asl")
|
|
||||||
defer si.Close()
|
|
||||||
|
|
||||||
if hasKeyboard {
|
|
||||||
Add_gpl(si)
|
|
||||||
si.WriteString("#include <drivers/pc80/pc/ps2_controller.asl>\n")
|
|
||||||
MainboardInit += fmt.Sprintf("\tpc_keyboard_init(NO_AUX_DEVICE);\n")
|
|
||||||
MainboardIncludes = append(MainboardIncludes, "pc80/keyboard.h")
|
|
||||||
}
|
|
||||||
|
|
||||||
ec := Create(ctx, "acpi/ec.asl")
|
|
||||||
defer ec.Close()
|
|
||||||
|
|
||||||
Add_gpl(ec)
|
|
||||||
ec.WriteString(`Device(EC)
|
|
||||||
{
|
|
||||||
Name (_HID, EISAID("PNP0C09"))
|
|
||||||
Name (_UID, 0)
|
|
||||||
`)
|
|
||||||
if GPEUnsure {
|
|
||||||
ec.WriteString("\t/* FIXME: Set GPE */\n")
|
|
||||||
ec.WriteString("\t/* Name (_GPE, ?) */\n")
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(ec, "\tName (_GPE, %d)\n", sbGPE)
|
|
||||||
}
|
|
||||||
ec.WriteString("/* FIXME: EC support */\n")
|
|
||||||
ec.WriteString("}\n")
|
|
||||||
}
|
|
|
@ -1,245 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func LenovoEC(ctx Context) {
|
|
||||||
ap := Create(ctx, "acpi/platform.asl")
|
|
||||||
defer ap.Close()
|
|
||||||
|
|
||||||
wakeGPE := 13
|
|
||||||
|
|
||||||
sbGPE := GuessECGPE(ctx)
|
|
||||||
var GPE int
|
|
||||||
var GPEUnsure bool
|
|
||||||
if sbGPE < 0 {
|
|
||||||
sbGPE = SouthBridge.EncodeGPE(1)
|
|
||||||
GPE = 1
|
|
||||||
GPEUnsure = true
|
|
||||||
SouthBridge.NeedRouteGPIOManually()
|
|
||||||
} else {
|
|
||||||
GPE = SouthBridge.DecodeGPE(sbGPE)
|
|
||||||
GPEUnsure = false
|
|
||||||
}
|
|
||||||
|
|
||||||
SouthBridge.EnableGPE(wakeGPE)
|
|
||||||
SouthBridge.EnableGPE(GPE)
|
|
||||||
|
|
||||||
GPEDefine := DSDTDefine{
|
|
||||||
Key: "THINKPAD_EC_GPE",
|
|
||||||
}
|
|
||||||
|
|
||||||
GPEDefine.Value = fmt.Sprintf("%d", sbGPE)
|
|
||||||
if GPEUnsure {
|
|
||||||
GPEDefine.Comment = "FIXME: Check this"
|
|
||||||
}
|
|
||||||
|
|
||||||
DSDTDefines = append(DSDTDefines,
|
|
||||||
DSDTDefine{
|
|
||||||
Key: "EC_LENOVO_H8_ME_WORKAROUND",
|
|
||||||
Value: "1",
|
|
||||||
}, GPEDefine)
|
|
||||||
|
|
||||||
Add_gpl(ap)
|
|
||||||
ap.WriteString(
|
|
||||||
`Method(_WAK, 1)
|
|
||||||
{
|
|
||||||
/* ME may not be up yet. */
|
|
||||||
Store(0, \_TZ.MEB1)
|
|
||||||
Store(0, \_TZ.MEB2)
|
|
||||||
Return(Package() {0, 0})
|
|
||||||
}
|
|
||||||
|
|
||||||
Method(_PTS,1)
|
|
||||||
{
|
|
||||||
\_SB.PCI0.LPCB.EC.RADI(0)
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
si := Create(ctx, "acpi/superio.asl")
|
|
||||||
defer si.Close()
|
|
||||||
|
|
||||||
Add_gpl(si)
|
|
||||||
si.WriteString("#include <drivers/pc80/pc/ps2_controller.asl>\n")
|
|
||||||
|
|
||||||
/* FIXME:XX Move this to ec/lenovo. */
|
|
||||||
smi := Create(ctx, "smihandler.c")
|
|
||||||
defer smi.Close()
|
|
||||||
|
|
||||||
AddSMMFile("smihandler.c", "")
|
|
||||||
|
|
||||||
Add_gpl(smi)
|
|
||||||
smi.WriteString(
|
|
||||||
`#include <arch/io.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
#include <cpu/x86/smm.h>
|
|
||||||
#include <ec/acpi/ec.h>
|
|
||||||
#include <ec/lenovo/h8/h8.h>
|
|
||||||
#include <delay.h>
|
|
||||||
#include <` + SouthBridge.GetGPIOHeader() + ">\n\n")
|
|
||||||
|
|
||||||
if GPEUnsure {
|
|
||||||
smi.WriteString("/* FIXME: check this */\n")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(smi, "#define GPE_EC_SCI %d\n", GPE)
|
|
||||||
|
|
||||||
smi.WriteString("/* FIXME: check this */\n")
|
|
||||||
fmt.Fprintf(smi, "#define GPE_EC_WAKE %d\n", wakeGPE)
|
|
||||||
|
|
||||||
smi.WriteString(`
|
|
||||||
static void mainboard_smi_handle_ec_sci(void)
|
|
||||||
{
|
|
||||||
u8 status = inb(EC_SC);
|
|
||||||
u8 event;
|
|
||||||
|
|
||||||
if (!(status & EC_SCI_EVT))
|
|
||||||
return;
|
|
||||||
|
|
||||||
event = ec_query();
|
|
||||||
printk(BIOS_DEBUG, "EC event %#02x\n", event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mainboard_smi_gpi(u32 gpi_sts)
|
|
||||||
{
|
|
||||||
if (gpi_sts & (1 << GPE_EC_SCI))
|
|
||||||
mainboard_smi_handle_ec_sci();
|
|
||||||
}
|
|
||||||
|
|
||||||
int mainboard_smi_apmc(u8 data)
|
|
||||||
{
|
|
||||||
switch (data) {
|
|
||||||
case APM_CNT_ACPI_ENABLE:
|
|
||||||
/* use 0x1600/0x1604 to prevent races with userspace */
|
|
||||||
ec_set_ports(0x1604, 0x1600);
|
|
||||||
/* route EC_SCI to SCI */
|
|
||||||
gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SCI);
|
|
||||||
/* discard all events, and enable attention */
|
|
||||||
ec_write(0x80, 0x01);
|
|
||||||
break;
|
|
||||||
case APM_CNT_ACPI_DISABLE:
|
|
||||||
/* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't
|
|
||||||
provide a EC query function */
|
|
||||||
ec_set_ports(0x66, 0x62);
|
|
||||||
/* route EC_SCI to SMI */
|
|
||||||
gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI);
|
|
||||||
/* discard all events, and enable attention */
|
|
||||||
ec_write(0x80, 0x01);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mainboard_smi_sleep(u8 slp_typ)
|
|
||||||
{
|
|
||||||
if (slp_typ == 3) {
|
|
||||||
u8 ec_wake = ec_read(0x32);
|
|
||||||
/* If EC wake events are enabled, enable wake on EC WAKE GPE. */
|
|
||||||
if (ec_wake & 0x14) {
|
|
||||||
/* Redirect EC WAKE GPE to SCI. */
|
|
||||||
gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
ec := Create(ctx, "acpi/ec.asl")
|
|
||||||
defer ec.Close()
|
|
||||||
|
|
||||||
Add_gpl(ec)
|
|
||||||
ec.WriteString("#include <ec/lenovo/h8/acpi/ec.asl>\n")
|
|
||||||
|
|
||||||
KconfigBool["EC_LENOVO_PMH7"] = true
|
|
||||||
KconfigBool["EC_LENOVO_H8"] = true
|
|
||||||
|
|
||||||
pmh := DevTreeNode{
|
|
||||||
Chip: "ec/lenovo/pmh7",
|
|
||||||
Registers: map[string]string{
|
|
||||||
"backlight_enable": "true",
|
|
||||||
"dock_event_enable": "true",
|
|
||||||
},
|
|
||||||
Children: []DevTreeNode{
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "pnp",
|
|
||||||
Comment: "dummy",
|
|
||||||
Dev: 0xff,
|
|
||||||
Func: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
PutChip("lpc", pmh)
|
|
||||||
|
|
||||||
ecs := ctx.InfoSource.GetEC()
|
|
||||||
h8 := DevTreeNode{
|
|
||||||
Chip: "ec/lenovo/h8",
|
|
||||||
Children: []DevTreeNode{
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "pnp",
|
|
||||||
Comment: "dummy",
|
|
||||||
Dev: 0xff,
|
|
||||||
Func: 2,
|
|
||||||
IOs: map[uint16]uint16{
|
|
||||||
0x60: 0x62,
|
|
||||||
0x62: 0x66,
|
|
||||||
0x64: 0x1600,
|
|
||||||
0x66: 0x1604,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Comment: "FIXME: has_keyboard_backlight, has_power_management_beeps, has_uwb",
|
|
||||||
Registers: map[string]string{
|
|
||||||
"config0": FormatHex8(ecs[0]),
|
|
||||||
"config1": FormatHex8(ecs[1]),
|
|
||||||
"config2": FormatHex8(ecs[2]),
|
|
||||||
"config3": FormatHex8(ecs[3]),
|
|
||||||
"beepmask0": FormatHex8(ecs[4]),
|
|
||||||
"beepmask1": FormatHex8(ecs[5]),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for i := 0; i < 0x10; i++ {
|
|
||||||
if ecs[0x10+i] != 0 {
|
|
||||||
h8.Registers[fmt.Sprintf("event%x_enable", i)] = FormatHex8(ecs[0x10+i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PutChip("lpc", h8)
|
|
||||||
|
|
||||||
eeprom := DevTreeNode{
|
|
||||||
Chip: "drivers/i2c/at24rf08c",
|
|
||||||
Comment: "eeprom, 8 virtual devices, same chip",
|
|
||||||
Children: []DevTreeNode{
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "i2c",
|
|
||||||
Dev: 0x54,
|
|
||||||
},
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "i2c",
|
|
||||||
Dev: 0x55,
|
|
||||||
},
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "i2c",
|
|
||||||
Dev: 0x56,
|
|
||||||
},
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "i2c",
|
|
||||||
Dev: 0x57,
|
|
||||||
},
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "i2c",
|
|
||||||
Dev: 0x5c,
|
|
||||||
},
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "i2c",
|
|
||||||
Dev: 0x5d,
|
|
||||||
},
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "i2c",
|
|
||||||
Dev: 0x5e,
|
|
||||||
},
|
|
||||||
DevTreeNode{
|
|
||||||
Chip: "i2c",
|
|
||||||
Dev: 0x5f,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
PutChip("smbus", eeprom)
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
func NoEC(ctx Context) {
|
|
||||||
ap := Create(ctx, "acpi/platform.asl")
|
|
||||||
defer ap.Close()
|
|
||||||
|
|
||||||
Add_gpl(ap)
|
|
||||||
ap.WriteString(
|
|
||||||
`Method(_WAK, 1)
|
|
||||||
{
|
|
||||||
Return(Package() {0, 0})
|
|
||||||
}
|
|
||||||
|
|
||||||
Method(_PTS, 1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
si := Create(ctx, "acpi/superio.asl")
|
|
||||||
defer si.Close()
|
|
||||||
|
|
||||||
ec := Create(ctx, "acpi/ec.asl")
|
|
||||||
defer ec.Close()
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
module autoport
|
|
|
@ -1,113 +0,0 @@
|
||||||
/* code to generate common GPIO code for Intel 6/7/8 Series Chipset */
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func writeGPIOSet(ctx Context, sb *os.File,
|
|
||||||
val uint32, set uint, partno int, constraint uint32) {
|
|
||||||
|
|
||||||
max := uint(32)
|
|
||||||
if set == 3 {
|
|
||||||
max = 12
|
|
||||||
}
|
|
||||||
|
|
||||||
bits := [6][2]string{
|
|
||||||
{"GPIO_MODE_NATIVE", "GPIO_MODE_GPIO"},
|
|
||||||
{"GPIO_DIR_OUTPUT", "GPIO_DIR_INPUT"},
|
|
||||||
{"GPIO_LEVEL_LOW", "GPIO_LEVEL_HIGH"},
|
|
||||||
{"GPIO_RESET_PWROK", "GPIO_RESET_RSMRST"},
|
|
||||||
{"GPIO_NO_INVERT", "GPIO_INVERT"},
|
|
||||||
{"GPIO_NO_BLINK", "GPIO_BLINK"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := uint(0); i < max; i++ {
|
|
||||||
if (constraint>>i)&1 == 1 {
|
|
||||||
fmt.Fprintf(sb, " .gpio%d = %s,\n",
|
|
||||||
(set-1)*32+i,
|
|
||||||
bits[partno][(val>>i)&1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GPIO(ctx Context, inteltool InteltoolData) {
|
|
||||||
var constraint uint32
|
|
||||||
gpio := Create(ctx, "gpio.c")
|
|
||||||
defer gpio.Close()
|
|
||||||
|
|
||||||
AddBootBlockFile("gpio.c", "")
|
|
||||||
AddROMStageFile("gpio.c", "")
|
|
||||||
|
|
||||||
Add_gpl(gpio)
|
|
||||||
gpio.WriteString("#include <southbridge/intel/common/gpio.h>\n\n")
|
|
||||||
|
|
||||||
addresses := [3][6]int{
|
|
||||||
{0x00, 0x04, 0x0c, 0x60, 0x2c, 0x18},
|
|
||||||
{0x30, 0x34, 0x38, 0x64, -1, -1},
|
|
||||||
{0x40, 0x44, 0x48, 0x68, -1, -1},
|
|
||||||
}
|
|
||||||
|
|
||||||
for set := 1; set <= 3; set++ {
|
|
||||||
for partno, part := range []string{"mode", "direction", "level", "reset", "invert", "blink"} {
|
|
||||||
addr := addresses[set-1][partno]
|
|
||||||
if addr < 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Fprintf(gpio, "static const struct pch_gpio_set%d pch_gpio_set%d_%s = {\n",
|
|
||||||
set, set, part)
|
|
||||||
|
|
||||||
constraint = 0xffffffff
|
|
||||||
switch part {
|
|
||||||
case "direction":
|
|
||||||
/* Ignored on native mode */
|
|
||||||
constraint = inteltool.GPIO[uint16(addresses[set-1][0])]
|
|
||||||
case "level":
|
|
||||||
/* Level doesn't matter for input */
|
|
||||||
constraint = inteltool.GPIO[uint16(addresses[set-1][0])]
|
|
||||||
constraint &^= inteltool.GPIO[uint16(addresses[set-1][1])]
|
|
||||||
case "reset":
|
|
||||||
/* Only show reset */
|
|
||||||
constraint = inteltool.GPIO[uint16(addresses[set-1][3])]
|
|
||||||
case "invert":
|
|
||||||
/* Only on input and only show inverted GPIO */
|
|
||||||
constraint = inteltool.GPIO[uint16(addresses[set-1][0])]
|
|
||||||
constraint &= inteltool.GPIO[uint16(addresses[set-1][1])]
|
|
||||||
constraint &= inteltool.GPIO[uint16(addresses[set-1][4])]
|
|
||||||
case "blink":
|
|
||||||
/* Only on output and only show blinking GPIO */
|
|
||||||
constraint = inteltool.GPIO[uint16(addresses[set-1][0])]
|
|
||||||
constraint &^= inteltool.GPIO[uint16(addresses[set-1][1])]
|
|
||||||
constraint &= inteltool.GPIO[uint16(addresses[set-1][5])]
|
|
||||||
}
|
|
||||||
writeGPIOSet(ctx, gpio, inteltool.GPIO[uint16(addr)], uint(set), partno, constraint)
|
|
||||||
gpio.WriteString("};\n\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio.WriteString(`const struct pch_gpio_map mainboard_gpio_map = {
|
|
||||||
.set1 = {
|
|
||||||
.mode = &pch_gpio_set1_mode,
|
|
||||||
.direction = &pch_gpio_set1_direction,
|
|
||||||
.level = &pch_gpio_set1_level,
|
|
||||||
.blink = &pch_gpio_set1_blink,
|
|
||||||
.invert = &pch_gpio_set1_invert,
|
|
||||||
.reset = &pch_gpio_set1_reset,
|
|
||||||
},
|
|
||||||
.set2 = {
|
|
||||||
.mode = &pch_gpio_set2_mode,
|
|
||||||
.direction = &pch_gpio_set2_direction,
|
|
||||||
.level = &pch_gpio_set2_level,
|
|
||||||
.reset = &pch_gpio_set2_reset,
|
|
||||||
},
|
|
||||||
.set3 = {
|
|
||||||
.mode = &pch_gpio_set3_mode,
|
|
||||||
.direction = &pch_gpio_set3_direction,
|
|
||||||
.level = &pch_gpio_set3_level,
|
|
||||||
.reset = &pch_gpio_set3_reset,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
`)
|
|
||||||
}
|
|
|
@ -1,139 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type haswellmc struct {
|
|
||||||
variant string
|
|
||||||
}
|
|
||||||
|
|
||||||
func divceil(a uint32, b uint32) uint32 {
|
|
||||||
return (a + b - 1) / b
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPanelCfg(inteltool InteltoolData, isULT bool) string {
|
|
||||||
var refclk uint32
|
|
||||||
var pwm_hz uint32
|
|
||||||
|
|
||||||
if isULT {
|
|
||||||
refclk = 24000000
|
|
||||||
} else {
|
|
||||||
refclk = 135000000
|
|
||||||
}
|
|
||||||
if (inteltool.IGD[0xc8254] >> 16) != 0 {
|
|
||||||
pwm_hz = refclk / 128 / (inteltool.IGD[0xc8254] >> 16)
|
|
||||||
} else {
|
|
||||||
pwm_hz = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu_panel_power_up_delay := (inteltool.IGD[0xc7208] >> 16) & 0x1fff
|
|
||||||
gpu_panel_power_backlight_on_delay := inteltool.IGD[0xc7208] & 0x1fff
|
|
||||||
gpu_panel_power_down_delay := (inteltool.IGD[0xc720c] >> 16) & 0x1fff
|
|
||||||
gpu_panel_power_backlight_off_delay := inteltool.IGD[0xc720c] & 0x1fff
|
|
||||||
gpu_panel_power_cycle_delay := inteltool.IGD[0xc7210] & 0x1f
|
|
||||||
|
|
||||||
return fmt.Sprintf(`{
|
|
||||||
.up_delay_ms = %3d,
|
|
||||||
.down_delay_ms = %3d,
|
|
||||||
.cycle_delay_ms = %3d,
|
|
||||||
.backlight_on_delay_ms = %3d,
|
|
||||||
.backlight_off_delay_ms = %3d,
|
|
||||||
.backlight_pwm_hz = %3d,
|
|
||||||
}`,
|
|
||||||
divceil(gpu_panel_power_up_delay, 10),
|
|
||||||
divceil(gpu_panel_power_down_delay, 10),
|
|
||||||
(gpu_panel_power_cycle_delay-1)*100,
|
|
||||||
divceil(gpu_panel_power_backlight_on_delay, 10),
|
|
||||||
divceil(gpu_panel_power_backlight_off_delay, 10),
|
|
||||||
pwm_hz)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i haswellmc) Scan(ctx Context, addr PCIDevData) {
|
|
||||||
inteltool := ctx.InfoSource.GetInteltool()
|
|
||||||
|
|
||||||
isULT := (i.variant == "ULT")
|
|
||||||
DevTree = DevTreeNode{
|
|
||||||
Chip: "northbridge/intel/haswell",
|
|
||||||
MissingParent: "northbridge",
|
|
||||||
Comment: "FIXME: check ec_present, usb_xhci_on_resume, gfx",
|
|
||||||
Registers: map[string]string{
|
|
||||||
"gpu_dp_b_hotplug": FormatInt32((inteltool.IGD[0xc4030] >> 2) & 7),
|
|
||||||
"gpu_dp_c_hotplug": FormatInt32((inteltool.IGD[0xc4030] >> 10) & 7),
|
|
||||||
"gpu_dp_d_hotplug": FormatInt32((inteltool.IGD[0xc4030] >> 18) & 7),
|
|
||||||
"panel_cfg": getPanelCfg(inteltool, isULT),
|
|
||||||
"gpu_ddi_e_connected": FormatBool(((inteltool.IGD[0x64000] >> 4) & 1) == 0),
|
|
||||||
"ec_present": "false",
|
|
||||||
"usb_xhci_on_resume": "false",
|
|
||||||
/* FIXME:XX hardcoded. */
|
|
||||||
"gfx": "GMA_STATIC_DISPLAYS(0)",
|
|
||||||
},
|
|
||||||
Children: []DevTreeNode{
|
|
||||||
{
|
|
||||||
Chip: "cpu/intel/haswell",
|
|
||||||
Children: []DevTreeNode{
|
|
||||||
{
|
|
||||||
Chip: "cpu_cluster",
|
|
||||||
Dev: 0,
|
|
||||||
Ops: "haswell_cpu_bus_ops",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
Chip: "domain",
|
|
||||||
Dev: 0,
|
|
||||||
Ops: "haswell_pci_domain_ops",
|
|
||||||
PCIController: true,
|
|
||||||
ChildPCIBus: 0,
|
|
||||||
PCISlots: []PCISlot{
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x0, Func: 0}, writeEmpty: true, additionalComment: i.variant},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1, Func: 0}, writeEmpty: !isULT, additionalComment: "PCIe Bridge for discrete graphics"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x2, Func: 0}, writeEmpty: true, additionalComment: "Internal graphics"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x3, Func: 0}, writeEmpty: true, additionalComment: "Mini-HD audio"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if isULT {
|
|
||||||
DevTree.Registers["dq_pins_interleaved"] = FormatBool(((inteltool.MCHBAR[0x2008] >> 10) & 1) == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
PutPCIDev(addr, "Host bridge")
|
|
||||||
|
|
||||||
KconfigBool["NORTHBRIDGE_INTEL_HASWELL"] = true
|
|
||||||
KconfigBool["HAVE_ACPI_TABLES"] = true
|
|
||||||
KconfigBool["HAVE_ACPI_RESUME"] = true
|
|
||||||
|
|
||||||
DSDTIncludes = append(DSDTIncludes, DSDTInclude{
|
|
||||||
File: "cpu/intel/common/acpi/cpu.asl",
|
|
||||||
})
|
|
||||||
|
|
||||||
DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{
|
|
||||||
File: "northbridge/intel/haswell/acpi/hostbridge.asl",
|
|
||||||
}, DSDTInclude{
|
|
||||||
File: "drivers/intel/gma/acpi/default_brightness_levels.asl",
|
|
||||||
Comment: "FIXME: remove this if the board doesn't have backlight",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
RegisterPCI(0x8086, 0x0c00, haswellmc{variant: "Desktop"})
|
|
||||||
RegisterPCI(0x8086, 0x0c04, haswellmc{variant: "Mobile"})
|
|
||||||
RegisterPCI(0x8086, 0x0a04, haswellmc{variant: "ULT"})
|
|
||||||
RegisterPCI(0x8086, 0x0c08, haswellmc{variant: "Server"})
|
|
||||||
RegisterPCI(0x8086, 0x0d00, haswellmc{variant: "Crystal Well Desktop"})
|
|
||||||
RegisterPCI(0x8086, 0x0d04, haswellmc{variant: "Crystal Well Mobile"})
|
|
||||||
RegisterPCI(0x8086, 0x0d08, haswellmc{variant: "Crystal Well Server"})
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x0402, 0x0412, 0x0422, /* Desktop */
|
|
||||||
0x0406, 0x0416, 0x0426, /* Mobile */
|
|
||||||
0x040a, 0x041a, 0x042a, /* Server */
|
|
||||||
0x0a06, 0x0a16, 0x0a26, /* ULT */
|
|
||||||
0x0d16, 0x0d22, 0x0d26, 0x0d36, /* Mobile 4+3, GT3e */
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericVGA{GenericPCI{Comment: "VGA controller"}})
|
|
||||||
}
|
|
||||||
/* CPU HD Audio */
|
|
||||||
RegisterPCI(0x8086, 0x0a0c, GenericPCI{})
|
|
||||||
RegisterPCI(0x8086, 0x0c0c, GenericPCI{})
|
|
||||||
}
|
|
|
@ -1,190 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"bytes"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TryRunAndSave(output string, name string, arg []string) error {
|
|
||||||
cmd := exec.Command(name, arg...)
|
|
||||||
|
|
||||||
f, err := os.Create(output)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Stdout = f
|
|
||||||
cmd.Stderr = f
|
|
||||||
|
|
||||||
err = cmd.Start()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cmd.Wait()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunAndSave(output string, name string, arg ...string) {
|
|
||||||
err := TryRunAndSave(output, name, arg)
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
idx := strings.LastIndex(name, "/")
|
|
||||||
relname := name
|
|
||||||
if idx >= 0 {
|
|
||||||
relname = name[idx+1:]
|
|
||||||
}
|
|
||||||
relname = "./" + relname
|
|
||||||
err = TryRunAndSave(output, relname, arg)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAXPROMPTRETRY = 3
|
|
||||||
|
|
||||||
func PromptUser(prompt string, opts []string) (match string, err error) {
|
|
||||||
for i := 1; i < MAXPROMPTRETRY; i++ {
|
|
||||||
fmt.Printf("%s. (%s) Default:%s\n", prompt,
|
|
||||||
strings.Join(opts, "/"), opts[0])
|
|
||||||
var usrInput string
|
|
||||||
fmt.Scanln(&usrInput)
|
|
||||||
|
|
||||||
// Check for default entry
|
|
||||||
if usrInput == "" {
|
|
||||||
match = opts[0]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, opt := range opts {
|
|
||||||
if opt == usrInput {
|
|
||||||
match = opt
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = errors.New("max retries exceeded")
|
|
||||||
fmt.Fprintln(os.Stderr, "ERROR: max retries exceeded")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeHDALogs(outDir string, cardName string) {
|
|
||||||
SysDir := "/sys/class/sound/" + cardName + "/"
|
|
||||||
files, _ := ioutil.ReadDir(SysDir)
|
|
||||||
for _, f := range files {
|
|
||||||
if (strings.HasPrefix(f.Name(), "hw") || strings.HasPrefix(f.Name(), "hdaudio")) && f.IsDir() {
|
|
||||||
in, err := os.Open(SysDir + f.Name() + "/init_pin_configs")
|
|
||||||
defer in.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
out, err := os.Create(outDir + "/pin_" + strings.Replace(f.Name(), "hdaudio", "hw", -1))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
io.Copy(out, in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcDir := "/proc/asound/" + cardName + "/"
|
|
||||||
files, _ = ioutil.ReadDir(ProcDir)
|
|
||||||
for _, f := range files {
|
|
||||||
if strings.HasPrefix(f.Name(), "codec#") && !f.IsDir() {
|
|
||||||
in, err := os.Open(ProcDir + f.Name())
|
|
||||||
defer in.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
out, err := os.Create(outDir + "/" + f.Name())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
io.Copy(out, in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeLogs(outDir string) {
|
|
||||||
os.MkdirAll(outDir, 0700)
|
|
||||||
RunAndSave(outDir+"/lspci.log", "lspci", "-nnvvvxxxx")
|
|
||||||
RunAndSave(outDir+"/dmidecode.log", "dmidecode")
|
|
||||||
RunAndSave(outDir+"/acpidump.log", "acpidump")
|
|
||||||
|
|
||||||
inteltoolArgs := "-a"
|
|
||||||
opt, err := PromptUser("WARNING: The following tool MAY cause your system to hang when it attempts "+
|
|
||||||
"to probe for graphics registers. Having the graphics registers will help create a better port. "+
|
|
||||||
"Should autoport probe these registers?",
|
|
||||||
[]string{"y", "yes", "n", "no"})
|
|
||||||
|
|
||||||
// Continue even if there is an error
|
|
||||||
|
|
||||||
switch opt {
|
|
||||||
case "y", "yes":
|
|
||||||
inteltoolArgs += "f"
|
|
||||||
}
|
|
||||||
|
|
||||||
RunAndSave(outDir+"/inteltool.log", "../inteltool/inteltool", inteltoolArgs)
|
|
||||||
RunAndSave(outDir+"/ectool.log", "../ectool/ectool", "-pd")
|
|
||||||
RunAndSave(outDir+"/superiotool.log", "../superiotool/superiotool", "-ade")
|
|
||||||
|
|
||||||
SysSound := "/sys/class/sound/"
|
|
||||||
card := ""
|
|
||||||
cards, _ := ioutil.ReadDir(SysSound)
|
|
||||||
for _, f := range cards {
|
|
||||||
if strings.HasPrefix(f.Name(), "card") {
|
|
||||||
cid, err := ioutil.ReadFile(SysSound + f.Name() + "/id")
|
|
||||||
if err == nil && bytes.Equal(cid, []byte("PCH\n")) {
|
|
||||||
fmt.Fprintln(os.Stderr, "PCH sound card is", f.Name())
|
|
||||||
card = f.Name()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if card != "" {
|
|
||||||
MakeHDALogs(outDir, card)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintln(os.Stderr, "HDAudio not found on PCH.")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, fname := range []string{"cpuinfo", "ioports"} {
|
|
||||||
in, err := os.Open("/proc/" + fname)
|
|
||||||
defer in.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
out, err := os.Create(outDir + "/" + fname + ".log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
io.Copy(out, in)
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := os.Create(outDir + "/input_bustypes.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
ClassInputDir := "/sys/class/input/"
|
|
||||||
files, _ := ioutil.ReadDir(ClassInputDir)
|
|
||||||
for _, f := range files {
|
|
||||||
if strings.HasPrefix(f.Name(), "input") && !f.Mode().IsRegular() { /* Allow both dirs and symlinks. */
|
|
||||||
in, err := os.Open(ClassInputDir + f.Name() + "/id/bustype")
|
|
||||||
defer in.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
io.Copy(out, in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,417 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LogDevReader struct {
|
|
||||||
InputDirectory string
|
|
||||||
ACPITables map[string][]byte
|
|
||||||
EC []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func isXDigit(x uint8) bool {
|
|
||||||
if x >= '0' && x <= '9' {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if x >= 'a' && x <= 'f' {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if x >= 'A' && x <= 'F' {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type HexLine struct {
|
|
||||||
length uint
|
|
||||||
values [16]byte
|
|
||||||
start uint
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) ReadHexLine(line string) (hex HexLine) {
|
|
||||||
hex.start = 0
|
|
||||||
line = strings.Trim(line, " ")
|
|
||||||
fmt.Sscanf(line, "%x:", &hex.start)
|
|
||||||
ll, _ := fmt.Sscanf(line, "%x: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", &hex.start,
|
|
||||||
&hex.values[0], &hex.values[1], &hex.values[2],
|
|
||||||
&hex.values[3], &hex.values[4], &hex.values[5],
|
|
||||||
&hex.values[6], &hex.values[7], &hex.values[8],
|
|
||||||
&hex.values[9], &hex.values[10], &hex.values[11],
|
|
||||||
&hex.values[12], &hex.values[13], &hex.values[14],
|
|
||||||
&hex.values[15])
|
|
||||||
hex.length = uint(ll - 1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) AssignHexLine(inp string, target []byte) []byte {
|
|
||||||
hex := l.ReadHexLine(inp)
|
|
||||||
if hex.start+hex.length > uint(len(target)) {
|
|
||||||
target = target[0 : hex.start+hex.length]
|
|
||||||
}
|
|
||||||
copy(target[hex.start:hex.start+hex.length], hex.values[0:hex.length])
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) GetEC() []byte {
|
|
||||||
if l.EC != nil {
|
|
||||||
return l.EC
|
|
||||||
}
|
|
||||||
l.EC = make([]byte, 0x100, 0x100)
|
|
||||||
|
|
||||||
file, err := os.Open(l.InputDirectory + "/ectool.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
if len(line) > 7 && isXDigit(line[0]) && isXDigit(line[1]) && line[2] == ':' {
|
|
||||||
l.EC = l.AssignHexLine(line, l.EC)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return l.EC
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) GetACPI() (Tables map[string][]byte) {
|
|
||||||
if l.ACPITables != nil {
|
|
||||||
return l.ACPITables
|
|
||||||
}
|
|
||||||
l.ACPITables = Tables
|
|
||||||
|
|
||||||
file, err := os.Open(l.InputDirectory + "/acpidump.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
|
|
||||||
Tables = map[string][]byte{}
|
|
||||||
|
|
||||||
curTable := ""
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
/* Only supports ACPI tables up to 0x100000 in size, FIXME if needed */
|
|
||||||
is_hexline, _ := regexp.MatchString(" *[0-9A-Fa-f]{4,5}: ", line)
|
|
||||||
switch {
|
|
||||||
case len(line) >= 6 && line[5] == '@':
|
|
||||||
curTable = line[0:4]
|
|
||||||
Tables[curTable] = make([]byte, 0, 0x100000)
|
|
||||||
case is_hexline:
|
|
||||||
Tables[curTable] = l.AssignHexLine(line, Tables[curTable])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) GetPCIList() (PCIList []PCIDevData) {
|
|
||||||
file, err := os.Open(l.InputDirectory + "/lspci.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
|
|
||||||
PCIList = []PCIDevData{}
|
|
||||||
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
switch {
|
|
||||||
case !(len(line) < 7 || !isXDigit(line[0]) || !isXDigit(line[1]) || line[2] != ':' || !isXDigit(line[3]) || !isXDigit(line[4]) || line[5] != '.' || !isXDigit(line[6])):
|
|
||||||
cur := PCIDevData{}
|
|
||||||
fmt.Sscanf(line, "%x:%x.%x", &cur.Bus, &cur.Dev, &cur.Func)
|
|
||||||
lc := strings.LastIndex(line, ":")
|
|
||||||
li := strings.LastIndex(line[0:lc], "[")
|
|
||||||
if li < 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ven := 0
|
|
||||||
dev := 0
|
|
||||||
fmt.Sscanf(line[li+1:], "%x:%x", &ven, &dev)
|
|
||||||
cur.PCIDevID = uint16(dev)
|
|
||||||
cur.PCIVenID = uint16(ven)
|
|
||||||
cur.ConfigDump = make([]byte, 0x100, 0x1000)
|
|
||||||
PCIList = append(PCIList, cur)
|
|
||||||
case len(line) > 7 && isXDigit(line[0]) && line[1] == '0' && line[2] == ':':
|
|
||||||
start := 0
|
|
||||||
fmt.Sscanf(line, "%x:", &start)
|
|
||||||
cur := &PCIList[len(PCIList)-1]
|
|
||||||
cur.ConfigDump = l.AssignHexLine(line, cur.ConfigDump)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) GetInteltool() (ret InteltoolData) {
|
|
||||||
file, err := os.Open(l.InputDirectory + "/inteltool.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
paragraph := ""
|
|
||||||
ret.GPIO = map[uint16]uint32{}
|
|
||||||
ret.RCBA = map[uint16]uint32{}
|
|
||||||
ret.IOBP = map[uint32]uint32{}
|
|
||||||
ret.IGD = map[uint32]uint32{}
|
|
||||||
ret.MCHBAR = map[uint16]uint32{}
|
|
||||||
ret.PMBASE = map[uint16]uint32{}
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
switch {
|
|
||||||
case len(line) > 7 && line[0] == '0' && line[1] == 'x' && line[6] == ':' && paragraph == "RCBA":
|
|
||||||
addr, value := 0, 0
|
|
||||||
fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
|
|
||||||
ret.RCBA[uint16(addr)] = uint32(value)
|
|
||||||
case len(line) > 11 && line[0] == '0' && line[1] == 'x' && line[10] == ':' && paragraph == "IOBP":
|
|
||||||
addr, value := 0, 0
|
|
||||||
fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
|
|
||||||
ret.IOBP[uint32(addr)] = uint32(value)
|
|
||||||
case len(line) > 9 && line[0] == '0' && line[1] == 'x' && line[8] == ':' && paragraph == "IGD":
|
|
||||||
addr, value := 0, 0
|
|
||||||
fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
|
|
||||||
ret.IGD[uint32(addr)] = uint32(value)
|
|
||||||
case len(line) > 7 && line[0] == '0' && line[1] == 'x' && line[6] == ':' && paragraph == "MCHBAR":
|
|
||||||
addr, value := 0, 0
|
|
||||||
fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
|
|
||||||
ret.MCHBAR[uint16(addr)] = uint32(value)
|
|
||||||
case strings.Contains(line, "DEFAULT"):
|
|
||||||
continue
|
|
||||||
case strings.Contains(line, "DIFF"):
|
|
||||||
continue
|
|
||||||
case strings.HasPrefix(line, "gpiobase"):
|
|
||||||
addr, value := 0, 0
|
|
||||||
fmt.Sscanf(line, "gpiobase+0x%x: 0x%x", &addr, &value)
|
|
||||||
ret.GPIO[uint16(addr)] = uint32(value)
|
|
||||||
case strings.HasPrefix(line, "pmbase"):
|
|
||||||
addr, value := 0, 0
|
|
||||||
fmt.Sscanf(line, "pmbase+0x%x: 0x%x", &addr, &value)
|
|
||||||
ret.PMBASE[uint16(addr)] = uint32(value)
|
|
||||||
case strings.HasPrefix(line, "============="):
|
|
||||||
paragraph = strings.Trim(line, "= ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) GetDMI() (ret DMIData) {
|
|
||||||
file, err := os.Open(l.InputDirectory + "/dmidecode.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
paragraph := ""
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
if !strings.HasPrefix(line, "\t") {
|
|
||||||
paragraph = strings.TrimSpace(line)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
idx := strings.Index(line, ":")
|
|
||||||
if idx < 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := strings.TrimSpace(line[0:idx])
|
|
||||||
value := strings.TrimSpace(line[idx+1:])
|
|
||||||
switch paragraph + ":" + name {
|
|
||||||
case "System Information:Manufacturer":
|
|
||||||
ret.Vendor = value
|
|
||||||
case "System Information:Product Name":
|
|
||||||
ret.Model = value
|
|
||||||
case "System Information:Version":
|
|
||||||
ret.Version = value
|
|
||||||
case "Chassis Information:Type":
|
|
||||||
ret.IsLaptop = (value == "Notebook" || value == "Laptop")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) GetAzaliaCodecs() (ret []AzaliaCodec) {
|
|
||||||
cardno := -1
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
pin, err := os.Open(l.InputDirectory + "/pin_hwC" + strconv.Itoa(i) + "D0")
|
|
||||||
if err == nil {
|
|
||||||
pin.Close()
|
|
||||||
cardno = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if cardno == -1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for codecno := 0; codecno < 10; codecno++ {
|
|
||||||
cur := AzaliaCodec{CodecNo: codecno, PinConfig: map[int]uint32{}}
|
|
||||||
codec, err := os.Open(l.InputDirectory + "/codec#" + strconv.Itoa(codecno))
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer codec.Close()
|
|
||||||
pin, err := os.Open(l.InputDirectory + "/pin_hwC" + strconv.Itoa(cardno) +
|
|
||||||
"D" + strconv.Itoa(codecno))
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer pin.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(codec)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
if strings.HasPrefix(line, "Codec:") {
|
|
||||||
fmt.Sscanf(line, "Codec: %s", &cur.Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(line, "Vendor Id:") {
|
|
||||||
fmt.Sscanf(line, "Vendor Id: 0x%x", &cur.VendorID)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(line, "Subsystem Id:") {
|
|
||||||
fmt.Sscanf(line, "Subsystem Id: 0x%x", &cur.SubsystemID)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scanner = bufio.NewScanner(pin)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
addr := 0
|
|
||||||
val := uint32(0)
|
|
||||||
fmt.Sscanf(line, "0x%x 0x%x", &addr, &val)
|
|
||||||
cur.PinConfig[addr] = val
|
|
||||||
}
|
|
||||||
ret = append(ret, cur)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) GetIOPorts() []IOPorts {
|
|
||||||
file, err := os.Open(l.InputDirectory + "/ioports.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
ret := make([]IOPorts, 0, 100)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
el := IOPorts{}
|
|
||||||
fmt.Sscanf(line, " %x-%x : %s", &el.Start, &el.End, &el.Usage)
|
|
||||||
ret = append(ret, el)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) GetCPUModel() (ret []uint32) {
|
|
||||||
file, err := os.Open(l.InputDirectory + "/cpuinfo.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
ret = make([]uint32, 0, 100)
|
|
||||||
proc := 0
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
sep := strings.Index(line, ":")
|
|
||||||
if sep < 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key := strings.TrimSpace(line[0:sep])
|
|
||||||
val := strings.TrimSpace(line[sep+1:])
|
|
||||||
|
|
||||||
if key == "processor" {
|
|
||||||
proc, _ := strconv.Atoi(val)
|
|
||||||
if len(ret) <= proc {
|
|
||||||
ret = ret[0 : proc+1]
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if key == "cpu family" {
|
|
||||||
family, _ := strconv.Atoi(val)
|
|
||||||
ret[proc] |= uint32(((family & 0xf) << 8) | ((family & 0xff0) << 16))
|
|
||||||
}
|
|
||||||
if key == "model" {
|
|
||||||
model, _ := strconv.Atoi(val)
|
|
||||||
ret[proc] |= uint32(((model & 0xf) << 4) | ((model & 0xf0) << 12))
|
|
||||||
}
|
|
||||||
if key == "stepping" {
|
|
||||||
stepping, _ := strconv.Atoi(val)
|
|
||||||
ret[proc] |= uint32(stepping & 0xf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LogDevReader) HasPS2() bool {
|
|
||||||
file, err := os.Open(l.InputDirectory + "/input_bustypes.log")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
if strings.Index(line, "0011") >= 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var FlagLogInput = flag.String("input_log", ".", "Input log directory")
|
|
||||||
var FlagLogMkLogs = flag.Bool("make_logs", false, "Dump logs")
|
|
||||||
|
|
||||||
func MakeLogReader() *LogDevReader {
|
|
||||||
if *FlagLogMkLogs {
|
|
||||||
MakeLogs(*FlagLogInput)
|
|
||||||
}
|
|
||||||
return &LogDevReader{InputDirectory: *FlagLogInput}
|
|
||||||
}
|
|
|
@ -1,490 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type LPVariant int
|
|
||||||
|
|
||||||
const (
|
|
||||||
LYNX_POINT_MOBILE LPVariant = iota
|
|
||||||
LYNX_POINT_DESKTOP
|
|
||||||
LYNX_POINT_SERVER
|
|
||||||
LYNX_POINT_ULT
|
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
KconfigBool["SOUTHBRIDGE_INTEL_LYNXPOINT"] = true
|
|
||||||
if isULT {
|
|
||||||
KconfigBool["INTEL_LYNXPOINT_LP"] = true
|
|
||||||
}
|
|
||||||
KconfigBool["SERIRQ_CONTINUOUS_MODE"] = true
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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_gpl(bb)
|
|
||||||
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_gpl(sb)
|
|
||||||
sb.WriteString(`#include <stdint.h>
|
|
||||||
#include <northbridge/intel/haswell/haswell.h>
|
|
||||||
#include <northbridge/intel/haswell/raminit.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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void mb_get_spd_map(struct spd_info *spdi)
|
|
||||||
{
|
|
||||||
/* FIXME: check this */
|
|
||||||
spdi->addresses[0] = 0x50;
|
|
||||||
spdi->addresses[1] = 0x51;
|
|
||||||
spdi->addresses[2] = 0x52;
|
|
||||||
spdi->addresses[3] = 0x53;
|
|
||||||
}
|
|
||||||
|
|
||||||
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{
|
|
||||||
0x8c41, 0x8c49, 0x8c4b, 0x8c4f,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_MOBILE})
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, id := range []uint16{
|
|
||||||
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})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PCIe bridge */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
|
|
||||||
0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SMBus controller */
|
|
||||||
RegisterPCI(0x8086, 0x8c22, GenericPCI{MissingParent: "smbus"})
|
|
||||||
RegisterPCI(0x8086, 0x9c22, GenericPCI{MissingParent: "smbus"})
|
|
||||||
|
|
||||||
/* SATA */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x8c00, 0x8c02, 0x8c04, 0x8c06, 0x8c08, 0x8c0e,
|
|
||||||
0x8c01, 0x8c03, 0x8c05, 0x8c07, 0x8c09, 0x8c0f,
|
|
||||||
0x9c03, 0x9c05, 0x9c07, 0x9c0f,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EHCI */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x9c26, 0x8c26, 0x8c2d,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XHCI */
|
|
||||||
RegisterPCI(0x8086, 0x8c31, GenericPCI{})
|
|
||||||
RegisterPCI(0x8086, 0x9c31, GenericPCI{})
|
|
||||||
|
|
||||||
/* ME and children */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x8c3a, 0x8c3b, 0x8c3c, 0x8c3d,
|
|
||||||
0x9c3a, 0x9c3b, 0x9c3c, 0x9c3d,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ethernet */
|
|
||||||
RegisterPCI(0x8086, 0x8c33, GenericPCI{})
|
|
||||||
|
|
||||||
/* Thermal */
|
|
||||||
RegisterPCI(0x8086, 0x8c24, GenericPCI{})
|
|
||||||
RegisterPCI(0x8086, 0x9c24, GenericPCI{})
|
|
||||||
|
|
||||||
/* 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{})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,252 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
PIRQI = 0
|
|
||||||
PIRQJ = 1
|
|
||||||
PIRQK = 2
|
|
||||||
PIRQL = 3
|
|
||||||
PIRQM = 4
|
|
||||||
PIRQN = 5
|
|
||||||
PIRQO = 6
|
|
||||||
PIRQP = 7
|
|
||||||
PIRQQ = 8
|
|
||||||
PIRQR = 9
|
|
||||||
PIRQS = 10
|
|
||||||
PIRQT = 11
|
|
||||||
PIRQU = 12
|
|
||||||
PIRQV = 13
|
|
||||||
PIRQW = 14
|
|
||||||
PIRQX = 15
|
|
||||||
)
|
|
||||||
|
|
||||||
/* from sb/intel/lynxpoint/lp_gpio.c */
|
|
||||||
func lp_gpio_to_pirq(gpioNum uint16) int {
|
|
||||||
switch gpioNum {
|
|
||||||
case 8:
|
|
||||||
return PIRQI
|
|
||||||
case 9:
|
|
||||||
return PIRQJ
|
|
||||||
case 10:
|
|
||||||
return PIRQK
|
|
||||||
case 13:
|
|
||||||
return PIRQL
|
|
||||||
case 14:
|
|
||||||
return PIRQM
|
|
||||||
case 45:
|
|
||||||
return PIRQN
|
|
||||||
case 46:
|
|
||||||
return PIRQO
|
|
||||||
case 47:
|
|
||||||
return PIRQP
|
|
||||||
case 48:
|
|
||||||
return PIRQQ
|
|
||||||
case 49:
|
|
||||||
return PIRQR
|
|
||||||
case 50:
|
|
||||||
return PIRQS
|
|
||||||
case 51:
|
|
||||||
return PIRQT
|
|
||||||
case 52:
|
|
||||||
return PIRQU
|
|
||||||
case 53:
|
|
||||||
return PIRQV
|
|
||||||
case 54:
|
|
||||||
return PIRQW
|
|
||||||
case 55:
|
|
||||||
return PIRQX
|
|
||||||
default:
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func conf0str(conf0 uint32) string {
|
|
||||||
if (conf0 & 1) == 0 {
|
|
||||||
return "GPIO_MODE_NATIVE"
|
|
||||||
} else {
|
|
||||||
s := []string{"GPIO_MODE_GPIO"}
|
|
||||||
var gpio_output bool
|
|
||||||
if ((conf0 >> 2) & 1) == 1 {
|
|
||||||
s = append(s, "GPIO_DIR_INPUT")
|
|
||||||
gpio_output = false
|
|
||||||
} else {
|
|
||||||
s = append(s, "GPIO_DIR_OUTPUT")
|
|
||||||
gpio_output = true
|
|
||||||
}
|
|
||||||
if ((conf0 >> 3) & 1) == 1 {
|
|
||||||
s = append(s, "GPIO_INVERT")
|
|
||||||
}
|
|
||||||
if ((conf0 >> 4) & 1) == 1 {
|
|
||||||
s = append(s, "GPIO_IRQ_LEVEL")
|
|
||||||
}
|
|
||||||
if gpio_output {
|
|
||||||
if ((conf0 >> 31) & 1) == 1 {
|
|
||||||
s = append(s, "GPO_LEVEL_HIGH")
|
|
||||||
} else {
|
|
||||||
s = append(s, "GPO_LEVEL_LOW")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(s, " | ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func lpgpio_preset(conf0 uint32, owner uint32, route uint32, irqen uint32, pirq uint32) string {
|
|
||||||
if conf0 == 0xd { /* 0b1101: MODE_GPIO | INPUT | INVERT */
|
|
||||||
if owner == 0 { /* OWNER_ACPI */
|
|
||||||
if irqen == 0 && pirq == 0 {
|
|
||||||
if route == 0 { /* SCI */
|
|
||||||
return "GPIO_ACPI_SCI"
|
|
||||||
} else {
|
|
||||||
return "GPIO_ACPI_SMI"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
} else { /* OWNER_GPIO */
|
|
||||||
if route == 0 && irqen == 0 && pirq != 0 {
|
|
||||||
return "GPIO_INPUT_INVERT"
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf0 == 0x5 && owner == 1 { /* 0b101: MODE_GPIO | INPUT, OWNER_GPIO */
|
|
||||||
if route == 0 && irqen == 0 {
|
|
||||||
if pirq == 1 {
|
|
||||||
return "GPIO_PIRQ"
|
|
||||||
} else {
|
|
||||||
return "GPIO_INPUT"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if owner == 1 && irqen == 1 {
|
|
||||||
if route == 0 && pirq == 0 {
|
|
||||||
if conf0 == 0x5 { /* 0b00101 */
|
|
||||||
return "GPIO_IRQ_EDGE"
|
|
||||||
}
|
|
||||||
if conf0 == 0x15 { /* 0b10101 */
|
|
||||||
return "GPIO_IRQ_LEVEL"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func gpio_str(conf0 uint32, conf1 uint32, owner uint32, route uint32, irqen uint32, reset uint32, blink uint32, pirq uint32) string {
|
|
||||||
s := []string{}
|
|
||||||
s = append(s, fmt.Sprintf(".conf0 = %s", conf0str(conf0)))
|
|
||||||
if conf1 != 0 {
|
|
||||||
s = append(s, fmt.Sprintf(".conf1 = 0x%x", conf1))
|
|
||||||
}
|
|
||||||
if owner != 0 {
|
|
||||||
s = append(s, ".owner = GPIO_OWNER_GPIO")
|
|
||||||
}
|
|
||||||
if route != 0 {
|
|
||||||
s = append(s, ".route = GPIO_ROUTE_SMI")
|
|
||||||
}
|
|
||||||
if irqen != 0 {
|
|
||||||
s = append(s, ".irqen = GPIO_IRQ_ENABLE")
|
|
||||||
}
|
|
||||||
if reset != 0 {
|
|
||||||
s = append(s, ".reset = GPIO_RESET_RSMRST")
|
|
||||||
}
|
|
||||||
if blink != 0 {
|
|
||||||
s = append(s, ".blink = GPO_BLINK")
|
|
||||||
}
|
|
||||||
if pirq != 0 {
|
|
||||||
s = append(s, ".pirq = GPIO_PIRQ_APIC_ROUTE")
|
|
||||||
}
|
|
||||||
return strings.Join(s, ", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
/* start addresses of GPIO registers */
|
|
||||||
const (
|
|
||||||
GPIO_OWN = 0x0
|
|
||||||
GPIPIRQ2IOXAPIC = 0x10
|
|
||||||
GPO_BLINK = 0x18
|
|
||||||
GPI_ROUT = 0x30
|
|
||||||
GP_RST_SEL = 0x60
|
|
||||||
GPI_IE = 0x90
|
|
||||||
GPnCONFIGA = 0x100
|
|
||||||
GPnCONFIGB = 0x104
|
|
||||||
)
|
|
||||||
|
|
||||||
func PrintLPGPIO(gpio *os.File, inteltool InteltoolData) {
|
|
||||||
for gpioNum := uint16(0); gpioNum <= 94; gpioNum++ {
|
|
||||||
if gpioNum < 10 {
|
|
||||||
fmt.Fprintf(gpio, "\t[%d] = ", gpioNum)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(gpio, "\t[%d] = ", gpioNum)
|
|
||||||
}
|
|
||||||
conf0 := inteltool.GPIO[GPnCONFIGA+gpioNum*8]
|
|
||||||
conf1 := inteltool.GPIO[GPnCONFIGB+gpioNum*8]
|
|
||||||
set := gpioNum / 32
|
|
||||||
bit := gpioNum % 32
|
|
||||||
/* owner only effective in GPIO mode */
|
|
||||||
owner := (inteltool.GPIO[GPIO_OWN+set*4] >> bit) & 1
|
|
||||||
route := (inteltool.GPIO[GPI_ROUT+set*4] >> bit) & 1
|
|
||||||
irqen := (inteltool.GPIO[GPI_IE+set*4] >> bit) & 1
|
|
||||||
reset := (inteltool.GPIO[GP_RST_SEL+set*4] >> bit) & 1
|
|
||||||
var blink, pirq uint32
|
|
||||||
/* blink only effective in GPIO output mode */
|
|
||||||
if set == 0 {
|
|
||||||
blink = (inteltool.GPIO[GPO_BLINK] >> bit) & 1
|
|
||||||
} else {
|
|
||||||
blink = 0
|
|
||||||
}
|
|
||||||
irqset := lp_gpio_to_pirq(gpioNum)
|
|
||||||
if irqset >= 0 {
|
|
||||||
pirq = (inteltool.GPIO[GPIPIRQ2IOXAPIC] >> uint(irqset)) & 1
|
|
||||||
} else {
|
|
||||||
pirq = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf0 & 1) == 0 {
|
|
||||||
fmt.Fprintf(gpio, "LP_GPIO_NATIVE,\n")
|
|
||||||
} else if (conf0 & 4) == 0 {
|
|
||||||
/* configured as output */
|
|
||||||
if ((conf0 >> 31) & 1) == 0 {
|
|
||||||
fmt.Fprintf(gpio, "LP_GPIO_OUT_LOW,\n")
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(gpio, "LP_GPIO_OUT_HIGH,\n")
|
|
||||||
}
|
|
||||||
} else if (conf1 & 4) != 0 {
|
|
||||||
/* configured as input and sensing disabled */
|
|
||||||
fmt.Fprintf(gpio, "LP_GPIO_UNUSED,\n")
|
|
||||||
} else {
|
|
||||||
is_preset := false
|
|
||||||
if conf1 == 0 && reset == 0 && blink == 0 {
|
|
||||||
preset := lpgpio_preset(conf0, owner, route, irqen, pirq)
|
|
||||||
if preset != "" {
|
|
||||||
fmt.Fprintf(gpio, "LP_%s,\n", preset)
|
|
||||||
is_preset = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !is_preset {
|
|
||||||
fmt.Fprintf(gpio, "{ %s },\n", gpio_str(conf0, conf1, owner, route, irqen, reset, blink, pirq))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Lynxpoint_LP_GPIO(ctx Context, inteltool InteltoolData) {
|
|
||||||
gpio := Create(ctx, "gpio.c")
|
|
||||||
defer gpio.Close()
|
|
||||||
|
|
||||||
AddROMStageFile("gpio.c", "")
|
|
||||||
|
|
||||||
Add_gpl(gpio)
|
|
||||||
gpio.WriteString(`#include <southbridge/intel/lynxpoint/lp_gpio.h>
|
|
||||||
|
|
||||||
const struct pch_lp_gpio_map mainboard_lp_gpio_map[] = {
|
|
||||||
`)
|
|
||||||
PrintLPGPIO(gpio, inteltool)
|
|
||||||
gpio.WriteString("\tLP_GPIO_END\n};\n")
|
|
||||||
}
|
|
|
@ -1,915 +0,0 @@
|
||||||
/* This is just an experiment. Full automatic porting
|
|
||||||
is probably not possible but a lot can be automated. */
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PCIAddr struct {
|
|
||||||
Bus int
|
|
||||||
Dev int
|
|
||||||
Func int
|
|
||||||
}
|
|
||||||
|
|
||||||
type PCIDevData struct {
|
|
||||||
PCIAddr
|
|
||||||
PCIVenID uint16
|
|
||||||
PCIDevID uint16
|
|
||||||
ConfigDump []uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
type PCIDevice interface {
|
|
||||||
Scan(ctx Context, addr PCIDevData)
|
|
||||||
}
|
|
||||||
|
|
||||||
type InteltoolData struct {
|
|
||||||
GPIO map[uint16]uint32
|
|
||||||
RCBA map[uint16]uint32
|
|
||||||
IOBP map[uint32]uint32
|
|
||||||
IGD map[uint32]uint32
|
|
||||||
MCHBAR map[uint16]uint32
|
|
||||||
PMBASE map[uint16]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type DMIData struct {
|
|
||||||
Vendor string
|
|
||||||
Model string
|
|
||||||
Version string
|
|
||||||
IsLaptop bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type AzaliaCodec struct {
|
|
||||||
Name string
|
|
||||||
VendorID uint32
|
|
||||||
SubsystemID uint32
|
|
||||||
CodecNo int
|
|
||||||
PinConfig map[int]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type DevReader interface {
|
|
||||||
GetPCIList() []PCIDevData
|
|
||||||
GetDMI() DMIData
|
|
||||||
GetInteltool() InteltoolData
|
|
||||||
GetAzaliaCodecs() []AzaliaCodec
|
|
||||||
GetACPI() map[string][]byte
|
|
||||||
GetCPUModel() []uint32
|
|
||||||
GetEC() []byte
|
|
||||||
GetIOPorts() []IOPorts
|
|
||||||
HasPS2() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type IOPorts struct {
|
|
||||||
Start uint16
|
|
||||||
End uint16
|
|
||||||
Usage string
|
|
||||||
}
|
|
||||||
|
|
||||||
type SouthBridger interface {
|
|
||||||
GetGPIOHeader() string
|
|
||||||
EncodeGPE(int) int
|
|
||||||
DecodeGPE(int) int
|
|
||||||
EnableGPE(int)
|
|
||||||
NeedRouteGPIOManually()
|
|
||||||
}
|
|
||||||
|
|
||||||
var SouthBridge SouthBridger
|
|
||||||
var BootBlockFiles map[string]string = map[string]string{}
|
|
||||||
var ROMStageFiles map[string]string = map[string]string{}
|
|
||||||
var RAMStageFiles map[string]string = map[string]string{}
|
|
||||||
var SMMFiles map[string]string = map[string]string{}
|
|
||||||
var MainboardInit string
|
|
||||||
var MainboardEnable string
|
|
||||||
var MainboardIncludes []string
|
|
||||||
|
|
||||||
type Context struct {
|
|
||||||
MoboID string
|
|
||||||
KconfigName string
|
|
||||||
Vendor string
|
|
||||||
Model string
|
|
||||||
BaseDirectory string
|
|
||||||
InfoSource DevReader
|
|
||||||
SaneVendor string
|
|
||||||
}
|
|
||||||
|
|
||||||
type IOAPICIRQ struct {
|
|
||||||
APICID int
|
|
||||||
IRQNO [4]int
|
|
||||||
}
|
|
||||||
|
|
||||||
var IOAPICIRQs map[PCIAddr]IOAPICIRQ = map[PCIAddr]IOAPICIRQ{}
|
|
||||||
var KconfigBool map[string]bool = map[string]bool{}
|
|
||||||
var KconfigComment map[string]string = map[string]string{}
|
|
||||||
var KconfigString map[string]string = map[string]string{}
|
|
||||||
var KconfigHex map[string]uint32 = map[string]uint32{}
|
|
||||||
var KconfigInt map[string]int = map[string]int{}
|
|
||||||
var ROMSizeKB = 0
|
|
||||||
var ROMProtocol = ""
|
|
||||||
var FlashROMSupport = ""
|
|
||||||
|
|
||||||
func GetLE16(inp []byte) uint16 {
|
|
||||||
return uint16(inp[0]) | (uint16(inp[1]) << 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatHexLE16(inp []byte) string {
|
|
||||||
return fmt.Sprintf("0x%04x", GetLE16(inp))
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatHex32(u uint32) string {
|
|
||||||
return fmt.Sprintf("0x%08x", u)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatHex8(u uint8) string {
|
|
||||||
return fmt.Sprintf("0x%02x", u)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatInt32(u uint32) string {
|
|
||||||
return fmt.Sprintf("%d", u)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatHexLE32(d []uint8) string {
|
|
||||||
u := uint32(d[0]) | (uint32(d[1]) << 8) | (uint32(d[2]) << 16) | (uint32(d[3]) << 24)
|
|
||||||
return FormatHex32(u)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatBool(inp bool) string {
|
|
||||||
if inp {
|
|
||||||
return "1"
|
|
||||||
} else {
|
|
||||||
return "0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sanitize(inp string) string {
|
|
||||||
result := strings.ToLower(inp)
|
|
||||||
result = strings.Replace(result, " ", "_", -1)
|
|
||||||
result = strings.Replace(result, ",", "_", -1)
|
|
||||||
result = strings.Replace(result, "-", "_", -1)
|
|
||||||
for strings.HasSuffix(result, ".") {
|
|
||||||
result = result[0 : len(result)-1]
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddBootBlockFile(Name string, Condition string) {
|
|
||||||
BootBlockFiles[Name] = Condition
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddROMStageFile(Name string, Condition string) {
|
|
||||||
ROMStageFiles[Name] = Condition
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddRAMStageFile(Name string, Condition string) {
|
|
||||||
RAMStageFiles[Name] = Condition
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddSMMFile(Name string, Condition string) {
|
|
||||||
SMMFiles[Name] = Condition
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsIOPortUsedBy(ctx Context, port uint16, name string) bool {
|
|
||||||
for _, io := range ctx.InfoSource.GetIOPorts() {
|
|
||||||
if io.Start <= port && port <= io.End && io.Usage == name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var FlagOutDir = flag.String("coreboot_dir", ".", "Resulting coreboot directory")
|
|
||||||
|
|
||||||
func writeMF(mf *os.File, files map[string]string, category string) {
|
|
||||||
keys := []string{}
|
|
||||||
for file, _ := range files {
|
|
||||||
keys = append(keys, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
for _, file := range keys {
|
|
||||||
condition := files[file]
|
|
||||||
if condition == "" {
|
|
||||||
fmt.Fprintf(mf, "%s-y += %s\n", category, file)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(mf, "%s-$(%s) += %s\n", category, condition, file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Create(ctx Context, name string) *os.File {
|
|
||||||
li := strings.LastIndex(name, "/")
|
|
||||||
if li > 0 {
|
|
||||||
os.MkdirAll(ctx.BaseDirectory+"/"+name[0:li], 0700)
|
|
||||||
}
|
|
||||||
mf, err := os.Create(ctx.BaseDirectory + "/" + name)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return mf
|
|
||||||
}
|
|
||||||
|
|
||||||
func Add_gpl(f *os.File) {
|
|
||||||
fmt.Fprintln(f, "/* SPDX-License-Identifier: GPL-2.0-only */")
|
|
||||||
fmt.Fprintln(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RestorePCI16Simple(f *os.File, pcidev PCIDevData, addr uint16) {
|
|
||||||
fmt.Fprintf(f, " pci_write_config16(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x);\n",
|
|
||||||
pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
|
|
||||||
pcidev.ConfigDump[addr+1],
|
|
||||||
pcidev.ConfigDump[addr])
|
|
||||||
}
|
|
||||||
|
|
||||||
func RestorePCI32Simple(f *os.File, pcidev PCIDevData, addr uint16) {
|
|
||||||
fmt.Fprintf(f, " pci_write_config32(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x%02x%02x);\n",
|
|
||||||
pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
|
|
||||||
pcidev.ConfigDump[addr+3],
|
|
||||||
pcidev.ConfigDump[addr+2],
|
|
||||||
pcidev.ConfigDump[addr+1],
|
|
||||||
pcidev.ConfigDump[addr])
|
|
||||||
}
|
|
||||||
|
|
||||||
func RestoreRCBA32(f *os.File, inteltool InteltoolData, addr uint16) {
|
|
||||||
fmt.Fprintf(f, "\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr])
|
|
||||||
}
|
|
||||||
|
|
||||||
type PCISlot struct {
|
|
||||||
PCIAddr
|
|
||||||
alias string
|
|
||||||
additionalComment string
|
|
||||||
writeEmpty bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type DevTreeNode struct {
|
|
||||||
Bus int
|
|
||||||
Dev int
|
|
||||||
Func int
|
|
||||||
Disabled bool
|
|
||||||
Registers map[string]string
|
|
||||||
IOs map[uint16]uint16
|
|
||||||
Children []DevTreeNode
|
|
||||||
PCISlots []PCISlot
|
|
||||||
PCIController bool
|
|
||||||
ChildPCIBus int
|
|
||||||
MissingParent string
|
|
||||||
SubVendor uint16
|
|
||||||
SubSystem uint16
|
|
||||||
Chip string
|
|
||||||
Ops string
|
|
||||||
Comment string
|
|
||||||
}
|
|
||||||
|
|
||||||
var DevTree DevTreeNode
|
|
||||||
var MissingChildren map[string][]DevTreeNode = map[string][]DevTreeNode{}
|
|
||||||
var unmatchedPCIChips map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
|
|
||||||
var unmatchedPCIDevices map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
|
|
||||||
|
|
||||||
func Offset(dt *os.File, offset int) {
|
|
||||||
for i := 0; i < offset; i++ {
|
|
||||||
fmt.Fprintf(dt, "\t")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MatchDev(dev *DevTreeNode) {
|
|
||||||
for idx := range dev.Children {
|
|
||||||
MatchDev(&dev.Children[idx])
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, slot := range dev.PCISlots {
|
|
||||||
slotChip, ok := unmatchedPCIChips[slot.PCIAddr]
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if slot.additionalComment != "" && slotChip.Comment != "" {
|
|
||||||
slotChip.Comment = slot.additionalComment + " " + slotChip.Comment
|
|
||||||
} else {
|
|
||||||
slotChip.Comment = slot.additionalComment + slotChip.Comment
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(unmatchedPCIChips, slot.PCIAddr)
|
|
||||||
MatchDev(&slotChip)
|
|
||||||
dev.Children = append(dev.Children, slotChip)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dev.PCIController {
|
|
||||||
for slot, slotDev := range unmatchedPCIChips {
|
|
||||||
if slot.Bus == dev.ChildPCIBus {
|
|
||||||
delete(unmatchedPCIChips, slot)
|
|
||||||
MatchDev(&slotDev)
|
|
||||||
dev.Children = append(dev.Children, slotDev)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, slot := range dev.PCISlots {
|
|
||||||
slotDev, ok := unmatchedPCIDevices[slot.PCIAddr]
|
|
||||||
if !ok {
|
|
||||||
if slot.writeEmpty {
|
|
||||||
dev.Children = append(dev.Children,
|
|
||||||
DevTreeNode{
|
|
||||||
Registers: map[string]string{},
|
|
||||||
Chip: "pci",
|
|
||||||
Bus: slot.Bus,
|
|
||||||
Dev: slot.Dev,
|
|
||||||
Func: slot.Func,
|
|
||||||
Comment: slot.additionalComment,
|
|
||||||
Disabled: true,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if slot.additionalComment != "" && slotDev.Comment != "" {
|
|
||||||
slotDev.Comment = slot.additionalComment + " " + slotDev.Comment
|
|
||||||
} else {
|
|
||||||
slotDev.Comment = slot.additionalComment + slotDev.Comment
|
|
||||||
}
|
|
||||||
|
|
||||||
MatchDev(&slotDev)
|
|
||||||
dev.Children = append(dev.Children, slotDev)
|
|
||||||
delete(unmatchedPCIDevices, slot.PCIAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dev.MissingParent != "" {
|
|
||||||
for _, child := range MissingChildren[dev.MissingParent] {
|
|
||||||
MatchDev(&child)
|
|
||||||
dev.Children = append(dev.Children, child)
|
|
||||||
}
|
|
||||||
delete(MissingChildren, dev.MissingParent)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dev.PCIController {
|
|
||||||
for slot, slotDev := range unmatchedPCIDevices {
|
|
||||||
if slot.Bus == dev.ChildPCIBus {
|
|
||||||
MatchDev(&slotDev)
|
|
||||||
dev.Children = append(dev.Children, slotDev)
|
|
||||||
delete(unmatchedPCIDevices, slot)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeOn(dt *os.File, dev DevTreeNode) {
|
|
||||||
if dev.Disabled {
|
|
||||||
fmt.Fprintf(dt, "off")
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(dt, "on")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteDev(dt *os.File, offset int, alias string, dev DevTreeNode) {
|
|
||||||
Offset(dt, offset)
|
|
||||||
switch dev.Chip {
|
|
||||||
case "cpu_cluster", "lapic", "domain", "ioapic":
|
|
||||||
fmt.Fprintf(dt, "device %s 0x%x ", dev.Chip, dev.Dev)
|
|
||||||
writeOn(dt, dev)
|
|
||||||
case "pci", "pnp":
|
|
||||||
if alias != "" {
|
|
||||||
fmt.Fprintf(dt, "device ref %s ", alias)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func)
|
|
||||||
}
|
|
||||||
writeOn(dt, dev)
|
|
||||||
case "i2c":
|
|
||||||
fmt.Fprintf(dt, "device %s %02x ", dev.Chip, dev.Dev)
|
|
||||||
writeOn(dt, dev)
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(dt, "chip %s", dev.Chip)
|
|
||||||
}
|
|
||||||
if dev.Comment != "" {
|
|
||||||
fmt.Fprintf(dt, " # %s", dev.Comment)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(dt, "\n")
|
|
||||||
if dev.Ops != "" {
|
|
||||||
Offset(dt, offset+1)
|
|
||||||
fmt.Fprintf(dt, "ops %s\n", dev.Ops)
|
|
||||||
}
|
|
||||||
if dev.Chip == "pci" && dev.SubSystem != 0 && dev.SubVendor != 0 {
|
|
||||||
Offset(dt, offset+1)
|
|
||||||
fmt.Fprintf(dt, "subsystemid 0x%04x 0x%04x\n", dev.SubVendor, dev.SubSystem)
|
|
||||||
}
|
|
||||||
|
|
||||||
ioapic, ok := IOAPICIRQs[PCIAddr{Bus: dev.Bus, Dev: dev.Dev, Func: dev.Func}]
|
|
||||||
if dev.Chip == "pci" && ok {
|
|
||||||
for pin, irq := range ioapic.IRQNO {
|
|
||||||
if irq != 0 {
|
|
||||||
Offset(dt, offset+1)
|
|
||||||
fmt.Fprintf(dt, "ioapic_irq %d INT%c 0x%x\n", ioapic.APICID, 'A'+pin, irq)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keys := []string{}
|
|
||||||
for reg, _ := range dev.Registers {
|
|
||||||
keys = append(keys, reg)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
for _, reg := range keys {
|
|
||||||
val := dev.Registers[reg]
|
|
||||||
Offset(dt, offset+1)
|
|
||||||
fmt.Fprintf(dt, "register \"%s\" = \"%s\"\n", reg, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
ios := []int{}
|
|
||||||
for reg, _ := range dev.IOs {
|
|
||||||
ios = append(ios, int(reg))
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Ints(ios)
|
|
||||||
|
|
||||||
for _, reg := range ios {
|
|
||||||
val := dev.IOs[uint16(reg)]
|
|
||||||
Offset(dt, offset+1)
|
|
||||||
fmt.Fprintf(dt, "io 0x%x = 0x%x\n", reg, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, child := range dev.Children {
|
|
||||||
alias = ""
|
|
||||||
for _, slot := range dev.PCISlots {
|
|
||||||
if slot.PCIAddr.Bus == child.Bus &&
|
|
||||||
slot.PCIAddr.Dev == child.Dev && slot.PCIAddr.Func == child.Func {
|
|
||||||
alias = slot.alias
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WriteDev(dt, offset+1, alias, child)
|
|
||||||
}
|
|
||||||
|
|
||||||
Offset(dt, offset)
|
|
||||||
fmt.Fprintf(dt, "end\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutChip(domain string, cur DevTreeNode) {
|
|
||||||
MissingChildren[domain] = append(MissingChildren[domain], cur)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutPCIChip(addr PCIDevData, cur DevTreeNode) {
|
|
||||||
unmatchedPCIChips[addr.PCIAddr] = cur
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutPCIDevParent(addr PCIDevData, comment string, parent string) {
|
|
||||||
cur := DevTreeNode{
|
|
||||||
Registers: map[string]string{},
|
|
||||||
Chip: "pci",
|
|
||||||
Bus: addr.Bus,
|
|
||||||
Dev: addr.Dev,
|
|
||||||
Func: addr.Func,
|
|
||||||
MissingParent: parent,
|
|
||||||
Comment: comment,
|
|
||||||
}
|
|
||||||
if addr.ConfigDump[0xa] == 0x04 && addr.ConfigDump[0xb] == 0x06 {
|
|
||||||
cur.PCIController = true
|
|
||||||
cur.ChildPCIBus = int(addr.ConfigDump[0x19])
|
|
||||||
|
|
||||||
loopCtr := 0
|
|
||||||
for capPtr := addr.ConfigDump[0x34]; capPtr != 0; capPtr = addr.ConfigDump[capPtr+1] {
|
|
||||||
/* Avoid hangs. There are only 0x100 different possible values for capPtr.
|
|
||||||
If we iterate longer than that, we're in endless loop. */
|
|
||||||
loopCtr++
|
|
||||||
if loopCtr > 0x100 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if addr.ConfigDump[capPtr] == 0x0d {
|
|
||||||
cur.SubVendor = GetLE16(addr.ConfigDump[capPtr+4 : capPtr+6])
|
|
||||||
cur.SubSystem = GetLE16(addr.ConfigDump[capPtr+6 : capPtr+8])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cur.SubVendor = GetLE16(addr.ConfigDump[0x2c:0x2e])
|
|
||||||
cur.SubSystem = GetLE16(addr.ConfigDump[0x2e:0x30])
|
|
||||||
}
|
|
||||||
unmatchedPCIDevices[addr.PCIAddr] = cur
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutPCIDev(addr PCIDevData, comment string) {
|
|
||||||
PutPCIDevParent(addr, comment, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenericPCI struct {
|
|
||||||
Comment string
|
|
||||||
Bus0Subdiv string
|
|
||||||
MissingParent string
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenericVGA struct {
|
|
||||||
GenericPCI
|
|
||||||
}
|
|
||||||
|
|
||||||
type DSDTInclude struct {
|
|
||||||
Comment string
|
|
||||||
File string
|
|
||||||
}
|
|
||||||
|
|
||||||
type DSDTDefine struct {
|
|
||||||
Key string
|
|
||||||
Comment string
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
var DSDTIncludes []DSDTInclude
|
|
||||||
var DSDTPCI0Includes []DSDTInclude
|
|
||||||
var DSDTDefines []DSDTDefine
|
|
||||||
|
|
||||||
func (g GenericPCI) Scan(ctx Context, addr PCIDevData) {
|
|
||||||
PutPCIDevParent(addr, g.Comment, g.MissingParent)
|
|
||||||
}
|
|
||||||
|
|
||||||
var IGDEnabled bool = false
|
|
||||||
|
|
||||||
func (g GenericVGA) Scan(ctx Context, addr PCIDevData) {
|
|
||||||
KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x",
|
|
||||||
addr.PCIVenID,
|
|
||||||
addr.PCIDevID)
|
|
||||||
PutPCIDevParent(addr, g.Comment, g.MissingParent)
|
|
||||||
IGDEnabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeKconfigName(ctx Context) {
|
|
||||||
kn := Create(ctx, "Kconfig.name")
|
|
||||||
defer kn.Close()
|
|
||||||
|
|
||||||
fmt.Fprintf(kn, "config %s\n\tbool \"%s\"\n", ctx.KconfigName, ctx.Model)
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeComment(name string) string {
|
|
||||||
cmt, ok := KconfigComment[name]
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return " # " + cmt
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeKconfig(ctx Context) {
|
|
||||||
kc := Create(ctx, "Kconfig")
|
|
||||||
defer kc.Close()
|
|
||||||
|
|
||||||
fmt.Fprintf(kc, "if %s\n\n", ctx.KconfigName)
|
|
||||||
|
|
||||||
fmt.Fprintf(kc, "config BOARD_SPECIFIC_OPTIONS\n\tdef_bool y\n")
|
|
||||||
keys := []string{}
|
|
||||||
for name, val := range KconfigBool {
|
|
||||||
if val {
|
|
||||||
keys = append(keys, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
for _, name := range keys {
|
|
||||||
fmt.Fprintf(kc, "\tselect %s%s\n", name, makeComment(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = nil
|
|
||||||
for name, val := range KconfigBool {
|
|
||||||
if !val {
|
|
||||||
keys = append(keys, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
for _, name := range keys {
|
|
||||||
fmt.Fprintf(kc, `
|
|
||||||
config %s%s
|
|
||||||
bool
|
|
||||||
default n
|
|
||||||
`, name, makeComment(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = nil
|
|
||||||
for name, _ := range KconfigString {
|
|
||||||
keys = append(keys, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
for _, name := range keys {
|
|
||||||
fmt.Fprintf(kc, `
|
|
||||||
config %s%s
|
|
||||||
string
|
|
||||||
default "%s"
|
|
||||||
`, name, makeComment(name), KconfigString[name])
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = nil
|
|
||||||
for name, _ := range KconfigHex {
|
|
||||||
keys = append(keys, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
for _, name := range keys {
|
|
||||||
fmt.Fprintf(kc, `
|
|
||||||
config %s%s
|
|
||||||
hex
|
|
||||||
default 0x%x
|
|
||||||
`, name, makeComment(name), KconfigHex[name])
|
|
||||||
}
|
|
||||||
|
|
||||||
keys = nil
|
|
||||||
for name, _ := range KconfigInt {
|
|
||||||
keys = append(keys, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
for _, name := range keys {
|
|
||||||
fmt.Fprintf(kc, `
|
|
||||||
config %s%s
|
|
||||||
int
|
|
||||||
default %d
|
|
||||||
`, name, makeComment(name), KconfigInt[name])
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(kc, "endif\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
const MoboDir = "/src/mainboard/"
|
|
||||||
|
|
||||||
func makeVendor(ctx Context) {
|
|
||||||
vendor := ctx.Vendor
|
|
||||||
vendorSane := ctx.SaneVendor
|
|
||||||
vendorDir := *FlagOutDir + MoboDir + vendorSane
|
|
||||||
vendorUpper := strings.ToUpper(vendorSane)
|
|
||||||
kconfig := vendorDir + "/Kconfig"
|
|
||||||
if _, err := os.Stat(kconfig); os.IsNotExist(err) {
|
|
||||||
f, err := os.Create(kconfig)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
f.WriteString(`if VENDOR_` + vendorUpper + `
|
|
||||||
|
|
||||||
choice
|
|
||||||
prompt "Mainboard model"
|
|
||||||
|
|
||||||
source "src/mainboard/` + vendorSane + `/*/Kconfig.name"
|
|
||||||
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
source "src/mainboard/` + vendorSane + `/*/Kconfig"
|
|
||||||
|
|
||||||
config MAINBOARD_VENDOR
|
|
||||||
string
|
|
||||||
default "` + vendor + `"
|
|
||||||
|
|
||||||
endif # VENDOR_` + vendorUpper + "\n")
|
|
||||||
}
|
|
||||||
kconfigName := vendorDir + "/Kconfig.name"
|
|
||||||
if _, err := os.Stat(kconfigName); os.IsNotExist(err) {
|
|
||||||
f, err := os.Create(kconfigName)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
f.WriteString(`config VENDOR_` + vendorUpper + `
|
|
||||||
bool "` + vendor + `"
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func GuessECGPE(ctx Context) int {
|
|
||||||
/* FIXME:XX Use iasl -d and/or better parsing */
|
|
||||||
dsdt := ctx.InfoSource.GetACPI()["DSDT"]
|
|
||||||
idx := bytes.Index(dsdt, []byte{0x08, '_', 'G', 'P', 'E', 0x0a}) /* Name (_GPE, byte). */
|
|
||||||
if idx > 0 {
|
|
||||||
return int(dsdt[idx+6])
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func GuessSPDMap(ctx Context) []uint8 {
|
|
||||||
dmi := ctx.InfoSource.GetDMI()
|
|
||||||
|
|
||||||
if dmi.Vendor == "LENOVO" {
|
|
||||||
return []uint8{0x50, 0x52, 0x51, 0x53}
|
|
||||||
}
|
|
||||||
return []uint8{0x50, 0x51, 0x52, 0x53}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
ctx := Context{}
|
|
||||||
|
|
||||||
ctx.InfoSource = MakeLogReader()
|
|
||||||
|
|
||||||
dmi := ctx.InfoSource.GetDMI()
|
|
||||||
|
|
||||||
ctx.Vendor = dmi.Vendor
|
|
||||||
|
|
||||||
if dmi.Vendor == "LENOVO" {
|
|
||||||
ctx.Model = dmi.Version
|
|
||||||
} else {
|
|
||||||
ctx.Model = dmi.Model
|
|
||||||
}
|
|
||||||
|
|
||||||
if dmi.IsLaptop {
|
|
||||||
KconfigBool["SYSTEM_TYPE_LAPTOP"] = true
|
|
||||||
}
|
|
||||||
ctx.SaneVendor = sanitize(ctx.Vendor)
|
|
||||||
for {
|
|
||||||
last := ctx.SaneVendor
|
|
||||||
for _, suf := range []string{"_inc", "_co", "_corp"} {
|
|
||||||
ctx.SaneVendor = strings.TrimSuffix(ctx.SaneVendor, suf)
|
|
||||||
}
|
|
||||||
if last == ctx.SaneVendor {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx.MoboID = ctx.SaneVendor + "/" + sanitize(ctx.Model)
|
|
||||||
ctx.KconfigName = "BOARD_" + strings.ToUpper(ctx.SaneVendor+"_"+sanitize(ctx.Model))
|
|
||||||
ctx.BaseDirectory = *FlagOutDir + MoboDir + ctx.MoboID
|
|
||||||
KconfigString["MAINBOARD_DIR"] = ctx.MoboID
|
|
||||||
KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model
|
|
||||||
|
|
||||||
os.MkdirAll(ctx.BaseDirectory, 0700)
|
|
||||||
|
|
||||||
makeVendor(ctx)
|
|
||||||
|
|
||||||
ScanRoot(ctx)
|
|
||||||
|
|
||||||
if IGDEnabled {
|
|
||||||
KconfigBool["MAINBOARD_HAS_LIBGFXINIT"] = true
|
|
||||||
KconfigComment["MAINBOARD_HAS_LIBGFXINIT"] = "FIXME: check this"
|
|
||||||
AddRAMStageFile("gma-mainboard.ads", "CONFIG_MAINBOARD_USE_LIBGFXINIT")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(BootBlockFiles) > 0 || len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 {
|
|
||||||
mf := Create(ctx, "Makefile.mk")
|
|
||||||
defer mf.Close()
|
|
||||||
writeMF(mf, BootBlockFiles, "bootblock")
|
|
||||||
writeMF(mf, ROMStageFiles, "romstage")
|
|
||||||
writeMF(mf, RAMStageFiles, "ramstage")
|
|
||||||
writeMF(mf, SMMFiles, "smm")
|
|
||||||
}
|
|
||||||
|
|
||||||
devtree := Create(ctx, "devicetree.cb")
|
|
||||||
defer devtree.Close()
|
|
||||||
|
|
||||||
MatchDev(&DevTree)
|
|
||||||
WriteDev(devtree, 0, "", DevTree)
|
|
||||||
|
|
||||||
if MainboardInit != "" || MainboardEnable != "" || MainboardIncludes != nil {
|
|
||||||
mainboard := Create(ctx, "mainboard.c")
|
|
||||||
defer mainboard.Close()
|
|
||||||
Add_gpl(mainboard)
|
|
||||||
mainboard.WriteString("#include <device/device.h>\n")
|
|
||||||
for _, include := range MainboardIncludes {
|
|
||||||
mainboard.WriteString("#include <" + include + ">\n")
|
|
||||||
}
|
|
||||||
mainboard.WriteString("\n")
|
|
||||||
if MainboardInit != "" {
|
|
||||||
mainboard.WriteString(`static void mainboard_init(struct device *dev)
|
|
||||||
{
|
|
||||||
` + MainboardInit + "}\n\n")
|
|
||||||
}
|
|
||||||
if MainboardInit != "" || MainboardEnable != "" {
|
|
||||||
mainboard.WriteString("static void mainboard_enable(struct device *dev)\n{\n")
|
|
||||||
if MainboardInit != "" {
|
|
||||||
mainboard.WriteString("\tdev->ops->init = mainboard_init;\n\n")
|
|
||||||
}
|
|
||||||
mainboard.WriteString(MainboardEnable)
|
|
||||||
mainboard.WriteString("}\n\n")
|
|
||||||
mainboard.WriteString(`struct chip_operations mainboard_ops = {
|
|
||||||
.enable_dev = mainboard_enable,
|
|
||||||
};
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bi := Create(ctx, "board_info.txt")
|
|
||||||
defer bi.Close()
|
|
||||||
|
|
||||||
fixme := ""
|
|
||||||
|
|
||||||
if dmi.IsLaptop {
|
|
||||||
bi.WriteString("Category: laptop\n")
|
|
||||||
} else {
|
|
||||||
bi.WriteString("Category: desktop\n")
|
|
||||||
fixme += "check category, "
|
|
||||||
}
|
|
||||||
|
|
||||||
missing := "ROM package, ROM socketed"
|
|
||||||
|
|
||||||
if ROMProtocol != "" {
|
|
||||||
fmt.Fprintf(bi, "ROM protocol: %s\n", ROMProtocol)
|
|
||||||
} else {
|
|
||||||
missing += ", ROM protocol"
|
|
||||||
}
|
|
||||||
|
|
||||||
if FlashROMSupport != "" {
|
|
||||||
fmt.Fprintf(bi, "Flashrom support: %s\n", FlashROMSupport)
|
|
||||||
} else {
|
|
||||||
missing += ", Flashrom support"
|
|
||||||
}
|
|
||||||
|
|
||||||
missing += ", Release year"
|
|
||||||
|
|
||||||
if fixme != "" {
|
|
||||||
fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(bi, "FIXME: put %s\n", missing)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ROMSizeKB == 0 {
|
|
||||||
KconfigBool["BOARD_ROMSIZE_KB_2048"] = true
|
|
||||||
KconfigComment["BOARD_ROMSIZE_KB_2048"] = "FIXME: correct this"
|
|
||||||
} else {
|
|
||||||
KconfigBool[fmt.Sprintf("BOARD_ROMSIZE_KB_%d", ROMSizeKB)] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
makeKconfig(ctx)
|
|
||||||
makeKconfigName(ctx)
|
|
||||||
|
|
||||||
dsdt := Create(ctx, "dsdt.asl")
|
|
||||||
defer dsdt.Close()
|
|
||||||
|
|
||||||
for _, define := range DSDTDefines {
|
|
||||||
if define.Comment != "" {
|
|
||||||
fmt.Fprintf(dsdt, "\t/* %s. */\n", define.Comment)
|
|
||||||
}
|
|
||||||
dsdt.WriteString("#define " + define.Key + " " + define.Value + "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
Add_gpl(dsdt)
|
|
||||||
dsdt.WriteString(
|
|
||||||
`
|
|
||||||
#include <acpi/acpi.h>
|
|
||||||
|
|
||||||
DefinitionBlock(
|
|
||||||
"dsdt.aml",
|
|
||||||
"DSDT",
|
|
||||||
ACPI_DSDT_REV_2,
|
|
||||||
OEM_ID,
|
|
||||||
ACPI_TABLE_CREATOR,
|
|
||||||
0x20141018 /* OEM revision */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
#include <acpi/dsdt_top.asl>
|
|
||||||
#include "acpi/platform.asl"
|
|
||||||
`)
|
|
||||||
|
|
||||||
for _, x := range DSDTIncludes {
|
|
||||||
if x.Comment != "" {
|
|
||||||
fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(dsdt, "\t#include <%s>\n", x.File)
|
|
||||||
}
|
|
||||||
|
|
||||||
dsdt.WriteString(`
|
|
||||||
Device (\_SB.PCI0)
|
|
||||||
{
|
|
||||||
`)
|
|
||||||
for _, x := range DSDTPCI0Includes {
|
|
||||||
if x.Comment != "" {
|
|
||||||
fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(dsdt, "\t\t#include <%s>\n", x.File)
|
|
||||||
}
|
|
||||||
dsdt.WriteString(
|
|
||||||
` }
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
if IGDEnabled {
|
|
||||||
gma := Create(ctx, "gma-mainboard.ads")
|
|
||||||
defer gma.Close()
|
|
||||||
|
|
||||||
gma.WriteString(`-- SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
with HW.GFX.GMA;
|
|
||||||
with HW.GFX.GMA.Display_Probing;
|
|
||||||
|
|
||||||
use HW.GFX.GMA;
|
|
||||||
use HW.GFX.GMA.Display_Probing;
|
|
||||||
|
|
||||||
private package GMA.Mainboard is
|
|
||||||
|
|
||||||
-- FIXME: check this
|
|
||||||
ports : constant Port_List :=
|
|
||||||
(DP1,
|
|
||||||
DP2,
|
|
||||||
DP3,
|
|
||||||
HDMI1,
|
|
||||||
HDMI2,
|
|
||||||
HDMI3,
|
|
||||||
Analog,
|
|
||||||
LVDS,
|
|
||||||
eDP);
|
|
||||||
|
|
||||||
end GMA.Mainboard;
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type rce823 struct {
|
|
||||||
variant string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r rce823) Scan(ctx Context, addr PCIDevData) {
|
|
||||||
if addr.Dev == 0 && addr.Func == 0 {
|
|
||||||
cur := DevTreeNode{
|
|
||||||
Chip: "drivers/ricoh/rce822",
|
|
||||||
Comment: "Ricoh cardreader",
|
|
||||||
Registers: map[string]string{
|
|
||||||
|
|
||||||
"sdwppol": fmt.Sprintf("%d", (addr.ConfigDump[0xfb]&2)>>1),
|
|
||||||
"disable_mask": fmt.Sprintf("0x%x", addr.ConfigDump[0xcb]),
|
|
||||||
},
|
|
||||||
PCISlots: []PCISlot{
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Bus: addr.Bus, Dev: 0x0, Func: 0}, writeEmpty: false},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Bus: addr.Bus, Dev: 0x0, Func: 1}, writeEmpty: false},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Bus: addr.Bus, Dev: 0x0, Func: 2}, writeEmpty: false},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Bus: addr.Bus, Dev: 0x0, Func: 3}, writeEmpty: false},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Bus: addr.Bus, Dev: 0x0, Func: 4}, writeEmpty: false},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Bus: addr.Bus, Dev: 0x0, Func: 5}, writeEmpty: false},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Bus: addr.Bus, Dev: 0x0, Func: 6}, writeEmpty: false},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Bus: addr.Bus, Dev: 0x0, Func: 7}, writeEmpty: false},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
PutPCIChip(addr, cur)
|
|
||||||
}
|
|
||||||
PutPCIDev(addr, "Ricoh SD card reader")
|
|
||||||
KconfigBool["DRIVERS_RICOH_RCE822"] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
RegisterPCI(0x1180, 0xe822, rce823{})
|
|
||||||
RegisterPCI(0x1180, 0xe823, rce823{})
|
|
||||||
}
|
|
|
@ -1,457 +0,0 @@
|
||||||
# Porting coreboot using autoport
|
|
||||||
|
|
||||||
## Supported platforms
|
|
||||||
|
|
||||||
### Chipset
|
|
||||||
For any Sandy Bridge or Ivy Bridge platform the generated result should
|
|
||||||
be bootable, possibly with minor fixes.
|
|
||||||
|
|
||||||
### EC / SuperIO
|
|
||||||
EC support is likely to work on Intel-based thinkpads. Other laptops are
|
|
||||||
likely to miss EC support. SuperIO support on desktops is more likely to
|
|
||||||
work out of the box than any EC.
|
|
||||||
|
|
||||||
## How to use autoport
|
|
||||||
|
|
||||||
Enable as many devices as possible in the firmware setup of your system.
|
|
||||||
This is useful to detect as many devices as possible and make the port
|
|
||||||
more complete, as disabled devices cannot be detected.
|
|
||||||
|
|
||||||
Boot into target machine under any Linux-based distribution and install
|
|
||||||
the following tools on it:
|
|
||||||
* `gcc`
|
|
||||||
* `golang`
|
|
||||||
* `lspci`
|
|
||||||
* `dmidecode`
|
|
||||||
* `acpidump` (part of `acpica` on some distros)
|
|
||||||
|
|
||||||
Clone the coreboot tree and `cd` into it. For more detailed steps, refer
|
|
||||||
to Rookie Guide, Lesson 1. Afterwards, run these commands:
|
|
||||||
|
|
||||||
cd util/ectool
|
|
||||||
make
|
|
||||||
cd ../inteltool
|
|
||||||
make
|
|
||||||
cd ../superiotool
|
|
||||||
make
|
|
||||||
cd ../autoport
|
|
||||||
go build
|
|
||||||
sudo ./autoport --input_log=logs --make_logs --coreboot_dir=../..
|
|
||||||
|
|
||||||
Note: in case you have problems getting gcc and golang on the target
|
|
||||||
machine, you can compile the utilities on another computer and copy
|
|
||||||
the binaries to the target machine. You will still need the other
|
|
||||||
listed programs on the target machine, but you may place them in the
|
|
||||||
same directory as autoport.
|
|
||||||
|
|
||||||
Check for unknown detected PCI devices, e.g.:
|
|
||||||
|
|
||||||
Unknown PCI device 8086:0085, assuming removable
|
|
||||||
|
|
||||||
If autoport says `assuming removable`, you are fine. If it doesn't,
|
|
||||||
you may want to add the relevant PCI IDs to autoport. Run `lspci -nn`
|
|
||||||
and check which device this is using the PCI ID. Devices which are not
|
|
||||||
part of the chipset, such as GPUs or network cards, can be considered
|
|
||||||
removable, whereas devices inside the CPU or the PCH such as integrated
|
|
||||||
GPUs and bus controllers (SATA, USB, LPC, SMBus...) are non-removable.
|
|
||||||
|
|
||||||
Your board has now been added to the tree. However, do not flash it
|
|
||||||
in its current state. It can brick your machine. Instead, keep this
|
|
||||||
new port and the logs from `util/autoport/logs` somewhere safe. The
|
|
||||||
following steps will back up your current firmware, which is always
|
|
||||||
recommended, since coreboot may not boot on the first try.
|
|
||||||
|
|
||||||
Disassemble your computer and find the flash chip(s). Since there could be
|
|
||||||
more than one, this guide will refer to "flash chips" as one or more chips.
|
|
||||||
Refer to <https://flashrom.org/Technology> as a reference. The flash chip is
|
|
||||||
usually in a `SOIC-8` (2x4 pins, 200mil) or `SOIC-16` (2x8 pins) package. As
|
|
||||||
it can be seen on flashrom's wiki, the former package is like any other 8-pin
|
|
||||||
chip on the mainboard, but it is slightly larger. The latter package is much
|
|
||||||
easier to locate. Always make sure it is a flash chip by looking up what its
|
|
||||||
model, printed on it, refers to.
|
|
||||||
|
|
||||||
There may be a smaller flash chip for the EC on some laptops, and other chips
|
|
||||||
such as network cards may use similar flash chips. These should be left as-is.
|
|
||||||
If in doubt, ask!
|
|
||||||
|
|
||||||
Once located, use an external flasher to read the flash chips with `flashrom -r`.
|
|
||||||
Verify with `flashrom -v` several times that reading is consistent. If it is not,
|
|
||||||
troubleshoot your flashing setup. Save the results somewhere safe, preferably on
|
|
||||||
media that cannot be easily overwritten and on several devices. You may need this
|
|
||||||
later. The write process erases the flash chips first, and erased data on a flash
|
|
||||||
chip is lost for a very long time, usually forever!
|
|
||||||
|
|
||||||
Compile coreboot for your ported mainboard with some console enabled. The most
|
|
||||||
common ones are EHCI debug, serial port and SPI flash console as a last resort.
|
|
||||||
If your system is a laptop and has a dedicated video card, you may need to add
|
|
||||||
a video BIOS (VBIOS) to coreboot to be able to see any video output. Desktop
|
|
||||||
video cards, as well as some MXM video cards, have this VBIOS on a flash chip
|
|
||||||
on the card's PCB, so this step is not necessary for them.
|
|
||||||
|
|
||||||
Flash coreboot on the machine. On recent Intel chipsets, the flash space is split
|
|
||||||
in several regions. Only the one known as "BIOS region" should be flashed. If
|
|
||||||
there is only one flash chip present, this is best done by adding the `--ifd`
|
|
||||||
and `-i bios` parameters flashrom has (from v1.0 onwards) to specify what flash
|
|
||||||
descriptor region it should operate on. If the ME (Management Engine) region is
|
|
||||||
not readable, which is the case on most systems, use the `--noverify-all`
|
|
||||||
parameter as well.
|
|
||||||
|
|
||||||
For systems with two flash chips, this is not so easy. It is probably better to
|
|
||||||
ask in coreboot or flashrom communication channels, such as via IRC or on the
|
|
||||||
mailing lists.
|
|
||||||
|
|
||||||
Once flashed, try to boot. Anything is possible. If a log is generated, save it
|
|
||||||
and use it to address any issues. See the next section for useful information.
|
|
||||||
Find all the sections marked with `FIXME` and correct them.
|
|
||||||
|
|
||||||
Send your work to review.coreboot.org. I mean it, your effort is very appreciated.
|
|
||||||
Refer to Rookie Guide, Lesson 2 for instructions on how to submit a patch.
|
|
||||||
|
|
||||||
## Manual fixes
|
|
||||||
### SPD
|
|
||||||
In order to initialize the RAM memory, coreboot needs to know its timings, which vary between
|
|
||||||
modules. Socketed RAM has a small EEPROM chip, which is accessible via SMBus and contains the
|
|
||||||
timing data. This data is usually known as SPD. Unfortunately, the SMBus addresses may not
|
|
||||||
correlate with the RAM slots and cannot always be detected automatically. The address map is
|
|
||||||
encoded in function `mainboard_get_spd` in `romstage.c`. By default, autoport uses the most
|
|
||||||
common map `0x50, 0x51, 0x52, 0x53` on everything except for Lenovo systems, which are known
|
|
||||||
to use `0x50, 0x52, 0x51, 0x53`. To detect the correct memory map, the easiest way is to boot
|
|
||||||
on the vendor firmware with just one module in channel 0, slot 0, and check the SMBus address
|
|
||||||
the EEPROM has. Under Linux, you can use these commands to see what is on SMBus:
|
|
||||||
|
|
||||||
$ sudo modprobe i2c-dev
|
|
||||||
$ sudo modprobe i2c-i801
|
|
||||||
$ sudo i2cdetect -l
|
|
||||||
i2c-0 i2c i915 gmbus ssc I2C adapter
|
|
||||||
i2c-1 i2c i915 gmbus vga I2C adapter
|
|
||||||
i2c-2 i2c i915 gmbus panel I2C adapter
|
|
||||||
i2c-3 i2c i915 gmbus dpc I2C adapter
|
|
||||||
i2c-4 i2c i915 gmbus dpb I2C adapter
|
|
||||||
i2c-5 i2c i915 gmbus dpd I2C adapter
|
|
||||||
i2c-6 i2c DPDDC-B I2C adapter
|
|
||||||
i2c-7 i2c DPDDC-C I2C adapter
|
|
||||||
i2c-8 i2c DPDDC-D I2C adapter
|
|
||||||
i2c-9 smbus SMBus I801 adapter at 0400 SMBus adapter
|
|
||||||
|
|
||||||
$ sudo i2cdetect 9
|
|
||||||
WARNING! This program can confuse your I2C bus, cause data loss and worse!
|
|
||||||
I will probe file /dev/i2c-9.
|
|
||||||
I will probe address range 0x03-0x77.
|
|
||||||
Continue? [Y/n] y
|
|
||||||
0 1 2 3 4 5 6 7 8 9 a b c d e f
|
|
||||||
00: -- -- -- -- -- 08 -- -- -- -- -- -- --
|
|
||||||
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
|
||||||
20: -- -- -- -- 24 -- -- -- -- -- -- -- -- -- -- --
|
|
||||||
30: 30 31 -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
|
||||||
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
|
||||||
50: 50 -- -- -- 54 55 56 57 -- -- -- -- 5c 5d 5e 5f
|
|
||||||
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
|
|
||||||
70: -- -- -- -- -- -- -- --
|
|
||||||
|
|
||||||
Make sure to replace the `9` on the last command with the bus number for SMBus on
|
|
||||||
your system. Here, there is a module at address `0x50`. Since only one module was
|
|
||||||
installed on the first slot of the first channel, we know the first position of
|
|
||||||
the SPD array must be `0x50`. After testing all the slots, your `mainboard_get_spd`
|
|
||||||
should look similar to this:
|
|
||||||
|
|
||||||
void mainboard_get_spd(spd_raw_data *spd) {
|
|
||||||
read_spd(&spd[0], 0x50);
|
|
||||||
read_spd(&spd[1], 0x51);
|
|
||||||
read_spd(&spd[2], 0x52);
|
|
||||||
read_spd(&spd[3], 0x53);
|
|
||||||
}
|
|
||||||
|
|
||||||
Note that there should be one line per memory slot on the mainboard.
|
|
||||||
|
|
||||||
Note: slot labelling may be missing or unreliable. Use `inteltool` to see
|
|
||||||
which slots have modules in them.
|
|
||||||
|
|
||||||
This procedure is ideal, if your RAM is socketed. If you have soldered RAM,
|
|
||||||
remove any socketed memory modules and check if any EEPROM appears on SMBus.
|
|
||||||
If this is the case, you can proceed as if the RAM was socketed. However,
|
|
||||||
you may have to guess some entries if there multiple EEPROMs appear.
|
|
||||||
|
|
||||||
Most of the time, soldered RAM does not have an EEPROM. Instead, the SPD data is
|
|
||||||
inside the main flash chip where the firmware is. If this is the case, you need
|
|
||||||
to generate the SPD data to use with coreboot. Look at `inteltool.log`. There
|
|
||||||
should be something like this:
|
|
||||||
|
|
||||||
/* SPD matching current mode: */
|
|
||||||
/* CH0S0 */
|
|
||||||
00: 92 11 0b 03 04 00 00 09 03 52 01 08 0a 00 80 00
|
|
||||||
10: 6e 78 6e 32 6e 11 18 81 20 08 3c 3c 00 f0 00 00
|
|
||||||
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 00
|
|
||||||
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6d 17
|
|
||||||
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
/* CH1S0 */
|
|
||||||
00: 92 11 0b 03 04 00 00 09 03 52 01 08 0a 00 80 00
|
|
||||||
10: 6e 78 6e 32 6e 11 18 81 20 08 3c 3c 00 f0 00 00
|
|
||||||
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 00
|
|
||||||
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6d 17
|
|
||||||
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
|
|
||||||
This is not a full-fledged SPD dump, as it only lists
|
|
||||||
the currently-used speed configuration, and lacks info
|
|
||||||
such as a serial number, vendor and model. Use `xxd`
|
|
||||||
to create a binary file with this SPD data:
|
|
||||||
|
|
||||||
$ cat | xxd -r > spd.bin <<EOF
|
|
||||||
00: 92 11 0b 03 04 00 00 09 03 52 01 08 0a 00 80 00
|
|
||||||
10: 6e 78 6e 32 6e 11 18 81 20 08 3c 3c 00 f0 00 00
|
|
||||||
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 00
|
|
||||||
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6d 17
|
|
||||||
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|
||||||
EOF (press Ctrl + D)
|
|
||||||
|
|
||||||
Then, move the generated file into your mainboard's directory
|
|
||||||
and hook it up to the build system by adding the following
|
|
||||||
lines to `Makefile.mk`:
|
|
||||||
|
|
||||||
cbfs-files-y += spd.bin
|
|
||||||
spd.bin-file := spd.bin
|
|
||||||
spd.bin-type := raw
|
|
||||||
|
|
||||||
Now we need coreboot to use this SPD file. The following example
|
|
||||||
shows a hybrid configuration, in which one module is soldered and
|
|
||||||
the other one is socketed:
|
|
||||||
|
|
||||||
void mainboard_get_spd(spd_raw_data *spd)
|
|
||||||
{
|
|
||||||
void *spd_file;
|
|
||||||
size_t spd_file_len = 0;
|
|
||||||
/* C0S0 is a soldered RAM with no real SPD. Use stored SPD. */
|
|
||||||
spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_RAW,
|
|
||||||
&spd_file_len);
|
|
||||||
if (spd_file && spd_file_len >= 128)
|
|
||||||
memcpy(&spd[0], spd_file, 128);
|
|
||||||
|
|
||||||
/* C1S0 is a physical slot. */
|
|
||||||
read_spd(&spd[2], 0x52);
|
|
||||||
}
|
|
||||||
|
|
||||||
If several slots are soldered there are two ways to handle them:
|
|
||||||
|
|
||||||
* If all use the same SPD data, use the same file for all the slots. Do
|
|
||||||
not forget to copy the data on all the array elements that need it.
|
|
||||||
* If they use different data, use several files.
|
|
||||||
|
|
||||||
If memory initialization is not working, in particular write training (timB)
|
|
||||||
on DIMM's second rank fails, try enabling rank 1 mirroring, which can't be
|
|
||||||
detected by inteltool. It is described by SPD field "Address Mapping from Edge
|
|
||||||
Connector to DRAM", byte `63` (`0x3f`). Bit 0 describes Rank 1 Mapping,
|
|
||||||
0 = standard, 1 = mirrored; set it to 1. Bits 1-7 are reserved.
|
|
||||||
|
|
||||||
### `board_info.txt`
|
|
||||||
|
|
||||||
`board_info.txt` is a text file used in the board status page to list all
|
|
||||||
the supported boards and their specifications. Most of the information
|
|
||||||
cannot be detected by autoport. Common entries are:
|
|
||||||
|
|
||||||
* `ROM package`, `ROM protocol` and `ROM socketed`:
|
|
||||||
These refer to the flash chips you found earlier. You can visit
|
|
||||||
<https://flashrom.org/Technology> for more information.
|
|
||||||
|
|
||||||
* `Release year`: Use the power of Internet to find that information.
|
|
||||||
* `Category`: This describes the type of mainboard you have.
|
|
||||||
Valid categories are:
|
|
||||||
* `desktop`. Desktops and workstations.
|
|
||||||
* `server`. Servers.
|
|
||||||
* `laptop`. Laptops, notebooks and netbooks.
|
|
||||||
* `half`. Embedded / PC/104 / Half-size boards.
|
|
||||||
* `mini`. Mini-ITX / Micro-ITX / Nano-ITX
|
|
||||||
* `settop`. Set-top-boxes / Thin clients.
|
|
||||||
* `eval`. Development / Evaluation Boards.
|
|
||||||
* `sbc`. Single-Board computer.
|
|
||||||
* `emulation`: Virtual machines and emulators. May require especial care
|
|
||||||
as they often behave differently from real counterparts.
|
|
||||||
* `misc`. Anything not fitting the categories above. Not recommended.
|
|
||||||
|
|
||||||
* `Flashrom support`: This means whether the internal programmer is usable.
|
|
||||||
If flashing coreboot internally works, this should be set to `y`. Else,
|
|
||||||
feel free to investigate why it is not working.
|
|
||||||
|
|
||||||
### `USBDEBUG_HCD_INDEX`
|
|
||||||
|
|
||||||
Which controller the most easily accessible USB debug port is. On Intel,
|
|
||||||
1 is for `00:1d.0` and 2 is for `00:1a.0` (yes, it's reversed). Refer to
|
|
||||||
<https://www.coreboot.org/EHCI_Debug_Port> for more info.
|
|
||||||
|
|
||||||
If you are able to use EHCI debug without setting the HCD index manually,
|
|
||||||
this is correct.
|
|
||||||
|
|
||||||
### `BOARD_ROMSIZE_KB_2048`
|
|
||||||
|
|
||||||
This parameter refers to the total size of the flash chips coreboot will be in.
|
|
||||||
This value must be correct for S3 resume to work properly. This parameter also
|
|
||||||
defines the size of the generated coreboot image, but that is not a major issue
|
|
||||||
since tools like `dd` can be used to cut fragments of a coreboot image to flash
|
|
||||||
on smaller chips.
|
|
||||||
|
|
||||||
This should be detected automatically, but it may not be detected properly in
|
|
||||||
some cases. If it was not detected, put the correct total size here to serve
|
|
||||||
as a sane default when configuring coreboot.
|
|
||||||
|
|
||||||
### `DRAM_RESET_GATE_GPIO`
|
|
||||||
|
|
||||||
When the computer is suspended to RAM (ACPI S3), the RAM reset signal must not
|
|
||||||
reach the RAM modules. Otherwise, the computer will not resume and any opened
|
|
||||||
programs will be lost. This is done by powering down a MOSFET, which disconnects
|
|
||||||
the reset signal from the RAM modules. Most manufacturers put this gate on GPIO
|
|
||||||
60 but Lenovo is known to put it on GPIO 10. If suspending and resuming works,
|
|
||||||
this value is correct. This can also be determined from the board's schematics.
|
|
||||||
|
|
||||||
## GNVS
|
|
||||||
|
|
||||||
`mainboard_fill_gnvs` sets values in GNVS, which then ACPI makes use of for
|
|
||||||
various power-related functions. Normally, there is no need to modify it
|
|
||||||
on laptops (desktops have no "lid"!) but it makes sense to proofread it.
|
|
||||||
|
|
||||||
## `gfx.ndid` and `gfx.did`
|
|
||||||
|
|
||||||
Those describe which video outputs are declared in ACPI tables.
|
|
||||||
Normally, there is no need to have these values, but if you miss some
|
|
||||||
non-standard video output, you can declare it there. Bit 31 is set to
|
|
||||||
indicate the presence of the output. Byte 1 is the type and byte 0 is
|
|
||||||
used for disambigution so that ID composed of byte 1 and 0 is unique.
|
|
||||||
|
|
||||||
Types are:
|
|
||||||
* 1 = VGA
|
|
||||||
* 2 = TV
|
|
||||||
* 3 = DVI
|
|
||||||
* 4 = LCD
|
|
||||||
|
|
||||||
## `c*_acpower` and `c*_battery`
|
|
||||||
|
|
||||||
Which mwait states to match to which ACPI levels. Normally, there is no
|
|
||||||
need to modify anything unless your device has very special power saving
|
|
||||||
requirements.
|
|
||||||
|
|
||||||
## `install_intel_vga_int15_handler`
|
|
||||||
|
|
||||||
This is used with the Intel VGA BIOS, which is not the default option.
|
|
||||||
It is more error-prone than open-source graphics initialization, so do
|
|
||||||
not bother with this until your mainboard boots. This is a function
|
|
||||||
which takes four parameters:
|
|
||||||
1. Which type of LCD panel is connected.
|
|
||||||
2. Panel fit.
|
|
||||||
3. Boot display.
|
|
||||||
4. Display type.
|
|
||||||
|
|
||||||
Refer to `src/drivers/intel/gma/int15.h` to see which values can be used.
|
|
||||||
For desktops, there is no LCD panel directly connected to the Intel GPU,
|
|
||||||
so the first parameter should be `GMA_INT15_ACTIVE_LFP_NONE`. On other
|
|
||||||
mainboards, it depends.
|
|
||||||
|
|
||||||
## CMOS options
|
|
||||||
|
|
||||||
Due to the poor state of CMOS support in coreboot, autoport does not
|
|
||||||
support it and this probably won't change until the format in the tree
|
|
||||||
improves. If you really care about CMOS options:
|
|
||||||
|
|
||||||
* Create files `cmos.layout` and `cmos.default`
|
|
||||||
* Enable `HAVE_OPTION_TABLE` and `HAVE_CMOS_DEFAULT` in `Kconfig`
|
|
||||||
|
|
||||||
## EC (lenovo)
|
|
||||||
|
|
||||||
You need to set `has_keyboard_backlight` (backlit keyboard like X230),
|
|
||||||
`has_power_management_beeps` (optional beeps when e.g. plugging the cord
|
|
||||||
in) and `has_uwb` (third MiniPCIe slot) in accordance to functions available
|
|
||||||
on your machine
|
|
||||||
|
|
||||||
In rare cases autoport is unable to detect GPE. You can detect it from
|
|
||||||
dmesg or ACPI tables. Look for line in dmesg like
|
|
||||||
|
|
||||||
ACPI: EC: GPE = 0x11, I/O: command/status = 0x66, data = 0x62
|
|
||||||
|
|
||||||
This means that GPE is `0x11` in ACPI notation. This is the correct
|
|
||||||
value for `THINKPAD_EC_GPE`. To get the correct value for `GPE_EC_SCI`
|
|
||||||
you need to substract `0x10`, so value for it is `1`.
|
|
||||||
|
|
||||||
The pin used to wake the machine from EC is guessed. If your machine doesn't
|
|
||||||
wake on lid open and pressing of Fn, change `GPE_EC_WAKE`.
|
|
||||||
|
|
||||||
Keep `GPE_EC_WAKE` and `GPE_EC_SCI` in sync with `gpi*_routing`.
|
|
||||||
`gpi*_routing` matching `GPE_EC_WAKE` or `GPE_EC_SCI` is set to `2`
|
|
||||||
and all others are absent.
|
|
||||||
|
|
||||||
If your dock has LPC wires or needs some special treatement you may
|
|
||||||
need to add codes to initialize the dock and support code to
|
|
||||||
DSDT. See the `init_dock()` for `x60`, `x200` or `x201`.
|
|
||||||
|
|
||||||
## EC (generic laptop)
|
|
||||||
|
|
||||||
Almost any laptop has an embedded controller. In a nutshell, it's a
|
|
||||||
small, low-powered computer designed to be used on laptops. Exact
|
|
||||||
functionality differs between machines. Its main functions include:
|
|
||||||
|
|
||||||
* Control of power and rfkill to different component
|
|
||||||
* Keyboard (PS/2) interface implementation
|
|
||||||
* Battery, AC, LID and thermal information exporting
|
|
||||||
* Hotkey support
|
|
||||||
|
|
||||||
autoport automatically attempts to restore the dumped config but it
|
|
||||||
may or may not work and may even lead to a hang or powerdown. If your
|
|
||||||
machine stops at `Replaying EC dump ...` try commenting EC replay out
|
|
||||||
|
|
||||||
autoport tries to detect if machine has PS/2 interface and if so calls
|
|
||||||
`pc_keyboard_init` and exports relevant ACPI objects. If detection fails
|
|
||||||
you may have to add them yourself
|
|
||||||
|
|
||||||
ACPI methods `_PTS` (prepare to sleep) and `_WAK` (wake) are executed
|
|
||||||
when transitioning to sleep or wake state respectively. You may need to
|
|
||||||
add power-related calls there to either shutdown some components or to
|
|
||||||
add a workaround to stop giving OS thermal info until next refresh.
|
|
||||||
|
|
||||||
For exporting the battery/AC/LID/hotkey/thermal info you need to write
|
|
||||||
`acpi/ec.asl`. For an easy example look into `apple/macbook21` or
|
|
||||||
`packardbell/ms2290`. For information about needed methods consult
|
|
||||||
relevant ACPI specs. Tracing which EC events can be done using
|
|
||||||
[dynamic debug](https://wiki.ubuntu.com/Kernel/Reference/ACPITricksAndTips)
|
|
||||||
|
|
||||||
EC GPE needs to be routed to SCI in order for OS in order to receive
|
|
||||||
EC events like "hotkey X pressed" or "AC plugged". autoport attempts
|
|
||||||
to detect GPE but in rare cases may fail. You can detect it from
|
|
||||||
dmesg or ACPI tables. Look for line in dmesg like
|
|
||||||
|
|
||||||
ACPI: EC: GPE = 0x11, I/O: command/status = 0x66, data = 0x62
|
|
||||||
|
|
||||||
This means that GPE is `0x11` in ACPI notation. This is the correct
|
|
||||||
value for `_GPE`.
|
|
||||||
|
|
||||||
Keep GPE in sync with `gpi*_routing`.
|
|
||||||
`gpi*_routing` matching `GPE - 0x10` is set to `2`
|
|
||||||
and all others are absent. If EC has separate wake pin
|
|
||||||
then this GPE needs to be routed as well
|
|
|
@ -1,47 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
import "os"
|
|
||||||
|
|
||||||
var supportedPCIDevices map[uint32]PCIDevice = map[uint32]PCIDevice{}
|
|
||||||
var PCIMap map[PCIAddr]PCIDevData = map[PCIAddr]PCIDevData{}
|
|
||||||
|
|
||||||
func ScanRoot(ctx Context) {
|
|
||||||
for _, pciDev := range ctx.InfoSource.GetPCIList() {
|
|
||||||
PCIMap[pciDev.PCIAddr] = pciDev
|
|
||||||
}
|
|
||||||
for _, pciDev := range ctx.InfoSource.GetPCIList() {
|
|
||||||
vendevid := (uint32(pciDev.PCIDevID) << 16) | uint32(pciDev.PCIVenID)
|
|
||||||
|
|
||||||
dev, ok := supportedPCIDevices[vendevid]
|
|
||||||
if !ok {
|
|
||||||
if pciDev.PCIAddr.Bus != 0 {
|
|
||||||
fmt.Printf("Unknown PCI device %04x:%04x, assuming removable\n",
|
|
||||||
pciDev.PCIVenID, pciDev.PCIDevID)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Printf("Unsupported PCI device %04x:%04x\n",
|
|
||||||
pciDev.PCIVenID, pciDev.PCIDevID)
|
|
||||||
dev = GenericPCI{Comment: fmt.Sprintf("Unsupported PCI device %04x:%04x",
|
|
||||||
pciDev.PCIVenID, pciDev.PCIDevID)}
|
|
||||||
}
|
|
||||||
dev.Scan(ctx, pciDev)
|
|
||||||
}
|
|
||||||
if SouthBridge == nil {
|
|
||||||
fmt.Println("Could not detect southbridge. Aborting!")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
dmi := ctx.InfoSource.GetDMI()
|
|
||||||
if !dmi.IsLaptop {
|
|
||||||
NoEC(ctx)
|
|
||||||
} else if dmi.Vendor == "LENOVO" {
|
|
||||||
LenovoEC(ctx)
|
|
||||||
} else {
|
|
||||||
FIXMEEC(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterPCI(VenID uint16, DevID uint16, dev PCIDevice) {
|
|
||||||
vendevid := (uint32(DevID) << 16) | uint32(VenID)
|
|
||||||
supportedPCIDevices[vendevid] = dev
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type sandybridgemc struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i sandybridgemc) Scan(ctx Context, addr PCIDevData) {
|
|
||||||
inteltool := ctx.InfoSource.GetInteltool()
|
|
||||||
|
|
||||||
/* FIXME:XX Move this somewhere else. */
|
|
||||||
MainboardIncludes = append(MainboardIncludes, "drivers/intel/gma/int15.h")
|
|
||||||
MainboardEnable += (` /* FIXME: fix these values. */
|
|
||||||
install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS,
|
|
||||||
GMA_INT15_PANEL_FIT_DEFAULT,
|
|
||||||
GMA_INT15_BOOT_DISPLAY_DEFAULT, 0);
|
|
||||||
`)
|
|
||||||
|
|
||||||
DevTree = DevTreeNode{
|
|
||||||
Chip: "northbridge/intel/sandybridge",
|
|
||||||
MissingParent: "northbridge",
|
|
||||||
Comment: "FIXME: GPU registers may not always apply.",
|
|
||||||
Registers: map[string]string{
|
|
||||||
"gpu_dp_b_hotplug": FormatInt32((inteltool.IGD[0xc4030] >> 2) & 7),
|
|
||||||
"gpu_dp_c_hotplug": FormatInt32((inteltool.IGD[0xc4030] >> 10) & 7),
|
|
||||||
"gpu_dp_d_hotplug": FormatInt32((inteltool.IGD[0xc4030] >> 18) & 7),
|
|
||||||
"gpu_panel_port_select": FormatInt32((inteltool.IGD[0xc7208] >> 30) & 3),
|
|
||||||
"gpu_panel_power_up_delay": FormatInt32((inteltool.IGD[0xc7208] >> 16) & 0x1fff),
|
|
||||||
"gpu_panel_power_backlight_on_delay": FormatInt32(inteltool.IGD[0xc7208] & 0x1fff),
|
|
||||||
"gpu_panel_power_down_delay": FormatInt32((inteltool.IGD[0xc720c] >> 16) & 0x1fff),
|
|
||||||
"gpu_panel_power_backlight_off_delay": FormatInt32(inteltool.IGD[0xc720c] & 0x1fff),
|
|
||||||
"gpu_panel_power_cycle_delay": FormatInt32(inteltool.IGD[0xc7210] & 0xff),
|
|
||||||
"gpu_cpu_backlight": FormatHex32(inteltool.IGD[0x48254]),
|
|
||||||
"gpu_pch_backlight": FormatHex32((inteltool.IGD[0xc8254] >> 16) * 0x10001),
|
|
||||||
"gfx": fmt.Sprintf("GMA_STATIC_DISPLAYS(%d)", (inteltool.IGD[0xc6200] >> 12) & 1),
|
|
||||||
},
|
|
||||||
Children: []DevTreeNode{
|
|
||||||
{
|
|
||||||
Chip: "domain",
|
|
||||||
Dev: 0,
|
|
||||||
PCIController: true,
|
|
||||||
ChildPCIBus: 0,
|
|
||||||
PCISlots: []PCISlot{
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x0, Func: 0}, writeEmpty: true, alias: "host_bridge", additionalComment: "Host bridge"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x1, Func: 0}, writeEmpty: true, alias: "peg10", additionalComment: "PEG"},
|
|
||||||
PCISlot{PCIAddr: PCIAddr{Dev: 0x2, Func: 0}, writeEmpty: true, alias: "igd", additionalComment: "iGPU"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
PutPCIDev(addr, "Host bridge")
|
|
||||||
|
|
||||||
/* FIXME:XX some configs are unsupported. */
|
|
||||||
KconfigBool["NORTHBRIDGE_INTEL_SANDYBRIDGE"] = true
|
|
||||||
KconfigBool["USE_NATIVE_RAMINIT"] = true
|
|
||||||
KconfigBool["INTEL_INT15"] = true
|
|
||||||
KconfigBool["HAVE_ACPI_TABLES"] = true
|
|
||||||
KconfigBool["HAVE_ACPI_RESUME"] = true
|
|
||||||
|
|
||||||
DSDTIncludes = append(DSDTIncludes, DSDTInclude{
|
|
||||||
File: "cpu/intel/common/acpi/cpu.asl",
|
|
||||||
})
|
|
||||||
|
|
||||||
DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{
|
|
||||||
File: "northbridge/intel/sandybridge/acpi/sandybridge.asl",
|
|
||||||
}, DSDTInclude{
|
|
||||||
File: "drivers/intel/gma/acpi/default_brightness_levels.asl",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
RegisterPCI(0x8086, 0x0100, sandybridgemc{})
|
|
||||||
RegisterPCI(0x8086, 0x0104, sandybridgemc{})
|
|
||||||
RegisterPCI(0x8086, 0x0150, sandybridgemc{})
|
|
||||||
RegisterPCI(0x8086, 0x0154, sandybridgemc{})
|
|
||||||
RegisterPCI(0x8086, 0x0158, sandybridgemc{})
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x0102, 0x0106, 0x010a,
|
|
||||||
0x0112, 0x0116, 0x0122, 0x0126,
|
|
||||||
0x0152, 0x0156, 0x0162, 0x0166,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericVGA{GenericPCI{}})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PCIe bridge */
|
|
||||||
for _, id := range []uint16{
|
|
||||||
0x0101, 0x0105, 0x0109, 0x010d,
|
|
||||||
0x0151, 0x0155, 0x0159, 0x015d,
|
|
||||||
} {
|
|
||||||
RegisterPCI(0x8086, id, GenericPCI{})
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue