Vladimir Serbinenko (phcoder@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/7131
-gerrit
commit debe7854f48b9e8558e163709755432c15d3e24a Author: Vladimir Serbinenko phcoder@gmail.com Date: Wed Oct 15 21:51:47 2014 +0200
autoport: Experimental stuff
Change-Id: Ia126cf0939ef2dc2cdbb7ea100d2b63ea6b02f28 Signed-off-by: Vladimir Serbinenko phcoder@gmail.com --- util/autoport/azalia.go | 62 ++++ util/autoport/bd82x6x.go | 368 +++++++++++++++++++++++ util/autoport/i82801gx.go | 531 +++++++++++++++++++++++++++++++++ util/autoport/i945.go | 120 ++++++++ util/autoport/log_maker.go | 85 ++++++ util/autoport/log_reader.go | 319 ++++++++++++++++++++ util/autoport/main.go | 682 +++++++++++++++++++++++++++++++++++++++++++ util/autoport/rce823.go | 39 +++ util/autoport/root.go | 29 ++ util/autoport/sandybridge.go | 142 +++++++++ 10 files changed, 2377 insertions(+)
diff --git a/util/autoport/azalia.go b/util/autoport/azalia.go new file mode 100644 index 0000000..f9be1b1 --- /dev/null +++ b/util/autoport/azalia.go @@ -0,0 +1,62 @@ +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() + + az.WriteString( + `#include <device/azalia_device.h> + +const u32 cim_verb_data[] = { +`) + + for _, codec := range ctx.InfoSource.GetAzaliaCodecs() { + fmt.Fprintf(az, "\t0x%08x, /* Codec Vendor / Device ID: %s */\n", + codec.VendorID, codec.Name) + fmt.Fprintf(az, "\t0x%08x, /* Subsystem ID */\n", + codec.SubsystemID) + fmt.Fprintf(az, "\n\t0x%08x, /* Number of 4 dword sets */\n", + len(codec.PinConfig)+1) + fmt.Fprintf(az, "\t/* NID 0x01: Subsystem ID. */\n") + fmt.Fprintf(az, "\tAZALIA_SUBVENDOR(0x%x, 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, "\n\t/* NID 0x%02x. */\n", nid) + fmt.Fprintf(az, "\tAZALIA_PIN_CFG(0x%x, 0x%02x, 0x%08x),\n", + codec.CodecNo, nid, codec.PinConfig[nid]) + } + } + + az.WriteString( + `}; + +const u32 pc_beep_verbs[0] = {}; + +AZALIA_ARRAY_SIZES; +`) + + PutPCIDev(addr, "Audio controller") +} + +func init() { + /* I82801GX/I945 */ + RegisterPCI(0x8086, 0x27d8, azalia{}) + /* C216/ivybridge */ + RegisterPCI(0x8086, 0x1e20, azalia{}) +} diff --git a/util/autoport/bd82x6x.go b/util/autoport/bd82x6x.go new file mode 100644 index 0000000..8354ce0 --- /dev/null +++ b/util/autoport/bd82x6x.go @@ -0,0 +1,368 @@ +package main + +import ( + "fmt" + "os" +) + +type bd82x6x struct { + variant string +} + +func (b bd82x6x) writeGPIOSet(ctx Context, sb *os.File, + val uint32, set uint, partno int) { + + 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++ { + fmt.Fprintf(sb, " .gpio%d = %s,\n", + (set-1)*32+i, + bits[partno][(val>>i)&1]) + } +} + +func (b bd82x6x) GPIO(ctx Context, inteltool InteltoolData) { + gpio := Create(ctx, "gpio.c") + defer gpio.Close() + + AddROMStageFile("gpio.c", "") + + gpio.WriteString(`#include "southbridge/intel/bd82x6x/gpio.h" +`) + + adresses := [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 := adresses[set-1][partno] + if addr < 0 { + continue + } + fmt.Fprintf(gpio, "const struct pch_gpio_set%d pch_gpio_set%d_%s = {\n", + set, set, part) + + b.writeGPIOSet(ctx, gpio, inteltool.GPIO[uint16(addr)], uint(set), partno) + gpio.WriteString("};\n\n") + } + } + + gpio.WriteString(`static 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, + }, +}; +`) +} + +func (b bd82x6x) 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 << 2 + if flkb > highflkb { + highflkb = flkb + } + } + ROMSizeKB = int(highflkb) + /* Shared with ME. Flashrom is unable to handle it. */ + FlashROMSupport = "n" + } +} + +func (b bd82x6x) Scan(ctx Context, addr PCIDevData) { + inteltool := ctx.InfoSource.GetInteltool() + b.GPIO(ctx, inteltool) + + KconfigBool["SOUTHBRIDGE_INTEL_"+b.variant] = true + KconfigBool["SERIRQ_CONTINUOUS_MODE"] = true + KconfigComment["SERIRQ_CONTINUOUS_MODE"] = "FIXME: check this" + KconfigInt["USBDEBUG_HCD_INDEX"] = 2 + KconfigComment["USBDEBUG_HCD_INDEX"] = "FIXME: check this" + KconfigInt["DRAM_RESET_GATE_GPIO"] = 10 + KconfigComment["DRAM_RESET_GATE_GPIO"] = "FIXME: check this" + + /* Not strictly speaking correct. These subsys/subvendor referer to PCI devices. + But most systems don't have any of those. But the config needs to be set + nevertheless. So set it to southbridge subsys/subvendor. */ + KconfigHex["MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID"] = uint32(GetLE16(addr.ConfigDump[0x2c:0x2e])) + KconfigHex["MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID"] = uint32(GetLE16(addr.ConfigDump[0x2e:0x30])) + + ich9GetFlashSize(ctx) + + FADT := ctx.InfoSource.GetACPI()["FACP"] + + pcieHotplugMap := "{ " + + for port := 0; port < 7; port++ { + if b.IsPCIeHotplug(ctx, port) { + pcieHotplugMap += "1, " + } else { + pcieHotplugMap += "0, " + } + } + + if b.IsPCIeHotplug(ctx, 7) { + pcieHotplugMap += "1 }" + } else { + pcieHotplugMap += "0 }" + } + + cur := DevTreeNode{ + Chip: "southbridge/intel/bd82x6x", + Comment: "Intel Series 6 Cougar Point PCH, FIXME: set gpiX_routing and alt_gp_smi_en for EC support", + + 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), + + "p_cnt_throttling_supported": (FormatBool(FADT[104] == 1 && FADT[105] == 3)), + "c2_latency": FormatHexLE16(FADT[96:98]), + "docking_supported": (FormatBool((FADT[113] & (1 << 1)) != 0)), + }, + PCISlots: []PCISlot{ + PCISlot{PCIAddr: PCIAddr{Dev: 0x14, Func: 0}, writeEmpty: false, additionalComment: "USB 3.0 Controller"}, + 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: 0x19, Func: 0}, writeEmpty: true, additionalComment: "Intel Gigabit Ethernet"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1a, Func: 0}, writeEmpty: true, 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: true, additionalComment: "PCIe Port #7"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 7}, writeEmpty: true, additionalComment: "PCIe Port #8"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 0}, writeEmpty: true, additionalComment: "USB2 EHCI #1"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1e, Func: 0}, writeEmpty: true, additionalComment: "PCI bridge"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 0}, writeEmpty: true, additionalComment: "LPC bridge"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 2}, writeEmpty: true, additionalComment: "SATA Controller 1"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 3}, writeEmpty: true, additionalComment: "SMBus"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 5}, writeEmpty: true, additionalComment: "SATA Controller 2"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 6}, writeEmpty: true, additionalComment: "Thermal"}, + }, + } + + 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, "PCI-LPC bridge", "lpc") + + DSDTIncludes = append(DSDTIncludes, DSDTInclude{ + File: "southbridge/intel/bd82x6x/acpi/platform.asl", + }) + DSDTIncludes = append(DSDTIncludes, DSDTInclude{ + File: "southbridge/intel/bd82x6x/acpi/globalnvs.asl", + Comment: "global NVS and variables", + }) + DSDTIncludes = append(DSDTIncludes, DSDTInclude{ + File: "southbridge/intel/bd82x6x/acpi/sleepstates.asl", + }) + DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{ + File: "southbridge/intel/bd82x6x/acpi/pch.asl", + }) + + sb := Create(ctx, "early_southbridge.c") + defer sb.Close() + AddROMStageFile("early_southbridge.c", "") + sb.WriteString(`#include <stdint.h> +#include <string.h> +#include <lib.h> +#include <timestamp.h> +#include <arch/byteorder.h> +#include <arch/io.h> +#include <device/pci_def.h> +#include <device/pnp_def.h> +#include <cpu/x86/lapic.h> +#include <arch/acpi.h> +#include <console/console.h> +#include "northbridge/intel/sandybridge/sandybridge.h" +#include "northbridge/intel/sandybridge/raminit_native.h" +#include "southbridge/intel/bd82x6x/pch.h" +#include "southbridge/intel/bd82x6x/gpio.h" +#include <arch/cpu.h> +#include <cpu/x86/msr.h> + +void pch_enable_lpc(void) +{ +`) + RestorePCI16Simple(sb, addr, 0x82) + RestorePCI32Simple(sb, addr, 0x84) + RestorePCI32Simple(sb, addr, 0x88) + RestorePCI32Simple(sb, addr, 0x8c) + RestorePCI32Simple(sb, addr, 0x90) + + RestorePCI16Simple(sb, addr, 0x80) + + RestorePCI32Simple(sb, addr, 0xac) + + sb.WriteString(`} + +void rcba_config(void) +{ + /* Disable devices. */ +`) + RestoreRCBA32(sb, inteltool, 0x3414) + RestoreRCBA32(sb, inteltool, 0x3418) + + sb.WriteString("\n}\n") + + 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, + } + + 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 + } + } + } + fmt.Fprintf(sb, "\t{ %d, %d, %d },\n", + ((inteltool.RCBA[0x359c]>>port)&1)^1, + currentMap[inteltool.RCBA[uint16(0x3500+4*port)]], + OCPin) + } + sb.WriteString("};\n") + + sb.WriteString(` +/* FIXME: Put proper SPD map here. */ +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); +} +`) + + gnvs := Create(ctx, "gnvs.c") + defer gnvs.Close() + + gnvs.WriteString(`#include <southbridge/intel/bd82x6x/nvs.h> + +/* FIXME: check this function. */ +void acpi_create_gnvs(global_nvs_t *gnvs) +{ + /* Disable USB ports in S3 by default */ + gnvs->s3u0 = 0; + gnvs->s3u1 = 0; + + /* Disable USB ports in S5 by default */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + // the lid is open by default. + gnvs->lids = 1; + + gnvs->tcrt = 100; + gnvs->tpsv = 90; +} +`) + + AddRAMStageFile("gnvs.c", "") +} + +func init() { + RegisterPCI(0x8086, 0x1e49, bd82x6x{variant: "C216"}) + RegisterPCI(0x8086, 0x1e55, bd82x6x{variant: "C216"}) + RegisterPCI(0x8086, 0x1e56, bd82x6x{variant: "C216"}) + RegisterPCI(0x8086, 0x1e57, bd82x6x{variant: "C216"}) + RegisterPCI(0x8086, 0x1e5c, bd82x6x{variant: "C216"}) + RegisterPCI(0x8086, 0x1e5d, bd82x6x{variant: "C216"}) + RegisterPCI(0x8086, 0x1e5e, bd82x6x{variant: "C216"}) + RegisterPCI(0x8086, 0x1e5f, bd82x6x{variant: "C216"}) + RegisterPCI(0x8086, 0x1e31, GenericPCI{}) + RegisterPCI(0x8086, 0x1e26, GenericPCI{}) + RegisterPCI(0x8086, 0x1e2d, GenericPCI{}) + RegisterPCI(0x8086, 0x1e3a, GenericPCI{}) + RegisterPCI(0x8086, 0x1502, GenericPCI{}) + RegisterPCI(0x8086, 0x1e10, GenericPCI{}) + RegisterPCI(0x8086, 0x1e12, GenericPCI{}) + RegisterPCI(0x8086, 0x1e14, GenericPCI{}) + RegisterPCI(0x8086, 0x1e16, GenericPCI{}) + RegisterPCI(0x8086, 0x1e18, GenericPCI{}) + RegisterPCI(0x8086, 0x1e1a, GenericPCI{}) + RegisterPCI(0x8086, 0x1e1c, GenericPCI{}) + RegisterPCI(0x8086, 0x1e1e, GenericPCI{}) + RegisterPCI(0x8086, 0x1e03, GenericPCI{}) + RegisterPCI(0x8086, 0x1e22, GenericPCI{MissingParent: "smbus"}) +} diff --git a/util/autoport/i82801gx.go b/util/autoport/i82801gx.go new file mode 100644 index 0000000..4ffeb6a --- /dev/null +++ b/util/autoport/i82801gx.go @@ -0,0 +1,531 @@ +package main + +import ( + "fmt" + "os" +) + +type i82801gx struct { +} + +func (i i82801gx) writeGPIO(ctx Context, sb *os.File, inteltool InteltoolData, addr uint16, name string) { + fmt.Fprintf(sb, " outl(0x%08x, DEFAULT_GPIOBASE + %s);\n", + inteltool.GPIO[addr], name) +} + +func (i i82801gx) Scan(ctx Context, addr PCIDevData) { + + KconfigBool["HAVE_MP_TABLE"] = true + KconfigBool["SOUTHBRIDGE_INTEL_I82801GX"] = true + + sb := Create(ctx, "early_southbridge.c") + defer sb.Close() + AddROMStageFile("early_southbridge.c", "") + sb.WriteString(`#include <stdint.h> +#include <arch/io.h> +#include <device/pci_def.h> +#include <console/console.h> +#include "northbridge/intel/i945/i945.h" +#include "northbridge/intel/i945/raminit.h" +#include "southbridge/intel/i82801gx/i82801gx.h" + +/* FIXME: Put proper SPD map here. */ +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); +} + +void setup_ich7_gpios(void) +{ + printk(BIOS_DEBUG, " GPIOS..."); + +`) + inteltool := ctx.InfoSource.GetInteltool() + i.writeGPIO(ctx, sb, inteltool, 0x0, "GPIO_USE_SEL") + i.writeGPIO(ctx, sb, inteltool, 0x4, "GP_IO_SEL") + i.writeGPIO(ctx, sb, inteltool, 0xc, "GP_LVL") + i.writeGPIO(ctx, sb, inteltool, 0x18, "GPO_BLINK") + i.writeGPIO(ctx, sb, inteltool, 0x2c, "GPI_INV") + i.writeGPIO(ctx, sb, inteltool, 0x30, "GPIO_USE_SEL2") + i.writeGPIO(ctx, sb, inteltool, 0x34, "GP_IO_SEL2") + i.writeGPIO(ctx, sb, inteltool, 0x38, "GP_LVL2") + + sb.WriteString(`} + +void ich7_enable_lpc(void) +{ + // Enable Serial IRQ + pci_write_config8(PCI_DEV(0, 0x1f, 0), 0x64, 0xd0); + + // Enable address decodes +`) + + RestorePCI16Simple(sb, addr, 0x80) + RestorePCI16Simple(sb, addr, 0x82) + RestorePCI16Simple(sb, addr, 0x84) + RestorePCI16Simple(sb, addr, 0x86) + RestorePCI16Simple(sb, addr, 0x88) + RestorePCI16Simple(sb, addr, 0x8a) + RestorePCI16Simple(sb, addr, 0x8c) + RestorePCI16Simple(sb, addr, 0x8e) + RestorePCI16Simple(sb, addr, 0x90) + RestorePCI16Simple(sb, addr, 0x92) + + /* Just use the same interrupt map for all boards: just registers have to match ACPI. */ + sb.WriteString(`} + +void rcba_config(void) +{ + /* V0CTL Virtual Channel 0 Resource Control */ + RCBA32(0x0014) = 0x80000001; + /* V1CAP Virtual Channel 1 Resource Capability */ + RCBA32(0x001c) = 0x03128010; + + /* Disable devices. */ +`) + + RestoreRCBA32(sb, inteltool, 0x3418) + + sb.WriteString(` + /* Set up I/O Trap #3 for 0x800-0x80c (Trap) */ + RCBA32(0x1e9c) = 0x000200f0; + RCBA32(0x1e98) = 0x000c0801; +} +`) + + /* FIXME:XX does this one need adjustments? */ + sb.WriteString(`void early_ich7_init(void) +{ + uint8_t reg8; + uint32_t reg32; + + // program secondary mlt XXX byte? + pci_write_config8(PCI_DEV(0, 0x1e, 0), 0x1b, 0x20); + + // reset rtc power status + reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4); + reg8 &= ~(1 << 2); + pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8); + + // usb transient disconnect + reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xad); + reg8 |= (3 << 0); + pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xad, reg8); + + reg32 = pci_read_config32(PCI_DEV(0, 0x1d, 7), 0xfc); + reg32 |= (1 << 29) | (1 << 17); + pci_write_config32(PCI_DEV(0, 0x1d, 7), 0xfc, reg32); + + reg32 = pci_read_config32(PCI_DEV(0, 0x1d, 7), 0xdc); + reg32 |= (1 << 31) | (1 << 27); + pci_write_config32(PCI_DEV(0, 0x1d, 7), 0xdc, reg32); + + RCBA32(0x0088) = 0x0011d000; + RCBA16(0x01fc) = 0x060f; + RCBA32(0x01f4) = 0x86000040; + RCBA32(0x0214) = 0x10030549; + RCBA32(0x0218) = 0x00020504; + RCBA8(0x0220) = 0xc5; + reg32 = RCBA32(0x3410); + reg32 |= (1 << 6); + RCBA32(0x3410) = reg32; + reg32 = RCBA32(0x3430); + reg32 &= ~(3 << 0); + reg32 |= (1 << 0); + RCBA32(0x3430) = reg32; + RCBA32(0x3418) |= (1 << 0); + RCBA16(0x0200) = 0x2008; + RCBA8(0x2027) = 0x0d; + RCBA16(0x3e08) |= (1 << 7); + RCBA16(0x3e48) |= (1 << 7); + RCBA32(0x3e0e) |= (1 << 7); + RCBA32(0x3e4e) |= (1 << 7); + + // next step only on ich7m b0 and later: + reg32 = RCBA32(0x2034); + reg32 &= ~(0x0f << 16); + reg32 |= (5 << 16); + RCBA32(0x2034) = reg32; +} +`) + + ioapic := DevTreeNode{ + Chip: "drivers/generic/ioapic", + Registers: map[string]string{ + /* FIXME:XX hardcoded. */ + "have_isa_interrupts": "1", + "irq_on_fsb": "1", + "enable_virtual_wire": "0", + "base": "0xfec00000", + }, + Children: []DevTreeNode{ + { + Chip: "ioapic", + Dev: 2, + }, + }, + } + + PutPCIChip(addr, ioapic) + + ideConfig := uint8(0) + ide, ok := PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 1}] + if ok { + ideConfig = ide.ConfigDump[0x54] + } + + FADT := ctx.InfoSource.GetACPI()["FACP"] + + cur := DevTreeNode{ + Chip: "southbridge/intel/i82801gx", + Comment: "Southbridge, FIXME: set gpiX_routing, gpe0_en and alt_gp_smi_en for EC support", + MissingParent: "southbridge", + Registers: map[string]string{ + /* FIXME:XX should be a CMOS config */ + "sata_ahci": "0x1", + + "sata_ports_implemented": fmt.Sprintf("0x%x", PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 2}].ConfigDump[0x92]&0xf), + "ide_enable_primary": fmt.Sprintf("%d", (ideConfig>>1)&1), + "ide_enable_secondary": fmt.Sprintf("%d", (ideConfig>>3)&1), + "c4onc3_enable": fmt.Sprintf("%d", ((addr.ConfigDump[0xa0] >> 7) & 1)), + "p_cnt_throttling_supported": (FormatBool(FADT[104] == 1 && FADT[105] == 3)), + "c3_latency": FormatHexLE16(FADT[98:100]), + "docking_supported": (FormatBool((FADT[113] & (1 << 1)) != 0)), + }, + PCISlots: []PCISlot{ + 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: true, additionalComment: "PCIe Port #7"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 7}, writeEmpty: true, additionalComment: "PCIe Port #8"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 0}, writeEmpty: true, additionalComment: "USB UHCI"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 1}, writeEmpty: true, additionalComment: "USB UHCI"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 2}, writeEmpty: true, additionalComment: "USB UHCI"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 3}, writeEmpty: true, additionalComment: "USB UHCI"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 7}, writeEmpty: true, additionalComment: "USB EHCI"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1e, Func: 0}, writeEmpty: true, additionalComment: "PCI bridge"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 0}, writeEmpty: true, additionalComment: "LPC bridge"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 1}, writeEmpty: true, additionalComment: "IDE Controller"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 2}, writeEmpty: true, additionalComment: "SATA Controller"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 3}, writeEmpty: true, additionalComment: "SMBus"}, + }, + } + + PutPCIChip(addr, cur) + PutPCIDevParent(addr, "PCI-LPC bridge", "lpc") + + IOAPICIRQs[PCIAddr{Bus: 0, Dev: 0x00}] = IOAPICIRQ{APICID: 2, IRQNO: [4]int{0x10, 0, 0, 0}} + IOAPICIRQs[PCIAddr{Bus: 0, Dev: 0x07}] = IOAPICIRQ{APICID: 2, IRQNO: [4]int{0x10, 0, 0, 0}} + IOAPICIRQs[PCIAddr{Bus: 0, Dev: 0x1b}] = IOAPICIRQ{APICID: 2, IRQNO: [4]int{0x16, 0, 0, 0}} + IOAPICIRQs[PCIAddr{Bus: 0, Dev: 0x1c}] = IOAPICIRQ{APICID: 2, IRQNO: [4]int{0x11, 0x10, 0x12, 0x13}} + IOAPICIRQs[PCIAddr{Bus: 0, Dev: 0x1d}] = IOAPICIRQ{APICID: 2, IRQNO: [4]int{0x17, 0x13, 0x12, 0x10}} + IOAPICIRQs[PCIAddr{Bus: 0, Dev: 0x1e}] = IOAPICIRQ{APICID: 2, IRQNO: [4]int{0x16, 0x14, 0, 0}} + IOAPICIRQs[PCIAddr{Bus: 0, Dev: 0x1f}] = IOAPICIRQ{APICID: 2, IRQNO: [4]int{0x12, 0x13, 0, 0x10}} + + DSDTIncludes = append(DSDTIncludes, DSDTInclude{ + File: "southbridge/intel/i82801gx/acpi/globalnvs.asl", + Comment: "global NVS and variables", + }) + DSDTIncludes = append(DSDTIncludes, DSDTInclude{ + File: "southbridge/intel/i82801gx/acpi/platform.asl", + }) + DSDTIncludes = append(DSDTIncludes, DSDTInclude{ + File: "southbridge/intel/i82801gx/acpi/sleepstates.asl", + }) + DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{ + File: "southbridge/intel/i82801gx/acpi/ich7.asl", + }) + + ai := Create(ctx, "acpi/ich7_pci_irqs.asl") + defer ai.Close() + + /* FIXME:XX hardcoded. */ + ai.WriteString( + `/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +/* This is board specific information: IRQ routing for the + * 0:1e.0 PCI bridge of the ICH7 + */ + +If (PICM) { + Return (Package() { + Package (0x04) { 0x0000FFFF, 0x00, 0x00, 0x15 }, + Package (0x04) { 0x0000FFFF, 0x01, 0x00, 0x16 }, + Package (0x04) { 0x0000FFFF, 0x02, 0x00, 0x17 }, + Package (0x04) { 0x0000FFFF, 0x03, 0x00, 0x14 }, + Package (0x04) { 0x0001FFFF, 0x00, 0x00, 0x16 }, + Package (0x04) { 0x0001FFFF, 0x01, 0x00, 0x15 }, + Package (0x04) { 0x0001FFFF, 0x02, 0x00, 0x14 }, + Package (0x04) { 0x0001FFFF, 0x03, 0x00, 0x17 }, + Package (0x04) { 0x0002FFFF, 0x00, 0x00, 0x12 }, + Package (0x04) { 0x0002FFFF, 0x01, 0x00, 0x13 }, + Package (0x04) { 0x0002FFFF, 0x02, 0x00, 0x11 }, + Package (0x04) { 0x0002FFFF, 0x03, 0x00, 0x10 }, + Package (0x04) { 0x0003FFFF, 0x00, 0x00, 0x13 }, + Package (0x04) { 0x0003FFFF, 0x01, 0x00, 0x12 }, + Package (0x04) { 0x0003FFFF, 0x02, 0x00, 0x15 }, + Package (0x04) { 0x0003FFFF, 0x03, 0x00, 0x16 }, + Package (0x04) { 0x0005FFFF, 0x00, 0x00, 0x11 }, + Package (0x04) { 0x0005FFFF, 0x01, 0x00, 0x14 }, + Package (0x04) { 0x0005FFFF, 0x02, 0x00, 0x16 }, + Package (0x04) { 0x0005FFFF, 0x03, 0x00, 0x15 }, + Package (0x04) { 0x0008FFFF, 0x00, 0x00, 0x14 } + }) + } Else { + Return (Package() { + Package (0x04) { 0x0000FFFF, 0x00, _SB.PCI0.LPCB.LNKF, 0x00 }, + Package (0x04) { 0x0000FFFF, 0x01, _SB.PCI0.LPCB.LNKG, 0x00 }, + Package (0x04) { 0x0000FFFF, 0x02, _SB.PCI0.LPCB.LNKH, 0x00 }, + Package (0x04) { 0x0000FFFF, 0x03, _SB.PCI0.LPCB.LNKE, 0x00 }, + Package (0x04) { 0x0001FFFF, 0x00, _SB.PCI0.LPCB.LNKG, 0x00 }, + Package (0x04) { 0x0001FFFF, 0x01, _SB.PCI0.LPCB.LNKF, 0x00 }, + Package (0x04) { 0x0001FFFF, 0x02, _SB.PCI0.LPCB.LNKE, 0x00 }, + Package (0x04) { 0x0001FFFF, 0x03, _SB.PCI0.LPCB.LNKH, 0x00 }, + Package (0x04) { 0x0002FFFF, 0x00, _SB.PCI0.LPCB.LNKC, 0x00 }, + Package (0x04) { 0x0002FFFF, 0x01, _SB.PCI0.LPCB.LNKD, 0x00 }, + Package (0x04) { 0x0002FFFF, 0x02, _SB.PCI0.LPCB.LNKB, 0x00 }, + Package (0x04) { 0x0002FFFF, 0x03, _SB.PCI0.LPCB.LNKA, 0x00 }, + Package (0x04) { 0x0003FFFF, 0x00, _SB.PCI0.LPCB.LNKD, 0x00 }, + Package (0x04) { 0x0003FFFF, 0x01, _SB.PCI0.LPCB.LNKC, 0x00 }, + Package (0x04) { 0x0003FFFF, 0x02, _SB.PCI0.LPCB.LNKF, 0x00 }, + Package (0x04) { 0x0003FFFF, 0x03, _SB.PCI0.LPCB.LNKG, 0x00 }, + Package (0x04) { 0x0005FFFF, 0x00, _SB.PCI0.LPCB.LNKB, 0x00 }, + Package (0x04) { 0x0005FFFF, 0x01, _SB.PCI0.LPCB.LNKE, 0x00 }, + Package (0x04) { 0x0005FFFF, 0x02, _SB.PCI0.LPCB.LNKG, 0x00 }, + Package (0x04) { 0x0005FFFF, 0x03, _SB.PCI0.LPCB.LNKF, 0x00 }, + Package (0x04) { 0x0008FFFF, 0x00, _SB.PCI0.LPCB.LNKE, 0x00 } + }) +} +`) + + ec := Create(ctx, "acpi/ec.asl") + defer ec.Close() + ec.WriteString("/* FIXME: Add EC support here. */") + + at := Create(ctx, "acpi_tables.c") + defer at.Close() + + at.WriteString( + `#include <stdint.h> +#include "southbridge/intel/i82801gx/nvs.h" + +/* FIXME: check this function. */ +void acpi_create_gnvs(global_nvs_t *gnvs) +{ + /* Enable both COM ports */ + gnvs->cmap = 0x01; + gnvs->cmbp = 0x01; +} +`) + + si := Create(ctx, "acpi/superio.asl") + defer si.Close() + si.WriteString("/* FIXME: Add superio support here. */") + + ap := Create(ctx, "acpi/platform.asl") + defer ap.Close() + + /* FIXME:XX hardcoded. */ + ap.WriteString( + `Method(_WAK,1) +{ + Return(Package(){0,0}) +} + +Scope(_SB) +{ + Method(_INI, 0) + { + \GOS() + } +} +`) + + + + sh := Create(ctx, "smihandler.c") + defer sh.Close() + + /* FIXME:XX hardcoded. */ + sh.WriteString( + ` +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <arch/io.h> +#include <console/console.h> +#include <cpu/x86/smm.h> +#include "southbridge/intel/i82801gx/nvs.h" +#include "southbridge/intel/i82801gx/i82801gx.h" +#include <pc80/mc146818rtc.h> +#include <delay.h> + +static void mainboard_smm_init(void) +{ + printk(BIOS_DEBUG, "initializing SMI\n"); +} + +int mainboard_io_trap_handler(int smif) +{ + static int smm_initialized; + + if (!smm_initialized) { + mainboard_smm_init(); + smm_initialized = 1; + } + + switch (smif) { + default: + return 0; + } + + /* On success, the IO Trap Handler returns 1 + * On failure, the IO Trap Handler returns a value != 1 */ + return 1; +} + +int mainboard_smi_apmc(u8 data) +{ + u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc; + + printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase, data); + + if (!pmbase) + return 0; + + switch(data) { + case APM_CNT_ACPI_ENABLE: + /* FIXME: Add EC support here */ + break; + case APM_CNT_ACPI_DISABLE: + /* FIXME: Add EC support here */ + break; + default: + break; + } + return 0; +} +`) + mb := Create(ctx, "mainboard.c") + defer mb.Close() + + /* FIXME:XX hardcoded. */ + mb.WriteString( + `/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 Sven Schnelle svens@stackframe.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <console/console.h> +#include <device/device.h> +#include <arch/io.h> +#include <delay.h> +#include <device/pci_def.h> +#include <device/pci_ops.h> +#include <device/pci_ids.h> +#include <arch/io.h> +#include <arch/interrupt.h> +#include <northbridge/intel/i945/i945.h> +#include <pc80/mc146818rtc.h> +#include <arch/x86/include/arch/acpigen.h> +#include <smbios.h> +#include <drivers/intel/gma/int15.h> + +static void mainboard_init(device_t dev) +{ + install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, GMA_INT15_PANEL_FIT_DEFAULT, INT15_5F35_CL_DISPLAY_DEFAULT, 3); +} + +static void mainboard_enable(device_t dev) +{ + dev->ops->init = mainboard_init; +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable, +}; +`) + +} + +func init() { + RegisterPCI(0x8086, 0x27b9, i82801gx{}) + RegisterPCI(0x8086, 0x27c8, GenericPCI{}) + RegisterPCI(0x8086, 0x27c9, GenericPCI{}) + RegisterPCI(0x8086, 0x27ca, GenericPCI{}) + RegisterPCI(0x8086, 0x27cb, GenericPCI{}) + RegisterPCI(0x8086, 0x27cc, GenericPCI{}) + + RegisterPCI(0x8086, 0x27d0, GenericPCI{}) + RegisterPCI(0x8086, 0x27d2, GenericPCI{}) + RegisterPCI(0x8086, 0x27d4, GenericPCI{}) + RegisterPCI(0x8086, 0x27d6, GenericPCI{}) + + RegisterPCI(0x8086, 0x2448, GenericPCI{}) + + RegisterPCI(0x8086, 0x27c5, GenericPCI{}) + RegisterPCI(0x8086, 0x27c4, GenericPCI{}) + RegisterPCI(0x8086, 0x27df, GenericPCI{}) + RegisterPCI(0x8086, 0x27da, GenericPCI{MissingParent: "smbus"}) +} diff --git a/util/autoport/i945.go b/util/autoport/i945.go new file mode 100644 index 0000000..9a29002 --- /dev/null +++ b/util/autoport/i945.go @@ -0,0 +1,120 @@ +package main + +import ( + "log" + "strings" +) + +type i945mc struct { + variant string +} + +func (i i945mc) Scan(ctx Context, addr PCIDevData) { + + cpuModel := ctx.InfoSource.GetCPUModel()[0] + socket := "" + switch cpuModel >> 4 { + case 0x69, 0x6d, 0x6e, 0x6f: + socket = "mFCPGA478" + case 0x106c: + socket = "441" + default: + log.Fatalf("unsupported cpu: 0x%x", cpuModel) + } + DevTree = DevTreeNode{ + Chip: "northbridge/intel/i945", + MissingParent: "northbridge", + Registers: map[string]string{ + /* FIXME:XX hardcoded. */ + "gpu_hotplug": "0x00000220", + "gpu_lvds_use_spread_spectrum_clock": "1", + "gpu_lvds_is_dual_channel": "0", + "gpu_backlight": "0x1280128", + "gfx.ndid": "3", + "gfx.did": "{ 0x80000100, 0x80000240, 0x80000410, 0x80000410, 0x00000005 }", + }, + Children: []DevTreeNode{ + { + Chip: "cpu_cluster", + Dev: 0, + Children: []DevTreeNode{ + { + Chip: "cpu/intel/socket_" + socket, + Children: []DevTreeNode{ + { + Chip: "lapic", + Dev: 0, + }, + }, + }, + }, + }, + { + Chip: "domain", + Dev: 0, + PCIController: true, + ChildPCIBus: 0, + PCISlots: []PCISlot{ + PCISlot{PCIAddr: PCIAddr{Dev: 0x0, Func: 0}, writeEmpty: true, additionalComment: "Host bridge"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x2, Func: 0}, writeEmpty: true, additionalComment: "VGA"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x2, Func: 1}, writeEmpty: true, additionalComment: "Display controller"}, + }, + }, + }, + } + PutPCIDev(addr, "Host bridge") + + /* FIXME:XX Move part to northbridge? */ + /* FIXME:XX some configs are unsupported. */ + KconfigBool["MAINBOARD_HAS_NATIVE_VGA_INIT"] = true + KconfigBool["MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG"] = true + KconfigBool["VGA"] = true + KconfigBool["MAINBOARD_DO_EDID"] = true + KconfigBool["EARLY_CBMEM_INIT"] = true + KconfigBool["INTEL_EDID"] = true + KconfigBool["CPU_INTEL_SOCKET_"+strings.ToUpper(socket)] = true + KconfigBool["NORTHBRIDGE_INTEL_I945"] = true + KconfigBool["CHANNEL_XOR_RANDOMIZATION"] = true + KconfigBool["INTEL_INT15"] = true + KconfigBool["HAVE_ACPI_TABLES"] = true + KconfigBool["HAVE_ACPI_RESUME"] = true + + KconfigHex["DCACHE_RAM_BASE"] = 0xffdf8000 + KconfigHex["DCACHE_RAM_SIZE"] = 0x8000 + KconfigHex["MMCONF_BASE_ADDRESS"] = 0xf0000000 + KconfigInt["MAX_CPUS"] = 2 + + DSDTIncludes = append(DSDTIncludes, DSDTInclude{ + File: "cpu/intel/model_6dx/acpi/cpu.asl", + }) + + DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{ + File: "northbridge/intel/i945/acpi/i945.asl", + }) + + KconfigBool["NORTHBRIDGE_INTEL_SUBTYPE_" + i.variant] = true + + cs := Create(ctx, "cstates.c") + defer cs.Close() + AddRAMStageFile("cstates.c", "") + + cs.WriteString( + `#include <arch/acpigen.h> +#include <device/device.h> +#include <northbridge/intel/i945/i945.h> + +/* FIXME: fill this. */ +int get_cst_entries(acpi_cstate_t **entries) +{ + return 0; +} +`) +} + +func init() { + RegisterPCI(0x8086, 0x27a0, i945mc{variant:"I945GM"}) + RegisterPCI(0x8086, 0x27ac, i945mc{variant:"I945GM"}) + RegisterPCI(0x8086, 0x27a2, GenericVGA{GenericPCI{Comment: "VGA controller"}}) + RegisterPCI(0x8086, 0x27ae, GenericVGA{GenericPCI{Comment: "VGA controller"}}) + RegisterPCI(0x8086, 0x27a6, GenericPCI{Comment: "display controller"}) +} diff --git a/util/autoport/log_maker.go b/util/autoport/log_maker.go new file mode 100644 index 0000000..8db428d --- /dev/null +++ b/util/autoport/log_maker.go @@ -0,0 +1,85 @@ +package main + +import ( + "io" + "io/ioutil" + "log" + "os" + "os/exec" + "strings" +) + +func RunAndSave(output string, name string, arg ...string) { + 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 { + log.Fatal(err) + } + cmd.Wait() +} + +func MakeLogs(outDir string) { + os.MkdirAll(outDir, 0700) + RunAndSave(outDir+"/lspci.log", "lspci", "-nnvvvxxxx") + RunAndSave(outDir+"/dmidecode.log", "dmidecode") + RunAndSave(outDir+"/acpidump.log", "acpidump") + /* FIXME:XX */ + RunAndSave(outDir+"/inteltool.log", "../inteltool/inteltool", "-a") + + SysDir := "/sys/class/sound/card0/" + 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/card0/" + 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) + } + } + + in, err := os.Open("/proc/cpuinfo") + defer in.Close() + if err != nil { + log.Fatal(err) + } + out, err := os.Create(outDir + "/cpuinfo.log") + if err != nil { + log.Fatal(err) + } + defer out.Close() + io.Copy(out, in) +} diff --git a/util/autoport/log_reader.go b/util/autoport/log_reader.go new file mode 100644 index 0000000..2fcfbd1 --- /dev/null +++ b/util/autoport/log_reader.go @@ -0,0 +1,319 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "log" + "os" + "strconv" + "strings" +) + +type LogDevReader struct { + InputDirectory string + ACPITables map[string][]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) 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() + switch { + case len(line) >= 6 && line[5] == '@': + curTable = line[0:4] + Tables[curTable] = make([]byte, 0, 100000) + case len(line) > 7 && line[0:2] == " " && isXDigit(line[2]) && isXDigit(line[3]) && isXDigit(line[4]) && isXDigit(line[5]) && line[6] == ':': + 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.IGD = map[uint32]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) > 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 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, "============="): + 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) { + 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_hwC0D" + 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) 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 +} + +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} +} diff --git a/util/autoport/main.go b/util/autoport/main.go new file mode 100644 index 0000000..be28b66 --- /dev/null +++ b/util/autoport/main.go @@ -0,0 +1,682 @@ +/* This is just an experiment. Full automatic porting + is probably not possible but a lot can be automated. */ +package main + +import ( + "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 + IGD map[uint32]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 +} + +var ROMStageFiles map[string]string = map[string]string{} +var RAMStageFiles map[string]string = map[string]string{} + +type Context struct { + MoboID string + KconfigName string + Vendor string + Model string + BaseDirectory string + InfoSource DevReader +} + +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 KconfigStringUnquoted 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 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) + for strings.HasSuffix(result, ".") { + result = result[0 : len(result)-1] + } + return result +} + +func AddROMStageFile(Name string, Condition string) { + ROMStageFiles[Name] = Condition +} + +func AddRAMStageFile(Name string, Condition string) { + RAMStageFiles[Name] = Condition +} + +var FlagOutDir = flag.String("coreboot_dir", ".", "Resulting coreboot directory") + +func writeMF(mf *os.File, files map[string]string, category string) { + for file, condition := range files { + 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 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_config16(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 + additionalComment string + writeEmpty bool +} + +type DevTreeNode struct { + Bus int + Dev int + Func int + Disabled bool + Registers map[string]string + Children []DevTreeNode + PCISlots []PCISlot + PCIController bool + ChildPCIBus int + MissingParent string + SubVendor uint16 + SubSystem uint16 + Chip 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, 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": + fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func) + 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.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) + } + + for _, child := range dev.Children { + WriteDev(dt, offset+1, 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 +} + +var DSDTIncludes []DSDTInclude +var DSDTPCI0Includes []DSDTInclude + +func (g GenericPCI) Scan(ctx Context, addr PCIDevData) { + PutPCIDevParent(addr, g.Comment, g.MissingParent) +} + +func (g GenericVGA) Scan(ctx Context, addr PCIDevData) { + KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x", + addr.PCIVenID, + addr.PCIDevID) + KconfigString["VGA_BIOS_FILE"] = fmt.Sprintf("pci%04x,%04x.rom", + addr.PCIVenID, + addr.PCIDevID) + PutPCIDevParent(addr, g.Comment, g.MissingParent) +} + +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 # dummy\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 KconfigStringUnquoted { + keys = append(keys, name) + } + + sort.Strings(keys) + + for _, name := range keys { + fmt.Fprintf(kc, ` +config %s%s + string + default %s +`, name, makeComment(name), KconfigStringUnquoted[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") +} + +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.MoboID = sanitize(ctx.Vendor) + "/" + sanitize(ctx.Model) + ctx.KconfigName = "BOARD_" + strings.ToUpper(sanitize(ctx.Vendor)+"_"+sanitize(ctx.Model)) + ctx.BaseDirectory = *FlagOutDir + "/src/mainboard/" + ctx.MoboID + KconfigStringUnquoted["MAINBOARD_DIR"] = ctx.MoboID + KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model + + os.MkdirAll(ctx.BaseDirectory, 0700) + + ScanRoot(ctx) + + if len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 { + mf := Create(ctx, "Makefile.inc") + defer mf.Close() + writeMF(mf, ROMStageFiles, "romstage") + writeMF(mf, RAMStageFiles, "ramstage") + } + + devtree := Create(ctx, "devicetree.cb") + defer devtree.Close() + + MatchDev(&DevTree) + WriteDev(devtree, 0, DevTree) + + 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: 2012" + + if fixme != "" { + fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing) + } else { + fmt.Fprintf(bi, "FIXME: put %s\n", missing) + } + + rs := Create(ctx, "romstage.c") + defer rs.Close() + rs.WriteString("/* dummy file */\n") + + 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() + + dsdt.WriteString( + `DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x03, // DSDT revision: ACPI v3.0 + "COREv4", // OEM id + "COREBOOT", // OEM table id + 0x20141018 // OEM revision +) +{ + // Some generic macros + #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(` + Scope (_SB) { + Device (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( + ` } + } +} +`) + +} diff --git a/util/autoport/rce823.go b/util/autoport/rce823.go new file mode 100644 index 0000000..7c92109 --- /dev/null +++ b/util/autoport/rce823.go @@ -0,0 +1,39 @@ +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{}) +} diff --git a/util/autoport/root.go b/util/autoport/root.go new file mode 100644 index 0000000..60b5ccd --- /dev/null +++ b/util/autoport/root.go @@ -0,0 +1,29 @@ +package main + +import "fmt" + +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 { + 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) + } +} + +func RegisterPCI(VenID uint16, DevID uint16, dev PCIDevice) { + vendevid := (uint32(DevID) << 16) | uint32(VenID) + supportedPCIDevices[vendevid] = dev +} diff --git a/util/autoport/sandybridge.go b/util/autoport/sandybridge.go new file mode 100644 index 0000000..5b1149c --- /dev/null +++ b/util/autoport/sandybridge.go @@ -0,0 +1,142 @@ +package main + +type sandybridgemc struct { + variant string +} + +func (i sandybridgemc) Scan(ctx Context, addr PCIDevData) { + inteltool := ctx.InfoSource.GetInteltool() + pchLVDS := inteltool.IGD[0xe1180] + dualChannel := pchLVDS & (3 << 2) == (3 << 2) + pipe := (pchLVDS >> 30) & 1 + data_m1 := inteltool.IGD[0x60030 + 0x1000 * pipe] & 0xffffff + data_n1 := inteltool.IGD[0x60034 + 0x1000 * pipe] + link_m1 := inteltool.IGD[0x60040 + 0x1000 * pipe] + link_n1 := inteltool.IGD[0x60044 + 0x1000 * pipe] + data_factor := float32(data_m1) / float32(data_n1) + link_factor := float32(link_m1) / float32(link_n1) + num_lanes := uint32((link_factor / data_factor) * 18.0 / 8.0 + 0.5) + fp0 := inteltool.IGD[0xc6040 + 8 * pipe] + dpll := inteltool.IGD[0xc6014 + 4 * pipe] + pixel_m2 := fp0 & 0xff + pixel_m1 := (fp0 >> 8) & 0xff + 2 + pixel_p1 := uint32(1) + for i := dpll & 0x1ffff; i != 0 && i & 1 == 0; i >>= 1 { + pixel_p1++ + } + pixel_n := ((fp0 >> 16) & 0xff) + 2 + pixel_frequency := float32(120000 * (5 * pixel_m1 + pixel_m2)) / float32(pixel_n * pixel_p1 * 7.0) + if !dualChannel { + pixel_frequency /= 2 + } + link_frequency := pixel_frequency / link_factor + DevTree = DevTreeNode{ + Chip: "northbridge/intel/sandybridge", + MissingParent: "northbridge", + 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.use_spread_spectrum_clock": FormatBool((inteltool.IGD[0xc6200] >> 12) & 1 != 0), + "gfx.lvds_dual_channel": FormatBool(dualChannel), + "gfx.lvds_num_lanes": FormatInt32(num_lanes), + "gfx.link_frequency_270_mhz": FormatBool(link_frequency > 200000), + /* FIXME:XX hardcoded. */ + "gfx.ndid": "3", + "gfx.did": "{ 0x80000100, 0x80000240, 0x80000410, 0x80000410, 0x00000005 }", + }, + Children: []DevTreeNode{ + { + Chip: "cpu_cluster", + Dev: 0, + Children: []DevTreeNode{ + { + Chip: "cpu/intel/socket_rPGA989", + Children: []DevTreeNode{ + { + Chip: "lapic", + Dev: 0, + }, + }, + }, + + { + Chip: "cpu/intel/model_206ax", + Registers: map[string]string{ + /* FIXME:XX hardcoded. */ + "pstate_coord_type": "0xfe", + "c1_acpower": "1", + "c2_acpower": "3", + "c3_acpower": "5", + "c1_battery": "1", + "c2_battery": "3", + "c3_battery": "5", + }, + Children: []DevTreeNode{ + { + Chip: "lapic", + Dev: 0xacac, + Disabled: true, + }, + }, + }, + }, + }, + + { + Chip: "domain", + Dev: 0, + PCIController: true, + ChildPCIBus: 0, + PCISlots: []PCISlot{ + PCISlot{PCIAddr: PCIAddr{Dev: 0x0, Func: 0}, writeEmpty: true, additionalComment: "Host bridge"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x1, Func: 0}, writeEmpty: true, additionalComment: "PCIe Bridge for discrete graphics"}, + PCISlot{PCIAddr: PCIAddr{Dev: 0x2, Func: 0}, writeEmpty: true, additionalComment: "Internal graphics"}, + }, + }, + }, + } + + PutPCIDev(addr, "Host bridge") + + /* FIXME:XX Move part to northbridge? */ + /* FIXME:XX some configs are unsupported. */ + KconfigBool["MAINBOARD_HAS_NATIVE_VGA_INIT"] = true + KconfigBool["MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG"] = true + KconfigBool[i.variant+"BRIDGE_LVDS"] = true + + KconfigBool["VGA"] = true + KconfigBool["INTEL_EDID"] = true + KconfigBool["CPU_INTEL_SOCKET_RPGA989"] = true + KconfigBool["NORTHBRIDGE_INTEL_"+i.variant+"BRIDGE_NATIVE"] = true + KconfigBool["INTEL_INT15"] = true + KconfigBool["HAVE_ACPI_TABLES"] = true + KconfigBool["HAVE_ACPI_RESUME"] = true + + KconfigBool["HAVE_IFD_BIN"] = false + KconfigBool["HAVE_ME_BIN"] = false + + KconfigHex["MMCONF_BASE_ADDRESS"] = 0xf0000000 + KconfigInt["MAX_CPUS"] = 8 + + DSDTIncludes = append(DSDTIncludes, DSDTInclude{ + File: "cpu/intel/model_206ax/acpi/cpu.asl", + }) + + DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{ + File: "northbridge/intel/sandybridge/acpi/sandybridge.asl", + }) +} + +func init() { + RegisterPCI(0x8086, 0x0154, sandybridgemc{variant: "IVY"}) + RegisterPCI(0x8086, 0x0166, GenericVGA{GenericPCI{Comment: "VGA controller"}}) +}