the following patch was just integrated into master:
commit cd920bf1c07b35d497e4f16656cfcebe45aaf132
Author: Sergej Ivanov <getinaks(a)gmail.com>
Date: Tue Dec 1 18:53:54 2015 +0300
mainboard/biostar/am1ml: Force basic SPI read mode
This patch force AGESA to use basic SPI read mode.
Without it board hangs during spi configure if W25Q32 chip is used.
Change-Id: I3e17cd21702626be5061d2fc14adc0c22f167efb
Signed-off-by: Sergej Ivanov <getinaks(a)gmail.com>
Reviewed-on: https://review.coreboot.org/12580
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth(a)google.com>
See https://review.coreboot.org/12580 for details.
-gerrit
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12641
-gerrit
commit 34cff1861590d87ee177db73384e2f345a838e0a
Author: Patrick Georgi <patrick(a)georgi-clan.de>
Date: Fri Dec 4 16:52:18 2015 +0100
build system: add dependencies for GRUB2 and FILO
Make sure the build system knows how to start building the various
integrated payloads we support.
Change-Id: I2128d09c78795e0a41b055975e9f7052e3d951ee
Signed-off-by: Patrick Georgi <patrick(a)georgi-clan.de>
---
payloads/external/Makefile.inc | 3 +++
1 file changed, 3 insertions(+)
diff --git a/payloads/external/Makefile.inc b/payloads/external/Makefile.inc
index bfc24f1..344cbec 100644
--- a/payloads/external/Makefile.inc
+++ b/payloads/external/Makefile.inc
@@ -67,6 +67,7 @@ filo:
CONFIG_FILO_MASTER=$(CONFIG_FILO_MASTER) \
CONFIG_FILO_STABLE=$(CONFIG_FILO_STABLE)
+payloads/external/FILO/filo/build/filo.elf: filo
grub2:
$(MAKE) -C payloads/external/GRUB2 -f Makefile.inc \
@@ -74,3 +75,5 @@ grub2:
CC="$(CC_x86_32)" LD="$(LD_x86_32)" OBJDUMP="$(OBJDUMP_x86_32)" \
OBJCOPY="$(OBJCOPY_x86_32)" STRIP="$(STRIP_x86_32)" \
CONFIG_GRUB2_MASTER=$(CONFIG_GRUB2_MASTER)
+
+payloads/external/GRUB2/grub2/build/default_payload.elf: grub2
Michael Tasche (michael.tasche(a)esd.eu) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12632
-gerrit
commit e31a6754fa979f22521a2fd2f2fbab7ceb1ef454
Author: Michael Tasche <michael.tasche(a)esd.eu>
Date: Thu Dec 3 17:07:01 2015 +0100
esd/atom15: import esd atom15 board
This patch adds esd atom15 board with
Intel Atom E3815 SoC.
Change-Id: I430a40ad8ab3316d34ec5567329370f69db3f15e
Signed-off-by: Michael Tasche <michael.tasche(a)esd.eu>
---
src/mainboard/esd/Kconfig | 16 ++
src/mainboard/esd/Kconfig.name | 2 +
src/mainboard/esd/atom15/Kconfig | 70 +++++++++
src/mainboard/esd/atom15/Kconfig.name | 2 +
src/mainboard/esd/atom15/Makefile.inc | 17 ++
src/mainboard/esd/atom15/acpi/ec.asl | 0
src/mainboard/esd/atom15/acpi/mainboard.asl | 20 +++
src/mainboard/esd/atom15/acpi/superio.asl | 0
src/mainboard/esd/atom15/acpi_tables.c | 56 +++++++
src/mainboard/esd/atom15/board_info.txt | 4 +
src/mainboard/esd/atom15/cmos.layout | 116 ++++++++++++++
src/mainboard/esd/atom15/devicetree.cb | 93 +++++++++++
src/mainboard/esd/atom15/dsdt.asl | 53 +++++++
src/mainboard/esd/atom15/fadt.c | 32 ++++
src/mainboard/esd/atom15/gpio.c | 231 ++++++++++++++++++++++++++++
src/mainboard/esd/atom15/irqroute.c | 18 +++
src/mainboard/esd/atom15/irqroute.h | 82 ++++++++++
src/mainboard/esd/atom15/mainboard.c | 41 +++++
src/mainboard/esd/atom15/romstage.c | 78 ++++++++++
19 files changed, 931 insertions(+)
diff --git a/src/mainboard/esd/Kconfig b/src/mainboard/esd/Kconfig
new file mode 100644
index 0000000..3b9eb58
--- /dev/null
+++ b/src/mainboard/esd/Kconfig
@@ -0,0 +1,16 @@
+if VENDOR_ESD
+
+choice
+ prompt "Mainboard model"
+
+source "src/mainboard/esd/*/Kconfig.name"
+
+endchoice
+
+source "src/mainboard/esd/*/Kconfig"
+
+config MAINBOARD_VENDOR
+ string
+ default "esd"
+
+endif # VENDOR_ESD
diff --git a/src/mainboard/esd/Kconfig.name b/src/mainboard/esd/Kconfig.name
new file mode 100644
index 0000000..a44d854
--- /dev/null
+++ b/src/mainboard/esd/Kconfig.name
@@ -0,0 +1,2 @@
+config VENDOR_ESD
+ bool "electronic system design"
diff --git a/src/mainboard/esd/atom15/Kconfig b/src/mainboard/esd/atom15/Kconfig
new file mode 100644
index 0000000..3f4b76b
--- /dev/null
+++ b/src/mainboard/esd/atom15/Kconfig
@@ -0,0 +1,70 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+## Copyright (C) 2014 Intel Corporation
+##
+## 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.
+##
+
+if BOARD_ESD_ATOM15
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select SOC_INTEL_FSP_BAYTRAIL
+ select BOARD_ROMSIZE_KB_8192
+ select HAVE_ACPI_TABLES
+ select HAVE_OPTION_TABLE
+ select TSC_MONOTONIC_TIMER
+ select HAVE_ACPI_RESUME
+
+config MAINBOARD_DIR
+ string
+ default "esd/atom15"
+
+config MAINBOARD_PART_NUMBER
+ string
+ default "esd atom15"
+
+config MAX_CPUS
+ int
+ default 16
+
+config CACHE_ROM_SIZE_OVERRIDE
+ hex
+ default 0x800000
+
+config FSP_FILE
+ string
+ default "../intel/fsp/baytrail/BAYTRAIL_FSP.fd"
+
+config CBFS_SIZE
+ hex
+ default 0x00300000
+
+config ENABLE_FSP_FAST_BOOT
+ bool
+ depends on HAVE_FSP_BIN
+ default y
+
+config VIRTUAL_ROM_SIZE
+ hex
+ depends on ENABLE_FSP_FAST_BOOT
+ default 0x800000
+
+config POST_DEVICE
+ bool
+ default n
+
+config VGA_BIOS
+ bool
+ default y if FSP_PACKAGE_DEFAULT
+
+endif # BOARD_ESD_ATOM15
diff --git a/src/mainboard/esd/atom15/Kconfig.name b/src/mainboard/esd/atom15/Kconfig.name
new file mode 100644
index 0000000..cab7e86
--- /dev/null
+++ b/src/mainboard/esd/atom15/Kconfig.name
@@ -0,0 +1,2 @@
+config BOARD_ESD_ATOM15
+ bool "Atom15"
diff --git a/src/mainboard/esd/atom15/Makefile.inc b/src/mainboard/esd/atom15/Makefile.inc
new file mode 100644
index 0000000..3074df2
--- /dev/null
+++ b/src/mainboard/esd/atom15/Makefile.inc
@@ -0,0 +1,17 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 Google Inc.
+##
+## 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.
+##
+
+ramstage-y += gpio.c
+ramstage-y += irqroute.c
diff --git a/src/mainboard/esd/atom15/acpi/ec.asl b/src/mainboard/esd/atom15/acpi/ec.asl
new file mode 100644
index 0000000..e69de29
diff --git a/src/mainboard/esd/atom15/acpi/mainboard.asl b/src/mainboard/esd/atom15/acpi/mainboard.asl
new file mode 100644
index 0000000..b032ee1
--- /dev/null
+++ b/src/mainboard/esd/atom15/acpi/mainboard.asl
@@ -0,0 +1,20 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Google Inc.
+ *
+ * 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.
+ */
+
+Device (PWRB)
+{
+ Name(_HID, EisaId("PNP0C0C"))
+}
diff --git a/src/mainboard/esd/atom15/acpi/superio.asl b/src/mainboard/esd/atom15/acpi/superio.asl
new file mode 100644
index 0000000..e69de29
diff --git a/src/mainboard/esd/atom15/acpi_tables.c b/src/mainboard/esd/atom15/acpi_tables.c
new file mode 100644
index 0000000..48991f5
--- /dev/null
+++ b/src/mainboard/esd/atom15/acpi_tables.c
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ */
+
+#include <types.h>
+#include <string.h>
+#include <cbmem.h>
+#include <lib.h> // hexdump
+#include <console/console.h>
+#include <arch/acpi.h>
+#include <arch/ioapic.h>
+#include <arch/acpigen.h>
+#include <arch/smp/mpspec.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/msr.h>
+#include <baytrail/acpi.h>
+#include <baytrail/nvs.h>
+#include <baytrail/iomap.h>
+
+void acpi_create_gnvs(global_nvs_t *gnvs)
+{
+ acpi_init_gnvs(gnvs);
+
+ /* No TPM Present */
+ gnvs->tpmp = 0;
+
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+ /* Local APICs */
+ current = acpi_create_madt_lapics(current);
+
+ /* IOAPIC */
+ current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
+ 2, IO_APIC_ADDR, 0);
+
+ current = acpi_madt_irq_overrides(current);
+
+ return current;
+}
diff --git a/src/mainboard/esd/atom15/board_info.txt b/src/mainboard/esd/atom15/board_info.txt
new file mode 100644
index 0000000..b5099b3
--- /dev/null
+++ b/src/mainboard/esd/atom15/board_info.txt
@@ -0,0 +1,4 @@
+Category: sbc
+ROM protocol: SPI
+Flashrom support: y
+Release year: 2015
diff --git a/src/mainboard/esd/atom15/cmos.layout b/src/mainboard/esd/atom15/cmos.layout
new file mode 100644
index 0000000..8aaa522
--- /dev/null
+++ b/src/mainboard/esd/atom15/cmos.layout
@@ -0,0 +1,116 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2008 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.
+##
+
+# -----------------------------------------------------------------
+entries
+
+# -----------------------------------------------------------------
+# Status Register A
+# -----------------------------------------------------------------
+# Status Register B
+# -----------------------------------------------------------------
+# Status Register C
+#96 4 r 0 status_c_rsvd
+#100 1 r 0 uf_flag
+#101 1 r 0 af_flag
+#102 1 r 0 pf_flag
+#103 1 r 0 irqf_flag
+# -----------------------------------------------------------------
+# Status Register D
+#104 7 r 0 status_d_rsvd
+#111 1 r 0 valid_cmos_ram
+# -----------------------------------------------------------------
+# Diagnostic Status Register
+#112 8 r 0 diag_rsvd1
+
+# -----------------------------------------------------------------
+0 120 r 0 reserved_memory
+#120 264 r 0 unused
+
+# -----------------------------------------------------------------
+# RTC_BOOT_BYTE (coreboot hardcoded)
+384 1 e 4 boot_option
+388 4 r 0 reboot_bits
+#390 2 r 0 unused?
+
+# -----------------------------------------------------------------
+# coreboot config options: console
+392 3 e 5 baud_rate
+395 4 e 6 debug_level
+#399 1 r 0 unused
+
+# coreboot config options: cpu
+400 1 e 2 hyper_threading
+#401 7 r 0 unused
+
+# coreboot config options: southbridge
+408 1 e 1 nmi
+409 2 e 7 power_on_after_fail
+411 2 e 8 use_xhci_over_ehci
+#413 3 r 0 unused
+
+# MRC Scrambler Seed values
+896 32 r 0 mrc_scrambler_seed
+928 32 r 0 mrc_scrambler_seed_s3
+
+# coreboot config options: check sums
+984 16 h 0 check_sum
+#1000 24 r 0 amd_reserved
+
+#save timestamps in pre-ram boot areas
+1719 64 h 0 timestamp_value1
+1783 64 h 0 timestamp_value2
+1847 64 h 0 timestamp_value3
+1911 64 h 0 timestamp_value4
+1975 64 h 0 timestamp_value5
+
+# -----------------------------------------------------------------
+
+enumerations
+
+#ID value text
+1 0 Disable
+1 1 Enable
+2 0 Enable
+2 1 Disable
+4 0 Fallback
+4 1 Normal
+5 0 115200
+5 1 57600
+5 2 38400
+5 3 19200
+5 4 9600
+5 5 4800
+5 6 2400
+5 7 1200
+6 1 Emergency
+6 2 Alert
+6 3 Critical
+6 4 Error
+6 5 Warning
+6 6 Notice
+6 7 Info
+6 8 Debug
+6 9 Spew
+7 0 Disable
+7 1 Enable
+7 2 Keep
+8 0 EHCI
+8 1 XHCI
+8 2 Default
+# -----------------------------------------------------------------
+checksums
+
+checksum 392 415 984
diff --git a/src/mainboard/esd/atom15/devicetree.cb b/src/mainboard/esd/atom15/devicetree.cb
new file mode 100644
index 0000000..769a687
--- /dev/null
+++ b/src/mainboard/esd/atom15/devicetree.cb
@@ -0,0 +1,93 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+## Copyright (C) 2014 Intel Corporation
+##
+## 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.
+##
+
+chip soc/intel/fsp_baytrail
+
+ #### ACPI Register Settings ####
+ register "fadt_pm_profile" = "PM_UNSPECIFIED"
+ register "fadt_boot_arch" = "ACPI_FADT_LEGACY_FREE"
+
+ #### FSP register settings ####
+ register "PcdSataMode" = "SATA_MODE_AHCI"
+ register "PcdMrcInitSPDAddr1" = "SPD_ADDR_DEFAULT"
+ register "PcdMrcInitSPDAddr2" = "SPD_ADDR_DEFAULT"
+ register "PcdMrcInitMmioSize" = "MMIO_SIZE_DEFAULT"
+ register "PcdeMMCBootMode" = "EMMC_FOLLOWS_DEVICETREE"
+ register "PcdIgdDvmt50PreAlloc" = "IGD_MEMSIZE_DEFAULT"
+ register "PcdApertureSize" = "APERTURE_SIZE_DEFAULT"
+ register "PcdGttSize" = "GTT_SIZE_DEFAULT"
+ register "PcdLpssSioEnablePciMode" = "LPSS_PCI_MODE_DEFAULT"
+ register "AzaliaAutoEnable" = "AZALIA_FOLLOWS_DEVICETREE"
+ register "LpeAcpiModeEnable" = "LPE_ACPI_MODE_DISABLED"
+ register "IgdRenderStandby" = "IGD_RENDER_STANDBY_ENABLE"
+ register "EnableMemoryDown" = "MEMORY_DOWN_ENABLE"
+ register "DRAMSpeed" = "DRAM_SPEED_1066MHZ"
+ register "DRAMType" = "DRAM_TYPE_DDR3L"
+ register "DIMM0Enable" = "DIMM0_ENABLE"
+ register "DIMM1Enable" = "DIMM1_DISABLE"
+ register "DIMMDWidth" = "DIMM_DWIDTH_X16"
+ register "DIMMDensity" = "DIMM_DENSITY_4G_BIT"
+ register "DIMMBusWidth" = "DIMM_BUS_WIDTH_64BIT"
+ register "DIMMSides" = "DIMM_SIDES_1RANK"
+ register "DIMMtCL" = "8"
+ register "DIMMtRPtRCD" = "8"
+ register "DIMMtWR" = "8"
+ register "DIMMtWTR" = "4"
+ register "DIMMtRRD" = "6"
+ register "DIMMtRTP" = "4"
+ register "DIMMtFAW" = "27"
+
+ device cpu_cluster 0 on
+ device lapic 0 on end
+ end
+
+ device domain 0 on
+ device pci 00.0 on end # 8086 0F00 - SoC router -
+ device pci 02.0 off end # 8086 0F31 - GFX -
+ device pci 03.0 off end # 8086 0F38 - MIPI -
+
+ device pci 10.0 off end # 8086 0F14 - EMMC Port -
+ device pci 11.0 off end # 8086 0F15 - SDIO Port -
+ device pci 12.0 on end # 8086 0F16 - SD Port MicroSD on SD3
+ device pci 13.0 off end # 8086 0F23 - SATA AHCI -
+ device pci 14.0 off end # 8086 0F35 - USB XHCI -
+ device pci 15.0 off end # 8086 0F28 - LP Engine Audio -
+ device pci 17.0 off end # 8086 0F50 - MMC Port -
+ device pci 18.0 on end # 8086 0F40 - SIO - DMA -
+ device pci 18.1 on end # 8086 0F41 - I2C Port 1 (0) -
+ device pci 18.2 on end # 8086 0F42 - I2C Port 2 (1) -
+ device pci 18.3 on end # 8086 0F43 - I2C Port 3 (2) -
+ device pci 18.4 on end # 8086 0F44 - I2C Port 4 (3) -
+ device pci 18.5 on end # 8086 0F45 - I2C Port 5 (4) -
+ device pci 18.6 on end # 8086 0F46 - I2C Port 6 (5) EEPROM
+ device pci 18.7 off end # 8086 0F47 - I2C Port 7 (6) -
+ device pci 1a.0 off end # 8086 0F18 - TXE -
+ device pci 1b.0 off end # 8086 0F04 - HD Audio -
+ device pci 1c.0 on end # 8086 0F48 - PCIe Port 1 (0) -
+ device pci 1c.1 off end # 8086 0F4A - PCIe Port 2 (1) -
+ device pci 1c.2 on end # 8086 0F4C - PCIe Port 3 (2) ETHERNET
+ device pci 1c.3 on end # 8086 0F4E - PCIe Port 4 (3) CAN
+ device pci 1d.0 on end # 8086 0F34 - USB EHCI - Enabling EHCI -
+ device pci 1e.0 on end # 8086 0F06 - SIO - DMA -
+ device pci 1e.1 on end # 8086 0F08 - PWM 1 -
+ device pci 1e.2 on end # 8086 0F09 - PWM 2 -
+ device pci 1e.3 on end # 8086 0F0A - HSUART 1 Alternate uart
+ device pci 1e.4 off end # 8086 0F0C - HSUART 2 -
+ device pci 1e.5 off end # 8086 0F0E - SPI -
+ device pci 1f.0 on end # 8086 0F1C - LPC bridge No connector
+ device pci 1f.3 on end # 8086 0F12 - SMBus 0 SPC
+ end
+end
diff --git a/src/mainboard/esd/atom15/dsdt.asl b/src/mainboard/esd/atom15/dsdt.asl
new file mode 100644
index 0000000..63b9d03
--- /dev/null
+++ b/src/mainboard/esd/atom15/dsdt.asl
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 Google Inc.
+ * Copyright (C) 2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ */
+
+#define INCLUDE_LPE 1
+#define INCLUDE_SCC 1
+#define INCLUDE_EHCI 1
+#define INCLUDE_XHCI 1
+#define INCLUDE_LPSS 1
+
+
+DefinitionBlock(
+ "dsdt.aml",
+ "DSDT",
+ 0x02, // DSDT revision: ACPI v2.0
+ "COREv4", // OEM id
+ "COREBOOT", // OEM table id
+ 0x20110725 // OEM revision
+)
+{
+ // Some generic macros
+ #include <soc/intel/fsp_baytrail/acpi/platform.asl>
+
+ // global NVS and variables
+ #include <soc/intel/fsp_baytrail/acpi/globalnvs.asl>
+
+ #include <soc/intel/fsp_baytrail/acpi/cpu.asl>
+
+ Scope (\_SB) {
+ Device (PCI0)
+ {
+ #include <soc/intel/fsp_baytrail/acpi/southcluster.asl>
+ }
+ }
+
+ /* Chipset specific sleep states */
+ #include <soc/intel/fsp_baytrail/acpi/sleepstates.asl>
+
+ #include "acpi/mainboard.asl"
+}
diff --git a/src/mainboard/esd/atom15/fadt.c b/src/mainboard/esd/atom15/fadt.c
new file mode 100644
index 0000000..38b9bfd
--- /dev/null
+++ b/src/mainboard/esd/atom15/fadt.c
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ */
+
+#include <arch/acpi.h>
+#include <baytrail/acpi.h>
+
+void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
+{
+ acpi_header_t *header = &(fadt->header);
+
+ acpi_fill_in_fadt(fadt,facs,dsdt);
+
+ /* Platform specific customizations go here */
+
+ header->checksum = 0;
+ header->checksum =
+ acpi_checksum((void *) fadt, sizeof(acpi_fadt_t));
+
+}
diff --git a/src/mainboard/esd/atom15/gpio.c b/src/mainboard/esd/atom15/gpio.c
new file mode 100644
index 0000000..f617de4
--- /dev/null
+++ b/src/mainboard/esd/atom15/gpio.c
@@ -0,0 +1,231 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <baytrail/gpio.h>
+#include "irqroute.h"
+
+/*
+ * For multiplexed functions, look in EDS:
+ * 10.3 Ball Name and Function by Location
+ *
+ * The pads list is in the BWG_VOL2 Rev1p2:
+ * Note that Pad # is not the same as GPIO#
+ * 37 GPIO Handling:
+ * Table 37-1. SCORE Pads List
+ * Table 37-2. SSUSORE Pads List
+ */
+
+/* NCORE GPIOs */
+static const struct soc_gpio_map gpncore_gpio_map[] = {
+ GPIO_FUNC2, /* GPIO_S0_NC[00] - HDMI_HPD */
+ GPIO_FUNC2, /* GPIO_S0_NC[01] - HDMI_DDCDAT */
+ GPIO_FUNC2, /* GPIO_S0_NC[02] - HDMI_DDCCLK */
+ GPIO_NC, /* GPIO_S0_NC[03] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[04] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[05] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[06] - No Connect */
+ GPIO_FUNC2, /* GPIO_S0_NC[07] - DDI1_DDCDAT */
+ GPIO_NC, /* GPIO_S0_NC[08] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[09] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[10] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[11] - No Connect */
+ GPIO_FUNC(0, PULL_UP, 20K), /* GPIO_S0_NC[12] - TP15 */
+ GPIO_NC, /* GPIO_S0_NC[13] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[14] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[15] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[16] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[17] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[18] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[19] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[20] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[21] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[22] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[23] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[24] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[25] - No Connect */
+ GPIO_NC, /* GPIO_S0_NC[26] - No Connect */
+ GPIO_END
+};
+
+/* SCORE GPIOs (GPIO_S0_SC_XX)*/
+static const struct soc_gpio_map gpscore_gpio_map[] = {
+ GPIO_FUNC1, /* GPIO_S0_SC[000] - SATA_GP0 */
+ GPIO_FUNC1, /* GPIO_S0_SC[001] - SATA_GP1 */
+ GPIO_FUNC1, /* GPIO_S0_SC[002] - SATA_LED_B */
+ GPIO_FUNC1, /* GPIO_S0_SC[003] - PCIE_CLKREQ_0 */
+ GPIO_FUNC1, /* GPIO_S0_SC[004] - PCIE_CLKREQ_1 */
+ GPIO_FUNC1, /* GPIO_S0_SC[005] - PCIE_CLKREQ_2 */
+ GPIO_FUNC1, /* GPIO_S0_SC[006] - PCIE_CLKREQ_3 */
+ GPIO_FUNC2, /* GPIO_S0_SC[007] - SD3_WP */
+ GPIO_NC, /* GPIO_S0_SC[008] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[009] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[010] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[011] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[012] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[013] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[014] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[015] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[016] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[017] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[018] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[019] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[020] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[021] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[022] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[023] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[024] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[025] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[026] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[027] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[028] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[029] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[030] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[031] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[032] - No Connect */
+ GPIO_FUNC1, /* GPIO_S0_SC[033] - SD3_CLK */
+ GPIO_FUNC1, /* GPIO_S0_SC[034] - SD3_D0 */
+ GPIO_FUNC1, /* GPIO_S0_SC[035] - SD3_D1 */
+ GPIO_FUNC1, /* GPIO_S0_SC[036] - SD3_D2 */
+ GPIO_FUNC1, /* GPIO_S0_SC[037] - SD3_D3 */
+ GPIO_FUNC1, /* GPIO_S0_SC[038] - SD3_CD# */
+ GPIO_FUNC1, /* GPIO_S0_SC[039] - SD3_CMD */
+ GPIO_FUNC1, /* GPIO_S0_SC[040] - No Connect */
+ GPIO_FUNC1, /* GPIO_S0_SC[041] - /SD3_PWREN */
+ GPIO_NC, /* GPIO_S0_SC[042] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[043] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[044] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[045] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[046] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[047] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[048] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[049] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[050] - No Connect */
+ GPIO_FUNC1, /* GPIO_S0_SC[051] - PCU_SMB_DATA */
+ GPIO_FUNC1, /* GPIO_S0_SC[052] - PCU_SMB_CLK */
+ GPIO_FUNC1, /* GPIO_S0_SC[053] - PCU_SMB_ALERT */
+ GPIO_FUNC1, /* GPIO_S0_SC[054] - ILB_8254_SPKR */
+ GPIO_NC, /* GPIO_S0_SC[055] - No Connect */
+ GPIO_FUNC0, /* GPIO_S0_SC[056] - GPIO_S0_SC_56 */
+ GPIO_FUNC1, /* GPIO_S0_SC[057] - PCU_UART3_TXD */
+ GPIO_NC, /* GPIO_S0_SC[058] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[059] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[060] - No Connect */
+ GPIO_FUNC1, /* GPIO_S0_SC[061] - PCU_UART3_RXD */
+ GPIO_FUNC1, /* GPIO_S0_SC[062] - LPE_I2S_CLK */
+ GPIO_FUNC1, /* GPIO_S0_SC[063] - LPE_I2S_FRM */
+ GPIO_FUNC1, /* GPIO_S0_SC[064] - LPE_I2S_DATIN */
+ GPIO_FUNC1, /* GPIO_S0_SC[065] - LPE_I2S_DATOUT */
+ GPIO_FUNC1, /* GPIO_S0_SC[066] - SOC_SIO_SPI_CS1 */
+ GPIO_FUNC1, /* GPIO_S0_SC[067] - SOC_SIO_SPI_MISO */
+ GPIO_FUNC1, /* GPIO_S0_SC[068] - SOC_SIO_SPI_MOSI */
+ GPIO_FUNC1, /* GPIO_S0_SC[069] - SOC_SIO_SPI_CLK */
+ GPIO_FUNC1, /* GPIO_S0_SC[070] - SIO_UART1_RXD */
+ GPIO_FUNC1, /* GPIO_S0_SC[071] - SIO_UART1_TXD */
+ GPIO_NC, /* GPIO_S0_SC[072] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[073] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[074] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[075] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[076] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[077] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[078] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[079] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[080] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[081] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[082] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[083] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[084] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[085] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[086] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[087] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[088] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[089] - No Connect */
+ GPIO_FUNC1, /* GPIO_S0_SC[090] - EXP_I2C_SDA */
+ GPIO_FUNC1, /* GPIO_S0_SC[091] - EXP_I2C_SCL */
+ GPIO_FUNC1, /* GPIO_S0_SC[092] - 0R GND? */
+ GPIO_FUNC1, /* GPIO_S0_SC[093] - 0R GND? */
+ GPIO_FUNC1, /* GPIO_S0_SC[094] - SOC_PWM0 */
+ GPIO_FUNC1, /* GPIO_S0_SC[095] - SOC_PWM1 */
+ GPIO_NC, /* GPIO_S0_SC[096] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[097] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[098] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[099] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[100] - No Connect */
+ GPIO_NC, /* GPIO_S0_SC[101] - No Connect */
+ GPIO_END
+};
+
+/* SSUS GPIOs (GPIO_S5) */
+static const struct soc_gpio_map gpssus_gpio_map[] = {
+ GPIO_NC, /* GPIO_S5[00] - No Connect */
+ GPIO_FUNC6, /* GPIO_S5[01] - PMC_WAKE_PCIE[1] */
+ GPIO_FUNC6, /* GPIO_S5[02] - PMC_WAKE_PCIE[2] */
+ GPIO_FUNC6, /* GPIO_S5[03] - PMC_WAKE_PCIE[3] */
+ GPIO_NC, /* GPIO_S5[04] - No Connect */
+ GPIO_NC, /* GPIO_S5[05] - No Connect */
+ GPIO_NC, /* GPIO_S5[06] - No Connect */
+ GPIO_NC, /* GPIO_S5[07] - No Connect */
+ GPIO_NC, /* GPIO_S5[08] - No Connect */
+ GPIO_NC, /* GPIO_S5[09] - No Connect */
+ GPIO_OUT_HIGH, /* GPIO_S5[10] - GPIO_S5_10_UNLOCK */
+ GPIO_FUNC0, /* GPIO_S5[11] - SUSPWRDNACK */
+ GPIO_NC, /* GPIO_S5[12] - No Connect */
+ GPIO_NC, /* GPIO_S5[13] - No Connect */
+ GPIO_FUNC1, /* GPIO_S5[14] - GPIO_S514_J20 */
+ GPIO_FUNC0, /* GPIO_S5[15] - PMC_WAKE_PCIE[0] */
+ GPIO_FUNC(1, PULL_UP, 2K), /* GPIO_S5[16] - No Connect */
+ GPIO_NC, /* GPIO_S5[17] - No Connect */
+ GPIO_FUNC1, /* GPIO_S5[18] - T360 */
+ GPIO_FUNC0, /* GPIO_S5[19] - SOC_USB_HOST_OC0 */
+ GPIO_FUNC0, /* GPIO_S5[20] - SOC_USB_HOST_OC1 */
+ GPIO_FUNC0, /* GPIO_S5[21] - SOC_SPI_CS1B */
+ GPIO_NC, /* GPIO_S5[22] - No Connect */
+ GPIO_NC, /* GPIO_S5[23] - No Connect */
+ GPIO_NC, /* GPIO_S5[24] - No Connect */
+ GPIO_NC, /* GPIO_S5[25] - No Connect */
+ GPIO_NC, /* GPIO_S5[26] - No Connect */
+ GPIO_FUNC(0, PULL_DISABLE, 10K), /* GPIO_S5[27] - SW450-1 */
+ GPIO_FUNC(0, PULL_DISABLE, 10K), /* GPIO_S5[28] - SW450-2 */
+ GPIO_FUNC(0, PULL_DISABLE, 10K), /* GPIO_S5[29] - SW450-3 */
+ GPIO_FUNC(0, PULL_DISABLE, 10K), /* GPIO_S5[30] - SW450-4 */
+ GPIO_NC, /* GPIO_S5[31] - No Connect */
+ GPIO_NC, /* GPIO_S5[32] - No Connect */
+ GPIO_NC, /* GPIO_S5[33] - No Connect */
+ GPIO_NC, /* GPIO_S5[34] - No Connect */
+ GPIO_NC, /* GPIO_S5[35] - No Connect */
+ GPIO_NC, /* GPIO_S5[36] - No Connect */
+ GPIO_NC, /* GPIO_S5[37] - No Connect */
+ GPIO_NC, /* GPIO_S5[38] - No Connect */
+ GPIO_NC, /* GPIO_S5[39] - No Connect */
+ GPIO_NC, /* GPIO_S5[40] - No Connect */
+ GPIO_NC, /* GPIO_S5[41] - No Connect */
+ GPIO_NC, /* GPIO_S5[42] - No Connect */
+ GPIO_NC, /* GPIO_S5[43] - No Connect */
+ GPIO_END
+};
+
+static struct soc_gpio_config gpio_config = {
+ .ncore = gpncore_gpio_map,
+ .score = gpscore_gpio_map,
+ .ssus = gpssus_gpio_map,
+ .core_dirq = NULL,
+ .sus_dirq = NULL,
+};
+
+struct soc_gpio_config* mainboard_get_gpios(void)
+{
+ return &gpio_config;
+}
diff --git a/src/mainboard/esd/atom15/irqroute.c b/src/mainboard/esd/atom15/irqroute.c
new file mode 100644
index 0000000..db8c512
--- /dev/null
+++ b/src/mainboard/esd/atom15/irqroute.c
@@ -0,0 +1,18 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ *
+ * 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.
+ */
+
+#include "irqroute.h"
+
+DEFINE_IRQ_ROUTES;
diff --git a/src/mainboard/esd/atom15/irqroute.h b/src/mainboard/esd/atom15/irqroute.h
new file mode 100644
index 0000000..f866069
--- /dev/null
+++ b/src/mainboard/esd/atom15/irqroute.h
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ */
+
+#ifndef IRQROUTE_H
+#define IRQROUTE_H
+
+#include <soc/intel/fsp_baytrail/baytrail/irq.h>
+#include <soc/intel/fsp_baytrail/baytrail/pci_devs.h>
+
+/*
+ *IR02h GFX INT(A) - PIRQ A
+ *IR10h EMMC INT(ABCD) - PIRQ DEFG
+ *IR11h SDIO INT(A) - PIRQ B
+ *IR12h SD INT(A) - PIRQ C
+ *IR13h SATA INT(A) - PIRQ D
+ *IR14h XHCI INT(A) - PIRQ E
+ *IR15h LP Audio INT(A) - PIRQ F
+ *IR17h MMC INT(A) - PIRQ F
+ *IR18h SIO INT(ABCD) - PIRQ BADC
+ *IR1Ah TXE INT(A) - PIRQ F
+ *IR1Bh HD Audio INT(A) - PIRQ G
+ *IR1Ch PCIe INT(ABCD) - PIRQ EFGH
+ *IR1Dh EHCI INT(A) - PIRQ D
+ *IR1Eh SIO INT(ABCD) - PIRQ BDEF
+ *IR1Fh LPC INT(ABCD) - PIRQ HGBC
+ */
+
+/* PCIe bridge routing */
+#define BRIDGE1_DEV PCIE_DEV
+
+/* PCI bridge IRQs need to be updated in both tables and need to match */
+#define PCIE_BRIDGE_IRQ_ROUTES \
+ PCIE_BRIDGE_DEV(RP, BRIDGE1_DEV, E, F, G, H)
+
+#define PCI_DEV_PIRQ_ROUTES \
+ PCI_DEV_PIRQ_ROUTE(GFX_DEV, A, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(EMMC_DEV, D, E, F, G), \
+ PCI_DEV_PIRQ_ROUTE(SDIO_DEV, B, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(SD_DEV, C, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(SATA_DEV, D, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(XHCI_DEV, E, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(LPE_DEV, F, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(MMC45_DEV, F, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(SIO1_DEV, B, A, D, C), \
+ PCI_DEV_PIRQ_ROUTE(TXE_DEV, F, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(HDA_DEV, G, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(BRIDGE1_DEV, E, F, G, H), \
+ PCI_DEV_PIRQ_ROUTE(EHCI_DEV, D, A, A, A), \
+ PCI_DEV_PIRQ_ROUTE(SIO2_DEV, B, D, E, F), \
+ PCI_DEV_PIRQ_ROUTE(PCU_DEV, H, G, B, C)
+
+/*
+ * Route each PIRQ[A-H] to a PIC IRQ[0-15]
+ * Reserved: 0, 1, 2, 8, 13
+ * PS2 keyboard: 12
+ * ACPI/SCI: 9
+ * Floppy: 6
+ */
+#define PIRQ_PIC_ROUTES \
+ PIRQ_PIC(A, 3), \
+ PIRQ_PIC(B, 5), \
+ PIRQ_PIC(C, 7), \
+ PIRQ_PIC(D, 10), \
+ PIRQ_PIC(E, 11), \
+ PIRQ_PIC(F, 12), \
+ PIRQ_PIC(G, 14), \
+ PIRQ_PIC(H, 15)
+
+#endif /* IRQROUTE_H */
diff --git a/src/mainboard/esd/atom15/mainboard.c b/src/mainboard/esd/atom15/mainboard.c
new file mode 100644
index 0000000..70f96fc
--- /dev/null
+++ b/src/mainboard/esd/atom15/mainboard.c
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
+ * Copyright (C) 2014 Sage Electronic Engineering, LLC
+ *
+ * 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.
+ */
+
+#include <device/device.h>
+
+/*
+ * mainboard_enable is executed as first thing after enumerate_buses().
+ * This is the earliest point to add customization.
+ */
+static void mainboard_enable(device_t dev)
+{
+}
+
+/*
+ * mainboard_final is executed as one of the last items before loading the
+ * payload.
+ *
+ * This is the latest point to add customization.
+ */
+static void mainboard_final(void *chip_info)
+{
+}
+
+struct chip_operations mainboard_ops = {
+ .enable_dev = mainboard_enable,
+ .final = mainboard_final,
+};
diff --git a/src/mainboard/esd/atom15/romstage.c b/src/mainboard/esd/atom15/romstage.c
new file mode 100644
index 0000000..89fc9de
--- /dev/null
+++ b/src/mainboard/esd/atom15/romstage.c
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2013 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * 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.
+ */
+
+#include <baytrail/romstage.h>
+#include <drivers/intel/fsp1_0/fsp_util.h>
+#include <pc80/mc146818rtc.h>
+#include <console/console.h>
+#include <baytrail/gpio.h>
+#include "chip.h"
+
+/**
+ * /brief mainboard call for setup that needs to be done before fsp init
+ *
+ */
+void early_mainboard_romstage_entry()
+{
+
+}
+
+/**
+ * Get function disables - most of these will be done automatically
+ * @param fd_mask
+ * @param fd2_mask
+ */
+void get_func_disables(uint32_t *fd_mask, uint32_t *fd2_mask)
+{
+
+}
+
+/**
+ * /brief mainboard call for setup that needs to be done after fsp init
+ *
+ */
+void late_mainboard_romstage_entry()
+{
+
+ configure_ssus_gpio(27, PAD_FUNC0 | PAD_PULL_DISABLE, PAD_VAL_INPUT);
+ configure_ssus_gpio(28, PAD_FUNC0 | PAD_PULL_DISABLE, PAD_VAL_INPUT);
+ configure_ssus_gpio(29, PAD_FUNC0 | PAD_PULL_DISABLE, PAD_VAL_INPUT);
+ configure_ssus_gpio(30, PAD_FUNC0 | PAD_PULL_DISABLE, PAD_VAL_INPUT);
+
+ printk(0, "SW450: %d %d %d %d\n",
+ read_ssus_gpio(27),
+ read_ssus_gpio(28),
+ read_ssus_gpio(29),
+ read_ssus_gpio(30) );
+
+}
+
+void romstage_fsp_rt_buffer_callback(FSP_INIT_RT_BUFFER *FspRtBuffer)
+{
+ UPD_DATA_REGION *UpdData = FspRtBuffer->Common.UpdDataRgnPtr;
+ u8 use_xhci = UpdData->PcdEnableXhci;
+
+ /* Update XHCI UPD value if required */
+ get_option(&use_xhci, "use_xhci_over_ehci");
+ if ((use_xhci < 2) && (use_xhci != UpdData->PcdEnableXhci)) {
+ UpdData->PcdEnableXhci = use_xhci;
+ printk(FSP_INFO_LEVEL, "Xhci updated from CMOS:\t\t\t%s\n",
+ UpdData->PcdEnableXhci?"Enabled":"Disabled");
+ }
+
+ return;
+}
Ben Frisch (bfrisch(a)xes-inc.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12575
-gerrit
commit 577c9756918b0ef0f346c8bf4c60d49ceb9e39f1
Author: Benjamin Frisch <bfrisch(a)xes-inc.com>
Date: Mon Nov 30 12:23:31 2015 -0600
device: Resolve hang when a PCI device requests 4GB or more of MMIO space
When a PCI device's BAR requests 4GB or more MMIO space coreboot assigns the
device address 0. This results in the device overlapping DRAM and the boot
hangs with no feedback explaining the issue. Resolve this hang by first
detecting the exhaustion that available MMIO space under 4GB. Next,
selectively ignore PCI device resource requests based on the algorithm that
UEFI Firmware based on tianocore.org code does to accomplish the same.
This also meets requirements of the PCI Firmware Specification 3.1 and
Firmware Allocation of PCI Device Resources in Windows document which states
that firmware shall not allocate resources to devices that cannot fit in
available 32-bit MMIO space. Modern 64-bit Linux and 64-bit Windows since
Windows Vista will rebalance, allocate, and assign resources above the 4GB
boundry to 64-bit PCI device MMIO BARs resources as necessary as long 64-bit
MMIO space is defined in the ACPI _CRS method and the pci=realloc kernel
argument is provided in Linux.
The determination of which large 64-bit PCI MMIO resource requests to ignore
is based on how the exhaustion of available MMIO resources is handled by the
tianocore.org UEFI Firmware implemenation. If a PCI MMIO resource request
cannot be satisified, MMIO PCI resource requests of devices that are not on
bus 0 are skipped in the following order to attempt to make room to satisfy
the remaining PCI device MMIO space requests while keeping boot criticial
devices enabled:
1) Resource requests of the current PCI device with the largest 64-bit MMIO
resource request (without OPROMs)
2) Resource requests of the current PCI device with the largest 32-bit MMIO
resource request (without OPROMs)
3) Resource requests of the current PCI device with the largest MMIO
resource request (with OPROMs)
TEST=Tested on internal coreboot port based on older upstream
with device presenting 128 GB BAR with latest Linux kernel,
additional testing help and feedback is appreciated. Builds locally.
Change-Id: I0217d627ca77431075df5e24d49d6406c35893b7
Signed-off-by: Ben Frisch <bfrisch(a)xes-inc.com>
---
src/device/Kconfig | 46 ++++++++++++++++
src/device/device.c | 124 ++++++++++++++++++++++++++++++++------------
src/device/device_util.c | 109 ++++++++++++++++++++++++++++++++++++++
src/device/pci_device.c | 64 ++++++++++++++++-------
src/include/device/device.h | 4 ++
5 files changed, 295 insertions(+), 52 deletions(-)
diff --git a/src/device/Kconfig b/src/device/Kconfig
index 0113545..b9a734d 100644
--- a/src/device/Kconfig
+++ b/src/device/Kconfig
@@ -389,6 +389,52 @@ config SOFTWARE_I2C
I2C controller is not (yet) available. The platform code needs to
provide bindings to manually toggle I2C lines.
+choice SET_MAX_MEM_BAR_SIZE
+ prompt "Set Maximum memory BAR size to try to allocate "
+ optional
+ help
+ Select the maximum size PCI device memory BAR that coreboot will try
+ to allocate. If a BAR is found with a values above this size, coreboot
+ will disable the device and will not try to allocate any BARs.
+
+ If unsure, leave this disabled, and coreboot will find and disable any
+ devices that are too large to be allocated by itself. The
+ disadvantage is a slight boot time increase if a device has to be
+ disabled.
+
+config MAX_BAR_SIZE_256MB
+ bool "256 MB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 256 MB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+config MAX_BAR_SIZE_512MB
+ bool "512 MB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 512 MB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+config MAX_BAR_SIZE_1GB
+ bool "1 GB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 1 GB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+endchoice
+
+config MAX_MEM_BAR_SIZE_TO_ALLOCATE
+ hex
+ default 0x10000000 if MAX_BAR_SIZE_256MB
+ default 0x20000000 if MAX_BAR_SIZE_512MB
+ default 0x40000000 if MAX_BAR_SIZE_1GB
+ default 0
+
endmenu
menu "Display"
diff --git a/src/device/device.c b/src/device/device.c
index e23c9de..dc39dfc 100644
--- a/src/device/device.c
+++ b/src/device/device.c
@@ -690,7 +690,7 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
}
}
-static void avoid_fixed_resources(struct device *dev)
+static u8 avoid_fixed_resources(struct device *dev)
{
struct constraints limits;
struct resource *res;
@@ -743,9 +743,60 @@ static void avoid_fixed_resources(struct device *dev)
if (res->flags & IORESOURCE_MEM)
res->base = resource_max(res);
+ if (res->base < lim->base) {
+ /* This usually happens at the domain level, usually
+ * caused by a device having a BAR which is too big.
+ * Error out so we can retry.
+ */
+ printk(BIOS_WARNING,
+ "ERROR: Resource Base was lower than its limit!\n\t");
+ printk(BIOS_WARNING,
+ "%s@%02lx: base value 0x%08llx, lower limit 0x%08llx\n",
+ dev_path(dev), res->index, res->base, lim->base);
+ return 1;
+ }
+
printk(BIOS_SPEW, "%s:@%s %02lx base %08llx limit %08llx\n",
__func__, dev_path(dev), res->index, res->base, res->limit);
}
+
+ return 0;
+}
+
+static u8 avoid_all_fixed_resources(struct device *root)
+{
+ struct device *child;
+
+ /* For all domains. */
+ for (child = root->link_list->children; child; child = child->sibling) {
+ if (child->path.type == DEVICE_PATH_DOMAIN) {
+ if (avoid_fixed_resources(child)) {
+ printk(
+ BIOS_SPEW,
+ "Error trying to avoid fixed resources.");
+
+ /* Now find the device which is the largest
+ * and disable it.
+ */
+ struct device *largest = find_pci_dev_max_mem();
+
+ printk(BIOS_SPEW, "\tDisabling Device %s\n",
+ dev_path(largest));
+ if (largest)
+ largest->enabled = 0;
+
+ /* Clear out all devices on all domains, ready
+ * for re-scanning.
+ */
+ printk(BIOS_SPEW,
+ "\tClearing old resource computations.\n");
+ clear_computed_resources();
+ return 1;
+ }
+ }
+ }
+
+ return 0;
}
device_t vga_pri = 0;
@@ -1022,45 +1073,54 @@ void dev_configure(void)
root = &dev_root;
- /*
- * Each domain should create resources which contain the entire address
- * space for IO, MEM, and PREFMEM resources in the domain. The
- * allocation of device resources will be done from this address space.
- */
+ do {
+ /*
+ * Each domain should create resources which contain the entire
+ * address space for IO, MEM, and PREFMEM resources in the
+ * domain. The allocation of device resources will be done from
+ * this address space.
+ */
- /* Read the resources for the entire tree. */
+ /* Read the resources for the entire tree. */
- printk(BIOS_INFO, "Reading resources...\n");
- read_resources(root->link_list);
- printk(BIOS_INFO, "Done reading resources.\n");
+ printk(BIOS_INFO, "Reading resources...\n");
+ read_resources(root->link_list);
+ printk(BIOS_INFO, "Done reading resources.\n");
- print_resource_tree(root, BIOS_SPEW, "After reading.");
+ print_resource_tree(root, BIOS_SPEW, "After reading.");
- /* Compute resources for all domains. */
- for (child = root->link_list->children; child; child = child->sibling) {
- if (!(child->path.type == DEVICE_PATH_DOMAIN))
- continue;
- post_log_path(child);
- for (res = child->resource_list; res; res = res->next) {
- if (res->flags & IORESOURCE_FIXED)
- continue;
- if (res->flags & IORESOURCE_MEM) {
- compute_resources(child->link_list,
- res, IORESOURCE_TYPE_MASK, IORESOURCE_MEM);
- continue;
- }
- if (res->flags & IORESOURCE_IO) {
- compute_resources(child->link_list,
- res, IORESOURCE_TYPE_MASK, IORESOURCE_IO);
+ /* Compute resources for all domains. */
+ for (child = root->link_list->children;
+ child;
+ child = child->sibling) {
+ if (!(child->path.type == DEVICE_PATH_DOMAIN))
continue;
+ post_log_path(child);
+ for (res = child->resource_list; res; res = res->next) {
+ if (res->flags & IORESOURCE_FIXED)
+ continue;
+ if (res->flags & IORESOURCE_MEM) {
+ compute_resources(
+ child->link_list,
+ res,
+ IORESOURCE_TYPE_MASK,
+ IORESOURCE_MEM);
+ continue;
+ }
+ if (res->flags & IORESOURCE_IO) {
+ compute_resources(child->link_list,
+ res,
+ IORESOURCE_TYPE_MASK,
+ IORESOURCE_IO);
+ continue;
+ }
}
}
- }
- /* For all domains. */
- for (child = root->link_list->children; child; child=child->sibling)
- if (child->path.type == DEVICE_PATH_DOMAIN)
- avoid_fixed_resources(child);
+ /* Attempt to avoid all fixed resources, if this process
+ * succeeds then we can carry on, otherwise we should re-try.
+ */
+ } while (avoid_all_fixed_resources(root));
/* Store the computed resource allocations into device registers ... */
printk(BIOS_INFO, "Setting resources...\n");
diff --git a/src/device/device_util.c b/src/device/device_util.c
index ac18538..5d0ba50 100644
--- a/src/device/device_util.c
+++ b/src/device/device_util.c
@@ -921,3 +921,112 @@ int dev_count_cpu(void)
return count;
}
+
+enum allocation_passes {
+ PASS_1_CHECK_64_BIT_BARS = 0,
+ PASS_2_CHECK_32_BIT_BARS = 1,
+ PASS_3_CHECK_DEVS_WITH_OPROMS = 2,
+ MAX_PASS = PASS_3_CHECK_DEVS_WITH_OPROMS
+};
+
+/** @brief finds the enabled, non root-bus, pci device using the most memory.
+ *
+ * @return pointer to the device
+ */
+struct device *find_pci_dev_max_mem(void)
+{
+ struct device *dev;
+ struct device *largest_dev = NULL;
+ struct resource *res;
+ uint64_t memory_used = 0;
+ uint64_t most_memory_used = 0;
+ uint8_t pass;
+
+ for (pass = PASS_1_CHECK_64_BIT_BARS; pass <= MAX_PASS; pass++) {
+
+ /*
+ * Loop through all pci devices that are not on bus 0,
+ * skipping them if they're disabled, checking to see
+ * which uses the most memory.
+ */
+ for (dev = &dev_root; dev; dev = dev->next) {
+
+ /* Skip disabled, root bus, and non-pci devices */
+ if ((!(dev->path.type == DEVICE_PATH_PCI)) ||
+ (dev->bus->secondary == 0) ||
+ (dev->enabled == 0))
+ continue;
+
+ /* Total the memory used by the device */
+ memory_used = 0;
+ for (res = dev->resource_list; res; res = res->next) {
+
+ /* don't check 32-bit bars on the first pass */
+ if (pass == PASS_1_CHECK_64_BIT_BARS &&
+ ((res->flags & IORESOURCE_PCI64) == 0))
+ continue;
+
+ /* skip devices with option roms until last */
+ if ((pass < PASS_3_CHECK_DEVS_WITH_OPROMS)
+ && (res->index == PCI_ROM_ADDRESS)) {
+ memory_used = 0;
+ break;
+ }
+
+ if (res->flags & IORESOURCE_MEM)
+ memory_used += res->size;
+ }
+
+ /* Save the largest device found so far */
+ if (memory_used > most_memory_used) {
+ most_memory_used = memory_used;
+ largest_dev = dev;
+ }
+ }
+
+ /* break out of the pass loop when we find a device */
+ if (largest_dev != NULL)
+ break;
+ }
+
+ return largest_dev;
+}
+
+/** @brief clear all resources for a specified device. Leave index and next.
+ *
+ */
+void clear_device_resources(struct device *dev)
+{
+ struct resource *res;
+
+ for (res = dev->resource_list; res; res = res->next) {
+ res->align = 0;
+ res->base = 0;
+ res->flags = 0;
+ res->gran = 0;
+ res->limit = 0;
+ res->size = 0;
+ }
+}
+
+/** @brief clear all non-pnp resources.
+ *
+ */
+void clear_computed_resources(void)
+{
+ struct device *dev;
+
+ /*
+ * Loop through all non-pnp devices, clearing everything except index
+ * and the pointer to the next resource. This keeps them from having
+ * to be re-allocated.
+ */
+ for (dev = &dev_root; dev; dev = dev->next) {
+
+ //skip pnp devices - their resources are set early
+ if (dev->path.type == DEVICE_PATH_PNP)
+ continue;
+
+ clear_device_resources(dev);
+ }
+}
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index 5123229..dfc290b 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -248,27 +248,49 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
resource->limit = 0xffff;
} else {
/* A Memory mapped base address. */
- attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
- resource->flags |= IORESOURCE_MEM;
- if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH)
- resource->flags |= IORESOURCE_PREFETCH;
- attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
- if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
- /* 32bit limit. */
- resource->limit = 0xffffffffUL;
- } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
- /* 1MB limit. */
- resource->limit = 0x000fffffUL;
- } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
- /* 64bit limit. */
- resource->limit = 0xffffffffffffffffULL;
- resource->flags |= IORESOURCE_PCI64;
+ if (CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE &&
+ (resource->size > CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE)) {
+ /* Disable devices that attempt to allocate a BAR beyond
+ the max configured size. */
+ printk(BIOS_WARNING,
+ "Device at %s requested a 0x%llx byte BAR ",
+ dev_path(dev),
+ (unsigned long long)resource->size);
+ printk(BIOS_WARNING,
+ "for register 0x%02lx.\n",
+ index);
+ printk(BIOS_WARNING,
+ "The device exceeded largest allowed size of 0x%lx. ",
+ (unsigned long)
+ CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE);
+ printk(BIOS_WARNING, "Device disabled.\n");
+ dev->enabled = 0;
+ clear_device_resources(dev);
} else {
- /* Invalid value. */
- printk(BIOS_ERR, "Broken BAR with value %lx\n", attr);
- printk(BIOS_ERR, " on dev %s at index %02lx\n",
- dev_path(dev), index);
- resource->flags = 0;
+ attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+ resource->flags |= IORESOURCE_MEM;
+ if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ resource->flags |= IORESOURCE_PREFETCH;
+ attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
+ if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
+ /* 32bit limit. */
+ resource->limit = 0xffffffffUL;
+ } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
+ /* 1MB limit. */
+ resource->limit = 0x000fffffUL;
+ } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
+ /* 64bit limit. */
+ resource->limit = 0xffffffffffffffffULL;
+ resource->flags |= IORESOURCE_PCI64;
+ } else {
+ /* Invalid value. */
+ printk(BIOS_ERR,
+ "Broken BAR with value %lx\n",
+ attr);
+ printk(BIOS_ERR, " on dev %s at index %02lx\n",
+ dev_path(dev), index);
+ resource->flags = 0;
+ }
}
}
@@ -344,6 +366,8 @@ static void pci_read_bases(struct device *dev, unsigned int howmany)
(index < PCI_BASE_ADDRESS_0 + (howmany << 2));) {
struct resource *resource;
resource = pci_get_resource(dev, index);
+ if (dev->enabled == 0)
+ return;
index += (resource->flags & IORESOURCE_PCI64) ? 8 : 4;
}
diff --git a/src/include/device/device.h b/src/include/device/device.h
index 62460ae..c857dd2 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -234,6 +234,10 @@ void fixed_mem_resource(device_t dev, unsigned long index,
void scan_smbus(device_t bus);
void scan_lpc_bus(device_t bus);
+struct device *find_pci_dev_max_mem(void);
+void clear_computed_resources(void);
+void clear_device_resources(struct device *dev);
+
/* It is the caller's responsibility to adjust regions such that ram_resource()
* and mmio_resource() do not overlap.
*/
Ben Frisch (bfrisch(a)xes-inc.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12575
-gerrit
commit e3431755b234d8c95b461a60824bf0e9716f5036
Author: Benjamin Frisch <bfrisch(a)xes-inc.com>
Date: Mon Nov 30 12:23:31 2015 -0600
device: Resolve hang when a PCI device requests 4GB or more of MMIO space
When a PCI device's BAR requests 4GB or more MMIO space coreboot assigns the
device address 0. This results in the device overlapping DRAM and the boot
hangs with no feedback explaining the issue. Resolve this hang by first
detecting the exhaustion that available MMIO space under 4GB. Next,
selectively ignore PCI device resource requests based on the algorithm that
UEFI Firmware based on tianocore.org code does to accomplish the same.
This also meets requirements of the PCI Firmware Specification 3.1 and
Firmware Allocation of PCI Device Resources in Windows document which states
that firmware shall not allocate resources to devices that cannot fit in
available 32-bit MMIO space. Modern 64-bit Linux and 64-bit Windows since
Windows Vista will rebalance, allocate, and assign resources above the 4GB
boundry to 64-bit PCI device MMIO BARs resources as necessary as long 64-bit
MMIO space is defined in the ACPI _CRS method and the pci=realloc kernel
argument is provided in Linux.
The determination of which large 64-bit PCI MMIO resource requests to ignore is
based on how available MMIO space resouce exhaustion is handled by the
tianocore.org UEFI Firmware implemenation. If a PCI MMIO resource request
cannot be satisified, MMIO PCI resource requests of devices that are not on
bus 0 are skipped in the following order to attempt to make room to satisfy
the remaining PCI device MMIO space requests while keeping boot criticial
devices enabled:
1) Resource requests of the current PCI device with the largest 64-bit MMIO
resource request (without OPROMs)
2) Resource requests of the current PCI device with the largest 32-bit MMIO
resource request (without OPROMs)
3) Resource requests of the current PCI device with the largest MMIO
resource request (with OPROMs)
TEST=Tested on internal coreboot port based on older upstream
with device presenting 128 GB BAR with latest Linux kernel,
additional testing help and feedback is appreciated. Builds locally.
Change-Id: I0217d627ca77431075df5e24d49d6406c35893b7
Signed-off-by: Ben Frisch <bfrisch(a)xes-inc.com>
---
src/device/Kconfig | 46 ++++++++++++++++
src/device/device.c | 124 ++++++++++++++++++++++++++++++++------------
src/device/device_util.c | 109 ++++++++++++++++++++++++++++++++++++++
src/device/pci_device.c | 64 ++++++++++++++++-------
src/include/device/device.h | 4 ++
5 files changed, 295 insertions(+), 52 deletions(-)
diff --git a/src/device/Kconfig b/src/device/Kconfig
index 0113545..b9a734d 100644
--- a/src/device/Kconfig
+++ b/src/device/Kconfig
@@ -389,6 +389,52 @@ config SOFTWARE_I2C
I2C controller is not (yet) available. The platform code needs to
provide bindings to manually toggle I2C lines.
+choice SET_MAX_MEM_BAR_SIZE
+ prompt "Set Maximum memory BAR size to try to allocate "
+ optional
+ help
+ Select the maximum size PCI device memory BAR that coreboot will try
+ to allocate. If a BAR is found with a values above this size, coreboot
+ will disable the device and will not try to allocate any BARs.
+
+ If unsure, leave this disabled, and coreboot will find and disable any
+ devices that are too large to be allocated by itself. The
+ disadvantage is a slight boot time increase if a device has to be
+ disabled.
+
+config MAX_BAR_SIZE_256MB
+ bool "256 MB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 256 MB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+config MAX_BAR_SIZE_512MB
+ bool "512 MB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 512 MB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+config MAX_BAR_SIZE_1GB
+ bool "1 GB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 1 GB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+endchoice
+
+config MAX_MEM_BAR_SIZE_TO_ALLOCATE
+ hex
+ default 0x10000000 if MAX_BAR_SIZE_256MB
+ default 0x20000000 if MAX_BAR_SIZE_512MB
+ default 0x40000000 if MAX_BAR_SIZE_1GB
+ default 0
+
endmenu
menu "Display"
diff --git a/src/device/device.c b/src/device/device.c
index e23c9de..dc39dfc 100644
--- a/src/device/device.c
+++ b/src/device/device.c
@@ -690,7 +690,7 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
}
}
-static void avoid_fixed_resources(struct device *dev)
+static u8 avoid_fixed_resources(struct device *dev)
{
struct constraints limits;
struct resource *res;
@@ -743,9 +743,60 @@ static void avoid_fixed_resources(struct device *dev)
if (res->flags & IORESOURCE_MEM)
res->base = resource_max(res);
+ if (res->base < lim->base) {
+ /* This usually happens at the domain level, usually
+ * caused by a device having a BAR which is too big.
+ * Error out so we can retry.
+ */
+ printk(BIOS_WARNING,
+ "ERROR: Resource Base was lower than its limit!\n\t");
+ printk(BIOS_WARNING,
+ "%s@%02lx: base value 0x%08llx, lower limit 0x%08llx\n",
+ dev_path(dev), res->index, res->base, lim->base);
+ return 1;
+ }
+
printk(BIOS_SPEW, "%s:@%s %02lx base %08llx limit %08llx\n",
__func__, dev_path(dev), res->index, res->base, res->limit);
}
+
+ return 0;
+}
+
+static u8 avoid_all_fixed_resources(struct device *root)
+{
+ struct device *child;
+
+ /* For all domains. */
+ for (child = root->link_list->children; child; child = child->sibling) {
+ if (child->path.type == DEVICE_PATH_DOMAIN) {
+ if (avoid_fixed_resources(child)) {
+ printk(
+ BIOS_SPEW,
+ "Error trying to avoid fixed resources.");
+
+ /* Now find the device which is the largest
+ * and disable it.
+ */
+ struct device *largest = find_pci_dev_max_mem();
+
+ printk(BIOS_SPEW, "\tDisabling Device %s\n",
+ dev_path(largest));
+ if (largest)
+ largest->enabled = 0;
+
+ /* Clear out all devices on all domains, ready
+ * for re-scanning.
+ */
+ printk(BIOS_SPEW,
+ "\tClearing old resource computations.\n");
+ clear_computed_resources();
+ return 1;
+ }
+ }
+ }
+
+ return 0;
}
device_t vga_pri = 0;
@@ -1022,45 +1073,54 @@ void dev_configure(void)
root = &dev_root;
- /*
- * Each domain should create resources which contain the entire address
- * space for IO, MEM, and PREFMEM resources in the domain. The
- * allocation of device resources will be done from this address space.
- */
+ do {
+ /*
+ * Each domain should create resources which contain the entire
+ * address space for IO, MEM, and PREFMEM resources in the
+ * domain. The allocation of device resources will be done from
+ * this address space.
+ */
- /* Read the resources for the entire tree. */
+ /* Read the resources for the entire tree. */
- printk(BIOS_INFO, "Reading resources...\n");
- read_resources(root->link_list);
- printk(BIOS_INFO, "Done reading resources.\n");
+ printk(BIOS_INFO, "Reading resources...\n");
+ read_resources(root->link_list);
+ printk(BIOS_INFO, "Done reading resources.\n");
- print_resource_tree(root, BIOS_SPEW, "After reading.");
+ print_resource_tree(root, BIOS_SPEW, "After reading.");
- /* Compute resources for all domains. */
- for (child = root->link_list->children; child; child = child->sibling) {
- if (!(child->path.type == DEVICE_PATH_DOMAIN))
- continue;
- post_log_path(child);
- for (res = child->resource_list; res; res = res->next) {
- if (res->flags & IORESOURCE_FIXED)
- continue;
- if (res->flags & IORESOURCE_MEM) {
- compute_resources(child->link_list,
- res, IORESOURCE_TYPE_MASK, IORESOURCE_MEM);
- continue;
- }
- if (res->flags & IORESOURCE_IO) {
- compute_resources(child->link_list,
- res, IORESOURCE_TYPE_MASK, IORESOURCE_IO);
+ /* Compute resources for all domains. */
+ for (child = root->link_list->children;
+ child;
+ child = child->sibling) {
+ if (!(child->path.type == DEVICE_PATH_DOMAIN))
continue;
+ post_log_path(child);
+ for (res = child->resource_list; res; res = res->next) {
+ if (res->flags & IORESOURCE_FIXED)
+ continue;
+ if (res->flags & IORESOURCE_MEM) {
+ compute_resources(
+ child->link_list,
+ res,
+ IORESOURCE_TYPE_MASK,
+ IORESOURCE_MEM);
+ continue;
+ }
+ if (res->flags & IORESOURCE_IO) {
+ compute_resources(child->link_list,
+ res,
+ IORESOURCE_TYPE_MASK,
+ IORESOURCE_IO);
+ continue;
+ }
}
}
- }
- /* For all domains. */
- for (child = root->link_list->children; child; child=child->sibling)
- if (child->path.type == DEVICE_PATH_DOMAIN)
- avoid_fixed_resources(child);
+ /* Attempt to avoid all fixed resources, if this process
+ * succeeds then we can carry on, otherwise we should re-try.
+ */
+ } while (avoid_all_fixed_resources(root));
/* Store the computed resource allocations into device registers ... */
printk(BIOS_INFO, "Setting resources...\n");
diff --git a/src/device/device_util.c b/src/device/device_util.c
index ac18538..5d0ba50 100644
--- a/src/device/device_util.c
+++ b/src/device/device_util.c
@@ -921,3 +921,112 @@ int dev_count_cpu(void)
return count;
}
+
+enum allocation_passes {
+ PASS_1_CHECK_64_BIT_BARS = 0,
+ PASS_2_CHECK_32_BIT_BARS = 1,
+ PASS_3_CHECK_DEVS_WITH_OPROMS = 2,
+ MAX_PASS = PASS_3_CHECK_DEVS_WITH_OPROMS
+};
+
+/** @brief finds the enabled, non root-bus, pci device using the most memory.
+ *
+ * @return pointer to the device
+ */
+struct device *find_pci_dev_max_mem(void)
+{
+ struct device *dev;
+ struct device *largest_dev = NULL;
+ struct resource *res;
+ uint64_t memory_used = 0;
+ uint64_t most_memory_used = 0;
+ uint8_t pass;
+
+ for (pass = PASS_1_CHECK_64_BIT_BARS; pass <= MAX_PASS; pass++) {
+
+ /*
+ * Loop through all pci devices that are not on bus 0,
+ * skipping them if they're disabled, checking to see
+ * which uses the most memory.
+ */
+ for (dev = &dev_root; dev; dev = dev->next) {
+
+ /* Skip disabled, root bus, and non-pci devices */
+ if ((!(dev->path.type == DEVICE_PATH_PCI)) ||
+ (dev->bus->secondary == 0) ||
+ (dev->enabled == 0))
+ continue;
+
+ /* Total the memory used by the device */
+ memory_used = 0;
+ for (res = dev->resource_list; res; res = res->next) {
+
+ /* don't check 32-bit bars on the first pass */
+ if (pass == PASS_1_CHECK_64_BIT_BARS &&
+ ((res->flags & IORESOURCE_PCI64) == 0))
+ continue;
+
+ /* skip devices with option roms until last */
+ if ((pass < PASS_3_CHECK_DEVS_WITH_OPROMS)
+ && (res->index == PCI_ROM_ADDRESS)) {
+ memory_used = 0;
+ break;
+ }
+
+ if (res->flags & IORESOURCE_MEM)
+ memory_used += res->size;
+ }
+
+ /* Save the largest device found so far */
+ if (memory_used > most_memory_used) {
+ most_memory_used = memory_used;
+ largest_dev = dev;
+ }
+ }
+
+ /* break out of the pass loop when we find a device */
+ if (largest_dev != NULL)
+ break;
+ }
+
+ return largest_dev;
+}
+
+/** @brief clear all resources for a specified device. Leave index and next.
+ *
+ */
+void clear_device_resources(struct device *dev)
+{
+ struct resource *res;
+
+ for (res = dev->resource_list; res; res = res->next) {
+ res->align = 0;
+ res->base = 0;
+ res->flags = 0;
+ res->gran = 0;
+ res->limit = 0;
+ res->size = 0;
+ }
+}
+
+/** @brief clear all non-pnp resources.
+ *
+ */
+void clear_computed_resources(void)
+{
+ struct device *dev;
+
+ /*
+ * Loop through all non-pnp devices, clearing everything except index
+ * and the pointer to the next resource. This keeps them from having
+ * to be re-allocated.
+ */
+ for (dev = &dev_root; dev; dev = dev->next) {
+
+ //skip pnp devices - their resources are set early
+ if (dev->path.type == DEVICE_PATH_PNP)
+ continue;
+
+ clear_device_resources(dev);
+ }
+}
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index 5123229..dfc290b 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -248,27 +248,49 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
resource->limit = 0xffff;
} else {
/* A Memory mapped base address. */
- attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
- resource->flags |= IORESOURCE_MEM;
- if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH)
- resource->flags |= IORESOURCE_PREFETCH;
- attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
- if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
- /* 32bit limit. */
- resource->limit = 0xffffffffUL;
- } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
- /* 1MB limit. */
- resource->limit = 0x000fffffUL;
- } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
- /* 64bit limit. */
- resource->limit = 0xffffffffffffffffULL;
- resource->flags |= IORESOURCE_PCI64;
+ if (CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE &&
+ (resource->size > CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE)) {
+ /* Disable devices that attempt to allocate a BAR beyond
+ the max configured size. */
+ printk(BIOS_WARNING,
+ "Device at %s requested a 0x%llx byte BAR ",
+ dev_path(dev),
+ (unsigned long long)resource->size);
+ printk(BIOS_WARNING,
+ "for register 0x%02lx.\n",
+ index);
+ printk(BIOS_WARNING,
+ "The device exceeded largest allowed size of 0x%lx. ",
+ (unsigned long)
+ CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE);
+ printk(BIOS_WARNING, "Device disabled.\n");
+ dev->enabled = 0;
+ clear_device_resources(dev);
} else {
- /* Invalid value. */
- printk(BIOS_ERR, "Broken BAR with value %lx\n", attr);
- printk(BIOS_ERR, " on dev %s at index %02lx\n",
- dev_path(dev), index);
- resource->flags = 0;
+ attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+ resource->flags |= IORESOURCE_MEM;
+ if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ resource->flags |= IORESOURCE_PREFETCH;
+ attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
+ if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
+ /* 32bit limit. */
+ resource->limit = 0xffffffffUL;
+ } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
+ /* 1MB limit. */
+ resource->limit = 0x000fffffUL;
+ } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
+ /* 64bit limit. */
+ resource->limit = 0xffffffffffffffffULL;
+ resource->flags |= IORESOURCE_PCI64;
+ } else {
+ /* Invalid value. */
+ printk(BIOS_ERR,
+ "Broken BAR with value %lx\n",
+ attr);
+ printk(BIOS_ERR, " on dev %s at index %02lx\n",
+ dev_path(dev), index);
+ resource->flags = 0;
+ }
}
}
@@ -344,6 +366,8 @@ static void pci_read_bases(struct device *dev, unsigned int howmany)
(index < PCI_BASE_ADDRESS_0 + (howmany << 2));) {
struct resource *resource;
resource = pci_get_resource(dev, index);
+ if (dev->enabled == 0)
+ return;
index += (resource->flags & IORESOURCE_PCI64) ? 8 : 4;
}
diff --git a/src/include/device/device.h b/src/include/device/device.h
index 62460ae..c857dd2 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -234,6 +234,10 @@ void fixed_mem_resource(device_t dev, unsigned long index,
void scan_smbus(device_t bus);
void scan_lpc_bus(device_t bus);
+struct device *find_pci_dev_max_mem(void);
+void clear_computed_resources(void);
+void clear_device_resources(struct device *dev);
+
/* It is the caller's responsibility to adjust regions such that ram_resource()
* and mmio_resource() do not overlap.
*/
Ben Frisch (bfrisch(a)xes-inc.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12575
-gerrit
commit 2bc20d1cf15c61e8e4b31d585402d6cafa8d8a1e
Author: Benjamin Frisch <bfrisch(a)xes-inc.com>
Date: Mon Nov 30 12:23:31 2015 -0600
device: Resolve hang when a PCI device requests 4GB or more of MMIO space
When a PCI device's BAR requests 4GB or more MMIO space coreboot assigns the
device address 0. This results in the device overlapping DRAM and the boot
hangs with no feedback explaining the issue. Resolve this hang by first
detecting the exhaustion that available MMIO space under 4GB. Next,
selectively ignore PCI device resource requests based on the algorithm that
UEFI Firmware based on tianocore.org code does to accomplish the same.
This also meets requirements of the PCI Firmware Specification 3.1 and
Firmware Allocation of PCI Device Resources in Windows document which states
that firmware shall not allocate resources to devices that cannot fit in
available 32-bit MMIO space. Modern 64-bit Linux and 64-bit Windows since
Windows Vista will rebalance, allocate, and assign resources above the 4GB
boundry to 64-bit PCI device MMIO BARs resources as necessary as long 64-bit
MMIO space is defined in the ACPI _CRS method and the pci=realloc kernel
argument is provided in Linux.
The determination of which large 64-bit PCI MMIO resource requests to ignore is
based on how available MMIO space resouce exhaustion is handled by the
tianocore.org UEFI Firmware implemenation. If a PCI MMIO resource request
cannot be satisified, MMIO PCI resource requests of devices that are not on
bus 0 are skipped in the following order to attempt to make room to satisfy
the remaining PCI device MMIO space requests while keeping boot criticial
devices enabled:
1) Resource requests of the current PCI device with the largest 64-bit MMIO
resource request (without OPROMs)
2) Resource requests of the current PCI device with the largest 32-bit MMIO
resource request (without OPROMs)
3) Resource requests of the current PCI device with the largest MMIO
resource request (with OPROMs)
TEST=Tested on internal coreboot port based on older upstream
with device presenting 128 GB BAR with latest Linux kernel,
additional testing help and feedback is appreciated.
Change-Id: I0217d627ca77431075df5e24d49d6406c35893b7
Signed-off-by: Ben Frisch <bfrisch(a)xes-inc.com>
---
src/device/Kconfig | 46 ++++++++++++++++
src/device/device.c | 124 ++++++++++++++++++++++++++++++++------------
src/device/device_util.c | 109 ++++++++++++++++++++++++++++++++++++++
src/device/pci_device.c | 64 ++++++++++++++++-------
src/include/device/device.h | 4 ++
5 files changed, 295 insertions(+), 52 deletions(-)
diff --git a/src/device/Kconfig b/src/device/Kconfig
index 0113545..b9a734d 100644
--- a/src/device/Kconfig
+++ b/src/device/Kconfig
@@ -389,6 +389,52 @@ config SOFTWARE_I2C
I2C controller is not (yet) available. The platform code needs to
provide bindings to manually toggle I2C lines.
+choice SET_MAX_MEM_BAR_SIZE
+ prompt "Set Maximum memory BAR size to try to allocate "
+ optional
+ help
+ Select the maximum size PCI device memory BAR that coreboot will try
+ to allocate. If a BAR is found with a values above this size, coreboot
+ will disable the device and will not try to allocate any BARs.
+
+ If unsure, leave this disabled, and coreboot will find and disable any
+ devices that are too large to be allocated by itself. The
+ disadvantage is a slight boot time increase if a device has to be
+ disabled.
+
+config MAX_BAR_SIZE_256MB
+ bool "256 MB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 256 MB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+config MAX_BAR_SIZE_512MB
+ bool "512 MB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 512 MB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+config MAX_BAR_SIZE_1GB
+ bool "1 GB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 1 GB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+endchoice
+
+config MAX_MEM_BAR_SIZE_TO_ALLOCATE
+ hex
+ default 0x10000000 if MAX_BAR_SIZE_256MB
+ default 0x20000000 if MAX_BAR_SIZE_512MB
+ default 0x40000000 if MAX_BAR_SIZE_1GB
+ default 0
+
endmenu
menu "Display"
diff --git a/src/device/device.c b/src/device/device.c
index e23c9de..dc39dfc 100644
--- a/src/device/device.c
+++ b/src/device/device.c
@@ -690,7 +690,7 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
}
}
-static void avoid_fixed_resources(struct device *dev)
+static u8 avoid_fixed_resources(struct device *dev)
{
struct constraints limits;
struct resource *res;
@@ -743,9 +743,60 @@ static void avoid_fixed_resources(struct device *dev)
if (res->flags & IORESOURCE_MEM)
res->base = resource_max(res);
+ if (res->base < lim->base) {
+ /* This usually happens at the domain level, usually
+ * caused by a device having a BAR which is too big.
+ * Error out so we can retry.
+ */
+ printk(BIOS_WARNING,
+ "ERROR: Resource Base was lower than its limit!\n\t");
+ printk(BIOS_WARNING,
+ "%s@%02lx: base value 0x%08llx, lower limit 0x%08llx\n",
+ dev_path(dev), res->index, res->base, lim->base);
+ return 1;
+ }
+
printk(BIOS_SPEW, "%s:@%s %02lx base %08llx limit %08llx\n",
__func__, dev_path(dev), res->index, res->base, res->limit);
}
+
+ return 0;
+}
+
+static u8 avoid_all_fixed_resources(struct device *root)
+{
+ struct device *child;
+
+ /* For all domains. */
+ for (child = root->link_list->children; child; child = child->sibling) {
+ if (child->path.type == DEVICE_PATH_DOMAIN) {
+ if (avoid_fixed_resources(child)) {
+ printk(
+ BIOS_SPEW,
+ "Error trying to avoid fixed resources.");
+
+ /* Now find the device which is the largest
+ * and disable it.
+ */
+ struct device *largest = find_pci_dev_max_mem();
+
+ printk(BIOS_SPEW, "\tDisabling Device %s\n",
+ dev_path(largest));
+ if (largest)
+ largest->enabled = 0;
+
+ /* Clear out all devices on all domains, ready
+ * for re-scanning.
+ */
+ printk(BIOS_SPEW,
+ "\tClearing old resource computations.\n");
+ clear_computed_resources();
+ return 1;
+ }
+ }
+ }
+
+ return 0;
}
device_t vga_pri = 0;
@@ -1022,45 +1073,54 @@ void dev_configure(void)
root = &dev_root;
- /*
- * Each domain should create resources which contain the entire address
- * space for IO, MEM, and PREFMEM resources in the domain. The
- * allocation of device resources will be done from this address space.
- */
+ do {
+ /*
+ * Each domain should create resources which contain the entire
+ * address space for IO, MEM, and PREFMEM resources in the
+ * domain. The allocation of device resources will be done from
+ * this address space.
+ */
- /* Read the resources for the entire tree. */
+ /* Read the resources for the entire tree. */
- printk(BIOS_INFO, "Reading resources...\n");
- read_resources(root->link_list);
- printk(BIOS_INFO, "Done reading resources.\n");
+ printk(BIOS_INFO, "Reading resources...\n");
+ read_resources(root->link_list);
+ printk(BIOS_INFO, "Done reading resources.\n");
- print_resource_tree(root, BIOS_SPEW, "After reading.");
+ print_resource_tree(root, BIOS_SPEW, "After reading.");
- /* Compute resources for all domains. */
- for (child = root->link_list->children; child; child = child->sibling) {
- if (!(child->path.type == DEVICE_PATH_DOMAIN))
- continue;
- post_log_path(child);
- for (res = child->resource_list; res; res = res->next) {
- if (res->flags & IORESOURCE_FIXED)
- continue;
- if (res->flags & IORESOURCE_MEM) {
- compute_resources(child->link_list,
- res, IORESOURCE_TYPE_MASK, IORESOURCE_MEM);
- continue;
- }
- if (res->flags & IORESOURCE_IO) {
- compute_resources(child->link_list,
- res, IORESOURCE_TYPE_MASK, IORESOURCE_IO);
+ /* Compute resources for all domains. */
+ for (child = root->link_list->children;
+ child;
+ child = child->sibling) {
+ if (!(child->path.type == DEVICE_PATH_DOMAIN))
continue;
+ post_log_path(child);
+ for (res = child->resource_list; res; res = res->next) {
+ if (res->flags & IORESOURCE_FIXED)
+ continue;
+ if (res->flags & IORESOURCE_MEM) {
+ compute_resources(
+ child->link_list,
+ res,
+ IORESOURCE_TYPE_MASK,
+ IORESOURCE_MEM);
+ continue;
+ }
+ if (res->flags & IORESOURCE_IO) {
+ compute_resources(child->link_list,
+ res,
+ IORESOURCE_TYPE_MASK,
+ IORESOURCE_IO);
+ continue;
+ }
}
}
- }
- /* For all domains. */
- for (child = root->link_list->children; child; child=child->sibling)
- if (child->path.type == DEVICE_PATH_DOMAIN)
- avoid_fixed_resources(child);
+ /* Attempt to avoid all fixed resources, if this process
+ * succeeds then we can carry on, otherwise we should re-try.
+ */
+ } while (avoid_all_fixed_resources(root));
/* Store the computed resource allocations into device registers ... */
printk(BIOS_INFO, "Setting resources...\n");
diff --git a/src/device/device_util.c b/src/device/device_util.c
index ac18538..f68ca4a 100644
--- a/src/device/device_util.c
+++ b/src/device/device_util.c
@@ -921,3 +921,112 @@ int dev_count_cpu(void)
return count;
}
+
+enum allocation_passes {
+ PASS_1_CHECK_64_BIT_BARS = 0,
+ PASS_2_CHECK_32_BIT_BARS = 1,
+ PASS_3_CHECK_DEVS_WITH_OPROMS = 2,
+ MAX_PASS = PASS_3_CHECK_DEVS_WITH_OPROMS
+};
+
+/** @brief finds the enabled, non root-bus, pci device using the most memory.
+ *
+ * @return pointer to the device
+ */
+struct device *find_pci_dev_max_mem(void)
+{
+ struct device *dev;
+ struct device *largest_dev = NULL;
+ struct resource *res;
+ uint64_t memory_used = 0;
+ uint64_t most_memory_used = 0;
+ uint8_t pass;
+
+ for (pass = PASS_1_CHECK_64_BIT_BARS; pass <= MAX_PASS; pass++) {
+
+ /*
+ * Loop through all pci devices that are not on bus 0,
+ * skipping them if they're disabled, checking to see
+ * which uses the most memory.
+ */
+ for (dev = &dev_root; dev; dev = dev->next) {
+
+ /* Skip disabled, root bus, and non-pci devices */
+ if ((!(dev->path.type == DEVICE_PATH_PCI)) ||
+ (dev->bus->secondary == 0) ||
+ (dev->enabled == 0))
+ continue;
+
+ /* Total the memory used by the device */
+ memory_used = 0;
+ for (res = dev->resource_list; res; res = res->next) {
+
+ /* don't check 32-bit bars on the first pass */
+ if (pass == PASS_1_CHECK_64_BIT_BARS &&
+ ((res->flags & IORESOURCE_PCI64) == 0))
+ continue;
+
+ /* skip devices with option roms until last */
+ if ((pass < PASS_3_CHECK_DEVS_WITH_OPROMS)
+ && (res->index == PCI_ROM_ADDRESS)) {
+ memory_used = 0;
+ break;
+ }
+
+ if (res->flags & IORESOURCE_MEM)
+ memory_used += res->size;
+ }
+
+ /* Save the largest device found so far */
+ if (memory_used > most_memory_used) {
+ most_memory_used = memory_used;
+ largest_dev = dev;
+ }
+ }
+
+ /* break out of the pass loop when we find a device */
+ if (largest_dev != NULL)
+ break;
+ }
+
+ return largest_dev;
+}
+
+/** @brief clear all non-pnp resources.
+ *
+ */
+void clear_computed_resources(void)
+{
+ struct device *dev;
+
+ /*
+ * Loop through all non-pnp devices, clearing everything except index
+ * and the pointer to the next resource. This keeps them from having
+ * to be re-allocated.
+ */
+ for (dev = &dev_root; dev; dev = dev->next) {
+
+ //skip pnp devices - their resources are set early
+ if (dev->path.type == DEVICE_PATH_PNP)
+ continue;
+
+ clear_device_resources(dev);
+ }
+}
+
+/** @brief clear all resources for a specified device. Leave index and next.
+ *
+ */
+static void clear_device_resources(struct device *dev)
+{
+ struct resource *res;
+
+ for (res = dev->resource_list; res; res = res->next) {
+ res->align = 0;
+ res->base = 0;
+ res->flags = 0;
+ res->gran = 0;
+ res->limit = 0;
+ res->size = 0;
+ }
+}
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index 5123229..dfc290b 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -248,27 +248,49 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
resource->limit = 0xffff;
} else {
/* A Memory mapped base address. */
- attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
- resource->flags |= IORESOURCE_MEM;
- if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH)
- resource->flags |= IORESOURCE_PREFETCH;
- attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
- if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
- /* 32bit limit. */
- resource->limit = 0xffffffffUL;
- } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
- /* 1MB limit. */
- resource->limit = 0x000fffffUL;
- } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
- /* 64bit limit. */
- resource->limit = 0xffffffffffffffffULL;
- resource->flags |= IORESOURCE_PCI64;
+ if (CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE &&
+ (resource->size > CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE)) {
+ /* Disable devices that attempt to allocate a BAR beyond
+ the max configured size. */
+ printk(BIOS_WARNING,
+ "Device at %s requested a 0x%llx byte BAR ",
+ dev_path(dev),
+ (unsigned long long)resource->size);
+ printk(BIOS_WARNING,
+ "for register 0x%02lx.\n",
+ index);
+ printk(BIOS_WARNING,
+ "The device exceeded largest allowed size of 0x%lx. ",
+ (unsigned long)
+ CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE);
+ printk(BIOS_WARNING, "Device disabled.\n");
+ dev->enabled = 0;
+ clear_device_resources(dev);
} else {
- /* Invalid value. */
- printk(BIOS_ERR, "Broken BAR with value %lx\n", attr);
- printk(BIOS_ERR, " on dev %s at index %02lx\n",
- dev_path(dev), index);
- resource->flags = 0;
+ attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+ resource->flags |= IORESOURCE_MEM;
+ if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ resource->flags |= IORESOURCE_PREFETCH;
+ attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
+ if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
+ /* 32bit limit. */
+ resource->limit = 0xffffffffUL;
+ } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
+ /* 1MB limit. */
+ resource->limit = 0x000fffffUL;
+ } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
+ /* 64bit limit. */
+ resource->limit = 0xffffffffffffffffULL;
+ resource->flags |= IORESOURCE_PCI64;
+ } else {
+ /* Invalid value. */
+ printk(BIOS_ERR,
+ "Broken BAR with value %lx\n",
+ attr);
+ printk(BIOS_ERR, " on dev %s at index %02lx\n",
+ dev_path(dev), index);
+ resource->flags = 0;
+ }
}
}
@@ -344,6 +366,8 @@ static void pci_read_bases(struct device *dev, unsigned int howmany)
(index < PCI_BASE_ADDRESS_0 + (howmany << 2));) {
struct resource *resource;
resource = pci_get_resource(dev, index);
+ if (dev->enabled == 0)
+ return;
index += (resource->flags & IORESOURCE_PCI64) ? 8 : 4;
}
diff --git a/src/include/device/device.h b/src/include/device/device.h
index 62460ae..c857dd2 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -234,6 +234,10 @@ void fixed_mem_resource(device_t dev, unsigned long index,
void scan_smbus(device_t bus);
void scan_lpc_bus(device_t bus);
+struct device *find_pci_dev_max_mem(void);
+void clear_computed_resources(void);
+void clear_device_resources(struct device *dev);
+
/* It is the caller's responsibility to adjust regions such that ram_resource()
* and mmio_resource() do not overlap.
*/
Ben Frisch (bfrisch(a)xes-inc.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12575
-gerrit
commit 6e1fcddb363c9e28cd122d17829a9ccfbf228a50
Author: Benjamin Frisch <bfrisch(a)xes-inc.com>
Date: Mon Nov 30 12:23:31 2015 -0600
device: Resolve hang when a PCI device requests 4GB or more of MMIO space
When a PCI device's BAR requests 4GB or more MMIO space coreboot assigns the
device address 0. This results in the device overlapping DRAM and the boot
hangs with no feedback explaining the issue. Resolve this hang by first
detecting the exhaustion that available MMIO space under 4GB. Next,
selectively ignore PCI device resource requests based on the algorithm that
UEFI Firmware based on tianocore.org code does to accomplish the same.
This also meets requirements of the PCI Firmware Specification 3.1 and
Firmware Allocation of PCI Device Resources in Windows document which states
that firmware shall not allocate resources to devices that cannot fit in
available 32-bit MMIO space. Modern 64-bit Linux and 64-bit Windows since
Windows Vista will rebalance, allocate, and assign resources above the 4GB
boundry to 64-bit PCI device MMIO BARs resources as necessary as long 64-bit
MMIO space is defined in the ACPI _CRS method and the pci=realloc kernel
argument is provided in Linux.
The determination of which large 64-bit PCI MMIO resource requests to ignore is
based on how available MMIO space resouce exhaustion is handled by the
tianocore.org UEFI Firmware implemenation. If a PCI MMIO resource request
cannot be satisified, MMIO PCI resource requests of devices that are not on
bus 0 are skipped in the following order to attempt to make room to satisfy
the remaining PCI device MMIO space requests while keeping boot criticial
devices enabled:
1) Resource requests of the current PCI device with the largest 64-bit MMIO
resource request (without OPROMs)
2) Resource requests of the current PCI device with the largest 32-bit MMIO
resource request (without OPROMs)
3) Resource requests of the current PCI device with the largest MMIO resource
request (with OPROMs)
TEST=Tested on internal coreboot port based on older upstream
with device presenting 128 GB BAR with latest Linux kernel,
additional testing help and feedback is appreciated.
Change-Id: I0217d627ca77431075df5e24d49d6406c35893b7
Signed-off-by: Ben Frisch <bfrisch(a)xes-inc.com>
---
src/device/Kconfig | 46 ++++++++++++++++
src/device/device.c | 124 ++++++++++++++++++++++++++++++++------------
src/device/device_util.c | 109 ++++++++++++++++++++++++++++++++++++++
src/device/pci_device.c | 64 ++++++++++++++++-------
src/include/device/device.h | 4 ++
5 files changed, 295 insertions(+), 52 deletions(-)
diff --git a/src/device/Kconfig b/src/device/Kconfig
index 0113545..b9a734d 100644
--- a/src/device/Kconfig
+++ b/src/device/Kconfig
@@ -389,6 +389,52 @@ config SOFTWARE_I2C
I2C controller is not (yet) available. The platform code needs to
provide bindings to manually toggle I2C lines.
+choice SET_MAX_MEM_BAR_SIZE
+ prompt "Set Maximum memory BAR size to try to allocate "
+ optional
+ help
+ Select the maximum size PCI device memory BAR that coreboot will try
+ to allocate. If a BAR is found with a values above this size, coreboot
+ will disable the device and will not try to allocate any BARs.
+
+ If unsure, leave this disabled, and coreboot will find and disable any
+ devices that are too large to be allocated by itself. The
+ disadvantage is a slight boot time increase if a device has to be
+ disabled.
+
+config MAX_BAR_SIZE_256MB
+ bool "256 MB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 256 MB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+config MAX_BAR_SIZE_512MB
+ bool "512 MB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 512 MB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+config MAX_BAR_SIZE_1GB
+ bool "1 GB"
+ help
+ Set the maximum size PCI device memory BAR that coreboot will try to
+ allocate to 1 GB. If a BAR is found with a values above this size,
+ coreboot will disable the device and will not try to allocate any
+ BARs.
+
+endchoice
+
+config MAX_MEM_BAR_SIZE_TO_ALLOCATE
+ hex
+ default 0x10000000 if MAX_BAR_SIZE_256MB
+ default 0x20000000 if MAX_BAR_SIZE_512MB
+ default 0x40000000 if MAX_BAR_SIZE_1GB
+ default 0
+
endmenu
menu "Display"
diff --git a/src/device/device.c b/src/device/device.c
index e23c9de..dc39dfc 100644
--- a/src/device/device.c
+++ b/src/device/device.c
@@ -690,7 +690,7 @@ static void constrain_resources(struct device *dev, struct constraints* limits)
}
}
-static void avoid_fixed_resources(struct device *dev)
+static u8 avoid_fixed_resources(struct device *dev)
{
struct constraints limits;
struct resource *res;
@@ -743,9 +743,60 @@ static void avoid_fixed_resources(struct device *dev)
if (res->flags & IORESOURCE_MEM)
res->base = resource_max(res);
+ if (res->base < lim->base) {
+ /* This usually happens at the domain level, usually
+ * caused by a device having a BAR which is too big.
+ * Error out so we can retry.
+ */
+ printk(BIOS_WARNING,
+ "ERROR: Resource Base was lower than its limit!\n\t");
+ printk(BIOS_WARNING,
+ "%s@%02lx: base value 0x%08llx, lower limit 0x%08llx\n",
+ dev_path(dev), res->index, res->base, lim->base);
+ return 1;
+ }
+
printk(BIOS_SPEW, "%s:@%s %02lx base %08llx limit %08llx\n",
__func__, dev_path(dev), res->index, res->base, res->limit);
}
+
+ return 0;
+}
+
+static u8 avoid_all_fixed_resources(struct device *root)
+{
+ struct device *child;
+
+ /* For all domains. */
+ for (child = root->link_list->children; child; child = child->sibling) {
+ if (child->path.type == DEVICE_PATH_DOMAIN) {
+ if (avoid_fixed_resources(child)) {
+ printk(
+ BIOS_SPEW,
+ "Error trying to avoid fixed resources.");
+
+ /* Now find the device which is the largest
+ * and disable it.
+ */
+ struct device *largest = find_pci_dev_max_mem();
+
+ printk(BIOS_SPEW, "\tDisabling Device %s\n",
+ dev_path(largest));
+ if (largest)
+ largest->enabled = 0;
+
+ /* Clear out all devices on all domains, ready
+ * for re-scanning.
+ */
+ printk(BIOS_SPEW,
+ "\tClearing old resource computations.\n");
+ clear_computed_resources();
+ return 1;
+ }
+ }
+ }
+
+ return 0;
}
device_t vga_pri = 0;
@@ -1022,45 +1073,54 @@ void dev_configure(void)
root = &dev_root;
- /*
- * Each domain should create resources which contain the entire address
- * space for IO, MEM, and PREFMEM resources in the domain. The
- * allocation of device resources will be done from this address space.
- */
+ do {
+ /*
+ * Each domain should create resources which contain the entire
+ * address space for IO, MEM, and PREFMEM resources in the
+ * domain. The allocation of device resources will be done from
+ * this address space.
+ */
- /* Read the resources for the entire tree. */
+ /* Read the resources for the entire tree. */
- printk(BIOS_INFO, "Reading resources...\n");
- read_resources(root->link_list);
- printk(BIOS_INFO, "Done reading resources.\n");
+ printk(BIOS_INFO, "Reading resources...\n");
+ read_resources(root->link_list);
+ printk(BIOS_INFO, "Done reading resources.\n");
- print_resource_tree(root, BIOS_SPEW, "After reading.");
+ print_resource_tree(root, BIOS_SPEW, "After reading.");
- /* Compute resources for all domains. */
- for (child = root->link_list->children; child; child = child->sibling) {
- if (!(child->path.type == DEVICE_PATH_DOMAIN))
- continue;
- post_log_path(child);
- for (res = child->resource_list; res; res = res->next) {
- if (res->flags & IORESOURCE_FIXED)
- continue;
- if (res->flags & IORESOURCE_MEM) {
- compute_resources(child->link_list,
- res, IORESOURCE_TYPE_MASK, IORESOURCE_MEM);
- continue;
- }
- if (res->flags & IORESOURCE_IO) {
- compute_resources(child->link_list,
- res, IORESOURCE_TYPE_MASK, IORESOURCE_IO);
+ /* Compute resources for all domains. */
+ for (child = root->link_list->children;
+ child;
+ child = child->sibling) {
+ if (!(child->path.type == DEVICE_PATH_DOMAIN))
continue;
+ post_log_path(child);
+ for (res = child->resource_list; res; res = res->next) {
+ if (res->flags & IORESOURCE_FIXED)
+ continue;
+ if (res->flags & IORESOURCE_MEM) {
+ compute_resources(
+ child->link_list,
+ res,
+ IORESOURCE_TYPE_MASK,
+ IORESOURCE_MEM);
+ continue;
+ }
+ if (res->flags & IORESOURCE_IO) {
+ compute_resources(child->link_list,
+ res,
+ IORESOURCE_TYPE_MASK,
+ IORESOURCE_IO);
+ continue;
+ }
}
}
- }
- /* For all domains. */
- for (child = root->link_list->children; child; child=child->sibling)
- if (child->path.type == DEVICE_PATH_DOMAIN)
- avoid_fixed_resources(child);
+ /* Attempt to avoid all fixed resources, if this process
+ * succeeds then we can carry on, otherwise we should re-try.
+ */
+ } while (avoid_all_fixed_resources(root));
/* Store the computed resource allocations into device registers ... */
printk(BIOS_INFO, "Setting resources...\n");
diff --git a/src/device/device_util.c b/src/device/device_util.c
index ac18538..f68ca4a 100644
--- a/src/device/device_util.c
+++ b/src/device/device_util.c
@@ -921,3 +921,112 @@ int dev_count_cpu(void)
return count;
}
+
+enum allocation_passes {
+ PASS_1_CHECK_64_BIT_BARS = 0,
+ PASS_2_CHECK_32_BIT_BARS = 1,
+ PASS_3_CHECK_DEVS_WITH_OPROMS = 2,
+ MAX_PASS = PASS_3_CHECK_DEVS_WITH_OPROMS
+};
+
+/** @brief finds the enabled, non root-bus, pci device using the most memory.
+ *
+ * @return pointer to the device
+ */
+struct device *find_pci_dev_max_mem(void)
+{
+ struct device *dev;
+ struct device *largest_dev = NULL;
+ struct resource *res;
+ uint64_t memory_used = 0;
+ uint64_t most_memory_used = 0;
+ uint8_t pass;
+
+ for (pass = PASS_1_CHECK_64_BIT_BARS; pass <= MAX_PASS; pass++) {
+
+ /*
+ * Loop through all pci devices that are not on bus 0,
+ * skipping them if they're disabled, checking to see
+ * which uses the most memory.
+ */
+ for (dev = &dev_root; dev; dev = dev->next) {
+
+ /* Skip disabled, root bus, and non-pci devices */
+ if ((!(dev->path.type == DEVICE_PATH_PCI)) ||
+ (dev->bus->secondary == 0) ||
+ (dev->enabled == 0))
+ continue;
+
+ /* Total the memory used by the device */
+ memory_used = 0;
+ for (res = dev->resource_list; res; res = res->next) {
+
+ /* don't check 32-bit bars on the first pass */
+ if (pass == PASS_1_CHECK_64_BIT_BARS &&
+ ((res->flags & IORESOURCE_PCI64) == 0))
+ continue;
+
+ /* skip devices with option roms until last */
+ if ((pass < PASS_3_CHECK_DEVS_WITH_OPROMS)
+ && (res->index == PCI_ROM_ADDRESS)) {
+ memory_used = 0;
+ break;
+ }
+
+ if (res->flags & IORESOURCE_MEM)
+ memory_used += res->size;
+ }
+
+ /* Save the largest device found so far */
+ if (memory_used > most_memory_used) {
+ most_memory_used = memory_used;
+ largest_dev = dev;
+ }
+ }
+
+ /* break out of the pass loop when we find a device */
+ if (largest_dev != NULL)
+ break;
+ }
+
+ return largest_dev;
+}
+
+/** @brief clear all non-pnp resources.
+ *
+ */
+void clear_computed_resources(void)
+{
+ struct device *dev;
+
+ /*
+ * Loop through all non-pnp devices, clearing everything except index
+ * and the pointer to the next resource. This keeps them from having
+ * to be re-allocated.
+ */
+ for (dev = &dev_root; dev; dev = dev->next) {
+
+ //skip pnp devices - their resources are set early
+ if (dev->path.type == DEVICE_PATH_PNP)
+ continue;
+
+ clear_device_resources(dev);
+ }
+}
+
+/** @brief clear all resources for a specified device. Leave index and next.
+ *
+ */
+static void clear_device_resources(struct device *dev)
+{
+ struct resource *res;
+
+ for (res = dev->resource_list; res; res = res->next) {
+ res->align = 0;
+ res->base = 0;
+ res->flags = 0;
+ res->gran = 0;
+ res->limit = 0;
+ res->size = 0;
+ }
+}
diff --git a/src/device/pci_device.c b/src/device/pci_device.c
index 5123229..dfc290b 100644
--- a/src/device/pci_device.c
+++ b/src/device/pci_device.c
@@ -248,27 +248,49 @@ struct resource *pci_get_resource(struct device *dev, unsigned long index)
resource->limit = 0xffff;
} else {
/* A Memory mapped base address. */
- attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
- resource->flags |= IORESOURCE_MEM;
- if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH)
- resource->flags |= IORESOURCE_PREFETCH;
- attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
- if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
- /* 32bit limit. */
- resource->limit = 0xffffffffUL;
- } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
- /* 1MB limit. */
- resource->limit = 0x000fffffUL;
- } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
- /* 64bit limit. */
- resource->limit = 0xffffffffffffffffULL;
- resource->flags |= IORESOURCE_PCI64;
+ if (CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE &&
+ (resource->size > CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE)) {
+ /* Disable devices that attempt to allocate a BAR beyond
+ the max configured size. */
+ printk(BIOS_WARNING,
+ "Device at %s requested a 0x%llx byte BAR ",
+ dev_path(dev),
+ (unsigned long long)resource->size);
+ printk(BIOS_WARNING,
+ "for register 0x%02lx.\n",
+ index);
+ printk(BIOS_WARNING,
+ "The device exceeded largest allowed size of 0x%lx. ",
+ (unsigned long)
+ CONFIG_MAX_MEM_BAR_SIZE_TO_ALLOCATE);
+ printk(BIOS_WARNING, "Device disabled.\n");
+ dev->enabled = 0;
+ clear_device_resources(dev);
} else {
- /* Invalid value. */
- printk(BIOS_ERR, "Broken BAR with value %lx\n", attr);
- printk(BIOS_ERR, " on dev %s at index %02lx\n",
- dev_path(dev), index);
- resource->flags = 0;
+ attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
+ resource->flags |= IORESOURCE_MEM;
+ if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH)
+ resource->flags |= IORESOURCE_PREFETCH;
+ attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
+ if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
+ /* 32bit limit. */
+ resource->limit = 0xffffffffUL;
+ } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
+ /* 1MB limit. */
+ resource->limit = 0x000fffffUL;
+ } else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
+ /* 64bit limit. */
+ resource->limit = 0xffffffffffffffffULL;
+ resource->flags |= IORESOURCE_PCI64;
+ } else {
+ /* Invalid value. */
+ printk(BIOS_ERR,
+ "Broken BAR with value %lx\n",
+ attr);
+ printk(BIOS_ERR, " on dev %s at index %02lx\n",
+ dev_path(dev), index);
+ resource->flags = 0;
+ }
}
}
@@ -344,6 +366,8 @@ static void pci_read_bases(struct device *dev, unsigned int howmany)
(index < PCI_BASE_ADDRESS_0 + (howmany << 2));) {
struct resource *resource;
resource = pci_get_resource(dev, index);
+ if (dev->enabled == 0)
+ return;
index += (resource->flags & IORESOURCE_PCI64) ? 8 : 4;
}
diff --git a/src/include/device/device.h b/src/include/device/device.h
index 62460ae..c857dd2 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -234,6 +234,10 @@ void fixed_mem_resource(device_t dev, unsigned long index,
void scan_smbus(device_t bus);
void scan_lpc_bus(device_t bus);
+struct device *find_pci_dev_max_mem(void);
+void clear_computed_resources(void);
+void clear_device_resources(struct device *dev);
+
/* It is the caller's responsibility to adjust regions such that ram_resource()
* and mmio_resource() do not overlap.
*/