From 27ca9620581920aaaf3a657553bce0e42477523f Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Thu, 6 Jun 2019 16:53:59 -0600 Subject: [PATCH 001/221] nb/amd/amdfam10: die() on out of bounds reads These two functions try to access arrays of lengths 32 and 64 at indices of at most 259 and 71 (respectively). Something here is seriously wrong. This code was introduced in 2007, and aside from cosmetic changes, has had no modifications since then. I don't know what this code is supposed to do, and asking around on IRC, no one else did either. Until someone has the interest and time to work on it, let's at least add a die() to prevent the out of bounds access and alert the user that something is wrong. Change-Id: I5fc15a50a9f0e97add31e3a40da82a15f7427358 Signed-off-by: Jacob Garber Found-by: Coverity CID 12296{79-82} Reviewed-on: https://review.coreboot.org/c/coreboot/+/33404 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans --- src/northbridge/amd/amdfam10/ht_config.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/northbridge/amd/amdfam10/ht_config.c b/src/northbridge/amd/amdfam10/ht_config.c index 4810b99b59..8499dbb623 100644 --- a/src/northbridge/amd/amdfam10/ht_config.c +++ b/src/northbridge/amd/amdfam10/ht_config.c @@ -14,6 +14,7 @@ */ #include +#include #include #include @@ -127,6 +128,10 @@ u32 get_io_addr_index(u32 nodeid, u32 linkn) u32 index; for (index = 0; index < 256; index++) { + + if (index + 4 >= ARRAY_SIZE(sysconf.conf_io_addrx)) + die("Error! Out of bounds read in %s:%s\n", __FILE__, __func__); + if (sysconf.conf_io_addrx[index+4] == 0) { sysconf.conf_io_addr[index+4] = (nodeid & 0x3f); sysconf.conf_io_addrx[index+4] = 1 | ((linkn & 0x7)<<4); @@ -142,6 +147,10 @@ u32 get_mmio_addr_index(u32 nodeid, u32 linkn) u32 index; for (index = 0; index < 64; index++) { + + if (index + 8 >= ARRAY_SIZE(sysconf.conf_mmio_addrx)) + die("Error! Out of bounds read in %s:%s\n", __FILE__, __func__); + if (sysconf.conf_mmio_addrx[index+8] == 0) { sysconf.conf_mmio_addr[index+8] = (nodeid & 0x3f); sysconf.conf_mmio_addrx[index+8] = 1 | ((linkn & 0x7)<<4); From 7945f7541717f07c038a0fa4c38130bb1128e2d8 Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Wed, 27 Feb 2019 19:57:23 +0100 Subject: [PATCH 002/221] lint/clang-format: set to 96 chars per line coreboot has decided to go with 96 characters per line. Original Signed-off-by: Patrick Georgi Original Reviewed-on: https://review.coreboot.org/c/coreboot/+/31651 Change-Id: I9c99e5cca6548e23cf755dc37193ff2aa669ac10 Signed-off-by: Martin Roth Reviewed-on: https://review.coreboot.org/c/coreboot/+/33405 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese Reviewed-by: Werner Zeh --- .clang-format | 2 +- util/lint/lint-007-checkpatch | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.clang-format b/.clang-format index d853f50480..5c8aa3c439 100644 --- a/.clang-format +++ b/.clang-format @@ -7,7 +7,7 @@ AllowShortIfStatementsOnASingleLine: false IndentCaseLabels: false SortIncludes: false ContinuationIndentWidth: 8 -ColumnLimit: 0 +ColumnLimit: 96 AlwaysBreakBeforeMultilineStrings: true AllowShortLoopsOnASingleLine: false AllowShortFunctionsOnASingleLine: false diff --git a/util/lint/lint-007-checkpatch b/util/lint/lint-007-checkpatch index afa593e3b0..a7b63e8d7c 100755 --- a/util/lint/lint-007-checkpatch +++ b/util/lint/lint-007-checkpatch @@ -28,6 +28,8 @@ EXCLUDED_DIRS="^payloads/libpayload/util/kconfig\|\ ^src/vendorcode\|\ ^Documentation" +opts="--max-line-length 96" + # default: test src and util if [ "$1" = "" ]; then INCLUDED_DIRS="src util" @@ -35,7 +37,7 @@ if [ "$1" = "" ]; then elif [ "$1" = "diff" ]; then args=$( echo $EXCLUDED_DIRS | \ sed -e 's,\\|, ,g' -e 's,\^,--exclude=,g' ) - util/lint/checkpatch.pl --quiet --no-signoff $args - + util/lint/checkpatch.pl --quiet --no-signoff $opts $args - exit $? # Space separated list of directories to test else @@ -49,5 +51,5 @@ FILELIST=$( git ls-files $INCLUDED_DIRS | \ grep -v $EXCLUDED_DIRS ) for FILE in $FILELIST; do - util/lint/checkpatch.pl --show-types --file --quiet "$FILE" + util/lint/checkpatch.pl --show-types --file --quiet $opts "$FILE" done From de666dc9b86452d5efbda70aa2364877d2fcd449 Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Thu, 13 Jun 2019 10:46:54 -0700 Subject: [PATCH 003/221] mb/google/sarien: Disable unused GPIOs These 4 GPIOs are being disconnected in the next board so use the board ID to configure these pins as not connected to ensure they do not cause leakage. Also remove the ACPI _PTS S5 code that was configuring the GPIOs. This does mean they will cause small leakage in S5 on existing boards, but it will not affect the new boards. BUG=b:132393441 TEST=boot on sarien with fake board ID and ensure that coreboot configures these pads as expected. Change-Id: I6ac04b9a635829811a09aeab7cba3bb58cfcff47 Signed-off-by: Duncan Laurie Reviewed-on: https://review.coreboot.org/c/coreboot/+/33450 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh Reviewed-by: Bora Guvendik --- src/mainboard/google/sarien/ramstage.c | 12 ++++++++++++ .../arcada/include/variant/acpi/mainboard.asl | 9 --------- .../sarien/include/variant/acpi/mainboard.asl | 9 --------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/mainboard/google/sarien/ramstage.c b/src/mainboard/google/sarien/ramstage.c index 1d220461cf..811afa1b16 100644 --- a/src/mainboard/google/sarien/ramstage.c +++ b/src/mainboard/google/sarien/ramstage.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -60,6 +61,13 @@ void smbios_fill_dimm_locator(const struct dimm_info *dimm, } #endif +static const struct pad_config gpio_unused[] = { +/* SUSWARN# */ PAD_NC(GPP_A13, NONE), +/* SUSACK# */ PAD_NC(GPP_A15, NONE), +/* M2_SKT2_CFG0 */ PAD_NC(GPP_H12, NONE), +/* M2_SKT2_CFG1 */ PAD_NC(GPP_H13, NONE), +}; + void mainboard_silicon_init_params(FSP_S_CONFIG *params) { const struct pad_config *gpio_table; @@ -67,6 +75,10 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *params) gpio_table = variant_gpio_table(&num_gpios); cnl_configure_pads(gpio_table, num_gpios); + + /* Disable unused pads for devices with board ID > 2 */ + if (board_id() > 2) + gpio_configure_pads(gpio_unused, ARRAY_SIZE(gpio_unused)); } static void mainboard_enable(struct device *dev) diff --git a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl index 4b05ba8e90..41121d28fe 100644 --- a/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl +++ b/src/mainboard/google/sarien/variants/arcada/include/variant/acpi/mainboard.asl @@ -15,8 +15,6 @@ #define CAM_EN GPP_B11 /* Active low */ #define TS_PD GPP_E7 -#define SSD_EN GPP_H13 -#define SSD_RST GPP_H12 /* Method called from LPIT prior to enter s0ix state */ Method (MS0X, 1) @@ -37,13 +35,6 @@ Method (MPTS, 1) /* Clear touch screen pd pin to avoid leakage */ \_SB.PCI0.CTXS (TS_PD) - - /* Clear SSD EN adn RST pin to avoid leakage */ - If (Arg0 == 5) { - \_SB.PCI0.CTXS (SSD_RST) - Sleep(1) - \_SB.PCI0.CTXS (SSD_EN) - } } /* Method called from _WAK prior to wakeup */ diff --git a/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl b/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl index 4b05ba8e90..41121d28fe 100644 --- a/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl +++ b/src/mainboard/google/sarien/variants/sarien/include/variant/acpi/mainboard.asl @@ -15,8 +15,6 @@ #define CAM_EN GPP_B11 /* Active low */ #define TS_PD GPP_E7 -#define SSD_EN GPP_H13 -#define SSD_RST GPP_H12 /* Method called from LPIT prior to enter s0ix state */ Method (MS0X, 1) @@ -37,13 +35,6 @@ Method (MPTS, 1) /* Clear touch screen pd pin to avoid leakage */ \_SB.PCI0.CTXS (TS_PD) - - /* Clear SSD EN adn RST pin to avoid leakage */ - If (Arg0 == 5) { - \_SB.PCI0.CTXS (SSD_RST) - Sleep(1) - \_SB.PCI0.CTXS (SSD_EN) - } } /* Method called from _WAK prior to wakeup */ From 6ff848aaf811789460f7bf6f0f89f71aa7fe8bee Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Thu, 13 Jun 2019 11:07:04 -0700 Subject: [PATCH 004/221] ec/google/wilco: Read back from EC RAM after S0ix entry We are seeing an EC interrupt after setting the EC RAM offset that indicates that the EC should transition to S0ix mode and this is preventing the kernel from going into S0ix on the first try. As a workaround if we read back from the EC RAM while still in the _DSM handler it seems to prevent this problem. BUG=b:130644677 BRANCH=sarien TEST=ensure s0ix entry works on the first try with sarien Change-Id: Id607c4c2b14b79d0cd1bcea0c2032be2f2c0c141 Signed-off-by: Duncan Laurie Reviewed-on: https://review.coreboot.org/c/coreboot/+/33455 Reviewed-by: Shaunak Saha Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/ec/google/wilco/acpi/ec.asl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ec/google/wilco/acpi/ec.asl b/src/ec/google/wilco/acpi/ec.asl index 4fa887b1b4..532f421780 100644 --- a/src/ec/google/wilco/acpi/ec.asl +++ b/src/ec/google/wilco/acpi/ec.asl @@ -154,6 +154,12 @@ Device (EC0) If (Arg0) { Printf ("EC Enter S0ix") W (CSEX, One) + + /* + * Read back from EC RAM after enabling S0ix + * to prevent EC from aborting S0ix entry. + */ + R (EVT1) } Else { Printf ("EC Exit S0ix") W (CSEX, Zero) From 6440cb6945df740648ab3193a7d2025527b84522 Mon Sep 17 00:00:00 2001 From: Paul Fagerburg Date: Thu, 13 Jun 2019 14:38:08 -0600 Subject: [PATCH 005/221] mb/google/hatch/variants/helios: Use LPDDR3 memory Change the SPD makefile to use the LPDDR3 SPDs. Set up the arrays for mapping SoC DQS pins to LPDDR3 pins. BRANCH=none BUG=b:133455595 TEST=`FEATURES="noclean" FW_NAME="helios" emerge-hatch chromeos-ec depthcharge vboot_reference libpayload coreboot-private-files intel-cmlfsp coreboot-private-files-hatch coreboot chromeos-bootimage` Ensure the firmware builds without error. Change-Id: Iebaba2ec65dfcf36674b4733b421ada107b22b09 Signed-off-by: Paul Fagerburg Reviewed-on: https://review.coreboot.org/c/coreboot/+/33456 Reviewed-by: Furquan Shaikh Reviewed-by: Shelley Chen Reviewed-by: Tim Wawrzynczak Tested-by: build bot (Jenkins) --- .../google/hatch/variants/helios/Makefile.inc | 10 ++- .../google/hatch/variants/helios/memory.c | 68 +++++++++++++++++++ 2 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 src/mainboard/google/hatch/variants/helios/memory.c diff --git a/src/mainboard/google/hatch/variants/helios/Makefile.inc b/src/mainboard/google/hatch/variants/helios/Makefile.inc index cf6ee5ac97..ddafa3297f 100644 --- a/src/mainboard/google/hatch/variants/helios/Makefile.inc +++ b/src/mainboard/google/hatch/variants/helios/Makefile.inc @@ -12,9 +12,7 @@ ## GNU General Public License for more details. ## -SPD_SOURCES = 4G_2400 # 0b000 -SPD_SOURCES += empty_ddr4 # 0b001 -SPD_SOURCES += 8G_2400 # 0b010 -SPD_SOURCES += 8G_2666 # 0b011 -SPD_SOURCES += 16G_2400 # 0b100 -SPD_SOURCES += 16G_2666 # 0b101 +SPD_SOURCES = LP_8G_2133 # 0b0000 +SPD_SOURCES += LP_16G_2133 # 0b0001 + +romstage-y += memory.c diff --git a/src/mainboard/google/hatch/variants/helios/memory.c b/src/mainboard/google/hatch/variants/helios/memory.c new file mode 100644 index 0000000000..64b4cac8d0 --- /dev/null +++ b/src/mainboard/google/hatch/variants/helios/memory.c @@ -0,0 +1,68 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018 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 +#include +#include +#include + +static const struct cnl_mb_cfg baseboard_memcfg = { + /* + * The dqs_map arrays map the SoC pins to the lpddr3 pins + * for both channels. + * + * "The index of the array is CPU byte number, the values are DRAM byte + * numbers." - doc #573387 + * + * the index = pin number on SoC + * the value = pin number on lpddr3 part + */ + .dqs_map[DDR_CH0] = {4, 7, 5, 6, 0, 3, 2, 1}, + .dqs_map[DDR_CH1] = {0, 3, 2, 1, 4, 7, 6, 5}, + + .dq_map[DDR_CH0] = { + {0xf0, 0xf}, + {0x0, 0xf}, + {0xf0, 0xf}, + {0xf0, 0x0}, + {0xff, 0x0}, + {0xff, 0x0} + }, + .dq_map[DDR_CH1] = { + {0xf, 0xf0}, + {0x0, 0xf0}, + {0xf, 0xf0}, + {0xf, 0x0}, + {0xff, 0x0}, + {0xff, 0x0} + }, + + /* Helios uses 200, 80.6 and 162 rcomp resistors */ + .rcomp_resistor = {200, 81, 162}, + + /* Helios Rcomp target values */ + .rcomp_targets = {100, 40, 40, 23, 40}, + + /* Set CaVref config to 0 for LPDDR3 */ + .vref_ca_config = 0, + + /* Disable Early Command Training */ + .ect = 0, +}; + +void variant_memory_params(struct cnl_mb_cfg *bcfg) +{ + memcpy(bcfg, &baseboard_memcfg, sizeof(baseboard_memcfg)); +} From cc480096317fde0563935a82ade7126d4efe1d8c Mon Sep 17 00:00:00 2001 From: Pavel Sayekat Date: Thu, 13 Jun 2019 19:43:14 +0600 Subject: [PATCH 006/221] util/superiotool/nuvoton.c: add NCT5539D register dump Values taken from NCT5539D datasheet V1.1 (June 30th, 2015). Tested on ASUS-H110M-E/M.2 mainboard (Kabylake i3-7100 CPU). Change-Id: Ib55068035ca574b22d0fea81e1a291f7cf0329d3 Signed-off-by: Pavel Sayekat Reviewed-on: https://review.coreboot.org/c/coreboot/+/33421 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: Felix Held --- util/superiotool/nuvoton.c | 62 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/util/superiotool/nuvoton.c b/util/superiotool/nuvoton.c index 82772e78a7..75522441e6 100644 --- a/util/superiotool/nuvoton.c +++ b/util/superiotool/nuvoton.c @@ -582,6 +582,68 @@ static const struct superio_registers reg_table[] = { {0x30,0xe0,0xe1,0xe2,0xe3,EOT}, {0x20,0x20,0x04,0x05,0x01,EOT}}, {EOT}}}, + {0xd121, "NCT5539D", { + {NOLDN, NULL, + {0x10,0x11,0x13,0x14,0x1a,0x1b,0x1c,0x1d,0x22,0x24, + 0x25,0x26,0x27,0x28,0x2a,0x2b,0x2c,0x2d,0x2f,EOT}, + {0xff,0xff,0x00,0x00,0x30,0x50,0x10,0x00,0xff,0x04, + 0x00,MISC,0x03,0x00,0xc0,0x00,0x01,MISC,MISC,EOT}}, + {0x02, "UART A", + {0x30,0x60,0x61,0x70,0xf0,0xf2,EOT}, + {0x01,0x03,0xf8,0x04,0x00,0x00,EOT}}, + {0x05, "Keyboard Controller", + {0x30,0x60,0x61,0x62,0x63,0x70,0x72,0xf0,EOT}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,EOT}}, + {0x06, "CIR", + {0x30,0x60,0x61,0x70,EOT}, + {0x00,0x00,0x00,0x00,EOT}}, + {0x07, "GPIO 7, GPIO 8", + {0x30,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xec,0xed,EOT}, + {0x00,0xff,NANA,0x00,NANA,0xff,NANA,0x00,NANA,0x00,0x00,EOT}}, + {0x08, "WDT1, WDT3, GPIO 0, KBC P20", + {0x30,0x60,0x61,0xe0,0xe1,0xe2,0xe3,0xe4,0xf5,0xf6, + 0xf7,0xf8,0xf9,0xfa,0xfe,0xff,EOT}, + {0x00,0x00,0x00,0xff,NANA,0x00,NANA,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00, 0x00,EOT}}, + {0x09, "GPIO 2, GPIO 3, GPIO 4, GPIO 5", + {0x30,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8, + 0xe9,0xea,0xeb,0xee, 0xf0,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,EOT}, + {0x00,0xff,NANA,0x00,NANA,0x7f,NANA,0x00,NANA,NANA, + 0x00,0x00,0x00,0x00,0xff,NANA,0x00,0xff,NANA,0x00,NANA,EOT}}, + {0x0a, "ACPI", + {0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe9,0xec, + 0xed,0xee,0xf0,0xf1,0xf2,0xf3,0xf6,0xf7,0xfc,EOT}, + {0x01,0x00,0x00,0x00,0x00,0x02,0x1a,0x00,0x00,0x00, + 0x01,0x00,0x10,0x48,0x5c,0x00,0x00,0xc0,0x80,EOT}}, + {0x0b, "Hardware Monitor, Front Panel LED", + {0x30,0x60,0x61,0x70,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5, + 0xe6,0xe7,0xec,0xed,0xf0,0xf1,0xf2,0xf6,0xf7,0xf8, + 0xf9,0xfa,0xfb,0xfc,EOT}, + {0x00,0x00,0x00,0x00,0x7f,0x7f,0x7f,0x7f,0x7f,0xa8, + 0x08,0x7f,0x00,0x81,0x00,0x00,0x00,0x00,0x87,0x47, + 0x00,0x00,0x00,0x02,EOT}}, + {0x0d, "BCLK, WDT2", + {0xe7,0xe8,0xeb,0xed,0xf0,0xf3,EOT}, + {0x10,0x32,0x14,0x00,0x00,0x00,EOT}}, + {0x0e, "CIR Wake-Up", + {0x30,0x60,0x61,0x70,EOT}, + {0x00,0x00,0x00,0x00,EOT}}, + {0x0f, "GPIO Push-Pull or Open-Drain selection", + {0xe1,0xe2,0xe3,0xe4,0xe6,0xe7,0xe9,EOT}, + {0xff,0x7f,0xff,0xff,0xff,0xff,0xff,EOT}}, + {0x11, "GPIO, RI PSOUT Wake-Up Status", + {0xe1,0xe2,0xe9,EOT}, + {0x00,0x00,0x00,EOT}}, + {0x12, "SW Error Control", + {0xe1,0xe7,0xea,0xeb,0xec,EOT}, + {0x00,0x00,0x10,0x00,0x00,EOT}}, + {0x15, "Fading LED", + {0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,EOT}, + {0xff,0x7f,0x00,0x56,0x56,0x17,0x00,0x0f,0x10,EOT}}, + {0x16, "Deep Sleep", + {0x30,0xe0,0xe1,0xe2,0xe3,EOT}, + {0xa0,0x20,0x04,0x05,0x01,EOT}}, + {EOT}}}, {EOT} }; From b31f49b9119e6a4ce13bc6ce865abd2390a4fe32 Mon Sep 17 00:00:00 2001 From: Tim Wawrzynczak Date: Tue, 28 May 2019 14:19:04 -0600 Subject: [PATCH 007/221] mainboard/google/hatch: Update Helios device tree Update Helios device tree override to match schematics. BUG=b:133182138 BRANCH=none TEST=Compiles Change-Id: I3d15fc43651a289d16ffb3cfadaea8f786e858fc Signed-off-by: Tim Wawrzynczak Reviewed-on: https://review.coreboot.org/c/coreboot/+/33050 Reviewed-by: Paul Fagerburg Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- .../hatch/variants/helios/overridetree.cb | 93 ++++++++++++++++++- 1 file changed, 88 insertions(+), 5 deletions(-) diff --git a/src/mainboard/google/hatch/variants/helios/overridetree.cb b/src/mainboard/google/hatch/variants/helios/overridetree.cb index 84f0e29afa..405f85f210 100644 --- a/src/mainboard/google/hatch/variants/helios/overridetree.cb +++ b/src/mainboard/google/hatch/variants/helios/overridetree.cb @@ -14,13 +14,15 @@ chip soc/intel/cannonlake [PchSerialIoIndexUART2] = PchSerialIoDisabled, }" + # No PCIe WiFi + register "PcieRpEnable[13]" = "0" + # Intel Common SoC Config #+-------------------+---------------------------+ #| Field | Value | #+-------------------+---------------------------+ #| I2C0 | Trackpad | #| I2C1 | Touchscreen | - #| I2C2 | Digitizer | #| I2C4 | Audio | #+-------------------+---------------------------+ register "common_soc_config" = "{ @@ -30,9 +32,6 @@ chip soc/intel/cannonlake .i2c[1] = { .speed = I2C_SPEED_FAST, }, - .i2c[2] = { - .speed = I2C_SPEED_FAST, - }, .i2c[4] = { .speed = I2C_SPEED_FAST, }, @@ -42,5 +41,89 @@ chip soc/intel/cannonlake }, }" - device domain 0 on end + device domain 0 on + device pci 14.0 on + chip drivers/usb/acpi + device usb 0.0 on + chip drivers/usb/acpi + # No Type-A port + device usb 2.2 off end + end + chip drivers/usb/acpi + # No Type-A Port + device usb 2.3 off end + end + chip drivers/usb/acpi + # No WWAN + device usb 2.5 off end + end + chip drivers/usb/acpi + # No WWAN + device usb 3.4 off end + end + end + end + end + + # Native SD Card interface unused + device pci 14.5 off end + + device pci 15.0 on + chip drivers/i2c/generic + register "hid" = ""ELAN0000"" + register "desc" = ""ELAN Touchpad"" + register "irq" = "ACPI_IRQ_EDGE_LOW(GPP_A20_IRQ)" + register "wake" = "GPE0_DW0_21" + device i2c 15 on end + end + end + + device pci 15.1 on + chip drivers/i2c/hid + register "generic.hid" = ""GDIX0000"" + register "generic.desc" = ""Goodix Touchscreen"" + register "generic.irq" = "ACPI_IRQ_EDGE_LOW(GPP_D16_IRQ)" + register "generic.probed" = "1" + register "generic.reset_gpio" = + "ACPI_GPIO_OUTPUT_ACTIVE_LOW(GPP_D15)" + register "generic.reset_delay_ms" = "10" + register "generic.reset_off_delay_ms" = "1" + register "generic.has_power_resource" = "1" + register "hid_desc_reg_offset" = "0x01" + device i2c 5d on end + end + chip drivers/generic/gpio_keys + register "name" = ""PENH"" + register "gpio" = "ACPI_GPIO_IRQ_EDGE_BOTH(GPP_A8)" + register "key.wake" = "GPE0_DW0_08" + register "key.wakeup_event_action" = "EV_ACT_ASSERTED" + register "key.dev_name" = ""EJCT"" + register "key.linux_code" = "SW_PEN_INSERTED" + register "key.linux_input_type" = "EV_SW" + register "key.label" = ""pen_eject"" + device generic 0 on end + end + end # I2C 1 + + # I2C #2 unused + device pci 15.2 off end + + # I2C #3 unused + device pci 15.3 off end + + device pci 19.0 on + chip drivers/i2c/generic + register "hid" = ""10EC5682"" + register "name" = ""RT58"" + register "desc" = ""Realtek RT5682"" + register "irq_gpio" = "ACPI_GPIO_IRQ_EDGE_BOTH(GPP_H0)" + register "property_count" = "1" + # Set the jd_src to RT5668_JD1 for jack detection + register "property_list[0].type" = "ACPI_DP_TYPE_INTEGER" + register "property_list[0].name" = ""realtek,jd-src"" + register "property_list[0].integer" = "1" + device i2c 1a on end + end + end #I2C #4 + end end From d203bc95d27ef9d76fd2c80da10b98f2c8081383 Mon Sep 17 00:00:00 2001 From: Tim Wawrzynczak Date: Wed, 12 Jun 2019 10:02:12 -0600 Subject: [PATCH 008/221] hatch: Fix pen eject wake polarity The gpio_key wakeup_event_action in the ACPI tables was backwards, causing devices to wake up on pen insertion instead of removal. Changed to EV_ACT_DEASSERTED. BUG=b:134547896 BRANCH=none TEST=Verified in OS, device only wakes up on pen removal Change-Id: I0816ed9fb23cf00fd8e40bcdd25ff7a9f48badbd Signed-off-by: Tim Wawrzynczak Reviewed-on: https://review.coreboot.org/c/coreboot/+/33427 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/mainboard/google/hatch/variants/hatch/overridetree.cb | 2 +- src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/hatch/variants/hatch/overridetree.cb b/src/mainboard/google/hatch/variants/hatch/overridetree.cb index 562bb8b229..3846b609f8 100644 --- a/src/mainboard/google/hatch/variants/hatch/overridetree.cb +++ b/src/mainboard/google/hatch/variants/hatch/overridetree.cb @@ -88,7 +88,7 @@ chip soc/intel/cannonlake register "name" = ""PENH"" register "gpio" = "ACPI_GPIO_IRQ_EDGE_BOTH(GPP_A8)" register "key.wake" = "GPE0_DW0_08" - register "key.wakeup_event_action" = "EV_ACT_ASSERTED" + register "key.wakeup_event_action" = "EV_ACT_DEASSERTED" register "key.dev_name" = ""EJCT"" register "key.linux_code" = "SW_PEN_INSERTED" register "key.linux_input_type" = "EV_SW" diff --git a/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb b/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb index eec7880752..fe7869dd4b 100644 --- a/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb +++ b/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb @@ -73,7 +73,7 @@ chip soc/intel/cannonlake register "name" = ""PENH"" register "gpio" = "ACPI_GPIO_IRQ_EDGE_BOTH(GPP_A8)" register "key.wake" = "GPE0_DW0_08" - register "key.wakeup_event_action" = "EV_ACT_ASSERTED" + register "key.wakeup_event_action" = "EV_ACT_DEASSERTED" register "key.dev_name" = ""EJCT"" register "key.linux_code" = "SW_PEN_INSERTED" register "key.linux_input_type" = "EV_SW" From 30645bff5e6c4a873d27f0d99ca2834488c0f119 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 13 May 2019 14:57:51 -0500 Subject: [PATCH 009/221] drivers/fsp1_0: select CACHE_MRC_SETTINGS if MRC_CACHE_FMAP Rather than force the user to create the RW_MRC_CACHE FMAP region, simply select CACHE_MRC_SETTINGS so it's done automatically for them. Signed-off-by: Matt DeVillier Change-Id: Iaa1da6015c1bfafe8ea81ca34ef8851f0c689487 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33453 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/drivers/intel/fsp1_0/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/drivers/intel/fsp1_0/Kconfig b/src/drivers/intel/fsp1_0/Kconfig index 361dd5ea85..d72d331a96 100644 --- a/src/drivers/intel/fsp1_0/Kconfig +++ b/src/drivers/intel/fsp1_0/Kconfig @@ -88,10 +88,11 @@ config ENABLE_MRC_CACHE config MRC_CACHE_FMAP bool "Use MRC Cache in FMAP" depends on ENABLE_MRC_CACHE + select CACHE_MRC_SETTINGS default n help Use the region "RW_MRC_CACHE" in FMAP instead of "mrc.cache" in CBFS. - You must define a region in your FMAP named "RW_MRC_CACHE". + Your FMAP must contain a region named "RW_MRC_CACHE". config MRC_CACHE_SIZE hex "Fast Boot Data Cache Size" From 3bf4e28fb83ee1550e8adc1f1dcf993ccb79bdf4 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 22 May 2019 16:57:54 +0200 Subject: [PATCH 010/221] nb/i945: Drop CHANNEL_XOR_RANDOMIZATION selection CHANNEL_XOR_RANDOMIZATION is configurable for no reason. Change-Id: I31e6ed6cb040dcba756cbfd2247d90753d372915 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32928 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/mainboard/apple/macbook21/Kconfig | 1 - src/mainboard/asus/p5gc-mx/Kconfig | 1 - src/mainboard/getac/p470/Kconfig | 1 - src/mainboard/gigabyte/ga-945gcm-s2l/Kconfig | 1 - src/mainboard/ibase/mb899/Kconfig | 1 - src/mainboard/intel/d945gclf/Kconfig | 1 - src/mainboard/kontron/986lcd-m/Kconfig | 1 - src/mainboard/lenovo/t60/Kconfig | 1 - src/mainboard/lenovo/x60/Kconfig | 1 - src/mainboard/lenovo/z61t/Kconfig | 1 - src/mainboard/roda/rk886ex/Kconfig | 1 - src/northbridge/intel/i945/Kconfig | 4 ---- src/northbridge/intel/i945/raminit.c | 4 ---- 13 files changed, 19 deletions(-) diff --git a/src/mainboard/apple/macbook21/Kconfig b/src/mainboard/apple/macbook21/Kconfig index 6535f8f7e5..84c00cfa9c 100644 --- a/src/mainboard/apple/macbook21/Kconfig +++ b/src/mainboard/apple/macbook21/Kconfig @@ -13,7 +13,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_CMOS_DEFAULT select HAVE_MP_TABLE select BOARD_ROMSIZE_KB_2048 - select CHANNEL_XOR_RANDOMIZATION select INTEL_INT15 select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME diff --git a/src/mainboard/asus/p5gc-mx/Kconfig b/src/mainboard/asus/p5gc-mx/Kconfig index 21e57bb6b2..193364ab72 100644 --- a/src/mainboard/asus/p5gc-mx/Kconfig +++ b/src/mainboard/asus/p5gc-mx/Kconfig @@ -29,7 +29,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME select BOARD_ROMSIZE_KB_512 - select CHANNEL_XOR_RANDOMIZATION select MAINBOARD_HAS_NATIVE_VGA_INIT select INTEL_GMA_HAVE_VBT diff --git a/src/mainboard/getac/p470/Kconfig b/src/mainboard/getac/p470/Kconfig index a5eed1a659..9fe40bcb8f 100644 --- a/src/mainboard/getac/p470/Kconfig +++ b/src/mainboard/getac/p470/Kconfig @@ -32,7 +32,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_ACPI_RESUME select UDELAY_LAPIC select BOARD_ROMSIZE_KB_1024 - select CHANNEL_XOR_RANDOMIZATION select INTEL_INT15 select I945_LVDS diff --git a/src/mainboard/gigabyte/ga-945gcm-s2l/Kconfig b/src/mainboard/gigabyte/ga-945gcm-s2l/Kconfig index ea3142a087..e9ed54d828 100644 --- a/src/mainboard/gigabyte/ga-945gcm-s2l/Kconfig +++ b/src/mainboard/gigabyte/ga-945gcm-s2l/Kconfig @@ -29,7 +29,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME select BOARD_ROMSIZE_KB_512 - select CHANNEL_XOR_RANDOMIZATION select MAINBOARD_HAS_NATIVE_VGA_INIT select REALTEK_8168_RESET if BOARD_GIGABYTE_GA_945GCM_S2L select INTEL_GMA_HAVE_VBT diff --git a/src/mainboard/ibase/mb899/Kconfig b/src/mainboard/ibase/mb899/Kconfig index 621395daac..fcc2e38751 100644 --- a/src/mainboard/ibase/mb899/Kconfig +++ b/src/mainboard/ibase/mb899/Kconfig @@ -14,7 +14,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_OPTION_TABLE select HAVE_ACPI_RESUME select BOARD_ROMSIZE_KB_512 - select CHANNEL_XOR_RANDOMIZATION select INTEL_INT15 config MAINBOARD_DIR diff --git a/src/mainboard/intel/d945gclf/Kconfig b/src/mainboard/intel/d945gclf/Kconfig index 70fa848bed..46d82ec5f7 100644 --- a/src/mainboard/intel/d945gclf/Kconfig +++ b/src/mainboard/intel/d945gclf/Kconfig @@ -28,7 +28,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME select BOARD_ROMSIZE_KB_512 - select CHANNEL_XOR_RANDOMIZATION select MAINBOARD_HAS_NATIVE_VGA_INIT select INTEL_GMA_HAVE_VBT diff --git a/src/mainboard/kontron/986lcd-m/Kconfig b/src/mainboard/kontron/986lcd-m/Kconfig index 43bdf14501..9dadd55cbe 100644 --- a/src/mainboard/kontron/986lcd-m/Kconfig +++ b/src/mainboard/kontron/986lcd-m/Kconfig @@ -14,7 +14,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_OPTION_TABLE select HAVE_ACPI_RESUME select BOARD_ROMSIZE_KB_1024 - select CHANNEL_XOR_RANDOMIZATION select INTEL_INT15 select OVERRIDE_CLOCK_DISABLE diff --git a/src/mainboard/lenovo/t60/Kconfig b/src/mainboard/lenovo/t60/Kconfig index a6a88b37d3..e4e87c93ef 100644 --- a/src/mainboard/lenovo/t60/Kconfig +++ b/src/mainboard/lenovo/t60/Kconfig @@ -17,7 +17,6 @@ config BOARD_SPECIFIC_OPTIONS select INTEL_INT15 select HAVE_MP_TABLE select BOARD_ROMSIZE_KB_2048 - select CHANNEL_XOR_RANDOMIZATION select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME select H8_DOCK_EARLY_INIT diff --git a/src/mainboard/lenovo/x60/Kconfig b/src/mainboard/lenovo/x60/Kconfig index 6db7f11259..e3aabf3485 100644 --- a/src/mainboard/lenovo/x60/Kconfig +++ b/src/mainboard/lenovo/x60/Kconfig @@ -19,7 +19,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_PIRQ_TABLE select HAVE_MP_TABLE select BOARD_ROMSIZE_KB_2048 - select CHANNEL_XOR_RANDOMIZATION select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME select USE_OPTION_TABLE diff --git a/src/mainboard/lenovo/z61t/Kconfig b/src/mainboard/lenovo/z61t/Kconfig index a22307712b..de48d95050 100644 --- a/src/mainboard/lenovo/z61t/Kconfig +++ b/src/mainboard/lenovo/z61t/Kconfig @@ -17,7 +17,6 @@ config BOARD_SPECIFIC_OPTIONS select INTEL_INT15 select HAVE_MP_TABLE select BOARD_ROMSIZE_KB_2048 - select CHANNEL_XOR_RANDOMIZATION select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME select H8_DOCK_EARLY_INIT diff --git a/src/mainboard/roda/rk886ex/Kconfig b/src/mainboard/roda/rk886ex/Kconfig index 821a9a1b6a..9e97529dca 100644 --- a/src/mainboard/roda/rk886ex/Kconfig +++ b/src/mainboard/roda/rk886ex/Kconfig @@ -17,7 +17,6 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME select BOARD_ROMSIZE_KB_1024 - select CHANNEL_XOR_RANDOMIZATION select INTEL_INT15 config MAINBOARD_DIR diff --git a/src/northbridge/intel/i945/Kconfig b/src/northbridge/intel/i945/Kconfig index 2c21420088..93251965c1 100644 --- a/src/northbridge/intel/i945/Kconfig +++ b/src/northbridge/intel/i945/Kconfig @@ -56,10 +56,6 @@ config I945_LVDS for the LVDS port. A linear framebuffer is only supported for LVDS. -config CHANNEL_XOR_RANDOMIZATION - bool - default n - config MMCONF_BASE_ADDRESS hex default 0xf0000000 diff --git a/src/northbridge/intel/i945/raminit.c b/src/northbridge/intel/i945/raminit.c index 797ea1229d..281e7b2679 100644 --- a/src/northbridge/intel/i945/raminit.c +++ b/src/northbridge/intel/i945/raminit.c @@ -2112,12 +2112,8 @@ static void sdram_post_jedec_initialization(struct sys_info *sysinfo) if (sysinfo->interleaved) { reg32 = MCHBAR32(DCC); -#if CONFIG(CHANNEL_XOR_RANDOMIZATION) reg32 &= ~(1 << 10); reg32 |= (1 << 9); -#else - reg32 &= ~(1 << 9); -#endif MCHBAR32(DCC) = reg32; } From 7c369c1e450ec4ffecdf770cadb21f2ca2b06b53 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Mon, 3 Jun 2019 19:02:31 -0700 Subject: [PATCH 011/221] libpayload/i8042/keyboard: Log errors during initialization Add error messages for all failed commands in keyboard_init(). Change-Id: Ie42ccbc4d850912c83e00376b27f192d5b652057 Signed-off-by: Furquan Shaikh Signed-off-by: Paul Menzel Reviewed-on: https://review.coreboot.org/c/coreboot/+/33446 Tested-by: build bot (Jenkins) --- payloads/libpayload/drivers/i8042/keyboard.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/payloads/libpayload/drivers/i8042/keyboard.c b/payloads/libpayload/drivers/i8042/keyboard.c index 3e5f988c48..48d35a07f7 100644 --- a/payloads/libpayload/drivers/i8042/keyboard.c +++ b/payloads/libpayload/drivers/i8042/keyboard.c @@ -319,25 +319,33 @@ void keyboard_init(void) /* Set scancode set 1 */ ret = keyboard_cmd(I8042_KBCMD_SET_SCANCODE); - if (!ret && !CONFIG(LP_PC_KEYBOARD_IGNORE_INIT_FAILURE)) + if (!ret && !CONFIG(LP_PC_KEYBOARD_IGNORE_INIT_FAILURE)) { + printf("ERROR: Keyboard set scancode failed!\n"); return; + } ret = keyboard_cmd(I8042_SCANCODE_SET_1); - if (!ret && !CONFIG(LP_PC_KEYBOARD_IGNORE_INIT_FAILURE)) + if (!ret && !CONFIG(LP_PC_KEYBOARD_IGNORE_INIT_FAILURE)) { + printf("ERROR: Keyboard scancode set#1 failed!\n"); return; + } /* * Set default parameters. * Fix for broken QEMU ps/2 make scancodes. */ ret = keyboard_cmd(0xf6); - if (!ret) + if (!ret) { + printf("ERROR: Keyboard set default params failed!\n"); return; + } /* Enable scanning */ ret = keyboard_cmd(I8042_KBCMD_EN); - if (!ret && !CONFIG(LP_PC_KEYBOARD_IGNORE_INIT_FAILURE)) + if (!ret && !CONFIG(LP_PC_KEYBOARD_IGNORE_INIT_FAILURE)) { + printf("ERROR: Keyboard enable scanning failed!\n"); return; + } console_add_input_driver(&cons); } From 8cf8a6375e5a9acfe418d3f48a9942d7356aac41 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 9 Jun 2019 10:23:25 +0200 Subject: [PATCH 012/221] device/cpu_device.c: Use 'unsigned int' instead of 'unsigned' Change-Id: I9f96d8c8e6cf2715e62ab3715da83740db8cce40 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33329 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans Reviewed-by: Vlado Cibic --- src/device/cpu_device.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/device/cpu_device.c b/src/device/cpu_device.c index b07b555b52..f59cce3573 100644 --- a/src/device/cpu_device.c +++ b/src/device/cpu_device.c @@ -17,7 +17,7 @@ #include #include -struct device *add_cpu_device(struct bus *cpu_bus, unsigned apic_id, +struct device *add_cpu_device(struct bus *cpu_bus, unsigned int apic_id, int enabled) { struct device_path cpu_path; @@ -42,8 +42,9 @@ struct device *add_cpu_device(struct bus *cpu_bus, unsigned apic_id, return cpu; } -void set_cpu_topology(struct device *cpu, unsigned node, unsigned package, - unsigned core, unsigned thread) +void set_cpu_topology(struct device *cpu, unsigned int node, + unsigned int package, unsigned int core, + unsigned int thread) { cpu->path.apic.node_id = node; cpu->path.apic.package_id = package; From fb5a83df3c557c9105b17b49e08219a61155c520 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Mon, 3 Jun 2019 17:17:11 -0600 Subject: [PATCH 013/221] mb/google/poppy/var/nami: Ensure SPD index is non-zero Memory id's are 1-indexed for DDR4, so we need to check that the SPD index is non-zero before converting it to the 0-indexed value in the bitmap. Change-Id: Icc542239d91c39b89c23f31856c28e7c20b2fc4d Signed-off-by: Jacob Garber Found-by: Coverity CID 1387028 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33183 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/mainboard/google/poppy/variants/nami/memory.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mainboard/google/poppy/variants/nami/memory.c b/src/mainboard/google/poppy/variants/nami/memory.c index b7f51851c7..b6e3d2cd08 100644 --- a/src/mainboard/google/poppy/variants/nami/memory.c +++ b/src/mainboard/google/poppy/variants/nami/memory.c @@ -66,8 +66,12 @@ static void fill_ddr4_memory_params(struct memory_params *p) p->type = MEMORY_DDR4; p->use_sec_spd = 0; + int spd_index = variant_memory_sku(); + if (spd_index == 0) + die("SPD index is 0\n"); + /* Rcomp resistor values are different for SDP and DDP. */ - if (ddp_bitmap & MEM_ID(variant_memory_sku())) { + if (ddp_bitmap & MEM_ID(spd_index)) { p->rcomp_resistor = rcomp_resistor_ddp; p->rcomp_resistor_size = sizeof(rcomp_resistor_ddp); } else { From 5fa1469af5b6862ca8e95a20d560f4c8a7f15204 Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Fri, 14 Jun 2019 13:36:17 +0800 Subject: [PATCH 014/221] mb/google/octopus/variants/bloog: Set tcc offset for bloog Change tcc offset from 0 to 10 degree celsius for bloog. BUG=b:135225497 BRANCH=octopus TEST=Build and verify test result by thermal team. Change-Id: I4cbff846914a776c67692005f8b40cd73cfaf231 Signed-off-by: Tony Huang Reviewed-on: https://review.coreboot.org/c/coreboot/+/33461 Tested-by: build bot (Jenkins) Reviewed-by: Marco Chen Reviewed-by: Furquan Shaikh Reviewed-by: Justin TerAvest --- src/mainboard/google/octopus/variants/bloog/overridetree.cb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mainboard/google/octopus/variants/bloog/overridetree.cb b/src/mainboard/google/octopus/variants/bloog/overridetree.cb index cf70bb3108..6c64ba78e0 100644 --- a/src/mainboard/google/octopus/variants/bloog/overridetree.cb +++ b/src/mainboard/google/octopus/variants/bloog/overridetree.cb @@ -53,6 +53,9 @@ chip soc/intel/apollolake #| I2C6 | Trackpad | #| I2C7 | Touchscreen | #+-------------------+---------------------------+ + + register "tcc_offset" = "10" + register "common_soc_config" = "{ .gspi[0] = { .speed_mhz = 1, From 74d22d403032f66eb96e73e27c201d698e07394b Mon Sep 17 00:00:00 2001 From: Tim Wawrzynczak Date: Fri, 14 Jun 2019 11:26:00 -0600 Subject: [PATCH 015/221] mainboard/google/hatch: Scrub Helios GPIOs Helios has a number of GPIO changes w/r/t to its baseboard. Override early, sleep and normal GPIOs as appropriate. BUG=b:135257452 BRANCH=none TEST=Compile only (no boards to test with) Change-Id: I45793ad6515df5af5b925d92106bd943374353d4 Signed-off-by: Tim Wawrzynczak Reviewed-on: https://review.coreboot.org/c/coreboot/+/33485 Tested-by: build bot (Jenkins) Reviewed-by: Paul Fagerburg Reviewed-by: Furquan Shaikh --- .../google/hatch/variants/helios/Makefile.inc | 2 + .../google/hatch/variants/helios/gpio.c | 128 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 src/mainboard/google/hatch/variants/helios/gpio.c diff --git a/src/mainboard/google/hatch/variants/helios/Makefile.inc b/src/mainboard/google/hatch/variants/helios/Makefile.inc index ddafa3297f..fbd69c40a9 100644 --- a/src/mainboard/google/hatch/variants/helios/Makefile.inc +++ b/src/mainboard/google/hatch/variants/helios/Makefile.inc @@ -16,3 +16,5 @@ SPD_SOURCES = LP_8G_2133 # 0b0000 SPD_SOURCES += LP_16G_2133 # 0b0001 romstage-y += memory.c +bootblock-y += gpio.c +ramstage-y += gpio.c diff --git a/src/mainboard/google/hatch/variants/helios/gpio.c b/src/mainboard/google/hatch/variants/helios/gpio.c new file mode 100644 index 0000000000..4353fc0a91 --- /dev/null +++ b/src/mainboard/google/hatch/variants/helios/gpio.c @@ -0,0 +1,128 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2019 Google 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 +#include +#include +#include + +static const struct pad_config gpio_table[] = { + /* A0 : RCIN# ==> NC */ + PAD_NC(GPP_A0, NONE), + /* A6 : SERIRQ ==> NC */ + PAD_NC(GPP_A6, NONE), + /* A18 : ISH_GP0 ==> NC */ + PAD_NC(GPP_A18, NONE), + /* A19 : ISH_GP1 ==> NC */ + PAD_NC(GPP_A19, NONE), + /* A20 : ISH_GP2 ==> NC */ + PAD_NC(GPP_A20, NONE), + /* B19 : GSPI1_CS0# ==> NC */ + PAD_NC(GPP_B19, NONE), + /* C1 : SMBDATA ==> NC */ + PAD_NC(GPP_C1, NONE), + /* C6 : GPP_C6 ==> NC */ + PAD_NC(GPP_C6, NONE), + /* C7 : GPP_C7 ==> NC */ + PAD_NC(GPP_C7, NONE), + /* C15 : UART1_CTS# ==> NC */ + PAD_NC(GPP_C15, NONE), + /* C23 : UART2_CTS# ==> NC */ + PAD_NC(GPP_C23, NONE), + /* D5 : ISH_I2C0_SDA ==> NC */ + PAD_NC(GPP_D5, NONE), + /* D6 : ISH_I2C0_SCL ==> NC */ + PAD_NC(GPP_D6, NONE), + /* D7 : ISH_I2C1_SDA ==> NC */ + PAD_NC(GPP_D7, NONE), + /* D8 : ISH_I2C1_SCL ==> NC */ + PAD_NC(GPP_D8, NONE), + /* D10 : ISH_SPI_CLK ==> EN_PP3300_PP1800_FP */ + PAD_CFG_GPO(GPP_D10, 0, DEEP), + /* D21 : SPI1_IO2 ==> NC */ + PAD_NC(GPP_D21, NONE), + /* F0 : GPP_F0 ==> NC */ + PAD_NC(GPP_F0, NONE), + /* F1 : GPP_F1 ==> NC */ + PAD_NC(GPP_F1, NONE), + /* F3 : GPP_F3 ==> MEM_STRAP_3 */ + PAD_CFG_GPI(GPP_F3, NONE, PLTRST), + /* F10 : GPP_F10 ==> MEM_STRAP_2 */ + PAD_CFG_GPI(GPP_F10, NONE, PLTRST), + /* F11 : EMMC_CMD ==> NC */ + PAD_NC(GPP_F11, NONE), + /* F20 : EMMC_RCLK ==> NC */ + PAD_NC(GPP_F20, NONE), + /* F21 : EMMC_CLK ==> NC */ + PAD_NC(GPP_F21, NONE), + /* F22 : EMMC_RESET# ==> NC */ + PAD_NC(GPP_F22, NONE), + /* G0 : GPP_G0 ==> NC */ + PAD_NC(GPP_G0, NONE), + /* G1 : GPP_G1 ==> NC */ + PAD_NC(GPP_G1, NONE), + /* G2 : GPP_G2 ==> NC */ + PAD_NC(GPP_G2, NONE), + /* G3 : GPP_G3 ==> NC */ + PAD_NC(GPP_G3, NONE), + /* G4 : GPP_G4 ==> NC */ + PAD_NC(GPP_G4, NONE), + /* G5 : GPP_G5 ==> NC */ + PAD_NC(GPP_G5, NONE), + /* G6 : GPP_G6 ==> NC */ + PAD_NC(GPP_G6, NONE), + /* H4 : I2C2_SDA ==> NC */ + PAD_NC(GPP_H4, NONE), + /* H5 : I2C2_SCL ==> NC */ + PAD_NC(GPP_H5, NONE), + /* H13 : M2_SKT2_CFG1 ==> SPKR_RST_L */ + PAD_CFG_GPO(GPP_H13, 0, PLTRST), + /* H14 : M2_SKT2_CFG2 ==> TOUCHSCREEN_STOP_L */ + PAD_CFG_GPO(GPP_H14, 0, PLTRST), + /* H19 : TIMESYNC[0] ==> MEM_STRAP_0 */ + PAD_CFG_GPI(GPP_H19, NONE, PLTRST), + /* H22 : MEM_STRAP_1 */ + PAD_CFG_GPI(GPP_H22, NONE, PLTRST), +}; + +const struct pad_config *override_gpio_table(size_t *num) +{ + *num = ARRAY_SIZE(gpio_table); + return gpio_table; +} + +/* GPIOs configured before ramstage */ +static const struct pad_config early_gpio_table[] = { + PAD_NC(GPP_C23, NONE), +}; + +const struct pad_config *override_early_gpio_table(size_t *num) +{ + *num = ARRAY_SIZE(early_gpio_table); + return early_gpio_table; +} + +/* + * GPIO settings before entering all sleep states + */ +static const struct pad_config sleep_gpio_table[] = { + PAD_CFG_GPO(GPP_A12, 1, DEEP), /* FPMCU_RST_ODL */ +}; + +const struct pad_config *variant_sleep_gpio_table(u8 slp_typ, size_t *num) +{ + *num = ARRAY_SIZE(sleep_gpio_table); + return sleep_gpio_table; +} From e94335e9fd00ee5c707eb927922ef09b9487c5d6 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Tue, 4 Jun 2019 11:35:14 -0600 Subject: [PATCH 016/221] nb/amd/amdmct/mct: Simplify conditional These if statements can be combined to merge the two branches of the conditional and remove the duplicate pDCTstat->Speed == 3 check. Change-Id: I41aa19b4b7ed7b1a0e4f83f72e66869760e677dd Signed-off-by: Jacob Garber Found-by: Coverity CID 1229583 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33211 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/northbridge/amd/amdmct/mct/mctardk3.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/northbridge/amd/amdmct/mct/mctardk3.c b/src/northbridge/amd/amdmct/mct/mctardk3.c index ce79a5245b..4eac790d5c 100644 --- a/src/northbridge/amd/amdmct/mct/mctardk3.c +++ b/src/northbridge/amd/amdmct/mct/mctardk3.c @@ -90,21 +90,13 @@ void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat, valx &= 0xAA; valx >>= 1; } - if (mctGet_NVbits(NV_MAX_DIMMS) == 8) { - val &= valx; - if (val != 0) { + val &= valx; + if (val != 0) { + if (mctGet_NVbits(NV_MAX_DIMMS) == 8 || + pDCTstat->Speed == 3) { pDCTstat->CH_ADDR_TMG[dct] &= 0xFFFF00FF; pDCTstat->CH_ADDR_TMG[dct] |= 0x00002F00; } - } else { - val &= valx; - if (val != 0) { - if (pDCTstat->Speed == 3 || pDCTstat->Speed == 3) { - pDCTstat->CH_ADDR_TMG[dct] &= 0xFFFF00FF; - pDCTstat->CH_ADDR_TMG[dct] |= 0x00002F00; - } - } - } } } From d844431af09aafd65656f77b699c737966b30086 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Mon, 10 Jun 2019 13:47:56 +0200 Subject: [PATCH 017/221] vendorcode/agesa: Fix check for valid PhyLane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found using GCC with flag -Wlogical-op Change-Id: Ia04ac5b1d0a4434c0ab2ca583b9b03dbfd0ffd41 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33362 Reviewed-by: Kyösti Mälkki Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- .../agesa/f12/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c | 2 +- .../agesa/f14/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c | 2 +- .../agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c | 2 +- .../agesa/f16kb/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vendorcode/amd/agesa/f12/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c b/src/vendorcode/amd/agesa/f12/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c index ee7ef01035..c76b290727 100644 --- a/src/vendorcode/amd/agesa/f12/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c +++ b/src/vendorcode/amd/agesa/f12/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c @@ -202,7 +202,7 @@ PcieConfigGetNumberOfPhyLane ( IN PCIe_ENGINE_CONFIG *Engine ) { - if (Engine->EngineData.StartLane >= UNUSED_LANE_ID || Engine->EngineData.StartLane >= UNUSED_LANE_ID) { + if (Engine->EngineData.StartLane >= UNUSED_LANE_ID || Engine->EngineData.EndLane >= UNUSED_LANE_ID) { return 0; } if (Engine->EngineData.StartLane > Engine->EngineData.EndLane) { diff --git a/src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c b/src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c index 788c0b779a..dae9899683 100644 --- a/src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c +++ b/src/vendorcode/amd/agesa/f14/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c @@ -178,7 +178,7 @@ PcieConfigGetNumberOfPhyLane ( IN PCIe_ENGINE_CONFIG *Engine ) { - if (Engine->EngineData.StartLane >= UNUSED_LANE_ID || Engine->EngineData.StartLane >= UNUSED_LANE_ID) { + if (Engine->EngineData.StartLane >= UNUSED_LANE_ID || Engine->EngineData.EndLane >= UNUSED_LANE_ID) { return 0; } if (Engine->EngineData.StartLane > Engine->EngineData.EndLane) { diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c b/src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c index 6466862194..9b7bcbded2 100644 --- a/src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c +++ b/src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c @@ -205,7 +205,7 @@ PcieConfigGetNumberOfPhyLane ( IN PCIe_ENGINE_CONFIG *Engine ) { - if (Engine->EngineData.StartLane >= UNUSED_LANE_ID || Engine->EngineData.StartLane >= UNUSED_LANE_ID) { + if (Engine->EngineData.StartLane >= UNUSED_LANE_ID || Engine->EngineData.EndLane >= UNUSED_LANE_ID) { return 0; } if (Engine->EngineData.StartLane > Engine->EngineData.EndLane) { diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c b/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c index 8e5e3dd43a..27e7bcefda 100644 --- a/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c +++ b/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbPcieConfig/PcieConfigLib.c @@ -205,7 +205,7 @@ PcieConfigGetNumberOfPhyLane ( IN PCIe_ENGINE_CONFIG *Engine ) { - if (Engine->EngineData.StartLane >= UNUSED_LANE_ID || Engine->EngineData.StartLane >= UNUSED_LANE_ID) { + if (Engine->EngineData.StartLane >= UNUSED_LANE_ID || Engine->EngineData.EndLane >= UNUSED_LANE_ID) { return 0; } if (Engine->EngineData.StartLane > Engine->EngineData.EndLane) { From a360d9a6bf6556a7e73c40f257e807a73964bb70 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Tue, 11 Jun 2019 13:18:04 +0200 Subject: [PATCH 018/221] vendorcode/agesa/*/Proc/IDS/Library/IdsLib.c: Fix logical 'or' tests "if (_pcidata != 0xFFFFFFFF || _pcidata != 0)", is always true. The right test should be && not ||. Error found using -Wlogical-op warning option. Change-Id: I537fa4867499e1e6e5f662086fabc99b91aa0c70 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33392 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/vendorcode/amd/agesa/f15tn/Proc/IDS/Library/IdsLib.c | 2 +- src/vendorcode/amd/agesa/f16kb/Proc/IDS/Library/IdsLib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/IDS/Library/IdsLib.c b/src/vendorcode/amd/agesa/f15tn/Proc/IDS/Library/IdsLib.c index 34a12a78e6..046d1826aa 100644 --- a/src/vendorcode/amd/agesa/f15tn/Proc/IDS/Library/IdsLib.c +++ b/src/vendorcode/amd/agesa/f15tn/Proc/IDS/Library/IdsLib.c @@ -900,7 +900,7 @@ IdsCheckPciExisit ( _pciaddr = PciAddr; _pciaddr.Address.Register = 0; LibAmdPciRead (AccessWidth32, _pciaddr, &_pcidata, StdHeader); - if (_pcidata != 0xFFFFFFFF || _pcidata != 0) { + if (_pcidata != 0xFFFFFFFF && _pcidata != 0) { status = TRUE; } return status; diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/IDS/Library/IdsLib.c b/src/vendorcode/amd/agesa/f16kb/Proc/IDS/Library/IdsLib.c index 0cb0a63680..b7a49b27f1 100644 --- a/src/vendorcode/amd/agesa/f16kb/Proc/IDS/Library/IdsLib.c +++ b/src/vendorcode/amd/agesa/f16kb/Proc/IDS/Library/IdsLib.c @@ -983,7 +983,7 @@ IdsCheckPciExisit ( _pciaddr = PciAddr; _pciaddr.Address.Register = 0; LibAmdPciRead (AccessWidth32, _pciaddr, &_pcidata, StdHeader); - if (_pcidata != 0xFFFFFFFF || _pcidata != 0) { + if (_pcidata != 0xFFFFFFFF && _pcidata != 0) { status = TRUE; } return status; From 8c03542f921459008242f290304f83b51c3c1f2d Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Tue, 11 Jun 2019 06:42:52 +0200 Subject: [PATCH 019/221] Makefile.inc: Add -Wlogical-op warning option Change-Id: Ie0491817a3a69c9f8e6f0f0d3cb755c642819df9 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33385 Reviewed-by: Arthur Heymans Reviewed-by: Angel Pons Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc index 14cd50c79d..2ba9446fdf 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -400,7 +400,7 @@ endif CFLAGS_common += -pipe -g -nostdinc -std=gnu11 CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes -CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs +CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -Wlogical-op CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie From 6f75154656d93eebee52b046d862b3f852ce2a67 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sat, 8 Jun 2019 11:28:52 +0200 Subject: [PATCH 020/221] arch/x86/Kconfig: Hide the prefix option on all but BOOTBLOCK_NORMAL Change-Id: Icf5e8fa18bea1cdfb85b8a4999d8fccea94d16b9 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33324 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/Kconfig | 7 ++++++- src/arch/x86/Kconfig | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Kconfig b/src/Kconfig index 5d74d671b2..72d826f43f 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -32,8 +32,13 @@ config LOCALVERSION the coreboot version number, so that you can easily distinguish boot logs of different boards from each other. +config CONFIGURABLE_CBFS_PREFIX + bool + help + Select this to prompt to use to configure the prefix for cbfs files. + config CBFS_PREFIX - string "CBFS prefix to use" + string "CBFS prefix to use" if CONFIGURABLE_CBFS_PREFIX default "fallback" help Select the prefix to all files put into the image. It's "fallback" diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig index 827c1cba02..5b1304fedb 100644 --- a/src/arch/x86/Kconfig +++ b/src/arch/x86/Kconfig @@ -247,6 +247,7 @@ config BOOTBLOCK_SIMPLE bool "Always load fallback" config BOOTBLOCK_NORMAL + select CONFIGURABLE_CBFS_PREFIX bool "Switch to normal if CMOS says so" endchoice From 2f5abf058e031d5f73213b75424f1f8f4832b2b5 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sun, 9 Jun 2019 14:01:43 +0200 Subject: [PATCH 021/221] arch/x86/Kconfig: hide the "Bootblock behaviour" option on non-romcc Selecting which cbfs prefix to load is only implemented with the romcc bootblock. Change-Id: I09523b94605f00ab15b5f0ea3986ac08e3a6afc6 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33341 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: Patrick Rudolph Reviewed-by: Nico Huber --- src/arch/x86/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig index 5b1304fedb..06aadedae6 100644 --- a/src/arch/x86/Kconfig +++ b/src/arch/x86/Kconfig @@ -239,9 +239,11 @@ config ROMSTAGE_DEBUG_SPINLOOP Add a spin (JMP .) in assembly_entry.S during early romstage to wait for a JTAG debugger to break into the execution sequence. +# Selecting a cbfs prefix from the bootblock is only implemented with romcc choice prompt "Bootblock behaviour" default BOOTBLOCK_SIMPLE + depends on !C_ENVIRONMENT_BOOTBLOCK config BOOTBLOCK_SIMPLE bool "Always load fallback" From 64e668051c087289ea012eb0f637d2d396af5d6e Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Thu, 13 Jun 2019 22:11:46 +0530 Subject: [PATCH 022/221] soc/intel/common: Fix booting issue without default IGD enabled This patch ensures to boot platform without onboard GFX (PCI B0:D2:F0) enabled from mainboard devicetree.cb. TEST=Previously platform was dying at "GMADR is not programmed!" with IGD disabled. Change-Id: I8c907ee25db4538a84890f2ccc3187afa86604b8 Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/c/coreboot/+/33449 Reviewed-by: Duncan Laurie Tested-by: build bot (Jenkins) --- .../intel/common/block/graphics/graphics.c | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/soc/intel/common/block/graphics/graphics.c b/src/soc/intel/common/block/graphics/graphics.c index 4cea21b075..ed9ae00bf8 100644 --- a/src/soc/intel/common/block/graphics/graphics.c +++ b/src/soc/intel/common/block/graphics/graphics.c @@ -33,15 +33,18 @@ __weak void graphics_soc_init(struct device *dev) pci_dev_init(dev); } -static uintptr_t graphics_get_bar(unsigned long index) +static int is_graphics_disabled(struct device *dev) { - struct device *dev = SA_DEV_IGD; - struct resource *gm_res; - assert(dev != NULL); - /* Check if Graphics PCI device is disabled */ if (!dev || !dev->enabled) - return 0; + return 1; + + return 0; +} + +static uintptr_t graphics_get_bar(struct device *dev, unsigned long index) +{ + struct resource *gm_res; gm_res = find_resource(dev, index); if (!gm_res) @@ -52,11 +55,16 @@ static uintptr_t graphics_get_bar(unsigned long index) uintptr_t graphics_get_memory_base(void) { + uintptr_t memory_base; + struct device *dev = SA_DEV_IGD; + + if (is_graphics_disabled(dev)) + return 0; /* * GFX PCI config space offset 0x18 know as Graphics * Memory Range Address (GMADR) */ - uintptr_t memory_base = graphics_get_bar(PCI_BASE_ADDRESS_2); + memory_base = graphics_get_bar(dev, PCI_BASE_ADDRESS_2); if (!memory_base) die_with_post_code(POST_HW_INIT_FAILURE, "GMADR is not programmed!"); @@ -66,14 +74,18 @@ uintptr_t graphics_get_memory_base(void) static uintptr_t graphics_get_gtt_base(void) { + static uintptr_t gtt_base; + struct device *dev = SA_DEV_IGD; + + if (is_graphics_disabled(dev)) + die("IGD is disabled!"); /* * GFX PCI config space offset 0x10 know as Graphics * Translation Table Memory Mapped Range Address * (GTTMMADR) */ - static uintptr_t gtt_base; if (!gtt_base) { - gtt_base = graphics_get_bar(PCI_BASE_ADDRESS_0); + gtt_base = graphics_get_bar(dev, PCI_BASE_ADDRESS_0); if (!gtt_base) die_with_post_code(POST_HW_INIT_FAILURE, "GTTMMADR is not programmed!"); From a533a8d3f563386f57838ef9994e78af6c7acc9d Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Sat, 15 Jun 2019 17:22:43 +0200 Subject: [PATCH 023/221] mb/lenovo/*/smihandler: Remove unused include All usage of pci_read_config8 was removed in commit d44d4f0f with Change-Id Ia959eb5b747846048396e66d4c926c96c27f3878 ("mb/lenovo/*: Remove useless smihandler code"). So we don't need this include anymore. Change-Id: Ic4f038c80e17799016ae7e92a5675cfe7c71e400 Signed-off-by: Peter Lemenkov Reviewed-on: https://review.coreboot.org/c/coreboot/+/33510 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: HAOUAS Elyes --- src/mainboard/lenovo/t420s/smihandler.c | 1 - src/mainboard/lenovo/t430s/smihandler.c | 1 - src/mainboard/lenovo/t520/smihandler.c | 1 - src/mainboard/lenovo/t530/smihandler.c | 1 - src/mainboard/lenovo/x220/smihandler.c | 1 - 5 files changed, 5 deletions(-) diff --git a/src/mainboard/lenovo/t420s/smihandler.c b/src/mainboard/lenovo/t420s/smihandler.c index 2713725b36..bc72a12e23 100644 --- a/src/mainboard/lenovo/t420s/smihandler.c +++ b/src/mainboard/lenovo/t420s/smihandler.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/t430s/smihandler.c b/src/mainboard/lenovo/t430s/smihandler.c index 2810e5ae91..f06eaf717f 100644 --- a/src/mainboard/lenovo/t430s/smihandler.c +++ b/src/mainboard/lenovo/t430s/smihandler.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/t520/smihandler.c b/src/mainboard/lenovo/t520/smihandler.c index 46ad664c3c..35a26c0ebd 100644 --- a/src/mainboard/lenovo/t520/smihandler.c +++ b/src/mainboard/lenovo/t520/smihandler.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/t530/smihandler.c b/src/mainboard/lenovo/t530/smihandler.c index 46ad664c3c..35a26c0ebd 100644 --- a/src/mainboard/lenovo/t530/smihandler.c +++ b/src/mainboard/lenovo/t530/smihandler.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/x220/smihandler.c b/src/mainboard/lenovo/x220/smihandler.c index 46ad664c3c..35a26c0ebd 100644 --- a/src/mainboard/lenovo/x220/smihandler.c +++ b/src/mainboard/lenovo/x220/smihandler.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include From d3c5544bec154c469fbcb19b143f5131c5b417ea Mon Sep 17 00:00:00 2001 From: Aamir Bohra Date: Sun, 16 Jun 2019 19:38:45 +0530 Subject: [PATCH 024/221] mb/google/hatch: Move memory strap GPIOs under variant gpio header Move the memory strap gpios to variant/gpio.h, as the memory straps are different for helios. Change-Id: I1833c9539687011ee27fd3e88c0581e30ca59354 Signed-off-by: Aamir Bohra Reviewed-on: https://review.coreboot.org/c/coreboot/+/33541 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/mainboard/google/hatch/romstage.c | 7 +------ .../google/hatch/variants/hatch/include/variant/gpio.h | 6 ++++++ .../google/hatch/variants/hatch_whl/include/variant/gpio.h | 6 ++++++ .../google/hatch/variants/helios/include/variant/gpio.h | 6 ++++++ .../google/hatch/variants/kindred/include/variant/gpio.h | 6 ++++++ .../google/hatch/variants/kohaku/include/variant/gpio.h | 6 ++++++ 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/mainboard/google/hatch/romstage.c b/src/mainboard/google/hatch/romstage.c index 2c630a8ce8..69fee28025 100644 --- a/src/mainboard/google/hatch/romstage.c +++ b/src/mainboard/google/hatch/romstage.c @@ -21,12 +21,7 @@ #include #include #include - -/* Memory configuration board straps */ -#define GPIO_MEM_CONFIG_0 GPP_F20 -#define GPIO_MEM_CONFIG_1 GPP_F21 -#define GPIO_MEM_CONFIG_2 GPP_F11 -#define GPIO_MEM_CONFIG_3 GPP_F22 +#include /* * GPIO_MEM_CH_SEL is set to 1 for single channel skus diff --git a/src/mainboard/google/hatch/variants/hatch/include/variant/gpio.h b/src/mainboard/google/hatch/variants/hatch/include/variant/gpio.h index 5d69eeddbc..e7d8a75937 100644 --- a/src/mainboard/google/hatch/variants/hatch/include/variant/gpio.h +++ b/src/mainboard/google/hatch/variants/hatch/include/variant/gpio.h @@ -18,4 +18,10 @@ #include +/* Memory configuration board straps */ +#define GPIO_MEM_CONFIG_0 GPP_F20 +#define GPIO_MEM_CONFIG_1 GPP_F21 +#define GPIO_MEM_CONFIG_2 GPP_F11 +#define GPIO_MEM_CONFIG_3 GPP_F22 + #endif diff --git a/src/mainboard/google/hatch/variants/hatch_whl/include/variant/gpio.h b/src/mainboard/google/hatch/variants/hatch_whl/include/variant/gpio.h index d99e2bbd65..29e590422f 100644 --- a/src/mainboard/google/hatch/variants/hatch_whl/include/variant/gpio.h +++ b/src/mainboard/google/hatch/variants/hatch_whl/include/variant/gpio.h @@ -18,4 +18,10 @@ #include +/* Memory configuration board straps */ +#define GPIO_MEM_CONFIG_0 GPP_F20 +#define GPIO_MEM_CONFIG_1 GPP_F21 +#define GPIO_MEM_CONFIG_2 GPP_F11 +#define GPIO_MEM_CONFIG_3 GPP_F22 + #endif diff --git a/src/mainboard/google/hatch/variants/helios/include/variant/gpio.h b/src/mainboard/google/hatch/variants/helios/include/variant/gpio.h index d99e2bbd65..92f9d412fd 100644 --- a/src/mainboard/google/hatch/variants/helios/include/variant/gpio.h +++ b/src/mainboard/google/hatch/variants/helios/include/variant/gpio.h @@ -18,4 +18,10 @@ #include +/* Memory configuration board straps */ +#define GPIO_MEM_CONFIG_0 GPP_H19 +#define GPIO_MEM_CONFIG_1 GPP_H22 +#define GPIO_MEM_CONFIG_2 GPP_F10 +#define GPIO_MEM_CONFIG_3 GPP_F3 + #endif diff --git a/src/mainboard/google/hatch/variants/kindred/include/variant/gpio.h b/src/mainboard/google/hatch/variants/kindred/include/variant/gpio.h index d99e2bbd65..29e590422f 100644 --- a/src/mainboard/google/hatch/variants/kindred/include/variant/gpio.h +++ b/src/mainboard/google/hatch/variants/kindred/include/variant/gpio.h @@ -18,4 +18,10 @@ #include +/* Memory configuration board straps */ +#define GPIO_MEM_CONFIG_0 GPP_F20 +#define GPIO_MEM_CONFIG_1 GPP_F21 +#define GPIO_MEM_CONFIG_2 GPP_F11 +#define GPIO_MEM_CONFIG_3 GPP_F22 + #endif diff --git a/src/mainboard/google/hatch/variants/kohaku/include/variant/gpio.h b/src/mainboard/google/hatch/variants/kohaku/include/variant/gpio.h index d99e2bbd65..29e590422f 100644 --- a/src/mainboard/google/hatch/variants/kohaku/include/variant/gpio.h +++ b/src/mainboard/google/hatch/variants/kohaku/include/variant/gpio.h @@ -18,4 +18,10 @@ #include +/* Memory configuration board straps */ +#define GPIO_MEM_CONFIG_0 GPP_F20 +#define GPIO_MEM_CONFIG_1 GPP_F21 +#define GPIO_MEM_CONFIG_2 GPP_F11 +#define GPIO_MEM_CONFIG_3 GPP_F22 + #endif From 14774769daae489834473457712cd4c635ac1fbd Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sat, 15 Jun 2019 12:25:53 +0200 Subject: [PATCH 025/221] drivers/ipmi: Fix coding style Fix 'do not use assignment in if condition'. Change-Id: I6e1b81a1b87de4315391618968c59cc3d3a66a77 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33492 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/drivers/ipmi/ipmi_kcs.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/drivers/ipmi/ipmi_kcs.c b/src/drivers/ipmi/ipmi_kcs.c index 8d106837f9..d17a1f98d2 100644 --- a/src/drivers/ipmi/ipmi_kcs.c +++ b/src/drivers/ipmi/ipmi_kcs.c @@ -144,34 +144,40 @@ static int ipmi_kcs_send_message(int port, int netfn, int lun, int cmd, { int ret; - if ((ret = ipmi_kcs_send_cmd_byte(port, IPMI_KCS_START_WRITE))) { + ret = ipmi_kcs_send_cmd_byte(port, IPMI_KCS_START_WRITE); + if (ret) { printk(BIOS_ERR, "IPMI START WRITE failed\n"); return ret; } - if ((ret = ipmi_kcs_send_data_byte(port, (netfn << 2) | (lun & 3)))) { + ret = ipmi_kcs_send_data_byte(port, (netfn << 2) | (lun & 3)); + if (ret) { printk(BIOS_ERR, "IPMI NETFN failed\n"); return ret; } - if ((ret = ipmi_kcs_send_data_byte(port, cmd))) { + ret = ipmi_kcs_send_data_byte(port, cmd); + if (ret) { printk(BIOS_ERR, "IPMI CMD failed\n"); return ret; } while (len-- > 1) { - if ((ret = ipmi_kcs_send_data_byte(port, *msg++))) { + ret = ipmi_kcs_send_data_byte(port, *msg++); + if (ret) { printk(BIOS_ERR, "IPMI BYTE WRITE failed\n"); return ret; } } - if ((ret = ipmi_kcs_send_cmd_byte(port, IPMI_KCS_END_WRITE))) { + ret = ipmi_kcs_send_cmd_byte(port, IPMI_KCS_END_WRITE); + if (ret) { printk(BIOS_ERR, "IPMI END WRITE failed\n"); return ret; } - if ((ret = ipmi_kcs_send_last_data_byte(port, *msg++))) { + ret = ipmi_kcs_send_last_data_byte(port, *msg++); + if (ret) { printk(BIOS_ERR, "IPMI BYTE WRITE failed\n"); return ret; } From 01c83a2e9975f71d53772a535cf13d3e76a46827 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Wed, 5 Jun 2019 13:36:55 +0200 Subject: [PATCH 026/221] 3rdparty/blobs: Update submodule, SNB improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sandybridge systemagent-r6 blob is modified: - To be more flexible about the location of the stack w.r.t. the heap - Place the MRC pool right below the MRC_VAR region - to work with the same DCACHE_RAM_BASE from the native raminit (could make the CAR linker symbols easily compatible if desired) This allows CAR setup compatibility between mrc.bin and native bootpath and also allows for BIOS/memory mappeds region larger than 8MB. This changes the semantics of CONFIG_DACHE_RAM_MRC_VAR_SIZE to also include the pool on top of MRC_VAR region. TESTED on T520 (boots and resumes from S3 with mrc.bin). Change-Id: I17d240656575b69a24718d90e4f2d2b7339d05a7 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33228 Reviewed-by: Kyösti Mälkki Reviewed-by: Angel Pons Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- 3rdparty/blobs | 2 +- src/arch/x86/car.ld | 7 ----- src/northbridge/intel/sandybridge/Kconfig | 13 ++++------ .../intel/sandybridge/raminit_mrc.c | 26 +++++++++++++++++-- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/3rdparty/blobs b/3rdparty/blobs index ca6cfcdbe1..d7600dd871 160000 --- a/3rdparty/blobs +++ b/3rdparty/blobs @@ -1 +1 @@ -Subproject commit ca6cfcdbe1cdeb38c2622ee2e5236cc4657e3377 +Subproject commit d7600dd8718a076f0f9a89e53968b484254624dc diff --git a/src/arch/x86/car.ld b/src/arch/x86/car.ld index 29b3600bbe..5802b02896 100644 --- a/src/arch/x86/car.ld +++ b/src/arch/x86/car.ld @@ -91,13 +91,6 @@ _car_global_end = .; _car_relocatable_data_end = .; -#if CONFIG(NORTHBRIDGE_INTEL_SANDYBRIDGE) && !CONFIG(USE_NATIVE_RAMINIT) - . = ABSOLUTE(0xff7e1000); - _mrc_pool = .; - . += 0x5000; - _emrc_pool = .; -#endif - #if !CONFIG(C_ENVIRONMENT_BOOTBLOCK) _car_stack_start = .; _car_stack_end = _car_region_end; diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig index 4f9da000a4..59cf92c0ee 100644 --- a/src/northbridge/intel/sandybridge/Kconfig +++ b/src/northbridge/intel/sandybridge/Kconfig @@ -78,12 +78,13 @@ config MMCONF_BASE_ADDRESS help The MRC blob requires it to be at 0xf0000000. -if USE_NATIVE_RAMINIT - config DCACHE_RAM_BASE hex default 0xfefe0000 + +if USE_NATIVE_RAMINIT + config DCACHE_RAM_SIZE hex default 0x20000 @@ -96,17 +97,13 @@ endif # USE_NATIVE_RAMINIT if !USE_NATIVE_RAMINIT -config DCACHE_RAM_BASE - hex - default 0xff7e0000 - config DCACHE_RAM_SIZE hex - default 0x1c000 + default 0x17000 config DCACHE_RAM_MRC_VAR_SIZE hex - default 0x4000 + default 0x9000 config MRC_FILE string "Intel System Agent path and filename" diff --git a/src/northbridge/intel/sandybridge/raminit_mrc.c b/src/northbridge/intel/sandybridge/raminit_mrc.c index e88d356593..a8acfbf980 100644 --- a/src/northbridge/intel/sandybridge/raminit_mrc.c +++ b/src/northbridge/intel/sandybridge/raminit_mrc.c @@ -265,9 +265,31 @@ void sdram_initialize(struct pei_data *pei_data) report_memory_config(); } -/* These are the location and structure of MRC_VAR data in CAR. */ +/* These are the location and structure of MRC_VAR data in CAR. + The CAR region looks like this: + +------------------+ -> DCACHE_RAM_BASE + | | + | | + | COREBOOT STACK | + | | + | | + +------------------+ -> DCACHE_RAM_BASE + DCACHE_RAM_SIZE + | | + | MRC HEAP | + | size = 0x5000 | + | | + +------------------+ + | | + | MRC VAR | + | size = 0x4000 | + | | + +------------------+ -> DACHE_RAM_BASE + DACHE_RAM_SIZE + + DCACHE_RAM_MRC_VAR_SIZE + + */ #define DCACHE_RAM_MRC_VAR_BASE \ - (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE) + (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE + \ + CONFIG_DCACHE_RAM_MRC_VAR_SIZE - 0x4000) struct mrc_var_data { u32 acpi_timer_flag; From 9065657957f5cb8c5a02695af7528263cfdceeaa Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Thu, 18 Apr 2019 15:46:35 +0200 Subject: [PATCH 027/221] src/mb/gigabyte/ga-h61m-s2pv: Correct devicetree Subsystem IDs were missing and GPIO settings were wrong. Plus, the PCI bridge was erroneously enabled, this board uses an ITE IT8892E PCIe to PCI bridge instead. Tested, board still boots. Change-Id: Ieb9dd8c835bc3652e7a3a118feca5551196bb81b Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/33522 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans Reviewed-by: Nico Huber --- .../gigabyte/ga-h61m-s2pv/devicetree.cb | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/devicetree.cb b/src/mainboard/gigabyte/ga-h61m-s2pv/devicetree.cb index e382cbde7f..e4ec810d45 100644 --- a/src/mainboard/gigabyte/ga-h61m-s2pv/devicetree.cb +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/devicetree.cb @@ -30,6 +30,7 @@ chip northbridge/intel/sandybridge end register "pci_mmio_size" = "2048" device domain 0x0 on + subsystemid 0x1458 0x5000 inherit device pci 00.0 on end # Host bridge device pci 01.0 on end # PCIe Bridge for discrete graphics (PCIEX16) device pci 02.0 on end # Internal graphics VGA controller @@ -57,7 +58,7 @@ chip northbridge/intel/sandybridge device pci 1c.6 off end # Unused PCIe Port device pci 1c.7 off end # Unused PCIe Port device pci 1d.0 on end # USB2 EHCI #1 - device pci 1e.0 on end # PCI bridge + device pci 1e.0 off end # PCI bridge device pci 1f.0 on # LPC bridge chip superio/ite/it8728f device pnp 2e.0 off end # Floppy, not routed. @@ -84,13 +85,15 @@ chip northbridge/intel/sandybridge device pnp 2e.6 on # Mouse irq 0x70 = 12 end - device pnp 2e.7 off # GPIO - io 0x25 = 0x40 - io 0x27 = 0x10 - io 0x2c = 0x80 + device pnp 2e.7 on # GPIO + irq 0x25 = 0x40 + irq 0x27 = 0x10 + irq 0x2c = 0x80 + io 0x60 = 0x0000 io 0x62 = 0x0a00 - io 0xcb = 0x00 - io 0xf1 = 0x40 + io 0x64 = 0x0000 + irq 0xcb = 0x00 + irq 0xf1 = 0x40 end device pnp 2e.a off end # CIR, not routed. end From 9b7e990d18d5f6212df6ea967428c28b802e1b64 Mon Sep 17 00:00:00 2001 From: Felix Singer Date: Wed, 22 May 2019 18:32:46 +0200 Subject: [PATCH 028/221] doc/mb/upsquared: Add documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds documentation about the UP² mainboard and the IFWI used by Apollolake platform. Change-Id: Ic708ddbd2616eee4e5ec2740b3eac18b408bde38 Signed-off-by: Felix Singer Reviewed-on: https://review.coreboot.org/c/coreboot/+/32935 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- Documentation/mainboard/up/squared/bottom.dia | Bin 0 -> 1112 bytes Documentation/mainboard/up/squared/bottom.jpg | Bin 38689 -> 48761 bytes .../up/squared/header_40pin_gpio_uart1.dia | Bin 0 -> 1853 bytes .../up/squared/header_40pin_gpio_uart1.svg | 126 +++++++++++++ .../up/squared/header_cn16_10pin_uart0.dia | Bin 0 -> 1752 bytes .../up/squared/header_cn16_10pin_uart0.svg | 112 ++++++++++++ .../up/squared/header_cn22_12pin_spi.dia | Bin 0 -> 2240 bytes .../up/squared/header_cn22_12pin_spi.svg | 165 ++++++++++++++++++ Documentation/mainboard/up/squared/index.md | 102 +++++++++-- .../soc/intel/apollolake/flash_layout.dia | Bin 0 -> 1988 bytes .../soc/intel/apollolake/flash_layout.svg | 122 +++++++++++++ Documentation/soc/intel/apollolake/index.md | 17 ++ Documentation/soc/intel/index.md | 1 + 13 files changed, 629 insertions(+), 16 deletions(-) create mode 100644 Documentation/mainboard/up/squared/bottom.dia create mode 100644 Documentation/mainboard/up/squared/header_40pin_gpio_uart1.dia create mode 100644 Documentation/mainboard/up/squared/header_40pin_gpio_uart1.svg create mode 100644 Documentation/mainboard/up/squared/header_cn16_10pin_uart0.dia create mode 100644 Documentation/mainboard/up/squared/header_cn16_10pin_uart0.svg create mode 100644 Documentation/mainboard/up/squared/header_cn22_12pin_spi.dia create mode 100644 Documentation/mainboard/up/squared/header_cn22_12pin_spi.svg create mode 100644 Documentation/soc/intel/apollolake/flash_layout.dia create mode 100644 Documentation/soc/intel/apollolake/flash_layout.svg create mode 100644 Documentation/soc/intel/apollolake/index.md diff --git a/Documentation/mainboard/up/squared/bottom.dia b/Documentation/mainboard/up/squared/bottom.dia new file mode 100644 index 0000000000000000000000000000000000000000..f298d669ab7f2ed9943adfe9c1161a4b5947b1c3 GIT binary patch literal 1112 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 W>Ph#-f51fQ_}WvZlKJJ&?EeA8zH%@C literal 38689 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 + + + + 40 pin GPIO header + + + GND + + + UART1 + TX + + + UART1 + RX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + 4 + + + 2 + + + 3 + + + 5 + + + 7 + + + 8 + + + 6 + + + 9 + + + 11 + + + 12 + + + 10 + + + + + + + + + + + + + + + + + diff --git a/Documentation/mainboard/up/squared/header_cn16_10pin_uart0.dia b/Documentation/mainboard/up/squared/header_cn16_10pin_uart0.dia new file mode 100644 index 0000000000000000000000000000000000000000..a35245b9cc4dd1d7e2bb1162a46f0c81c17b8410 GIT binary patch literal 1752 zcmV;}1}FI+iwFP!000021MQt%bE7sChVSz$81|-}$zmk&xm{;x(@xuq&bG6go#~xN zHi}Ibg9nrk-}JXv7!nKy+d&AzR-TDxY%Av=`F$TaNKxK@cw7g{J&6-P3a2X2bX6hY zBJ%ujIaR;j{QA~WKU`hB_k8@0{VZd=R@iTZN&0H4t|;BSn@k=a9<*SaU>e0*;NNKp znf!}`08dz>iF$RRDEk3COmX^N{w}68_UCt$C?Q^xsXE7tZ_7Bk3q3V!mA6|&K@=4I4a-$;;Et z`%M@0n=bA*ouAA$QA}g()5DbWC<+J;v#d0}Bkl7f3mhA`b|Nz9j@9+r2$N0JjVE4OKgw91=JPK|oC-MIsky;V6`?@|PKOX58I zb#a)9fT!^7)?PCB%UzhlT@r=HJIfFt&b_{$Y-4vyNzPFB&wtmcC7^x3Z7nUg|>t#t{w zbqOyWk-7w_F6~s85T&|wMa!~vf6kGmNL99sJ&$6K#HS8i*MOcqfZ^%@SOB(5=Z9?k zXXW!!ZQ*iztLxv7&mgzY46!~#h0n}hd}c_WNuPD@GsNvPORUe#!e@3bKC`6Hq|Z9{ znZfNdN3756!e?$TK6CzOK6{O-GQ(k)mEIQe;R~4z5avTa{w#H&oPbsF(T;SyGjQtJ39GrPyi* z71a*vrP@KV+Ia{%{6cR9C;RyaC!W$ zs>z$;SjRxuLa9lh1(|7d&DN34UOP6jTV|%|fSgzoRcX_N!rdCuQoG7> zQ_!&5^vDveruBYNNb54C?<==>?FUvq-6;nk)aI%H2HE>XH*)OH}B7?v`K^me;KYx{TEuW6P%f)c3s-bJaNA} zq-Kmm0R+?=20|C(BpCu9xKv)4F z92o#j2|(chgc5+G2B0+%0Qnbh7~%nFQ~+p<41k6Npl|>h5`d!ypgj-(`PT_q;sIz? z0BDU2fJg#RH~=jPz)=Ix83=&`DNN1|XCr@VEg82LhnW|L42n0az)4;n+%GM*>hd0A&e0ZUCZT00{Z_ zi4wmI23D5Az_BfZu_XY715hr588-lpfdJUShGgOa2sPb>W&uE`xw>tRXeG2R2`HR^ zavjXbmqHIjK-j?+Rsf0J!wRO?djM({w9u{qPOk?6(vXdu*N?y7KK(Kv|C~brzP*kD z?>jAoQ&~W`FG$J2UK!XCmQV*fShn3{?cA#}2RaN(faxv8lBoe3pcGR!yDWSCSo-?$ z^NoJ-`ESXlzGf*>tvHfRqi2)R!7kQfFPZe5O)zH@%GrcQ#ikp{rrxT@R4bBA<6+a0 z%`l+Z1)reUZT5G&VK|!OI554Twc8H^z}6eKoVOiDrC+rTT)7{{VEbW|Z-JOy-vT-2 z8LNwW1Bl%+zvLMs_Y4s2nR35s8%WO#<{3DkXY4L+9YV3U4ojY~`Z~{8r_M8$^vrOc zL4rNgR5v;u?96P5wTtZ{`_fErv}YTRK;2?F(;MyMm}pcseyHrK$H~_(*HBpz?2%ac u;pb1l`cYPsef>>7lMIwIk*}zl%wF&Q2jSI4>7Nu{UHk{z;$=C=cmMzi4@pn} literal 0 HcmV?d00001 diff --git a/Documentation/mainboard/up/squared/header_cn16_10pin_uart0.svg b/Documentation/mainboard/up/squared/header_cn16_10pin_uart0.svg new file mode 100644 index 0000000000..43efc77ac5 --- /dev/null +++ b/Documentation/mainboard/up/squared/header_cn16_10pin_uart0.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + 2 + + + 5 + + + 4 + + + 3 + + + 6 + + + 9 + + + 8 + + + 7 + + + 10 + + + GND + + + UART0 + RX + + + UART0 + TX + + + + + + + + + + + + + + + + + + 10 pin UART0/USB2 header (CN16) + + diff --git a/Documentation/mainboard/up/squared/header_cn22_12pin_spi.dia b/Documentation/mainboard/up/squared/header_cn22_12pin_spi.dia new file mode 100644 index 0000000000000000000000000000000000000000..ab556ff819f31430b28c7c92e58e6574dfa68886 GIT binary patch literal 2240 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 Oe)1oF4l#B;vj6~U^)e{{ literal 0 HcmV?d00001 diff --git a/Documentation/mainboard/up/squared/header_cn22_12pin_spi.svg b/Documentation/mainboard/up/squared/header_cn22_12pin_spi.svg new file mode 100644 index 0000000000..7853fb7e7c --- /dev/null +++ b/Documentation/mainboard/up/squared/header_cn22_12pin_spi.svg @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 9 + + + 5 + + + 7 + + + 8 + + + 1 + + + 4 + + + 3 + + + 2 + + + 6 + + + 11 + + + 12 + + + 10 + + + SPI header (CN22) + + + + + + + + + + + + + GND + + + GND + + + + + + + + MISO + + + + + + + + VCC + 1.8V + + + #HOLD + + + + + + + + + + + + + CLK + + + + + + + + MOSI + + + + + + + + #CS + + diff --git a/Documentation/mainboard/up/squared/index.md b/Documentation/mainboard/up/squared/index.md index dcf3ed192d..9242f76d8d 100644 --- a/Documentation/mainboard/up/squared/index.md +++ b/Documentation/mainboard/up/squared/index.md @@ -7,6 +7,12 @@ ### Bottom ![][overview_bottom] +* **Legend** + * [BLUE][header_cn16_link]: UART0 / USB connector + * [GREEN][header_gpio_link]: UART1 / GPIO header + * [RED][header_cn22_link]: SPI header + * YELLOW: Indicates pin 1 + ## Mainboard components ### Platform ```eval_rst @@ -46,6 +52,79 @@ +---------------------+------------+ ``` +### Debugging +#### UART0 (CN16) +This connector is located on the **bottom** side (see [here][overview_bottom_link]). +![][header_cn16] + + +#### UART1 (GPIO header) +The GPIO header is located on the **bottom** side (see [here][overview_bottom_link]). +![][header_gpio] + +## Building and flashing coreboot +### Using the SPI header +The SPI header is located on the **bottom** side (see [here][overview_bottom_link]). +![][header_cn22] + +### Preperations +In order to build coreboot, it's neccessary to extract some files from the vendor firmware. Make sure that you have a fully working dump. +```bash +[upsquared]$ ls +firmware_vendor.rom +``` + +```bash +[upsquared]$ mkdir extracted && cd extracted +[extracted]$ ifdtool -x ../firmware_vendor.rom +File ../firmware_vendor.rom is 16777216 bytes +Peculiar firmware descriptor, assuming Ibex Peak compatibility. + Flash Region 0 (Flash Descriptor): 00000000 - 00000fff + Flash Region 1 (BIOS): 00001000 - 00efefff + Flash Region 2 (Intel ME): 07fff000 - 00000fff (unused) + Flash Region 3 (GbE): 07fff000 - 00000fff (unused) + Flash Region 4 (Platform Data): 07fff000 - 00000fff (unused) + Flash Region 5 (Reserved): 00eff000 - 00ffefff + Flash Region 6 (Reserved): 07fff000 - 00000fff (unused) + Flash Region 7 (Reserved): 07fff000 - 00000fff (unused) + Flash Region 8 (EC): 07fff000 - 00000fff (unused) +``` + +```bash +flashregion_0_flashdescriptor.bin +flashregion_1_bios.bin +flashregion_5_reserved.bin +``` + +### Clean up +```bash +[coreboot]$ make distclean +``` + +### Configuring +```bash +[coreboot]$ touch .config +[coreboot]$ ./util/scripts/config --enable VENDOR_UP +[coreboot]$ ./util/scripts/config --enable BOARD_UP_SQUARED +[coreboot]$ ./util/scripts/config --enable NEED_IFWI +[coreboot]$ ./util/scripts/config --enable HAVE_IFD_BIN +[coreboot]$ ./util/scripts/config --set-str IFWI_FILE_NAME "" +[coreboot]$ ./util/scripts/config --set-str IFD_BIN_PATH "" +[coreboot]$ make olddefconfig +``` + +### Building +```bash +[coreboot]$ make +``` + +Now you should have a working and ready to use coreboot build at `build/coreboot.rom`. + +### Flashing +```bash +[coreboot]$ flashrom -p -w build/coreboot.rom +``` + ## Board status ### Working - bootblock, romstage, ramstage @@ -78,22 +157,13 @@ - mini PCIe - flashing with flashrom internally using Linux -## Building and flashing coreboot -### Building - -```bash -make distclean -touch .config -./util/scripts/config --enable VENDOR_UP -./util/scripts/config --enable BOARD_UP_SQUARED -./util/scripts/config --enable NEED_IFWI -./util/scripts/config --enable HAVE_IFD_BIN -./util/scripts/config --set-str IFWI_FILE_NAME "" -./util/scripts/config --set-str IFD_BIN_PATH "" -make olddefconfig -``` - -### Flashing +[header_cn16]: header_cn16_10pin_uart0.svg +[header_cn16_link]: #uart0-cn16 +[header_cn22]: header_cn22_12pin_spi.svg +[header_cn22_link]: #using-the-spi-header +[header_gpio]: header_40pin_gpio_uart1.svg +[header_gpio_link]: #uart1-gpio-header [overview_top]: top.jpg [overview_bottom]: bottom.jpg +[overview_bottom_link]: #bottom diff --git a/Documentation/soc/intel/apollolake/flash_layout.dia b/Documentation/soc/intel/apollolake/flash_layout.dia new file mode 100644 index 0000000000000000000000000000000000000000..4ea544061906b947349655474bda2427b7464dcc GIT binary patch literal 1988 zcmV;#2Rry5iwFP!000021MQt#bDKC6fZy{g824p&CY6zdK(tLdb(%~w+r~Rhy4yDo zwiSmhh76EfANIGe04K&azRHr#R-Q>_!19p-M~!b+XRm4F{qe!OzVE%^e}mW?8vGMsk{um2ZqoGjO|$v%@Bo6R#7mm2)rh5)NC9d7)Dt@-%Gvh+~};Arm^3>OPLXRLw3~Ydc7ZmIJyh_jiS}4T`vlv z*tqwCqsFW2{MBfV#55=5ERcQc4Olm3-jDgBP5yG-O+??acv|f6HcEWnBz?M_X);Gn z_P^9-)GFbP!ol&Y57w(#FT8P}^OswmU!R+(vO4dwx3GWjBff=7mMCX?({v?ARC#@A1b4S3@Cf?)K29j4-nP_At2f`z%?q%qH8+k#sX^)?9Ygr`xT1VTw~z zn|0nr;61T;B)&D?rj5}J9$6g2>!tqv^HJ%VMBRT_FC9(xGWEi~7x#_VMk{)3j2VOz zh~GbIw9UzjH9b8pjN8GPt92W_EGY~R$@J`JZO1&>-R`vLm=E3y2LT(2H-U@Dp_ToA zYni}w$RW-CZ`LOZ*s#-!;&2ubwlb$&er`r)=k;ttTmjKH%pcsO^JU}BWOt*u&*EhR zHvuGO{vxhzTDE1;&ALl&qK8fefiB-(t4%?3yzW;}ge&%#mNWs5Gyw{00s-XE22!;F z0@txI?*$^8D+G3diLk?use?Dwi8Q+&ORWD?n|b#&$K{E3Q)K<|^sn=i)6VJltJ90i z^Y+CY&R(!N%_E&COshK1&KuX>&<~#Y_`EP_7)kn+Sy9SOVDZ^cEVyT>-}7F#qM%_ll zHH~659UxJg2#HiWfL4hPxN%fM2b<4n6*_>n#)Eyt11zcv2up?ogaE|kg$)n})F$;o zgVuTbQsaOc9LU$AhJm`m0NM!*Si&%X`>pUMW>Mra$cL9_r)DmvOLBT?yD zfWm2smMJ$a(JiMXVl}ab&F7?J4g2p`n4<~8X^GH2gsx1l0x7&~wD7XIxi0YCQ?{3F z^J!^qsBe<4ct)B7`0_O6I@)Yt(X5j!^!Ao(20__T7I@o#C)?SV4}WSWn<6LMXfbAy zH|=Jtp_>iDokZTCcs3%EO9cp)sQ@{Os6b#^t55;aRIry+Ae@?pEcsNxSN|9akPT|Y z1Sjo_%l79}jRlI*b1jVp^~M6c8!Qk`Ohk@kEU?R1fQc$BaHL`Z)mX5XSYU6VxLr0B zI3*~+R=uF$>uIaqzWVK?b$0o?W&=f)yik)toymagh76o-#M@<(0k+CyU?D|hATX^} z$iUHLu$N>YoS}xPe1}2y&;|>S@xX$>A~voMA!H@Joo^T4Em}W+$?>F%O$>}c!GiwUrTCb;}n~?usIUm;5eCuT#uUGO5cUkj`gwr%F*;&gLfVK-?Y(^G_B+@O$)U2u-Xp5mO z#&+TfXum8*wdX-NlTk8TOcXt;s(I8UkH4bRK{$(1LB*pDD6|oI2}MuFHOgLWx35~C+b4f$Fi`f$QOyN4<^pG@;RtsNzf~qT907q{b}mAq!nrs#tLg^! z!UkxGYY`&tSo|d)EGXhww09Yaz~=tD7sruHhyYd*xm*^ww6&qohGH8Y15>G?D30@A WRX;wM_}TU2gZ}_x?y9Dmg#Z9nfx=G! literal 0 HcmV?d00001 diff --git a/Documentation/soc/intel/apollolake/flash_layout.svg b/Documentation/soc/intel/apollolake/flash_layout.svg new file mode 100644 index 0000000000..9322875d90 --- /dev/null +++ b/Documentation/soc/intel/apollolake/flash_layout.svg @@ -0,0 +1,122 @@ + + + + + + + + + DEVICE_EXTENSION + + + + + + + BIOS + + + + + + + IFD + + + + + + + IFWI + + + + + + + + + + + + + + + + + + + + + FMAP + + + + + + + CONSOLE + + + + + + + COREBOOT(CBFS) + + + + + + + BIOS_UNUSABLE + + + + + + + MRC + + + + + + + OBB + + + + + + + + + + + + + + + + + TXE + + + + + + + BOOTBLOCK + + + + + + + + + + + + diff --git a/Documentation/soc/intel/apollolake/index.md b/Documentation/soc/intel/apollolake/index.md new file mode 100644 index 0000000000..d4a5ee51ae --- /dev/null +++ b/Documentation/soc/intel/apollolake/index.md @@ -0,0 +1,17 @@ +# Apollolake +## SPI flash layout + +![][apl_flash_layout] + +With Apollolake Intel invented another flash layout for x86 firmware called IFWI (Intel FirmWare Image). + +Usually on x86 platforms the bootblock is stored at the end of the bios region +and the Intel ME / TXE has its own IFD region. On Apollolake both have been +moved into the IFWI region, which is a subregion of "BIOS", since it allows to +store multiple firmware components. + +The IFWI region can be manipulated by `ifwitool`. + +[apl_flash_layout]: flash_layout.svg + + diff --git a/Documentation/soc/intel/index.md b/Documentation/soc/intel/index.md index 86f4de7155..f30ff9a1d6 100644 --- a/Documentation/soc/intel/index.md +++ b/Documentation/soc/intel/index.md @@ -9,3 +9,4 @@ This section contains documentation about coreboot on specific Intel SOCs. - [Ice Lake/9th Gen Core-i series](icelake/index.md) - [MP Initialization](mp_init/mp_init.md) - [Firmware Interface Table](fit.md) +- [Apollolake](apollolake/index.md) From 0fd4f5057207ad1f013f5465762a4ef29541c5a2 Mon Sep 17 00:00:00 2001 From: Puthikorn Voravootivat Date: Mon, 3 Jun 2019 14:36:55 -0700 Subject: [PATCH 029/221] mb/google/poppy/variants/atlas: Update DPTF parameter The temperature delta between on-board thermistor and surface temp change, so update DPTF parameter accordingly. BUG=b:113101335 TEST=Tested in thermal chamber by thermal team. See comment 148 / 153 in the bug. Change-Id: Ie18be94fc1e7476755fb0e6947cce559854a82dd Signed-off-by: Puthikorn Voravootivat Reviewed-on: https://review.coreboot.org/c/coreboot/+/33180 Tested-by: build bot (Jenkins) Reviewed-by: Caveh Jalali Reviewed-by: Bob Moragues --- .../google/poppy/variants/atlas/include/variant/acpi/dptf.asl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/poppy/variants/atlas/include/variant/acpi/dptf.asl b/src/mainboard/google/poppy/variants/atlas/include/variant/acpi/dptf.asl index 570fbbbdfa..68633723ea 100644 --- a/src/mainboard/google/poppy/variants/atlas/include/variant/acpi/dptf.asl +++ b/src/mainboard/google/poppy/variants/atlas/include/variant/acpi/dptf.asl @@ -29,12 +29,12 @@ #define DPTF_TSR2_SENSOR_ID 3 #define DPTF_TSR2_SENSOR_NAME "DRAM" -#define DPTF_TSR2_PASSIVE 55 +#define DPTF_TSR2_PASSIVE 53 #define DPTF_TSR2_CRITICAL 75 #define DPTF_TSR3_SENSOR_ID 4 #define DPTF_TSR3_SENSOR_NAME "eMMC" -#define DPTF_TSR3_PASSIVE 52 +#define DPTF_TSR3_PASSIVE 50 #define DPTF_TSR3_CRITICAL 75 #undef DPTF_ENABLE_FAN_CONTROL From 913d8b5e454971b1dc4a8bd9d30cc37db5d7ce57 Mon Sep 17 00:00:00 2001 From: "Marty E. Plummer" Date: Sat, 15 Jun 2019 02:40:16 -0500 Subject: [PATCH 030/221] arm64: make comment match code Change-Id: I37b8d5715cb6a32d4853e77098094cd5cffb9a4c Signed-off-by: Marty E. Plummer Reviewed-on: https://review.coreboot.org/c/coreboot/+/33486 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Angel Pons Reviewed-by: Julius Werner --- src/arch/arm64/armv8/bootblock.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/arm64/armv8/bootblock.S b/src/arch/arm64/armv8/bootblock.S index e5758bca0d..3950f5530d 100644 --- a/src/arch/arm64/armv8/bootblock.S +++ b/src/arch/arm64/armv8/bootblock.S @@ -19,7 +19,7 @@ /* NOTE: When making changes to general ARM64 initialization, keep in mind that * there are other CPU entry points, using BOOTBLOCK_CUSTOM or entering the CPU * in a later stage (like Tegra). Changes should generally be put into - * arm64_cpu_init so they can be shared between those instances. */ + * arm64_init_cpu so they can be shared between those instances. */ ENTRY(_start) /* Initialize PSTATE, SCTLR and caches to clean state, set up stack. */ From db43afa8365eeac8495a6fe07d8f83e1c9f01146 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Fri, 14 Jun 2019 18:48:13 +0200 Subject: [PATCH 031/221] drivers/ipmi: Fix multiple issues * Set abort command define * Set debug level to SPEW * Support zero length data packet in ipmi_kcs_send_message That's required for commands like GET_DEVICE_ID, which have no additional data to send. * Read reply even if given no receive buffer * Prevent buffer overflow in read reply processing Tested on Wedge100s. Change-Id: Iefddd88a744c3b96751d3fe8c2951ca2115548ce Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33488 Reviewed-by: Felix Held Tested-by: build bot (Jenkins) --- src/drivers/ipmi/ipmi_kcs.c | 74 ++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/src/drivers/ipmi/ipmi_kcs.c b/src/drivers/ipmi/ipmi_kcs.c index d17a1f98d2..397a800df3 100644 --- a/src/drivers/ipmi/ipmi_kcs.c +++ b/src/drivers/ipmi/ipmi_kcs.c @@ -22,7 +22,7 @@ #define IPMI_KCS_STATE(_x) ((_x) >> 6) -#define IPMI_KCS_GET_STATUS_ABORT +#define IPMI_KCS_GET_STATUS_ABORT 0x60 #define IPMI_KCS_START_WRITE 0x61 #define IPMI_KCS_END_WRITE 0x62 #define IPMI_KCS_READ_BYTE 0x68 @@ -43,7 +43,7 @@ static unsigned char ipmi_kcs_status(int port) { unsigned char status = inb(IPMI_STAT(port)); - printk(BIOS_DEBUG, "%s: 0x%02x\n", __func__, status); + printk(BIOS_SPEW, "%s: 0x%02x\n", __func__, status); return status; } @@ -77,7 +77,7 @@ static int ipmi_kcs_send_data_byte(int port, const unsigned char byte) { unsigned char status; - printk(BIOS_DEBUG, "%s: %02x\n", __func__, byte); + printk(BIOS_SPEW, "%s: 0x%02x\n", __func__, byte); outb(byte, IPMI_DATA(port)); @@ -100,7 +100,7 @@ static int ipmi_kcs_send_last_data_byte(int port, const unsigned char byte) { unsigned char status; - printk(BIOS_DEBUG, "%s: %02x\n", __func__, byte); + printk(BIOS_SPEW, "%s: 0x%02x\n", __func__, byte); if (wait_ibf_timeout(port)) return 1; @@ -121,7 +121,7 @@ static int ipmi_kcs_send_last_data_byte(int port, const unsigned char byte) static int ipmi_kcs_send_cmd_byte(int port, const unsigned char byte) { - printk(BIOS_DEBUG, "%s: 0x%02x\n", __func__, byte); + printk(BIOS_SPEW, "%s: 0x%02x\n", __func__, byte); if (wait_ibf_timeout(port)) return 1; @@ -156,31 +156,47 @@ static int ipmi_kcs_send_message(int port, int netfn, int lun, int cmd, return ret; } - ret = ipmi_kcs_send_data_byte(port, cmd); - if (ret) { - printk(BIOS_ERR, "IPMI CMD failed\n"); - return ret; - } + if (!len) { + ret = ipmi_kcs_send_cmd_byte(port, IPMI_KCS_END_WRITE); + if (ret) { + printk(BIOS_ERR, "IPMI END WRITE failed\n"); + return ret; + } - while (len-- > 1) { - ret = ipmi_kcs_send_data_byte(port, *msg++); + ret = ipmi_kcs_send_last_data_byte(port, cmd); + if (ret) { + printk(BIOS_ERR, "IPMI BYTE WRITE failed\n"); + return ret; + } + } else { + ret = ipmi_kcs_send_data_byte(port, cmd); + if (ret) { + printk(BIOS_ERR, "IPMI CMD failed\n"); + return ret; + } + + while (len > 1) { + ret = ipmi_kcs_send_data_byte(port, *msg++); + if (ret) { + printk(BIOS_ERR, "IPMI BYTE WRITE failed\n"); + return ret; + } + len--; + } + + ret = ipmi_kcs_send_cmd_byte(port, IPMI_KCS_END_WRITE); + if (ret) { + printk(BIOS_ERR, "IPMI END WRITE failed\n"); + return ret; + } + + ret = ipmi_kcs_send_last_data_byte(port, *msg); if (ret) { printk(BIOS_ERR, "IPMI BYTE WRITE failed\n"); return ret; } } - ret = ipmi_kcs_send_cmd_byte(port, IPMI_KCS_END_WRITE); - if (ret) { - printk(BIOS_ERR, "IPMI END WRITE failed\n"); - return ret; - } - - ret = ipmi_kcs_send_last_data_byte(port, *msg++); - if (ret) { - printk(BIOS_ERR, "IPMI BYTE WRITE failed\n"); - return ret; - } return 0; } @@ -188,9 +204,6 @@ static int ipmi_kcs_read_message(int port, unsigned char *msg, int len) { int status, ret = 0; - if (!msg) - return 0; - if (wait_ibf_timeout(port)) return 1; @@ -201,15 +214,18 @@ static int ipmi_kcs_read_message(int port, unsigned char *msg, int len) return ret; if (IPMI_KCS_STATE(status) != IPMI_KCS_STATE_READ) { - printk(BIOS_ERR, "%s: wrong state: 0x%02x\n", __func__, status); + printk(BIOS_ERR, "%s: wrong state: 0x%02x\n", __func__, + status); return -1; } if (wait_obf_timeout(port)) return -1; - *msg++ = inb(IPMI_DATA(port)); - ret++; + if (msg && (ret < len)) { + *msg++ = inb(IPMI_DATA(port)); + ret++; + } if (wait_ibf_timeout(port)) return -1; From f20bf92bd522f7fdd8f009b0ac79ab5eb38c73c2 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Thu, 13 Jun 2019 14:14:56 +0200 Subject: [PATCH 032/221] MAINTAINERS: Add maintainers to ELTAN VENDORCODE Add maintainers to the new vendorcode. Change-Id: Ie3f99dd99c708f93bfcd19f52c57504e157e1eca Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33441 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f1ae076937..e7780a8d72 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -624,6 +624,12 @@ S: Supported F: */memlayout.h F: *.ld +ELTAN VENDORCODE +M: Frans Hendriks +M: Wim Vervoorn +S: Maintained +F: src/vendorcode/eltan + MISSING: TIMERS / DELAYS MISSING: TIMESTAMPS From 5326ad7d11229ef70c0d93e9b6b547d910d28ba2 Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Thu, 23 May 2019 12:41:44 +0200 Subject: [PATCH 033/221] libpayload: define cbtable tags as enum to identify conflicts We had a value that was overloaded thrice. By moving them in a common structure and ordering them by value such issues are hopefully avoided in the future. Change-Id: I0c7762601d7620413989b458fa634d7606accc9d Signed-off-by: Patrick Georgi Reviewed-on: https://review.coreboot.org/c/coreboot/+/32957 Reviewed-by: Arthur Heymans Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- payloads/libpayload/include/coreboot_tables.h | 104 +++++++++--------- 1 file changed, 49 insertions(+), 55 deletions(-) diff --git a/payloads/libpayload/include/coreboot_tables.h b/payloads/libpayload/include/coreboot_tables.h index 8e5cec04bf..7226c0ae94 100644 --- a/payloads/libpayload/include/coreboot_tables.h +++ b/payloads/libpayload/include/coreboot_tables.h @@ -33,6 +33,55 @@ #include #include +enum { + CB_TAG_UNUSED = 0x0000, + CB_TAG_MEMORY = 0x0001, + CB_TAG_HWRPB = 0x0002, + CB_TAG_MAINBOARD = 0x0003, + CB_TAG_VERSION = 0x0004, + CB_TAG_EXTRA_VERSION = 0x0005, + CB_TAG_BUILD = 0x0006, + CB_TAG_COMPILE_TIME = 0x0007, + CB_TAG_COMPILE_BY = 0x0008, + CB_TAG_COMPILE_HOST = 0x0009, + CB_TAG_COMPILE_DOMAIN = 0x000a, + CB_TAG_COMPILER = 0x000b, + CB_TAG_LINKER = 0x000c, + CB_TAG_ASSEMBLER = 0x000d, + CB_TAG_SERIAL = 0x000f, + CB_TAG_CONSOLE = 0x0010, + CB_TAG_FORWARD = 0x0011, + CB_TAG_FRAMEBUFFER = 0x0012, + CB_TAG_GPIO = 0x0013, + CB_TAG_TIMESTAMPS = 0x0016, + CB_TAG_CBMEM_CONSOLE = 0x0017, + CB_TAG_MRC_CACHE = 0x0018, + CB_TAG_VBNV = 0x0019, + CB_TAG_VBOOT_HANDOFF = 0x0020, + CB_TAG_X86_ROM_MTRR = 0x0021, + CB_TAG_DMA = 0x0022, + CB_TAG_RAM_OOPS = 0x0023, + CB_TAG_ACPI_GNVS = 0x0024, + CB_TAG_BOARD_ID = 0x0025, + CB_TAG_WIFI_CALIBRATION = 0x0027, + CB_TAG_RAM_CODE = 0x0028, + CB_TAG_SPI_FLASH = 0x0029, + CB_TAG_SERIALNO = 0x002a, + CB_TAG_MTC = 0x002b, + CB_TAG_VPD = 0x002c, + CB_TAG_SKU_ID = 0x002d, + CB_TAG_BOOT_MEDIA_PARAMS = 0x0030, + CB_TAG_TSC_INFO = 0x0032, + CB_TAG_MAC_ADDRS = 0x0033, + CB_TAG_VBOOT_WORKBUF = 0x0034, + CB_TAG_MMC_INFO = 0x0035, + CB_TAG_CMOS_OPTION_TABLE = 0x00c8, + CB_TAG_OPTION = 0x00c9, + CB_TAG_OPTION_ENUM = 0x00ca, + CB_TAG_OPTION_DEFAULTS = 0x00cb, + CB_TAG_OPTION_CHECKSUM = 0x00cc, +}; + struct cbuint64 { u32 lo; u32 hi; @@ -52,9 +101,6 @@ struct cb_record { u32 size; }; -#define CB_TAG_UNUSED 0x0000 -#define CB_TAG_MEMORY 0x0001 - struct cb_memory_range { struct cbuint64 start; struct cbuint64 size; @@ -75,16 +121,12 @@ struct cb_memory { struct cb_memory_range map[0]; }; -#define CB_TAG_HWRPB 0x0002 - struct cb_hwrpb { u32 tag; u32 size; u64 hwrpb; }; -#define CB_TAG_MAINBOARD 0x0003 - struct cb_mainboard { u32 tag; u32 size; @@ -93,25 +135,12 @@ struct cb_mainboard { u8 strings[0]; }; -#define CB_TAG_VERSION 0x0004 -#define CB_TAG_EXTRA_VERSION 0x0005 -#define CB_TAG_BUILD 0x0006 -#define CB_TAG_COMPILE_TIME 0x0007 -#define CB_TAG_COMPILE_BY 0x0008 -#define CB_TAG_COMPILE_HOST 0x0009 -#define CB_TAG_COMPILE_DOMAIN 0x000a -#define CB_TAG_COMPILER 0x000b -#define CB_TAG_LINKER 0x000c -#define CB_TAG_ASSEMBLER 0x000d - struct cb_string { u32 tag; u32 size; u8 string[0]; }; -#define CB_TAG_SERIAL 0x000f - struct cb_serial { u32 tag; u32 size; @@ -138,8 +167,6 @@ struct cb_serial { u32 uart_pci_addr; }; -#define CB_TAG_CONSOLE 0x00010 - struct cb_console { u32 tag; u32 size; @@ -153,15 +180,12 @@ struct cb_console { #define CB_TAG_CONSOLE_SROM 4 // OBSOLETE #define CB_TAG_CONSOLE_EHCI 5 -#define CB_TAG_FORWARD 0x00011 - struct cb_forward { u32 tag; u32 size; u64 forward; }; -#define CB_TAG_FRAMEBUFFER 0x0012 struct cb_framebuffer { u32 tag; u32 size; @@ -181,7 +205,6 @@ struct cb_framebuffer { u8 reserved_mask_size; }; -#define CB_TAG_GPIO 0x0013 #define CB_GPIO_ACTIVE_LOW 0 #define CB_GPIO_ACTIVE_HIGH 1 #define CB_GPIO_MAX_NAME_LENGTH 16 @@ -200,13 +223,6 @@ struct cb_gpios { struct cb_gpio gpios[0]; }; -#define CB_TAG_VBNV 0x0019 -#define CB_TAG_VBOOT_HANDOFF 0x0020 -#define CB_TAG_VBOOT_WORKBUF 0x0034 -#define CB_TAG_DMA 0x0022 -#define CB_TAG_RAM_OOPS 0x0023 -#define CB_TAG_MTC 0x002b -#define CB_TAG_VPD 0x002c struct lb_range { uint32_t tag; uint32_t size; @@ -214,18 +230,12 @@ struct lb_range { uint32_t range_size; }; -#define CB_TAG_TIMESTAMPS 0x0016 -#define CB_TAG_CBMEM_CONSOLE 0x0017 -#define CB_TAG_MRC_CACHE 0x0018 -#define CB_TAG_ACPI_GNVS 0x0024 -#define CB_TAG_WIFI_CALIBRATION 0x0027 struct cb_cbmem_tab { uint32_t tag; uint32_t size; uint64_t cbmem_tab; }; -#define CB_TAG_X86_ROM_MTRR 0x0021 struct cb_x86_rom_mtrr { uint32_t tag; uint32_t size; @@ -236,17 +246,12 @@ struct cb_x86_rom_mtrr { uint32_t index; }; - -#define CB_TAG_BOARD_ID 0x0025 -#define CB_TAG_RAM_CODE 0x0028 -#define CB_TAG_SKU_ID 0x002d struct cb_strapping_id { uint32_t tag; uint32_t size; uint32_t id_code; }; -#define CB_TAG_SPI_FLASH 0x0029 struct cb_spi_flash { uint32_t tag; uint32_t size; @@ -255,7 +260,6 @@ struct cb_spi_flash { uint32_t erase_cmd; }; -#define CB_TAG_BOOT_MEDIA_PARAMS 0x0030 struct cb_boot_media_params { uint32_t tag; uint32_t size; @@ -266,7 +270,6 @@ struct cb_boot_media_params { uint64_t boot_media_size; }; -#define CB_TAG_TSC_INFO 0x0032 struct cb_tsc_info { uint32_t tag; uint32_t size; @@ -274,7 +277,6 @@ struct cb_tsc_info { uint32_t freq_khz; }; -#define CB_TAG_MAC_ADDRS 0x0033 struct mac_address { uint8_t mac_addr[6]; uint8_t pad[2]; /* Pad it to 8 bytes to keep it simple. */ @@ -287,7 +289,6 @@ struct cb_macs { struct mac_address mac_addrs[0]; }; -#define CB_TAG_MMC_INFO 0x0035 struct cb_mmc_info { uint32_t tag; uint32_t size; @@ -302,17 +303,14 @@ struct cb_mmc_info { int32_t early_cmd1_status; }; -#define CB_TAG_SERIALNO 0x002a #define CB_MAX_SERIALNO_LENGTH 32 -#define CB_TAG_CMOS_OPTION_TABLE 0x00c8 struct cb_cmos_option_table { u32 tag; u32 size; u32 header_length; }; -#define CB_TAG_OPTION 0x00c9 #define CB_CMOS_MAX_NAME_LENGTH 32 struct cb_cmos_entries { u32 tag; @@ -324,8 +322,6 @@ struct cb_cmos_entries { u8 name[CB_CMOS_MAX_NAME_LENGTH]; }; - -#define CB_TAG_OPTION_ENUM 0x00ca #define CB_CMOS_MAX_TEXT_LENGTH 32 struct cb_cmos_enums { u32 tag; @@ -335,7 +331,6 @@ struct cb_cmos_enums { u8 text[CB_CMOS_MAX_TEXT_LENGTH]; }; -#define CB_TAG_OPTION_DEFAULTS 0x00cb #define CB_CMOS_IMAGE_BUFFER_SIZE 128 struct cb_cmos_defaults { u32 tag; @@ -345,7 +340,6 @@ struct cb_cmos_defaults { u8 default_set[CB_CMOS_IMAGE_BUFFER_SIZE]; }; -#define CB_TAG_OPTION_CHECKSUM 0x00cc #define CB_CHECKSUM_NONE 0 #define CB_CHECKSUM_PCBIOS 1 struct cb_cmos_checksum { From d0bd54486a7ac79f10450f3e026a1142154a2d15 Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Thu, 23 May 2019 12:41:44 +0200 Subject: [PATCH 034/221] commonlib: define cbtable tags as enum to identify conflicts We had a value that was overloaded thrice. By moving them in a common structure and ordering them by value such issues are hopefully avoided in the future. Also add a few values to libpayload that were only defined in commonlib. Change-Id: I227d078eebee2d92488454707d4dab8ecc24a4d8 Signed-off-by: Patrick Georgi Reviewed-on: https://review.coreboot.org/c/coreboot/+/32958 Reviewed-by: Arthur Heymans Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- payloads/libpayload/include/coreboot_tables.h | 3 + .../include/commonlib/coreboot_tables.h | 102 +++++++++--------- 2 files changed, 55 insertions(+), 50 deletions(-) diff --git a/payloads/libpayload/include/coreboot_tables.h b/payloads/libpayload/include/coreboot_tables.h index 7226c0ae94..b0d7c90389 100644 --- a/payloads/libpayload/include/coreboot_tables.h +++ b/payloads/libpayload/include/coreboot_tables.h @@ -63,6 +63,7 @@ enum { CB_TAG_RAM_OOPS = 0x0023, CB_TAG_ACPI_GNVS = 0x0024, CB_TAG_BOARD_ID = 0x0025, + CB_TAG_VERSION_TIMESTAMP = 0x0026, CB_TAG_WIFI_CALIBRATION = 0x0027, CB_TAG_RAM_CODE = 0x0028, CB_TAG_SPI_FLASH = 0x0029, @@ -71,10 +72,12 @@ enum { CB_TAG_VPD = 0x002c, CB_TAG_SKU_ID = 0x002d, CB_TAG_BOOT_MEDIA_PARAMS = 0x0030, + CB_TAG_CBMEM_ENTRY = 0x0031, CB_TAG_TSC_INFO = 0x0032, CB_TAG_MAC_ADDRS = 0x0033, CB_TAG_VBOOT_WORKBUF = 0x0034, CB_TAG_MMC_INFO = 0x0035, + CB_TAG_TCPA_LOG = 0x0036, CB_TAG_CMOS_OPTION_TABLE = 0x00c8, CB_TAG_OPTION = 0x00c9, CB_TAG_OPTION_ENUM = 0x00ca, diff --git a/src/commonlib/include/commonlib/coreboot_tables.h b/src/commonlib/include/commonlib/coreboot_tables.h index 277b7467fb..1ae5421bba 100644 --- a/src/commonlib/include/commonlib/coreboot_tables.h +++ b/src/commonlib/include/commonlib/coreboot_tables.h @@ -44,6 +44,58 @@ * table entries and be backwards compatible, but it is not required. */ +enum { + LB_TAG_UNUSED = 0x0000, + LB_TAG_MEMORY = 0x0001, + LB_TAG_HWRPB = 0x0002, + LB_TAG_MAINBOARD = 0x0003, + LB_TAG_VERSION = 0x0004, + LB_TAG_EXTRA_VERSION = 0x0005, + LB_TAG_BUILD = 0x0006, + LB_TAG_COMPILE_TIME = 0x0007, + LB_TAG_COMPILE_BY = 0x0008, + LB_TAG_COMPILE_HOST = 0x0009, + LB_TAG_COMPILE_DOMAIN = 0x000a, + LB_TAG_COMPILER = 0x000b, + LB_TAG_LINKER = 0x000c, + LB_TAG_ASSEMBLER = 0x000d, + LB_TAG_SERIAL = 0x000f, + LB_TAG_CONSOLE = 0x0010, + LB_TAG_FORWARD = 0x0011, + LB_TAG_FRAMEBUFFER = 0x0012, + LB_TAG_GPIO = 0x0013, + LB_TAG_TIMESTAMPS = 0x0016, + LB_TAG_CBMEM_CONSOLE = 0x0017, + LB_TAG_MRC_CACHE = 0x0018, + LB_TAG_VBNV = 0x0019, + LB_TAG_VBOOT_HANDOFF = 0x0020, + LB_TAG_X86_ROM_MTRR = 0x0021, + LB_TAG_DMA = 0x0022, + LB_TAG_RAM_OOPS = 0x0023, + LB_TAG_ACPI_GNVS = 0x0024, + LB_TAG_BOARD_ID = 0x0025, + LB_TAG_VERSION_TIMESTAMP = 0x0026, + LB_TAG_WIFI_CALIBRATION = 0x0027, + LB_TAG_RAM_CODE = 0x0028, + LB_TAG_SPI_FLASH = 0x0029, + LB_TAG_SERIALNO = 0x002a, + LB_TAG_MTC = 0x002b, + LB_TAG_VPD = 0x002c, + LB_TAG_SKU_ID = 0x002d, + LB_TAG_BOOT_MEDIA_PARAMS = 0x0030, + LB_TAG_CBMEM_ENTRY = 0x0031, + LB_TAG_TSC_INFO = 0x0032, + LB_TAG_MAC_ADDRS = 0x0033, + LB_TAG_VBOOT_WORKBUF = 0x0034, + LB_TAG_MMC_INFO = 0x0035, + LB_TAG_TCPA_LOG = 0x0036, + LB_TAG_CMOS_OPTION_TABLE = 0x00c8, + LB_TAG_OPTION = 0x00c9, + LB_TAG_OPTION_ENUM = 0x00ca, + LB_TAG_OPTION_DEFAULTS = 0x00cb, + LB_TAG_OPTION_CHECKSUM = 0x00cc, +}; + /* Since coreboot is usually compiled 32bit, gcc will align 64bit * types to 32bit boundaries. If the coreboot table is dumped on a * 64bit system, a uint64_t would be aligned to 64bit boundaries, @@ -97,9 +149,6 @@ struct lb_record { uint32_t size; /* size of record (in bytes) */ }; -#define LB_TAG_UNUSED 0x0000 - -#define LB_TAG_MEMORY 0x0001 struct lb_memory_range { struct lb_uint64 start; @@ -120,14 +169,12 @@ struct lb_memory { struct lb_memory_range map[0]; }; -#define LB_TAG_HWRPB 0x0002 struct lb_hwrpb { uint32_t tag; uint32_t size; uint64_t hwrpb; }; -#define LB_TAG_MAINBOARD 0x0003 struct lb_mainboard { uint32_t tag; uint32_t size; @@ -136,23 +183,12 @@ struct lb_mainboard { uint8_t strings[0]; }; -#define LB_TAG_VERSION 0x0004 -#define LB_TAG_EXTRA_VERSION 0x0005 -#define LB_TAG_BUILD 0x0006 -#define LB_TAG_COMPILE_TIME 0x0007 -#define LB_TAG_COMPILE_BY 0x0008 -#define LB_TAG_COMPILE_HOST 0x0009 -#define LB_TAG_COMPILE_DOMAIN 0x000a -#define LB_TAG_COMPILER 0x000b -#define LB_TAG_LINKER 0x000c -#define LB_TAG_ASSEMBLER 0x000d struct lb_string { uint32_t tag; uint32_t size; uint8_t string[0]; }; -#define LB_TAG_VERSION_TIMESTAMP 0x0026 struct lb_timestamp { uint32_t tag; uint32_t size; @@ -162,7 +198,6 @@ struct lb_timestamp { /* 0xe is taken by v3 */ -#define LB_TAG_SERIAL 0x000f struct lb_serial { uint32_t tag; uint32_t size; @@ -189,7 +224,6 @@ struct lb_serial { uint32_t uart_pci_addr; }; -#define LB_TAG_CONSOLE 0x0010 struct lb_console { uint32_t tag; uint32_t size; @@ -204,7 +238,6 @@ struct lb_console { #define LB_TAG_CONSOLE_EHCI 5 #define LB_TAG_CONSOLE_SERIAL8250MEM 6 -#define LB_TAG_FORWARD 0x0011 struct lb_forward { uint32_t tag; uint32_t size; @@ -250,7 +283,6 @@ struct lb_forward { * fields described above. It may, however, only implement a subset * of the possible color formats. */ -#define LB_TAG_FRAMEBUFFER 0x0012 struct lb_framebuffer { uint32_t tag; uint32_t size; @@ -270,7 +302,6 @@ struct lb_framebuffer { uint8_t reserved_mask_size; }; -#define LB_TAG_GPIO 0x0013 struct lb_gpio { uint32_t port; @@ -290,12 +321,6 @@ struct lb_gpios { struct lb_gpio gpios[0]; }; -#define LB_TAG_VBNV 0x0019 -#define LB_TAG_VBOOT_HANDOFF 0x0020 -#define LB_TAG_VBOOT_WORKBUF 0x0034 -#define LB_TAG_DMA 0x0022 -#define LB_TAG_RAM_OOPS 0x0023 -#define LB_TAG_MTC 0x002b struct lb_range { uint32_t tag; uint32_t size; @@ -306,13 +331,6 @@ struct lb_range { void lb_ramoops(struct lb_header *header); -#define LB_TAG_TIMESTAMPS 0x0016 -#define LB_TAG_CBMEM_CONSOLE 0x0017 -#define LB_TAG_MRC_CACHE 0x0018 -#define LB_TAG_ACPI_GNVS 0x0024 -#define LB_TAG_TCPA_LOG 0x0036 -#define LB_TAG_WIFI_CALIBRATION 0x0027 -#define LB_TAG_VPD 0x002c struct lb_cbmem_ref { uint32_t tag; uint32_t size; @@ -320,7 +338,6 @@ struct lb_cbmem_ref { uint64_t cbmem_addr; }; -#define LB_TAG_X86_ROM_MTRR 0x0021 struct lb_x86_rom_mtrr { uint32_t tag; uint32_t size; @@ -328,9 +345,6 @@ struct lb_x86_rom_mtrr { uint32_t index; }; -#define LB_TAG_BOARD_ID 0x0025 -#define LB_TAG_RAM_CODE 0x0028 -#define LB_TAG_SKU_ID 0x002d struct lb_strapping_id { uint32_t tag; @@ -338,7 +352,6 @@ struct lb_strapping_id { uint32_t id_code; }; -#define LB_TAG_SPI_FLASH 0x0029 struct lb_spi_flash { uint32_t tag; uint32_t size; @@ -347,7 +360,6 @@ struct lb_spi_flash { uint32_t erase_cmd; }; -#define LB_TAG_BOOT_MEDIA_PARAMS 0x0030 struct lb_boot_media_params { uint32_t tag; uint32_t size; @@ -361,7 +373,6 @@ struct lb_boot_media_params { /* * There can be more than one of these records as there is one per cbmem entry. */ -#define LB_TAG_CBMEM_ENTRY 0x0031 struct lb_cbmem_entry { uint32_t tag; uint32_t size; @@ -371,7 +382,6 @@ struct lb_cbmem_entry { uint32_t id; }; -#define LB_TAG_TSC_INFO 0x0032 struct lb_tsc_info { uint32_t tag; uint32_t size; @@ -379,13 +389,11 @@ struct lb_tsc_info { uint32_t freq_khz; }; -#define LB_TAG_MAC_ADDRS 0x0033 struct mac_address { uint8_t mac_addr[6]; uint8_t pad[2]; /* Pad it to 8 bytes to keep it simple. */ }; -#define LB_TAG_MMC_INFO 0x0035 struct lb_mmc_info { uint32_t tag; uint32_t size; @@ -407,11 +415,9 @@ struct lb_macs { struct mac_address mac_addrs[0]; }; -#define LB_TAG_SERIALNO 0x002a #define MAX_SERIALNO_LENGTH 32 /* The following structures are for the cmos definitions table */ -#define LB_TAG_CMOS_OPTION_TABLE 200 /* cmos header record */ struct cmos_option_table { uint32_t tag; /* CMOS definitions table type */ @@ -426,7 +432,6 @@ struct cmos_option_table { * starts at the beginning of the byte and the length is * fills complete bytes. */ -#define LB_TAG_OPTION 201 struct cmos_entries { uint32_t tag; /* entry type */ uint32_t size; /* length of this record */ @@ -444,7 +449,6 @@ struct cmos_entries { * This record is variable length. The text field may be * shorter than CMOS_MAX_TEXT_LENGTH. */ -#define LB_TAG_OPTION_ENUM 202 struct cmos_enums { uint32_t tag; /* enumeration type */ uint32_t size; /* length of this record */ @@ -458,7 +462,6 @@ struct cmos_enums { /* cmos defaults record * This record contains default settings for the cmos ram. */ -#define LB_TAG_OPTION_DEFAULTS 203 struct cmos_defaults { uint32_t tag; /* default type */ uint32_t size; /* length of this record */ @@ -468,7 +471,6 @@ struct cmos_defaults { uint8_t default_set[CMOS_IMAGE_BUFFER_SIZE]; /* default settings */ }; -#define LB_TAG_OPTION_CHECKSUM 204 struct cmos_checksum { uint32_t tag; uint32_t size; From 15110f12cb6d9e2f9e05854b99e8a5f404fa7c59 Mon Sep 17 00:00:00 2001 From: zaolin Date: Mon, 17 Jun 2019 01:23:15 +0200 Subject: [PATCH 035/221] Add intel-microcode submodule repository Change-Id: Icc5ac0a8033e371ecf2b4b28ba45dab961e86b3f Signed-off-by: Philipp Deppenwiese Reviewed-on: https://review.coreboot.org/c/coreboot/+/33550 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans Reviewed-by: Lijian Zhao --- .gitmodules | 5 +++++ 3rdparty/intel-microcode | 1 + 2 files changed, 6 insertions(+) create mode 160000 3rdparty/intel-microcode diff --git a/.gitmodules b/.gitmodules index 78e2c880f6..e18f0dc4c1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,8 @@ [submodule "opensbi"] path = 3rdparty/opensbi url = ../opensbi.git +[submodule "intel-microcode"] + path = 3rdparty/intel-microcode + url = ../intel-microcode.git + update = none + ignore = dirty diff --git a/3rdparty/intel-microcode b/3rdparty/intel-microcode new file mode 160000 index 0000000000..1dd14da6d1 --- /dev/null +++ b/3rdparty/intel-microcode @@ -0,0 +1 @@ +Subproject commit 1dd14da6d1ea5cfbd95923653f31c04aac3aa655 From 917420f7e8ca9047ef639fe8b642ebcc128e62d1 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 17 Jun 2019 10:49:48 +0200 Subject: [PATCH 036/221] Makefile.inc: Update 3rdparty/intel-microcode on USE_BLOBS Change-Id: I0caeff3ff5613a594a79441e849440ebdc9a9b87 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33553 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- Makefile.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc index 2ba9446fdf..48879bc9fd 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -193,9 +193,10 @@ ifneq ($(UPDATED_SUBMODULES),1) # try to fetch non-optional submodules if the source is under git forgetthis:=$(if $(GIT),$(shell git submodule update --init)) ifeq ($(CONFIG_USE_BLOBS),y) -# this is necessary because 3rdparty/blobs is update=none, and so is ignored +# this is necessary because 3rdparty/{blobs,intel-microcode} is update=none, and so is ignored # unless explicitly requested and enabled through --checkout forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/blobs)) +forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/intel-microcode)) ifeq ($(CONFIG_PLATFORM_USES_FSP1_0)$(CONFIG_PLATFORM_USES_FSP1_1)$(CONFIG_PLATFORM_USES_FSP2_0),y) # this is necessary because 3rdparty/fsp is update=none, and so is ignored # unless explicitly requested and enabled through --checkout From b0bbafe5ad3c8a300ceedab9ad607c789d20fc59 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 17 Jun 2019 12:42:53 +0200 Subject: [PATCH 037/221] soc/intel/skylake: Select microcode updates depending on discrete PCH Change-Id: I05e97484605306afc70c726187bda8091216c9cc Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33557 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/soc/intel/skylake/Makefile.inc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index e9f555f13c..129586a233 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -81,15 +81,17 @@ postcar-y += spi.c postcar-y += i2c.c postcar-y += uart.c - -# Skylake D0 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_406ex/microcode.bin +ifeq ($(CONFIG_SKYLAKE_SOC_PCH_H),y) # Skylake H Q0 cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_506ex/microcode.bin -# Kabylake H0, Y0 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_806ex/microcode.bin # Kabylake HB0 cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_906ex/microcode.bin +else +# Skylake D0 +cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_406ex/microcode.bin +# Kabylake H0, Y0 +cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_806ex/microcode.bin +endif # Missing for Skylake C0 (0x406e2), Kabylake G0 (0x406e8), Kabylake HA0 (0x506e8) # since those are probably pre-release samples. From a9c1a5f1f8d03cf8754ed7bd410e89c878b25cc7 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sat, 15 Jun 2019 18:21:58 +0200 Subject: [PATCH 038/221] sb/common/intel/spi.c: Don't use typedefs for structs Change-Id: Id0ed621b5b4b5634d454811b1e1beeb27fc69ea8 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33505 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber Reviewed-by: Angel Pons --- src/southbridge/intel/common/spi.c | 58 +++++++++++++++--------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c index bf2a44c86c..5a4b26fa66 100644 --- a/src/southbridge/intel/common/spi.c +++ b/src/southbridge/intel/common/spi.c @@ -38,11 +38,9 @@ static int spi_is_multichip(void); -typedef struct spi_slave ich_spi_slave; - static int g_ichspi_lock = 0; -typedef struct ich7_spi_regs { +struct ich7_spi_regs { uint16_t spis; uint16_t spic; uint32_t spia; @@ -53,9 +51,9 @@ typedef struct ich7_spi_regs { uint16_t optype; uint8_t opmenu[8]; uint32_t pbr[3]; -} __packed ich7_spi_regs; +} __packed; -typedef struct ich9_spi_regs { +struct ich9_spi_regs { uint32_t bfpr; uint16_t hsfs; uint16_t hsfc; @@ -86,15 +84,15 @@ typedef struct ich9_spi_regs { uint32_t srdl; uint32_t srdc; uint32_t srd; -} __packed ich9_spi_regs; +} __packed; -typedef struct ich_spi_controller { +struct ich_spi_controller { int locked; uint32_t flmap0; uint32_t flcomp; uint32_t hsfs; - ich9_spi_regs *ich9_spi; + struct ich9_spi_regs *ich9_spi; uint8_t *opmenu; int menubytes; uint16_t *preop; @@ -107,9 +105,9 @@ typedef struct ich_spi_controller { uint32_t *bbar; uint32_t *fpr; uint8_t fpr_max; -} ich_spi_controller; +}; -static ich_spi_controller g_cntlr; +static struct ich_spi_controller g_cntlr; enum { SPIS_SCIP = 0x0001, @@ -254,7 +252,7 @@ static void read_reg(const void *src, void *value, uint32_t size) static void ich_set_bbar(uint32_t minaddr) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; const uint32_t bbar_mask = 0x00ffff00; uint32_t ichspi_bbar; @@ -266,12 +264,12 @@ static void ich_set_bbar(uint32_t minaddr) void spi_init(void) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; uint8_t *rcrb; /* Root Complex Register Block */ uint32_t rcba; /* Root Complex Base Address */ uint8_t bios_cntl; - ich9_spi_regs *ich9_spi; - ich7_spi_regs *ich7_spi; + struct ich9_spi_regs *ich9_spi; + struct ich7_spi_regs *ich7_spi; uint16_t hsfs; #ifdef __SIMPLE_DEVICE__ @@ -284,7 +282,7 @@ void spi_init(void) /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */ rcrb = (uint8_t *)(rcba & 0xffffc000); if (CONFIG(SOUTHBRIDGE_INTEL_I82801GX)) { - ich7_spi = (ich7_spi_regs *)(rcrb + 0x3020); + ich7_spi = (struct ich7_spi_regs *)(rcrb + 0x3020); cntlr->opmenu = ich7_spi->opmenu; cntlr->menubytes = sizeof(ich7_spi->opmenu); cntlr->optype = &ich7_spi->optype; @@ -299,7 +297,7 @@ void spi_init(void) cntlr->fpr = &ich7_spi->pbr[0]; cntlr->fpr_max = 3; } else { - ich9_spi = (ich9_spi_regs *)(rcrb + 0x3800); + ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800); cntlr->ich9_spi = ich9_spi; hsfs = readw_(&ich9_spi->hsfs); g_ichspi_lock = hsfs & HSFS_FLOCKDN; @@ -399,7 +397,7 @@ static void spi_setup_type(spi_transaction *trans) static int spi_setup_opcode(spi_transaction *trans) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; uint16_t optypes; uint8_t opmenu[cntlr->menubytes]; @@ -480,7 +478,7 @@ static int spi_setup_offset(spi_transaction *trans) */ static int ich_status_poll(u16 bitmask, int wait_til_set) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; int timeout = 600000; /* This will result in 6 seconds */ u16 status = 0; @@ -501,7 +499,7 @@ static int ich_status_poll(u16 bitmask, int wait_til_set) static int spi_is_multichip(void) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; if (!(cntlr->hsfs & HSFS_FDV)) return 0; return !!((cntlr->flmap0 >> 8) & 3); @@ -510,7 +508,7 @@ static int spi_is_multichip(void) static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout, void *din, size_t bytesin) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; uint16_t control; int16_t opcode_index; int with_address; @@ -660,7 +658,7 @@ spi_xfer_exit: /* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */ static void ich_hwseq_set_addr(uint32_t addr) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; uint32_t addr_old = readl_(&cntlr->ich9_spi->faddr) & ~0x01FFFFFF; writel_((addr & 0x01FFFFFF) | addr_old, &cntlr->ich9_spi->faddr); @@ -673,7 +671,7 @@ static void ich_hwseq_set_addr(uint32_t addr) static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout, unsigned int len) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; uint16_t hsfs; uint32_t addr; @@ -713,7 +711,7 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout, static int ich_hwseq_erase(const struct spi_flash *flash, u32 offset, size_t len) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; u32 start, end, erase_size; int ret; uint16_t hsfc; @@ -763,7 +761,7 @@ out: static void ich_read_data(uint8_t *data, int len) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; int i; uint32_t temp32 = 0; @@ -778,7 +776,7 @@ static void ich_read_data(uint8_t *data, int len) static int ich_hwseq_read(const struct spi_flash *flash, u32 addr, size_t len, void *buf) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; uint16_t hsfc; uint16_t timeout = 100 * 60; uint8_t block_len; @@ -824,7 +822,7 @@ static int ich_hwseq_read(const struct spi_flash *flash, u32 addr, size_t len, */ static void ich_fill_data(const uint8_t *data, int len) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; uint32_t temp32 = 0; int i; @@ -848,7 +846,7 @@ static void ich_fill_data(const uint8_t *data, int len) static int ich_hwseq_write(const struct spi_flash *flash, u32 addr, size_t len, const void *buf) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; uint16_t hsfc; uint16_t timeout = 100 * 60; uint8_t block_len; @@ -904,7 +902,7 @@ static const struct spi_flash_ops spi_flash_ops = { static int spi_flash_programmer_probe(const struct spi_slave *spi, struct spi_flash *flash) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; if (CONFIG(SOUTHBRIDGE_INTEL_I82801GX)) return spi_flash_generic_probe(spi, flash); @@ -984,7 +982,7 @@ static int spi_flash_protect(const struct spi_flash *flash, const struct region *region, const enum ctrlr_prot_type type) { - ich_spi_controller *cntlr = &g_cntlr; + struct ich_spi_controller *cntlr = &g_cntlr; u32 start = region_offset(region); u32 end = start + region_sz(region) - 1; u32 reg; @@ -1043,7 +1041,7 @@ static int spi_flash_protect(const struct spi_flash *flash, static const struct spi_ctrlr spi_ctrlr = { .xfer_vector = xfer_vectors, - .max_xfer_size = member_size(ich9_spi_regs, fdata), + .max_xfer_size = member_size(struct ich9_spi_regs, fdata), .flash_probe = spi_flash_programmer_probe, .flash_protect = spi_flash_protect, }; From 21c5d43d723d5a52d5b4c0060a94d56bdf297424 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sat, 15 Jun 2019 18:23:29 +0200 Subject: [PATCH 039/221] sb/intel/common/spi.c: Add a pointer to the ich7 SPI registers Change-Id: I7509dc2124ee7057af075c7d0607ec615b930fa3 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33506 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber Reviewed-by: Angel Pons --- src/southbridge/intel/common/spi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c index 5a4b26fa66..f447515e58 100644 --- a/src/southbridge/intel/common/spi.c +++ b/src/southbridge/intel/common/spi.c @@ -92,7 +92,10 @@ struct ich_spi_controller { uint32_t flcomp; uint32_t hsfs; - struct ich9_spi_regs *ich9_spi; + union { + struct ich9_spi_regs *ich9_spi; + struct ich7_spi_regs *ich7_spi; + }; uint8_t *opmenu; int menubytes; uint16_t *preop; @@ -283,6 +286,7 @@ void spi_init(void) rcrb = (uint8_t *)(rcba & 0xffffc000); if (CONFIG(SOUTHBRIDGE_INTEL_I82801GX)) { ich7_spi = (struct ich7_spi_regs *)(rcrb + 0x3020); + cntlr->ich7_spi = ich7_spi; cntlr->opmenu = ich7_spi->opmenu; cntlr->menubytes = sizeof(ich7_spi->opmenu); cntlr->optype = &ich7_spi->optype; From 816aaba399537349b068afbd9bde702d00243f54 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 11 Jun 2019 11:10:25 +0200 Subject: [PATCH 040/221] sb/intel/spi: Check for the SPI lock bit during runtime The SPI swseq controller can be locked in other parts of the code, for instance when it's locked down in the finalize section. The driver has to be made aware of that. The simpler solution is to not keep track of the state and simply read out the lock bit on each SPI transfer. Change-Id: Ifcd5121b89d6f80fc1c1368786982d0d9fa1bf61 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33388 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber Reviewed-by: Angel Pons --- src/southbridge/intel/common/spi.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c index f447515e58..d9a77c3bb5 100644 --- a/src/southbridge/intel/common/spi.c +++ b/src/southbridge/intel/common/spi.c @@ -38,8 +38,6 @@ static int spi_is_multichip(void); -static int g_ichspi_lock = 0; - struct ich7_spi_regs { uint16_t spis; uint16_t spic; @@ -294,7 +292,6 @@ void spi_init(void) cntlr->data = (uint8_t *)ich7_spi->spid; cntlr->databytes = sizeof(ich7_spi->spid); cntlr->status = (uint8_t *)&ich7_spi->spis; - g_ichspi_lock = readw_(&ich7_spi->spis) & HSFS_FLOCKDN; cntlr->control = &ich7_spi->spic; cntlr->bbar = &ich7_spi->bbar; cntlr->preop = &ich7_spi->preop; @@ -304,7 +301,6 @@ void spi_init(void) ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800); cntlr->ich9_spi = ich9_spi; hsfs = readw_(&ich9_spi->hsfs); - g_ichspi_lock = hsfs & HSFS_FLOCKDN; cntlr->hsfs = hsfs; cntlr->opmenu = ich9_spi->opmenu; cntlr->menubytes = sizeof(ich9_spi->opmenu); @@ -336,6 +332,16 @@ void spi_init(void) pci_write_config8(dev, 0xdc, bios_cntl | 0x1); } +static int spi_locked(void) +{ + struct ich_spi_controller *cntlr = &g_cntlr; + if (CONFIG(SOUTHBRIDGE_INTEL_I82801GX)) { + return !!(readw_(&cntlr->ich7_spi->spis) & HSFS_FLOCKDN); + } else { + return !!(readw_(&cntlr->ich9_spi->hsfs) | HSFS_FLOCKDN); + } +} + static void spi_init_cb(void *unused) { spi_init(); @@ -407,7 +413,7 @@ static int spi_setup_opcode(spi_transaction *trans) trans->opcode = trans->out[0]; spi_use_out(trans, 1); - if (!g_ichspi_lock) { + if (!spi_locked()) { /* The lock is off, so just use index 0. */ writeb_(trans->opcode, cntlr->opmenu); optypes = readw_(cntlr->optype); @@ -552,7 +558,7 @@ static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout, * in order to prevent the Management Engine from * issuing a transaction between WREN and DATA. */ - if (!g_ichspi_lock) + if (!spi_locked()) writew_(trans.opcode, cntlr->preop); return 0; } From 7407210a6755b22862c22a87c21ed172cb646616 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 11 Jun 2019 11:23:52 +0200 Subject: [PATCH 041/221] sb/intel/bd82x6x/lpc.c: Remove reinitializing the SPI driver This was done to update the global variable g_ichspi_lock but this is now removed in favor of reading the lock bit during runtime instead of keeping track of the state. Change-Id: I8cb69a152b0e050d64d8979ee92de2d24136f8dc Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33390 Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/southbridge/intel/bd82x6x/lpc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/southbridge/intel/bd82x6x/lpc.c b/src/southbridge/intel/bd82x6x/lpc.c index 773750186f..661c1d483d 100644 --- a/src/southbridge/intel/bd82x6x/lpc.c +++ b/src/southbridge/intel/bd82x6x/lpc.c @@ -908,12 +908,6 @@ static void lpc_final(struct device *dev) if (CONFIG(INTEL_CHIPSET_LOCKDOWN) || acpi_is_wakeup_s3()) { outb(APM_CNT_FINALIZE, APM_CNT); - if (CONFIG(CONSOLE_SPI_FLASH)) - /* Re-init SPI driver to handle locked BAR. - This prevents flashconsole from hanging. - If other code needs to use SPI during - ramstage, whitelist it here. */ - spi_init(); } } } From ce0c5334a012230faf08fc3b901bb12010eb0208 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Thu, 13 Jun 2019 11:57:35 -0600 Subject: [PATCH 042/221] sb/amd/cimx/sb900: Change logical negation to bitwise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit data &= !BIT0 will clear data, since !BIT0 evaluates to 0 (oops). We only want to clear bit 0, not the whole thing, so use bitwise negation instead. Change-Id: I2179119e0d2d4aceaf4f8b499bf4c5baf4ef677f Signed-off-by: Jacob Garber Found-by: Coverity CID 1241812 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33454 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki Reviewed-by: Marshall Dawson --- src/southbridge/amd/cimx/sb900/early.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/southbridge/amd/cimx/sb900/early.c b/src/southbridge/amd/cimx/sb900/early.c index 5ebe47e5fb..1aa9a5a4ba 100644 --- a/src/southbridge/amd/cimx/sb900/early.c +++ b/src/southbridge/amd/cimx/sb900/early.c @@ -39,7 +39,7 @@ void sb_poweron_init(void) //Enable/Disable PCI Bridge Device 14 Function 4. outb(0xEA, 0xCD6); data = inb(0xCD7); - data &= !BIT0; + data &= ~BIT0; if (!CONFIG(PCIB_ENABLE)) { data |= BIT0; } From b90739d73d7664067b48edcd7d800f05cd374aa2 Mon Sep 17 00:00:00 2001 From: Eric Lai Date: Thu, 13 Jun 2019 15:21:20 +0800 Subject: [PATCH 043/221] drivers/i2c/sx9310: Print I2C SAR device info Print I2C SAR device info so that it is available in cbmem logs. BUG=none BRANCH=none TEST=Boot up and check cbmem -c can find the SAR I2C info Signed-off-by: Eric Lai Change-Id: Ia143932bb660ed2c2cea76310f11ede2b727adf4 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33432 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/drivers/i2c/sx9310/sx9310.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/drivers/i2c/sx9310/sx9310.c b/src/drivers/i2c/sx9310/sx9310.c index aafd7c7cc8..8157874d07 100644 --- a/src/drivers/i2c/sx9310/sx9310.c +++ b/src/drivers/i2c/sx9310/sx9310.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -74,6 +75,9 @@ static void i2c_sx9310_fill_ssdt(struct device *dev) acpigen_pop_len(); /* Device */ acpigen_pop_len(); /* Scope */ + + printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), + config->desc ? : dev->chip_ops->name, dev_path(dev)); } #undef REGISTER From 7752645041c3094f9f58bc347d2bc1c23fe2cfb0 Mon Sep 17 00:00:00 2001 From: John Su Date: Tue, 11 Jun 2019 08:59:03 +0800 Subject: [PATCH 044/221] mb/google/hatch/variants/hatch: Adjust all I2C CLK to meet spec After adjustment on Hatch Touch Pad CLK: 383.4 KHz Touch Screen CLK: 381.6 KHz SAR Sensor CLK: 392.0 KHz Audio codec CLK: 386.0 KHz BUG=b:134911522 BRANCH=master TEST=emerge-hatch coreboot chromeos-bootimage measure by scope with hatch. Change-Id: Iee2b692c268381af267b70e92a577ac89ce41cbb Signed-off-by: John Su Reviewed-on: https://review.coreboot.org/c/coreboot/+/33384 Tested-by: build bot (Jenkins) Reviewed-by: Paul Fagerburg Reviewed-by: Furquan Shaikh --- .../google/hatch/variants/hatch/overridetree.cb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/mainboard/google/hatch/variants/hatch/overridetree.cb b/src/mainboard/google/hatch/variants/hatch/overridetree.cb index 3846b609f8..d676843720 100644 --- a/src/mainboard/google/hatch/variants/hatch/overridetree.cb +++ b/src/mainboard/google/hatch/variants/hatch/overridetree.cb @@ -35,12 +35,23 @@ chip soc/intel/cannonlake }, .i2c[0] = { .speed = I2C_SPEED_FAST, + .rise_time_ns = 50, + .fall_time_ns = 15, }, .i2c[1] = { .speed = I2C_SPEED_FAST, + .rise_time_ns = 60, + .fall_time_ns = 25, + }, + .i2c[3] = { + .speed = I2C_SPEED_FAST, + .rise_time_ns = 150, + .fall_time_ns = 150, }, .i2c[4] = { .speed = I2C_SPEED_FAST, + .rise_time_ns = 120, + .fall_time_ns = 120, }, }" From 9d98e5ae0dc0ff0833c762586b296f4f91f9d485 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Fri, 14 Jun 2019 19:00:04 +0200 Subject: [PATCH 045/221] acpi: Add SPMI table Add the SPMI table as defined in the IPMI spec v2: https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf Tested on Wedge100s. Change-Id: Idff5134ce4c124f7e76acb0080da404b0c0dfffe Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33487 Reviewed-by: Felix Held Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- src/arch/x86/acpi.c | 53 ++++++++++++++++++++++++++++++++ src/arch/x86/include/arch/acpi.h | 48 ++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c index bf9813cbfe..1b8aaae64b 100644 --- a/src/arch/x86/acpi.c +++ b/src/arch/x86/acpi.c @@ -772,6 +772,57 @@ void acpi_create_vfct(struct device *device, header->checksum = acpi_checksum((void *)vfct, header->length); } +void acpi_create_ipmi(struct device *device, + struct acpi_spmi *spmi, + const u16 ipmi_revision, + const acpi_addr_t *addr, + const enum acpi_ipmi_interface_type type, + const s8 gpe_interrupt, + const u32 apic_interrupt, + const u32 uid) +{ + acpi_header_t *header = &(spmi->header); + memset((void *)spmi, 0, sizeof(struct acpi_spmi)); + + /* Fill out header fields. */ + memcpy(header->signature, "SPMI", 4); + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); + memcpy(header->asl_compiler_id, ASLC, 4); + + header->asl_compiler_revision = asl_revision; + header->length = sizeof(struct acpi_spmi); + header->revision = get_acpi_table_revision(SPMI); + + spmi->reserved = 1; + + if (device->path.type == DEVICE_PATH_PCI) { + spmi->pci_device_flag = ACPI_IPMI_PCI_DEVICE_FLAG; + spmi->pci_bus = device->bus->secondary; + spmi->pci_device = device->path.pci.devfn >> 3; + spmi->pci_function = device->path.pci.devfn & 0x7; + } else if (type != IPMI_INTERFACE_SSIF) { + memcpy(spmi->uid, &uid, sizeof(spmi->uid)); + } + + spmi->base_address = *addr; + spmi->specification_revision = ipmi_revision; + + spmi->interface_type = type; + + if (gpe_interrupt >= 0 && gpe_interrupt < 32) { + spmi->gpe = gpe_interrupt; + spmi->interrupt_type |= ACPI_IPMI_INT_TYPE_SCI; + } + if (apic_interrupt > 0) { + spmi->global_system_interrupt = apic_interrupt; + spmi->interrupt_type |= ACPI_IPMI_INT_TYPE_APIC; + } + + /* Calculate checksum. */ + header->checksum = acpi_checksum((void *)spmi, header->length); +} + void acpi_create_ivrs(acpi_ivrs_t *ivrs, unsigned long (*acpi_fill_ivrs)(acpi_ivrs_t *ivrs_struct, unsigned long current)) @@ -1490,6 +1541,8 @@ int get_acpi_table_revision(enum acpi_tables table) return 1; case SLIT: /* ACPI 2.0 upto 6.3: 1 */ return 1; + case SPMI: /* IMPI 2.0 */ + return 5; case HPET: /* Currently 1. Table added in ACPI 2.0. */ return 1; case VFCT: /* ACPI 2.0/3.0/4.0: 1 */ diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h index dbf46a9b1b..e48b2da567 100644 --- a/src/arch/x86/include/arch/acpi.h +++ b/src/arch/x86/include/arch/acpi.h @@ -82,7 +82,7 @@ enum acpi_tables { BERT, DBG2, DMAR, DSDT, FACS, FADT, HEST, HPET, IVRS, MADT, MCFG, RSDP, RSDT, SLIT, SRAT, SSDT, TCPA, TPM2, XSDT, ECDT, /* Additional proprietary tables used by coreboot */ - VFCT, NHLT + VFCT, NHLT, SPMI }; /* RSDP (Root System Description Pointer) */ @@ -782,6 +782,43 @@ enum acpi_upc_type { UPC_TYPE_HUB }; +enum acpi_ipmi_interface_type { + IPMI_INTERFACE_RESERVED = 0, + IPMI_INTERFACE_KCS, + IPMI_INTERFACE_SMIC, + IPMI_INTERFACE_BT, + IPMI_INTERFACE_SSIF, +}; + +#define ACPI_IPMI_PCI_DEVICE_FLAG (1 << 0) +#define ACPI_IPMI_INT_TYPE_SCI (1 << 0) +#define ACPI_IPMI_INT_TYPE_APIC (1 << 1) + +/* ACPI IPMI 2.0 */ +struct acpi_spmi { + struct acpi_table_header header; + u8 interface_type; + u8 reserved; + u16 specification_revision; + u8 interrupt_type; + u8 gpe; + u8 reserved2; + u8 pci_device_flag; + + u32 global_system_interrupt; + acpi_addr_t base_address; + union { + struct { + u8 pci_segment_group; + u8 pci_bus; + u8 pci_device; + u8 pci_function; + }; + u8 uid[4]; + }; + u8 reserved3; +} __packed; + unsigned long fw_cfg_acpi_tables(unsigned long start); /* These are implemented by the target port or north/southbridge. */ @@ -834,6 +871,15 @@ void acpi_create_vfct(struct device *device, struct acpi_vfct *vfct_struct, unsigned long current)); +void acpi_create_ipmi(struct device *device, + struct acpi_spmi *spmi, + const u16 ipmi_revision, + const acpi_addr_t *addr, + const enum acpi_ipmi_interface_type type, + const s8 gpe_interrupt, + const u32 apic_interrupt, + const u32 uid); + void acpi_create_ivrs(acpi_ivrs_t *ivrs, unsigned long (*acpi_fill_ivrs)(acpi_ivrs_t *ivrs_struct, unsigned long current)); From c6a584182e63a9354f4ff875aa1906106ea73a9f Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Tue, 18 Jun 2019 16:53:22 +0200 Subject: [PATCH 046/221] xcompile: Fix harmless typo As CFLAGS_GCC and CFLAGS_CLANG are still the same at this point, this just removes some duplicate flags. Change-Id: I532e5fa146891b70e4c1949c614b280055524593 Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/33580 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Paul Menzel Reviewed-by: Patrick Georgi --- util/xcompile/xcompile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/xcompile/xcompile b/util/xcompile/xcompile index 7ab1cb7af8..050cc59827 100755 --- a/util/xcompile/xcompile +++ b/util/xcompile/xcompile @@ -162,7 +162,7 @@ testas() { "elf32-i386" ) LDFLAGS="$LDFLAGS -melf_i386" CFLAGS_GCC="$CFLAGS_GCC -Wl,-b,elf32-i386 -Wl,-melf_i386" - CFLAGS_CLANG="$CFLAGS_GCC -Wl,-b,elf32-i386 -Wl,-melf_i386" + CFLAGS_CLANG="$CFLAGS_CLANG -Wl,-b,elf32-i386 -Wl,-melf_i386" ;; esac From ac7eee405156e6f4e4c227fb9ddb28c9fdcd2317 Mon Sep 17 00:00:00 2001 From: Christian Walter Date: Mon, 17 Jun 2019 16:45:53 +0200 Subject: [PATCH 047/221] src/arch/x86/smbios: Change SMBIOS Version to 2.8 Change the SMBIOS Version from 2.7 to 2.8. Necessary changes were already pushed in https://review.coreboot.org/c/coreboot/+/33031 Change-Id: I237cdee7d43e814397b958e4cf941bf58949088d Signed-off-by: Christian Walter Reviewed-on: https://review.coreboot.org/c/coreboot/+/33564 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph Reviewed-by: HAOUAS Elyes --- src/arch/x86/smbios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c index 54c2b09c4a..7865c7ef98 100644 --- a/src/arch/x86/smbios.c +++ b/src/arch/x86/smbios.c @@ -1193,7 +1193,7 @@ unsigned long smbios_write_tables(unsigned long current) memcpy(se->anchor, "_SM_", 4); se->length = sizeof(struct smbios_entry); se->major_version = 2; - se->minor_version = 7; + se->minor_version = 8; se->max_struct_size = max_struct_size; se->struct_count = handle; memcpy(se->intermediate_anchor_string, "_DMI_", 5); From e625d0710647a85946fec50072aeec37390e4e8c Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Fri, 14 Dec 2018 12:02:01 +0100 Subject: [PATCH 048/221] mb/lenovo/x201: Remove unneeded includes Tested: still builds fine. Change-Id: I1ca4e42bd75a3e84afe8b30a60f02058b590416f Signed-off-by: Peter Lemenkov Reviewed-on: https://review.coreboot.org/c/coreboot/+/30217 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans Reviewed-by: HAOUAS Elyes --- src/mainboard/lenovo/x201/acpi_tables.c | 1 - src/mainboard/lenovo/x201/mainboard.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mainboard/lenovo/x201/acpi_tables.c b/src/mainboard/lenovo/x201/acpi_tables.c index 82991b267b..6fd47d7276 100644 --- a/src/mainboard/lenovo/x201/acpi_tables.c +++ b/src/mainboard/lenovo/x201/acpi_tables.c @@ -15,7 +15,6 @@ * GNU General Public License for more details. */ -#include #include #include "thermal.h" diff --git a/src/mainboard/lenovo/x201/mainboard.c b/src/mainboard/lenovo/x201/mainboard.c index b8129ad294..0e20afe610 100644 --- a/src/mainboard/lenovo/x201/mainboard.c +++ b/src/mainboard/lenovo/x201/mainboard.c @@ -23,11 +23,10 @@ #include #include #include - #include "dock.h" #include #include -#include +#include #include #include From fab13583b56795f32f2826e786f7e70574ace4c2 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Mon, 10 Jun 2019 14:49:42 +0200 Subject: [PATCH 049/221] mb/lenovo/t60/romstage: Remove unused include This commit follows up on commit 8b7a1614 with Change-Id: I73c557d6ef009fb2cac35fdea500dee76f525330 ("src/mainboard: Remove unneeded include "). Change-Id: I7f307bf5b6cdcfebe1a290ce344b962fcecc8781 Signed-off-by: Peter Lemenkov Reviewed-on: https://review.coreboot.org/c/coreboot/+/33366 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans --- src/mainboard/lenovo/t60/romstage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mainboard/lenovo/t60/romstage.c b/src/mainboard/lenovo/t60/romstage.c index 0c7c0cfb2d..820cd5265e 100644 --- a/src/mainboard/lenovo/t60/romstage.c +++ b/src/mainboard/lenovo/t60/romstage.c @@ -18,7 +18,6 @@ // __PRE_RAM__ means: use "unsigned" for device, not a struct. #include -#include #include #include #include From ca70593d0fa2d88d442fe42d193655012d143079 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Mon, 10 Jun 2019 14:44:28 +0200 Subject: [PATCH 050/221] mb/lenovo/z61t/romstage: Remove unused include This commit follows up on commit commit 89989cf6 with Change-Id: I1f44ffeb54955ed660162a791c6281f292b1116a ("src: Drop unused include "). Change-Id: I3dc12373b32b95d25ba7b302cbca5f927678315d Signed-off-by: Peter Lemenkov Reviewed-on: https://review.coreboot.org/c/coreboot/+/33365 Reviewed-by: Arthur Heymans Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- src/mainboard/lenovo/z61t/romstage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mainboard/lenovo/z61t/romstage.c b/src/mainboard/lenovo/z61t/romstage.c index 502eac39d5..716be16dad 100644 --- a/src/mainboard/lenovo/z61t/romstage.c +++ b/src/mainboard/lenovo/z61t/romstage.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include From 22230687aa23b69553d5317a491073a66eccfe3b Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Sat, 15 Jun 2019 17:34:23 +0200 Subject: [PATCH 051/221] mb/lenovo/*/romstage: Remove unused include byteorder.h Change-Id: I3e500aafd26b7524a6782883b9a30f55b544102d Signed-off-by: Peter Lemenkov Reviewed-on: https://review.coreboot.org/c/coreboot/+/33511 Reviewed-by: Angel Pons Reviewed-by: HAOUAS Elyes Reviewed-by: Arthur Heymans Tested-by: build bot (Jenkins) --- src/mainboard/lenovo/s230u/romstage.c | 1 - src/mainboard/lenovo/t420s/romstage.c | 1 - src/mainboard/lenovo/t430s/variants/t430s/romstage.c | 1 - src/mainboard/lenovo/t430s/variants/t431s/romstage.c | 1 - src/mainboard/lenovo/t520/romstage.c | 1 - src/mainboard/lenovo/t530/romstage.c | 1 - src/mainboard/lenovo/x1_carbon_gen1/romstage.c | 1 - src/mainboard/lenovo/x220/romstage.c | 1 - src/mainboard/lenovo/x230/romstage.c | 1 - 9 files changed, 9 deletions(-) diff --git a/src/mainboard/lenovo/s230u/romstage.c b/src/mainboard/lenovo/s230u/romstage.c index 03ee4dba06..32a3cc2c7d 100644 --- a/src/mainboard/lenovo/s230u/romstage.c +++ b/src/mainboard/lenovo/s230u/romstage.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mainboard/lenovo/t420s/romstage.c b/src/mainboard/lenovo/t420s/romstage.c index c42d165643..9c5171371c 100644 --- a/src/mainboard/lenovo/t420s/romstage.c +++ b/src/mainboard/lenovo/t420s/romstage.c @@ -15,7 +15,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/lenovo/t430s/variants/t430s/romstage.c b/src/mainboard/lenovo/t430s/variants/t430s/romstage.c index 5bc7b80961..84bd447ab2 100644 --- a/src/mainboard/lenovo/t430s/variants/t430s/romstage.c +++ b/src/mainboard/lenovo/t430s/variants/t430s/romstage.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/t430s/variants/t431s/romstage.c b/src/mainboard/lenovo/t430s/variants/t431s/romstage.c index 7591f8b873..e7b43db487 100644 --- a/src/mainboard/lenovo/t430s/variants/t431s/romstage.c +++ b/src/mainboard/lenovo/t430s/variants/t431s/romstage.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/t520/romstage.c b/src/mainboard/lenovo/t520/romstage.c index 96d07feac2..ebff37ff9c 100644 --- a/src/mainboard/lenovo/t520/romstage.c +++ b/src/mainboard/lenovo/t520/romstage.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/t530/romstage.c b/src/mainboard/lenovo/t530/romstage.c index 2b850a20b1..24e2d9cde0 100644 --- a/src/mainboard/lenovo/t530/romstage.c +++ b/src/mainboard/lenovo/t530/romstage.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/x1_carbon_gen1/romstage.c b/src/mainboard/lenovo/x1_carbon_gen1/romstage.c index c65060f9f9..a951fbc72e 100644 --- a/src/mainboard/lenovo/x1_carbon_gen1/romstage.c +++ b/src/mainboard/lenovo/x1_carbon_gen1/romstage.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/src/mainboard/lenovo/x220/romstage.c b/src/mainboard/lenovo/x220/romstage.c index a5b0c8189b..5f9a931340 100644 --- a/src/mainboard/lenovo/x220/romstage.c +++ b/src/mainboard/lenovo/x220/romstage.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/lenovo/x230/romstage.c b/src/mainboard/lenovo/x230/romstage.c index f97c3f503c..3f31141583 100644 --- a/src/mainboard/lenovo/x230/romstage.c +++ b/src/mainboard/lenovo/x230/romstage.c @@ -16,7 +16,6 @@ */ #include -#include #include #include #include From b79a04c71658bf34daa6409cfa4012a1cf9ad1f5 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 16 Jun 2019 13:23:24 +0200 Subject: [PATCH 052/221] src/mainboard: Remove unused include Change-Id: I3d638febddbd88cd4870795f96dd1bbf123c7ba3 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33537 Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- src/mainboard/apple/macbookair4_2/romstage.c | 1 - src/mainboard/google/eve/spd/spd.c | 1 - src/mainboard/google/glados/spd/spd.c | 1 - src/mainboard/hp/compaq_8200_elite_sff/romstage.c | 1 - src/mainboard/hp/z220_sff_workstation/romstage.c | 1 - src/mainboard/intel/cannonlake_rvp/romstage_fsp_params.c | 1 - src/mainboard/intel/cannonlake_rvp/spd/spd_util.c | 1 - src/mainboard/intel/harcuvar/spd/spd.c | 1 - src/mainboard/intel/icelake_rvp/romstage_fsp_params.c | 1 - src/mainboard/intel/icelake_rvp/spd/spd_util.c | 1 - src/mainboard/intel/kblrvp/romstage.c | 1 - src/mainboard/intel/kblrvp/spd/spd_util.c | 1 - src/mainboard/intel/kunimitsu/romstage_fsp20.c | 1 - src/mainboard/intel/kunimitsu/spd/spd.c | 1 - src/mainboard/intel/kunimitsu/spd/spd_util.c | 1 - src/mainboard/sapphire/pureplatinumh61/romstage.c | 1 - 16 files changed, 16 deletions(-) diff --git a/src/mainboard/apple/macbookair4_2/romstage.c b/src/mainboard/apple/macbookair4_2/romstage.c index 68556d96e6..6fee17ab0c 100644 --- a/src/mainboard/apple/macbookair4_2/romstage.c +++ b/src/mainboard/apple/macbookair4_2/romstage.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/src/mainboard/google/eve/spd/spd.c b/src/mainboard/google/eve/spd/spd.c index 077bed4bf1..fca670cbb9 100644 --- a/src/mainboard/google/eve/spd/spd.c +++ b/src/mainboard/google/eve/spd/spd.c @@ -14,7 +14,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/google/glados/spd/spd.c b/src/mainboard/google/glados/spd/spd.c index b3cf3f9416..9503582c9a 100644 --- a/src/mainboard/google/glados/spd/spd.c +++ b/src/mainboard/google/glados/spd/spd.c @@ -14,7 +14,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/hp/compaq_8200_elite_sff/romstage.c b/src/mainboard/hp/compaq_8200_elite_sff/romstage.c index 4b640689b7..3c388776c3 100644 --- a/src/mainboard/hp/compaq_8200_elite_sff/romstage.c +++ b/src/mainboard/hp/compaq_8200_elite_sff/romstage.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/hp/z220_sff_workstation/romstage.c b/src/mainboard/hp/z220_sff_workstation/romstage.c index 0804dd0c7a..9883879bae 100644 --- a/src/mainboard/hp/z220_sff_workstation/romstage.c +++ b/src/mainboard/hp/z220_sff_workstation/romstage.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include diff --git a/src/mainboard/intel/cannonlake_rvp/romstage_fsp_params.c b/src/mainboard/intel/cannonlake_rvp/romstage_fsp_params.c index 2396505906..edb5894ba5 100644 --- a/src/mainboard/intel/cannonlake_rvp/romstage_fsp_params.c +++ b/src/mainboard/intel/cannonlake_rvp/romstage_fsp_params.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/intel/cannonlake_rvp/spd/spd_util.c b/src/mainboard/intel/cannonlake_rvp/spd/spd_util.c index dd209dce55..0c2f74781b 100644 --- a/src/mainboard/intel/cannonlake_rvp/spd/spd_util.c +++ b/src/mainboard/intel/cannonlake_rvp/spd/spd_util.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include diff --git a/src/mainboard/intel/harcuvar/spd/spd.c b/src/mainboard/intel/harcuvar/spd/spd.c index 914e4fd14c..61bf2e589b 100644 --- a/src/mainboard/intel/harcuvar/spd/spd.c +++ b/src/mainboard/intel/harcuvar/spd/spd.c @@ -15,7 +15,6 @@ * */ -#include #include #include diff --git a/src/mainboard/intel/icelake_rvp/romstage_fsp_params.c b/src/mainboard/intel/icelake_rvp/romstage_fsp_params.c index fd1638bfab..5a4d6814c4 100644 --- a/src/mainboard/intel/icelake_rvp/romstage_fsp_params.c +++ b/src/mainboard/intel/icelake_rvp/romstage_fsp_params.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/intel/icelake_rvp/spd/spd_util.c b/src/mainboard/intel/icelake_rvp/spd/spd_util.c index 8d7eaf69ce..d7babbd082 100644 --- a/src/mainboard/intel/icelake_rvp/spd/spd_util.c +++ b/src/mainboard/intel/icelake_rvp/spd/spd_util.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/intel/kblrvp/romstage.c b/src/mainboard/intel/kblrvp/romstage.c index 1a483bda45..0385e29eac 100644 --- a/src/mainboard/intel/kblrvp/romstage.c +++ b/src/mainboard/intel/kblrvp/romstage.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/intel/kblrvp/spd/spd_util.c b/src/mainboard/intel/kblrvp/spd/spd_util.c index f22dcaa3b7..9318c3975d 100644 --- a/src/mainboard/intel/kblrvp/spd/spd_util.c +++ b/src/mainboard/intel/kblrvp/spd/spd_util.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include diff --git a/src/mainboard/intel/kunimitsu/romstage_fsp20.c b/src/mainboard/intel/kunimitsu/romstage_fsp20.c index ee1ddd58cb..536469339d 100644 --- a/src/mainboard/intel/kunimitsu/romstage_fsp20.c +++ b/src/mainboard/intel/kunimitsu/romstage_fsp20.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include #include "gpio.h" diff --git a/src/mainboard/intel/kunimitsu/spd/spd.c b/src/mainboard/intel/kunimitsu/spd/spd.c index bebb544a4d..db5e24e927 100644 --- a/src/mainboard/intel/kunimitsu/spd/spd.c +++ b/src/mainboard/intel/kunimitsu/spd/spd.c @@ -14,7 +14,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/intel/kunimitsu/spd/spd_util.c b/src/mainboard/intel/kunimitsu/spd/spd_util.c index b173628e29..288ee1e7ee 100644 --- a/src/mainboard/intel/kunimitsu/spd/spd_util.c +++ b/src/mainboard/intel/kunimitsu/spd/spd_util.c @@ -12,7 +12,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/mainboard/sapphire/pureplatinumh61/romstage.c b/src/mainboard/sapphire/pureplatinumh61/romstage.c index 296e8963c2..9a67ab295b 100644 --- a/src/mainboard/sapphire/pureplatinumh61/romstage.c +++ b/src/mainboard/sapphire/pureplatinumh61/romstage.c @@ -15,7 +15,6 @@ */ #include -#include #include #include #include From 3f347a1379c9da9ba9edf4e5cfc4cc37a0689b1f Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 16 Jun 2019 13:29:21 +0200 Subject: [PATCH 053/221] lib/spd_bin.c: Remove unused include Change-Id: Ifb8171e559c5c8081597291ffefabc676c7fa5e1 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33538 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/lib/spd_bin.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/spd_bin.c b/src/lib/spd_bin.c index b378d6377e..1598ff162f 100644 --- a/src/lib/spd_bin.c +++ b/src/lib/spd_bin.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include #include From ce2b2bad77716821235335cda9ede3849fb28e09 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Tue, 19 Mar 2019 14:45:31 -0600 Subject: [PATCH 054/221] util/amdfwtool: Update for Family 17h Add arguments for additional PSP blobs needed with Family 17h support, including the new AGESA binary loaders. Create a new type of structure and entry for a BIOS directory table, containing PMU code, microcode updates, as well as the BIOS initial code. Details on each of these items may be found in the AMD Platform Security Processor BIOS Architecture Design Guide for AMD Family 17h Processors (NDA only, #55758). BUG=b:126593573 TEST=Used with WIP Picasso Change-Id: I4899dedb6f5e29a27ff53787a566d5b8633a8ad5 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/33400 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- util/amdfwtool/amdfwtool.c | 627 +++++++++++++++++++++++++++++++++++-- 1 file changed, 607 insertions(+), 20 deletions(-) diff --git a/util/amdfwtool/amdfwtool.c b/util/amdfwtool/amdfwtool.c index ac9ee48888..37dbcd093f 100644 --- a/util/amdfwtool/amdfwtool.c +++ b/util/amdfwtool/amdfwtool.c @@ -90,6 +90,8 @@ #define PSP_COOKIE 0x50535024 /* 'PSP$' */ #define PSPL2_COOKIE 0x324c5024 /* '2LP$' */ #define PSP2_COOKIE 0x50535032 /* 'PSP2' */ +#define BDT1_COOKIE 0x44484224 /* 'DHB$ */ +#define BDT2_COOKIE 0x324c4224 /* '2LB$ */ /* * Beginning with Family 15h Models 70h-7F, a.k.a Stoney Ridge, the PSP @@ -193,6 +195,28 @@ static void usage(void) printf("-w | --smufirmware2 Add smufirmware2\n"); printf("-m | --smuscs Add smuscs\n"); printf("-T | --soft-fuse Override default soft fuse values\n"); + printf("-z | --abl-image Add AGESA Binary\n"); + printf("-J | --sec-gasket Add security gasket\n"); + printf("-B | --mp2-fw Add MP2 firmware\n"); + printf("-N | --secdebug Add secure unlock image\n"); + printf("-U | --token-unlock Reserve space for debug token\n"); + printf("-K | --drv-entry-pts Add PSP driver entry points\n"); + printf("-L | --ikek Add Wrapped iKEK\n"); + printf("-Y | --s0i3drv Add s0i3 driver\n"); + printf("\nBIOS options:\n"); + printf("-I | --instance Sets instance field for the next BIOS firmware\n"); + printf("-a | --apcb Add AGESA PSP customization block\n"); + printf("-Q | --apob-base Destination for AGESA PSP output block\n"); + printf("-F | --apob-nv-base Location of S3 resume data\n"); + printf("-H | --apob-nv-size Size of S3 resume data\n"); + printf("-y | --pmu-inst Add PMU firmware instruction portion\n"); + printf("-G | --pmu-data Add PMU firmware data portion\n"); + printf("-u | --ucode Add microcode patch\n"); + printf("-X | --mp2-config Add MP2 configuration\n"); + printf("-V | --bios-bin Add compressed image; auto source address\n"); + printf("-e | --bios-bin-src Address in flash of source if -V not used\n"); + printf("-v | --bios-bin-dest Destination for uncompressed BIOS\n"); + printf("-j | --bios-uncomp-size Uncompressed size of BIOS image\n"); printf("\n-o | --output output filename\n"); printf("-f | --flashsize ROM size in bytes\n"); printf(" size must be larger than %dKB\n", @@ -202,6 +226,39 @@ static void usage(void) printf("-h | --help show this help\n"); } +typedef enum _amd_bios_type { + AMD_BIOS_APCB = 0x60, + AMD_BIOS_APOB = 0x61, + AMD_BIOS_BIN = 0x62, + AMD_BIOS_APOB_NV = 0x63, + AMD_BIOS_PMUI = 0x64, + AMD_BIOS_PMUD = 0x65, + AMD_BIOS_UCODE = 0x66, + AMD_BIOS_APCB_BK = 0x68, + AMD_BIOS_MP2_CFG = 0x6a, + AMD_BIOS_L2_PTR = 0x70, + AMD_BIOS_INVALID, +} amd_bios_type; + +#define BDT_LVL1 0x1 +#define BDT_LVL2 0x2 +#define BDT_BOTH (BDT_LVL1 | BDT_LVL2) +typedef struct _amd_bios_entry { + amd_bios_type type; + int region_type; + int reset; + int copy; + int ro; + int zlib; + int inst; + int subpr; + uint64_t src; + uint64_t dest; + size_t size; + char *filename; + int level; +} amd_bios_entry; + typedef enum _amd_fw_type { AMD_FW_PSP_PUBKEY = 0, AMD_FW_PSP_BOOTLOADER = 1, @@ -216,6 +273,22 @@ typedef enum _amd_fw_type { AMD_FW_PSP_SMU_FIRMWARE2 = 18, AMD_PSP_FUSE_CHAIN = 11, AMD_FW_PSP_SMUSCS = 95, + AMD_DEBUG_UNLOCK = 0x13, + AMD_WRAPPED_IKEK = 0x21, + AMD_TOKEN_UNLOCK = 0x22, + AMD_SEC_GASKET = 0x24, + AMD_MP2_FW = 0x25, + AMD_DRIVER_ENTRIES = 0x28, + AMD_S0I3_DRIVER = 0x2d, + AMD_ABL0 = 0x30, + AMD_ABL1 = 0x31, + AMD_ABL2 = 0x32, + AMD_ABL3 = 0x33, + AMD_ABL4 = 0x34, + AMD_ABL5 = 0x35, + AMD_ABL6 = 0x36, + AMD_ABL7 = 0x37, + AMD_FW_PSP_WHITELIST = 0x3a, AMD_FW_L2_PTR = 0x40, AMD_FW_IMC, AMD_FW_GEC, @@ -252,8 +325,26 @@ static amd_fw_entry amd_psp_fw_table[] = { { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH }, { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH }, { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 }, + { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 }, + { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH }, + { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH }, + { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH }, + { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH }, + { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 }, + { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 }, + { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 }, + { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 }, + { .type = AMD_ABL0, .level = PSP_BOTH }, + { .type = AMD_ABL1, .level = PSP_BOTH }, + { .type = AMD_ABL2, .level = PSP_BOTH }, + { .type = AMD_ABL3, .level = PSP_BOTH }, + { .type = AMD_ABL4, .level = PSP_BOTH }, + { .type = AMD_ABL5, .level = PSP_BOTH }, + { .type = AMD_ABL6, .level = PSP_BOTH }, + { .type = AMD_ABL7, .level = PSP_BOTH }, { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH }, { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH }, + { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 }, { .type = AMD_FW_INVALID }, }; @@ -264,6 +355,28 @@ static amd_fw_entry amd_fw_table[] = { { .type = AMD_FW_INVALID }, }; +static amd_bios_entry amd_bios_table[] = { + { .type = AMD_BIOS_APCB, .level = BDT_BOTH }, + { .type = AMD_BIOS_APCB_BK, .level = BDT_BOTH }, + { .type = AMD_BIOS_APOB, .level = BDT_BOTH }, + { .type = AMD_BIOS_BIN, + .reset = 1, .copy = 1, .zlib = 1, .level = BDT_BOTH }, + { .type = AMD_BIOS_APOB_NV, .level = BDT_LVL2 }, + { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 0, .level = BDT_BOTH }, + { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 0, .level = BDT_BOTH }, + { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 0, .level = BDT_BOTH }, + { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 0, .level = BDT_BOTH }, + { .type = AMD_BIOS_PMUI, .inst = 1, .subpr = 1, .level = BDT_BOTH }, + { .type = AMD_BIOS_PMUD, .inst = 1, .subpr = 1, .level = BDT_BOTH }, + { .type = AMD_BIOS_PMUI, .inst = 4, .subpr = 1, .level = BDT_BOTH }, + { .type = AMD_BIOS_PMUD, .inst = 4, .subpr = 1, .level = BDT_BOTH }, + { .type = AMD_BIOS_UCODE, .inst = 0, .level = BDT_LVL2 }, + { .type = AMD_BIOS_UCODE, .inst = 1, .level = BDT_LVL2 }, + { .type = AMD_BIOS_UCODE, .inst = 2, .level = BDT_LVL2 }, + { .type = AMD_BIOS_MP2_CFG, .level = BDT_LVL2 }, + { .type = AMD_BIOS_INVALID }, +}; + typedef struct _embedded_firmware { uint32_t signature; /* 0x55aa55aa */ uint32_t imc_entry; @@ -271,6 +384,8 @@ typedef struct _embedded_firmware { uint32_t xhci_entry; uint32_t psp_entry; uint32_t comboable; + uint32_t bios0_entry; /* todo: add way to select correct entry */ + uint32_t bios1_entry; } __attribute__((packed, aligned(16))) embedded_firmware; typedef struct _psp_directory_header { @@ -316,6 +431,34 @@ typedef struct _psp_combo_directory { #define MAX_COMBO_ENTRIES 1 +typedef struct _bios_directory_hdr { + uint32_t cookie; + uint32_t checksum; + uint32_t num_entries; + uint32_t reserved; +} __attribute__((packed, aligned(16))) bios_directory_hdr; + +typedef struct _bios_directory_entry { + uint8_t type; + uint8_t region_type; + int reset:1; + int copy:1; + int ro:1; + int compressed:1; + int inst:4; + uint8_t subprog; /* b[7:3] reserved */ + uint32_t size; + uint64_t source; + uint64_t dest; +} __attribute__((packed)) bios_directory_entry; + +typedef struct _bios_directory_table { + bios_directory_hdr header; + bios_directory_entry entries[]; +} bios_directory_table; + +#define MAX_BIOS_ENTRIES 0x1f + typedef struct _context { char *rom; /* target buffer, size of flash device */ uint32_t rom_size; /* size of flash device */ @@ -365,6 +508,7 @@ static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie) { psp_combo_directory *cdir = directory; psp_directory_table *dir = directory; + bios_directory_table *bdir = directory; if (!count) return; @@ -394,6 +538,17 @@ static void fill_dir_header(void *directory, uint32_t count, uint32_t cookie) + sizeof(dir->header.num_entries) + sizeof(dir->header.reserved)); break; + case BDT1_COOKIE: + case BDT2_COOKIE: + bdir->header.cookie = cookie; + bdir->header.num_entries = count; + bdir->header.reserved = 0; + /* checksum everything that comes after the Checksum field */ + bdir->header.checksum = fletcher32(&bdir->header.num_entries, + count * sizeof(bios_directory_entry) + + sizeof(bdir->header.num_entries) + + sizeof(bdir->header.reserved)); + break; } } @@ -500,7 +655,18 @@ static void integrate_psp_firmwares(context *ctx, if (!(fw_table[i].level & level)) continue; - if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) { + if (fw_table[i].type == AMD_TOKEN_UNLOCK) { + if (!fw_table[i].other) + continue; + ctx->current = ALIGN(ctx->current, ERASE_ALIGNMENT); + pspdir->entries[count].type = fw_table[i].type; + pspdir->entries[count].size = 4096; /* TODO: doc? */ + pspdir->entries[count].addr = RUN_CURRENT(*ctx); + pspdir->entries[count].subprog = fw_table[i].subprog; + pspdir->entries[count].rsvd = 0; + ctx->current = ALIGN(ctx->current + 4096, 0x100U); + count++; + } else if (fw_table[i].type == AMD_PSP_FUSE_CHAIN) { pspdir->entries[count].type = fw_table[i].type; pspdir->entries[count].subprog = fw_table[i].subprog; pspdir->entries[count].rsvd = 0; @@ -575,13 +741,244 @@ static void integrate_psp_firmwares(context *ctx, fill_dir_header(pspdir, count, cookie); } -static const char *optstring = "x:i:g:AMS:p:b:s:r:k:c:n:d:t:u:w:m:T:o:f:l:h"; +static void *new_bios_dir(context *ctx, int multi) +{ + void *ptr; + + /* + * Force both onto boundary when multi. Primary table is after + * updatable table, so alignment ensures primary can stay intact + * if secondary is reprogrammed. + */ + if (multi) + ctx->current = ALIGN(ctx->current, TABLE_ERASE_ALIGNMENT); + else + ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT); + ptr = BUFF_CURRENT(*ctx); + ctx->current += sizeof(bios_directory_hdr) + + MAX_BIOS_ENTRIES * sizeof(bios_directory_entry); + return ptr; +} + +static int locate_bdt2_bios(bios_directory_table *level2, + uint64_t *source, uint32_t *size) +{ + int i; + + *source = 0; + *size = 0; + if (!level2) + return 0; + + for (i = 0 ; i < level2->header.num_entries ; i++) { + if (level2->entries[i].type == AMD_BIOS_BIN) { + *source = level2->entries[i].source; + *size = level2->entries[i].size; + return 1; + } + } + return 0; +} + +static int have_bios_tables(amd_bios_entry *table) +{ + int i; + + for (i = 0 ; table[i].type != AMD_BIOS_INVALID; i++) { + if (table[i].level & BDT_LVL1 && table[i].filename) + return 1; + } + return 0; +} + +static void integrate_bios_firmwares(context *ctx, + bios_directory_table *biosdir, + bios_directory_table *biosdir2, + amd_bios_entry *fw_table, + uint32_t cookie) +{ + ssize_t bytes; + unsigned int i, j, count; + int level; + + /* This function can create a primary table, a secondary table, or a + * flattened table which contains all applicable types. These if-else + * statements infer what the caller intended. If a 2nd-level cookie + * is passed, clearly a 2nd-level table is intended. However, a + * 1st-level cookie may indicate level 1 or flattened. If the caller + * passes a pointer to a 2nd-level table, then assume not flat. + */ + if (cookie == BDT2_COOKIE) + level = BDT_LVL2; + else if (biosdir2) + level = BDT_LVL1; + else + level = BDT_BOTH; + + ctx->current = ALIGN(ctx->current, BLOB_ALIGNMENT); + + for (i = 0, count = 0; fw_table[i].type != AMD_BIOS_INVALID; i++) { + if (!(fw_table[i].level & level)) + continue; + if (fw_table[i].filename == NULL && ( + fw_table[i].type != AMD_BIOS_APOB && + fw_table[i].type != AMD_BIOS_APOB_NV && + fw_table[i].type != AMD_BIOS_L2_PTR && + fw_table[i].type != AMD_BIOS_BIN)) + continue; + /* APOB_NV needs a size, else no S3 and skip item */ + if (fw_table[i].type == AMD_BIOS_APOB_NV && !fw_table[i].size) + continue; + + /* BIOS Directory items may have additional requirements */ + + /* APOB_NV must have a size if it has a source */ + if (fw_table[i].type == AMD_BIOS_APOB_NV && fw_table[i].src) { + if (!fw_table[i].size) { + printf("Error: APOB NV address provided, but no size\n"); + free(ctx->rom); + exit(1); + } + } + + /* APOB_DATA needs destination */ + if (fw_table[i].type == AMD_BIOS_APOB && !fw_table[i].dest) { + printf("Error: APOB destination not provided\n"); + free(ctx->rom); + exit(1); + } + + /* BIOS binary must have destination and uncompressed size. If + * no filename given, then user must provide a source address. + */ + if (fw_table[i].type == AMD_BIOS_BIN) { + if (!fw_table[i].dest || !fw_table[i].size) { + printf("Error: BIOS binary destination and uncompressed size are required\n"); + free(ctx->rom); + exit(1); + } + if (!fw_table[i].filename && !fw_table[i].src) { + printf("Error: BIOS binary assumed outside amdfw.rom but no source address given\n"); + free(ctx->rom); + exit(1); + } + } + + biosdir->entries[count].type = fw_table[i].type; + biosdir->entries[count].region_type = fw_table[i].region_type; + biosdir->entries[count].dest = fw_table[i].dest ? + fw_table[i].dest : (uint64_t)-1; + biosdir->entries[count].reset = fw_table[i].reset; + biosdir->entries[count].copy = fw_table[i].copy; + biosdir->entries[count].ro = fw_table[i].ro; + biosdir->entries[count].compressed = fw_table[i].zlib; + biosdir->entries[count].inst = fw_table[i].inst; + biosdir->entries[count].subprog = fw_table[i].subpr; + + switch (fw_table[i].type) { + case AMD_BIOS_APOB: + biosdir->entries[count].size = fw_table[i].size; + biosdir->entries[count].source = fw_table[i].src; + break; + case AMD_BIOS_APOB_NV: + if (fw_table[i].src) { + /* If source is given, use that and its size */ + biosdir->entries[count].source = fw_table[i].src; + biosdir->entries[count].size = fw_table[i].size; + } else { + /* Else reserve size bytes within amdfw.rom */ + ctx->current = ALIGN(ctx->current, ERASE_ALIGNMENT); + biosdir->entries[count].source = RUN_CURRENT(*ctx); + biosdir->entries[count].size = ALIGN( + fw_table[i].size, ERASE_ALIGNMENT); + memset(BUFF_CURRENT(*ctx), 0xff, + biosdir->entries[count].size); + ctx->current = ctx->current + + biosdir->entries[count].size; + } + break; + case AMD_BIOS_BIN: + /* Don't make a 2nd copy, point to the same one */ + if (level == BDT_LVL1 && locate_bdt2_bios(biosdir2, + &biosdir->entries[count].source, + &biosdir->entries[count].size)) + break; + + /* level 2, or level 1 and no copy found in level 2 */ + biosdir->entries[count].source = fw_table[i].src; + biosdir->entries[count].dest = fw_table[i].dest; + biosdir->entries[count].size = fw_table[i].size; + + if (!fw_table[i].filename) + break; + + bytes = copy_blob(BUFF_CURRENT(*ctx), + fw_table[i].filename, BUFF_ROOM(*ctx)); + if (bytes <= 0) { + free(ctx->rom); + exit(1); + } + + biosdir->entries[count].source = RUN_CURRENT(*ctx); + + ctx->current = ALIGN(ctx->current + bytes, 0x100U); + break; + default: /* everything else is copied from input */ + if (fw_table[i].type == AMD_BIOS_APCB || + fw_table[i].type == AMD_BIOS_APCB_BK) + ctx->current = ALIGN( + ctx->current, ERASE_ALIGNMENT); + + bytes = copy_blob(BUFF_CURRENT(*ctx), + fw_table[i].filename, BUFF_ROOM(*ctx)); + if (bytes <= 0) { + free(ctx->rom); + exit(1); + } + + biosdir->entries[count].size = (uint32_t)bytes; + biosdir->entries[count].source = RUN_CURRENT(*ctx); + + ctx->current = ALIGN(ctx->current + bytes, 0x100U); + break; + } + + count++; + } + + if (biosdir2) { + biosdir->entries[count].type = AMD_BIOS_L2_PTR; + biosdir->entries[count].size = + + MAX_BIOS_ENTRIES + * sizeof(bios_directory_entry); + biosdir->entries[count].source = + BUFF_TO_RUN(*ctx, biosdir2); + biosdir->entries[count].subprog = 0; + biosdir->entries[count].inst = 0; + biosdir->entries[count].copy = 0; + biosdir->entries[count].compressed = 0; + biosdir->entries[count].dest = -1; + biosdir->entries[count].reset = 0; + biosdir->entries[count].ro = 0; + count++; + } + + if (count > MAX_BIOS_ENTRIES) { + printf("Error: BIOS entries exceeds max allowed items\n"); + free(ctx->rom); + exit(1); + } + + fill_dir_header(biosdir, count, cookie); +} + +static const char *optstring = "x:i:g:AMS:p:b:s:r:k:c:n:d:t:u:w:m:T:z:J:B:K:L:Y:N:UW:I:a:Q:V:e:v:j:y:G:O:X:F:H:o:f:l:h"; static struct option long_options[] = { {"xhci", required_argument, 0, 'x' }, {"imc", required_argument, 0, 'i' }, {"gec", required_argument, 0, 'g' }, - /* PSP */ + /* PSP Directory Table items */ {"combo-capable", no_argument, 0, 'A' }, {"multilevel", no_argument, 0, 'M' }, {"subprogram", required_argument, 0, 'S' }, @@ -598,11 +995,34 @@ static struct option long_options[] = { {"smufirmware2", required_argument, 0, 'w' }, {"smuscs", required_argument, 0, 'm' }, {"soft-fuse", required_argument, 0, 'T' }, + {"abl-image", required_argument, 0, 'z' }, + {"sec-gasket", required_argument, 0, 'J' }, + {"mp2-fw", required_argument, 0, 'B' }, + {"drv-entry-pts", required_argument, 0, 'K' }, + {"ikek", required_argument, 0, 'L' }, + {"s0i3drv", required_argument, 0, 'Y' }, + {"secdebug", required_argument, 0, 'N' }, + {"token-unlock", no_argument, 0, 'U' }, + {"whitelist", required_argument, 0, 'W' }, + /* BIOS Directory Table items */ + {"instance", required_argument, 0, 'I' }, + {"apcb", required_argument, 0, 'a' }, + {"apob-base", required_argument, 0, 'Q' }, + {"bios-bin", required_argument, 0, 'V' }, + {"bios-bin-src", required_argument, 0, 'e' }, + {"bios-bin-dest", required_argument, 0, 'v' }, + {"bios-uncomp-size", required_argument, 0, 'j' }, + {"pmu-inst", required_argument, 0, 'y' }, + {"pmu-data", required_argument, 0, 'G' }, + {"ucode", required_argument, 0, 'O' }, + {"mp2-config", required_argument, 0, 'X' }, + {"apob-nv-base", required_argument, 0, 'F' }, + {"apob-nv-size", required_argument, 0, 'H' }, + /* other */ {"output", required_argument, 0, 'o' }, {"flashsize", required_argument, 0, 'f' }, {"location", required_argument, 0, 'l' }, {"help", no_argument, 0, 'h' }, - {NULL, 0, 0, 0 } }; @@ -619,6 +1039,19 @@ static void register_fw_fuse(char *str) } } +static void register_fw_token_unlock(void) +{ + int i; + + for (i = 0; i < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i++) { + if (amd_psp_fw_table[i].type != AMD_TOKEN_UNLOCK) + continue; + + amd_psp_fw_table[i].other = 1; + return; + } +} + static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[]) { unsigned int i; @@ -641,6 +1074,39 @@ static void register_fw_filename(amd_fw_type type, uint8_t sub, char filename[]) } } +static void register_bdt_data(amd_bios_type type, int sub, int ins, char name[]) +{ + int i; + + for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) { + if (amd_bios_table[i].type == type + && amd_bios_table[i].inst == ins + && amd_bios_table[i].subpr == sub) { + amd_bios_table[i].filename = name; + return; + } + } +} + +static void register_fw_addr(amd_fw_type type, char *src_str, + char *dst_str, char *size_str) +{ + int i; + for (i = 0; i < sizeof(amd_bios_table) / sizeof(amd_bios_entry); i++) { + if (amd_bios_table[i].type != type) + continue; + + if (src_str) + amd_bios_table[i].src = strtoull(src_str, NULL, 16); + if (dst_str) + amd_bios_table[i].dest = strtoull(dst_str, NULL, 16); + if (size_str) + amd_bios_table[i].size = strtoul(size_str, NULL, 16); + + return; + } +} + int main(int argc, char **argv) { int c; @@ -656,10 +1122,12 @@ int main(int argc, char **argv) context ctx = { .rom_size = CONFIG_ROM_SIZE, }; + /* Values cleared after each firmware or parameter, regardless if N/A */ + uint8_t sub = 0, instance = 0; + int abl_image = 0; uint32_t dir_location = 0; uint32_t romsig_offset; uint32_t rom_base_address; - uint8_t sub = 0; int multi = 0; while (1) { @@ -673,15 +1141,15 @@ int main(int argc, char **argv) switch (c) { case 'x': register_fw_filename(AMD_FW_XHCI, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'i': register_fw_filename(AMD_FW_IMC, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'g': register_fw_filename(AMD_FW_GEC, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'A': comboable = 1; @@ -689,69 +1157,167 @@ int main(int argc, char **argv) case 'M': multi = 1; break; + case 'U': + register_fw_token_unlock(); + sub = instance = 0; + break; case 'S': sub = (uint8_t)strtoul(optarg, &tmp, 16); break; + case 'I': + instance = strtoul(optarg, &tmp, 16); + break; case 'p': register_fw_filename(AMD_FW_PSP_PUBKEY, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'b': register_fw_filename(AMD_FW_PSP_BOOTLOADER, sub, optarg); - sub = 0; + sub = instance = 0; break; case 's': register_fw_filename(AMD_FW_PSP_SMU_FIRMWARE, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'r': register_fw_filename(AMD_FW_PSP_RECOVERY, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'k': register_fw_filename(AMD_FW_PSP_RTM_PUBKEY, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'c': register_fw_filename(AMD_FW_PSP_SECURED_OS, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'n': register_fw_filename(AMD_FW_PSP_NVRAM, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'd': register_fw_filename(AMD_FW_PSP_SECURED_DEBUG, sub, optarg); - sub = 0; + sub = instance = 0; break; case 't': register_fw_filename(AMD_FW_PSP_TRUSTLETS, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'u': register_fw_filename(AMD_FW_PSP_TRUSTLETKEY, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'w': register_fw_filename(AMD_FW_PSP_SMU_FIRMWARE2, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'm': register_fw_filename(AMD_FW_PSP_SMUSCS, sub, optarg); - sub = 0; + sub = instance = 0; break; case 'T': register_fw_fuse(optarg); fuse_defined = 1; sub = 0; break; + case 'a': + register_bdt_data(AMD_BIOS_APCB, sub, instance, optarg); + register_bdt_data(AMD_BIOS_APCB_BK, sub, + instance, optarg); + sub = instance = 0; + break; + case 'Q': + /* APOB destination */ + register_fw_addr(AMD_BIOS_APOB, 0, optarg, 0); + sub = instance = 0; + break; + case 'F': + /* APOB NV source */ + register_fw_addr(AMD_BIOS_APOB_NV, optarg, 0, 0); + sub = instance = 0; + break; + case 'H': + /* APOB NV size */ + register_fw_addr(AMD_BIOS_APOB_NV, 0, 0, optarg); + sub = instance = 0; + break; + case 'V': + register_bdt_data(AMD_BIOS_BIN, sub, instance, optarg); + sub = instance = 0; + break; + case 'e': + /* BIOS source */ + register_fw_addr(AMD_BIOS_BIN, optarg, 0, 0); + sub = instance = 0; + break; + case 'v': + /* BIOS destination */ + register_fw_addr(AMD_BIOS_BIN, 0, optarg, 0); + sub = instance = 0; + break; + case 'j': + /* BIOS destination size */ + register_fw_addr(AMD_BIOS_BIN, 0, 0, optarg); + sub = instance = 0; + break; + case 'y': + register_bdt_data(AMD_BIOS_PMUI, sub, instance, optarg); + sub = instance = 0; + break; + case 'G': + register_bdt_data(AMD_BIOS_PMUD, sub, instance, optarg); + sub = instance = 0; + break; + case 'O': + register_bdt_data(AMD_BIOS_UCODE, sub, + instance, optarg); + sub = instance = 0; + break; + case 'J': + register_fw_filename(AMD_SEC_GASKET, sub, optarg); + sub = instance = 0; + break; + case 'B': + register_fw_filename(AMD_MP2_FW, sub, optarg); + sub = instance = 0; + break; + case 'z': + register_fw_filename(AMD_ABL0 + abl_image++, + sub, optarg); + sub = instance = 0; + break; + case 'X': + register_bdt_data(AMD_BIOS_MP2_CFG, sub, + instance, optarg); + sub = instance = 0; + break; + case 'K': + register_fw_filename(AMD_DRIVER_ENTRIES, sub, optarg); + sub = instance = 0; + break; + case 'L': + register_fw_filename(AMD_WRAPPED_IKEK, sub, optarg); + sub = instance = 0; + break; + case 'Y': + register_fw_filename(AMD_S0I3_DRIVER, sub, optarg); + sub = instance = 0; + break; + case 'N': + register_fw_filename(AMD_DEBUG_UNLOCK, sub, optarg); + sub = instance = 0; + break; + case 'W': + register_fw_filename(AMD_FW_PSP_WHITELIST, sub, optarg); + sub = instance = 0; + break; case 'o': output = optarg; break; @@ -887,6 +1453,27 @@ int main(int argc, char **argv) fill_dir_header(combo_dir, 1, PSP2_COOKIE); #endif + if (have_bios_tables(amd_bios_table)) { + bios_directory_table *biosdir; + if (multi) { + /* Do 2nd level BIOS directory followed by 1st */ + bios_directory_table *biosdir2 = + new_bios_dir(&ctx, multi); + integrate_bios_firmwares(&ctx, biosdir2, 0, + amd_bios_table, BDT2_COOKIE); + + biosdir = new_bios_dir(&ctx, multi); + integrate_bios_firmwares(&ctx, biosdir, biosdir2, + amd_bios_table, BDT1_COOKIE); + } else { + /* flat: BDT1 cookie and no pointer to 2nd table */ + biosdir = new_bios_dir(&ctx, multi); + integrate_bios_firmwares(&ctx, biosdir, 0, + amd_bios_table, BDT1_COOKIE); + } + amd_romsig->bios1_entry = BUFF_TO_RUN(ctx, biosdir); + } + targetfd = open(output, O_RDWR | O_CREAT | O_TRUNC, 0666); if (targetfd >= 0) { write(targetfd, amd_romsig, ctx.current - romsig_offset); From 1264d64a742e6f911b77dd8c63eeebdba94389a6 Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Wed, 12 Jun 2019 16:38:15 -0600 Subject: [PATCH 055/221] grunt: Change Bayhub eMMC base clock to 200MHz The clock was previously set to 52MHz to workaround the fact that depthcharge didn't support tuning. Tuning has now been enabled in depthcharge: https://chromium-review.googlesource.com/c/chromiumos/platform/depthcharge/+/1655553 BUG=b:122244718 TEST=Verified on grunt that it speeds up boot by 130ms Change-Id: If847cea2a7848bcd175958db86e652d4f710201a Signed-off-by: Raul E Rangel Reviewed-on: https://review.coreboot.org/c/coreboot/+/33430 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- .../google/kahlee/variants/baseboard/mainboard.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/kahlee/variants/baseboard/mainboard.c b/src/mainboard/google/kahlee/variants/baseboard/mainboard.c index 996e6102fc..95274eb85d 100644 --- a/src/mainboard/google/kahlee/variants/baseboard/mainboard.c +++ b/src/mainboard/google/kahlee/variants/baseboard/mainboard.c @@ -61,12 +61,22 @@ void board_bh720(struct device *dev) write32((void *)(sdbar + BH720_MEM_RW_ADR), BH720_MEM_RW_WRITE | BH720_PCR_EMMC_SETTING); - /* Set Bayhub SD base CLK 50MHz: case#1 PCR 0x3E4[22] = 0 */ + /* Set Base clock to 200MHz(PCR 0x304[31:16] = 0x2510) */ + write32((void *)(sdbar + BH720_MEM_RW_ADR), + BH720_MEM_RW_READ | BH720_PCR_DrvStrength_PLL); + bh720_pcr_data = read32((void *)(sdbar + BH720_MEM_RW_DATA)); + bh720_pcr_data &= 0x0000FFFF; + bh720_pcr_data |= 0x2510 << 16; + write32((void *)(sdbar + BH720_MEM_RW_DATA), bh720_pcr_data); + write32((void *)(sdbar + BH720_MEM_RW_ADR), + BH720_MEM_RW_WRITE | BH720_PCR_DrvStrength_PLL); + + /* Use PLL Base clock PCR 0x3E4[22] = 1 */ write32((void *)(sdbar + BH720_MEM_RW_ADR), BH720_MEM_RW_READ | BH720_PCR_CSR); bh720_pcr_data = read32((void *)(sdbar + BH720_MEM_RW_DATA)); write32((void *)(sdbar + BH720_MEM_RW_DATA), - bh720_pcr_data & ~BH720_PCR_CSR_EMMC_MODE_SEL); + bh720_pcr_data | BH720_PCR_CSR_EMMC_MODE_SEL); write32((void *)(sdbar + BH720_MEM_RW_ADR), BH720_MEM_RW_WRITE | BH720_PCR_CSR); From f957201cf08a9f53cede3567669fccb7ad330ab3 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 11 Jun 2019 11:15:10 +0200 Subject: [PATCH 056/221] sb/intel/common/spi: Properly check if setting FRP succeeded Change-Id: Ib0b63c3b0342c62aeabb5c6e418eb9811fc6597d Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33389 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/southbridge/intel/common/spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c index d9a77c3bb5..e8c8f01407 100644 --- a/src/southbridge/intel/common/spi.c +++ b/src/southbridge/intel/common/spi.c @@ -1038,8 +1038,7 @@ static int spi_flash_protect(const struct spi_flash *flash, /* Set the FPR register and verify it is protected */ write32(&fpr_base[fpr], reg); - reg = read32(&fpr_base[fpr]); - if (!(reg & protect_mask)) { + if (reg != read32(&fpr_base[fpr])) { printk(BIOS_ERR, "ERROR: Unable to set SPI FPR %d\n", fpr); return -1; } From 0c5666828d154f6fc9c92fde8de918e39dd4231a Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 12 Jun 2019 19:13:00 +0200 Subject: [PATCH 057/221] {mb,sb}: Use get_acpi_table_revision(FADT) Change-Id: Id3d7f021a52e08906ae0a3f794756e397601fe96 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33428 Reviewed-by: Angel Pons Reviewed-by: Patrick Rudolph Reviewed-by: Frans Hendriks Tested-by: build bot (Jenkins) --- src/mainboard/amd/serengeti_cheetah_fam10/fadt.c | 2 +- src/mainboard/emulation/qemu-q35/acpi_tables.c | 2 +- src/mainboard/facebook/fbg1701/fadt.c | 2 +- src/mainboard/intel/strago/fadt.c | 2 +- src/mainboard/lenovo/t400/fadt.c | 2 +- src/mainboard/lenovo/x200/fadt.c | 2 +- src/mainboard/roda/rk9/fadt.c | 2 +- src/southbridge/amd/sb700/fadt.c | 2 +- src/southbridge/amd/sb800/fadt.c | 2 +- src/southbridge/nvidia/ck804/fadt.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mainboard/amd/serengeti_cheetah_fam10/fadt.c b/src/mainboard/amd/serengeti_cheetah_fam10/fadt.c index 2067024088..845af71c92 100644 --- a/src/mainboard/amd/serengeti_cheetah_fam10/fadt.c +++ b/src/mainboard/amd/serengeti_cheetah_fam10/fadt.c @@ -36,7 +36,7 @@ void acpi_create_fadt(acpi_fadt_t *fadt,acpi_facs_t *facs,void *dsdt){ memset((void *)fadt,0,sizeof(acpi_fadt_t)); memcpy(header->signature,"FACP",4); header->length = 244; - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id,OEM_ID,6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id,ASLC,4); diff --git a/src/mainboard/emulation/qemu-q35/acpi_tables.c b/src/mainboard/emulation/qemu-q35/acpi_tables.c index 2c6a2ecd25..a609b5df38 100644 --- a/src/mainboard/emulation/qemu-q35/acpi_tables.c +++ b/src/mainboard/emulation/qemu-q35/acpi_tables.c @@ -49,7 +49,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) memset((void *) fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = sizeof(acpi_fadt_t); - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); diff --git a/src/mainboard/facebook/fbg1701/fadt.c b/src/mainboard/facebook/fbg1701/fadt.c index 73adfad94c..60dd5b9a73 100644 --- a/src/mainboard/facebook/fbg1701/fadt.c +++ b/src/mainboard/facebook/fbg1701/fadt.c @@ -24,7 +24,7 @@ void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt) memset((void *) fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = sizeof(acpi_fadt_t); - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); diff --git a/src/mainboard/intel/strago/fadt.c b/src/mainboard/intel/strago/fadt.c index 9814d1e667..2a54254aa1 100644 --- a/src/mainboard/intel/strago/fadt.c +++ b/src/mainboard/intel/strago/fadt.c @@ -25,7 +25,7 @@ void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt) memset((void *) fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = sizeof(acpi_fadt_t); - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); diff --git a/src/mainboard/lenovo/t400/fadt.c b/src/mainboard/lenovo/t400/fadt.c index 673791f99c..e335787100 100644 --- a/src/mainboard/lenovo/t400/fadt.c +++ b/src/mainboard/lenovo/t400/fadt.c @@ -29,7 +29,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) memset((void *) fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = sizeof(acpi_fadt_t); - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); diff --git a/src/mainboard/lenovo/x200/fadt.c b/src/mainboard/lenovo/x200/fadt.c index 673791f99c..e335787100 100644 --- a/src/mainboard/lenovo/x200/fadt.c +++ b/src/mainboard/lenovo/x200/fadt.c @@ -29,7 +29,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) memset((void *) fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = sizeof(acpi_fadt_t); - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); diff --git a/src/mainboard/roda/rk9/fadt.c b/src/mainboard/roda/rk9/fadt.c index 673791f99c..e335787100 100644 --- a/src/mainboard/roda/rk9/fadt.c +++ b/src/mainboard/roda/rk9/fadt.c @@ -29,7 +29,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) memset((void *) fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = sizeof(acpi_fadt_t); - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); diff --git a/src/southbridge/amd/sb700/fadt.c b/src/southbridge/amd/sb700/fadt.c index 4bc36221ad..4a5746ccd7 100644 --- a/src/southbridge/amd/sb700/fadt.c +++ b/src/southbridge/amd/sb700/fadt.c @@ -37,7 +37,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) memset((void *)fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = 244; - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); diff --git a/src/southbridge/amd/sb800/fadt.c b/src/southbridge/amd/sb800/fadt.c index d94ac73b4a..71bdf2313b 100644 --- a/src/southbridge/amd/sb800/fadt.c +++ b/src/southbridge/amd/sb800/fadt.c @@ -37,7 +37,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) memset((void *)fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); header->length = 244; - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); diff --git a/src/southbridge/nvidia/ck804/fadt.c b/src/southbridge/nvidia/ck804/fadt.c index 6a096617f3..f6ad479d6f 100644 --- a/src/southbridge/nvidia/ck804/fadt.c +++ b/src/southbridge/nvidia/ck804/fadt.c @@ -35,7 +35,7 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) memcpy(header->signature, "FACP", 4); #ifdef LONG_FADT header->length = 244; - header->revision = 3; + header->revision = get_acpi_table_revision(FADT); #else header->length = 0x74; header->revision = 1; From ba5f318736d9ade42160932d4119c47867ae1f35 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Thu, 13 Jun 2019 12:47:22 +0200 Subject: [PATCH 058/221] sb/nvidia/ck804/fadt.c: Remove unused LONG_FADT LONG_FADT is not used at all. So remove it and use sizeof(acpi_fadt_t) for header length. Change-Id: I433d1b2e0f3b9505d7c52eb14f1a476fbe52a284 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33436 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: Lance Zhao --- src/southbridge/nvidia/ck804/fadt.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/southbridge/nvidia/ck804/fadt.c b/src/southbridge/nvidia/ck804/fadt.c index f6ad479d6f..713a51ea0a 100644 --- a/src/southbridge/nvidia/ck804/fadt.c +++ b/src/southbridge/nvidia/ck804/fadt.c @@ -33,13 +33,8 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt) /* Prepare the header */ memset((void *)fadt, 0, sizeof(acpi_fadt_t)); memcpy(header->signature, "FACP", 4); -#ifdef LONG_FADT - header->length = 244; + header->length = sizeof(acpi_fadt_t); header->revision = get_acpi_table_revision(FADT); -#else - header->length = 0x74; - header->revision = 1; -#endif memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); From 685b377e7e56ed6a046204baf73c43d76a87f4b4 Mon Sep 17 00:00:00 2001 From: sridhar Date: Thu, 13 Jun 2019 14:26:00 +0530 Subject: [PATCH 059/221] mb/intel/whl_rvp: Configure FSP UPDs of DDI ports for whlrvp This patch configures FSP UPD values for HPD and DDC of DDI ports for WHLRVP. BUG=none TEST=Tested that eDP & DP works on WHLRVP Signed-off-by: Usha P Signed-off-by: sridhar Change-Id: I576469f5564e3e56159762752dbe4557e9dc1912 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33435 Reviewed-by: Subrata Banik Reviewed-by: Maulik V Vaghela Tested-by: build bot (Jenkins) --- .../coffeelake_rvp/variants/whl_u/devicetree.cb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mainboard/intel/coffeelake_rvp/variants/whl_u/devicetree.cb b/src/mainboard/intel/coffeelake_rvp/variants/whl_u/devicetree.cb index e30da3af4d..429d5daca8 100644 --- a/src/mainboard/intel/coffeelake_rvp/variants/whl_u/devicetree.cb +++ b/src/mainboard/intel/coffeelake_rvp/variants/whl_u/devicetree.cb @@ -9,6 +9,19 @@ chip soc/intel/cannonlake register "ScsEmmcHs400Enabled" = "1" register "HeciEnabled" = "1" + # Enable eDP device + register "DdiPortEdp" = "1" + # Enable HPD for DDI ports B/C/D/F + register "DdiPortBHpd" = "1" + register "DdiPortCHpd" = "1" + register "DdiPortDHpd" = "1" + register "DdiPortFHpd" = "1" + # Enable DDC for DDI ports B/C/D/F + register "DdiPortBDdc" = "1" + register "DdiPortCDdc" = "1" + register "DdiPortDDdc" = "1" + register "DdiPortFDdc" = "1" + register "usb2_ports[0]" = "USB2_PORT_TYPE_C(OC0)" register "usb2_ports[1]" = "USB2_PORT_MID(OC0)" register "usb2_ports[2]" = "USB2_PORT_MID(OC0)" From b09de70eda443d2fc9f4891c7647aac4526a8e99 Mon Sep 17 00:00:00 2001 From: Aamir Bohra Date: Wed, 29 May 2019 13:33:32 +0530 Subject: [PATCH 060/221] mb/google/hatch: Remove unused USB2 port5 from baseboard devicetree Hatch newer board revision do not use USB port5 for discrete BT. Hence remove the port configuration and UBS2 P5 asl entry. The older board version would continue to use USB2 P5 hence moved the entry to overridetree.cb Change-Id: I98297d6b81e3184b7b0a14710f3790f5df30d68b Signed-off-by: Aamir Bohra Reviewed-on: https://review.coreboot.org/c/coreboot/+/33060 Tested-by: build bot (Jenkins) Reviewed-by: Paul Fagerburg Reviewed-by: Furquan Shaikh Reviewed-by: Subrata Banik --- .../hatch/variants/baseboard/devicetree.cb | 12 +++--------- .../hatch/variants/hatch_whl/overridetree.cb | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/mainboard/google/hatch/variants/baseboard/devicetree.cb b/src/mainboard/google/hatch/variants/baseboard/devicetree.cb index 112c279fcb..a66c74328e 100644 --- a/src/mainboard/google/hatch/variants/baseboard/devicetree.cb +++ b/src/mainboard/google/hatch/variants/baseboard/devicetree.cb @@ -56,12 +56,12 @@ chip soc/intel/cannonlake register "usb2_ports[1]" = "USB2_PORT_TYPE_C(OC2)" # Type-C Port 1 register "usb2_ports[2]" = "USB2_PORT_SHORT(OC3)" # Type-A Port 0 register "usb2_ports[3]" = "USB2_PORT_LONG(OC3)" # Type-A Port 1 - register "usb2_ports[4]" = "USB2_PORT_MID(OC_SKIP)" # BT + register "usb2_ports[4]" = "USB2_PORT_EMPTY" register "usb2_ports[5]" = "USB2_PORT_MID(OC_SKIP)" # WWAN register "usb2_ports[6]" = "USB2_PORT_LONG(OC_SKIP)" # Camera register "usb2_ports[7]" = "USB2_PORT_EMPTY" register "usb2_ports[8]" = "USB2_PORT_EMPTY" - register "usb2_ports[9]" = "USB2_PORT_MID(OC_SKIP)" # CnVi BT + register "usb2_ports[9]" = "USB2_PORT_MID(OC_SKIP)" # BT register "usb3_ports[0]" = "USB3_PORT_DEFAULT(OC2)" # Type-C Port 0 register "usb3_ports[1]" = "USB3_PORT_DEFAULT(OC2)" # Type-C Port 1 @@ -144,12 +144,6 @@ chip soc/intel/cannonlake register "group" = "ACPI_PLD_GROUP(2, 2)" device usb 2.3 on end end - chip drivers/usb/acpi - register "desc" = ""Discrete bluetooth"" - register "type" = "UPC_TYPE_INTERNAL" - register "reset_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_LOW(GPP_C14)" - device usb 2.4 on end - end chip drivers/usb/acpi register "desc" = ""WWAN"" register "type" = "UPC_TYPE_INTERNAL" @@ -161,7 +155,7 @@ chip soc/intel/cannonlake device usb 2.6 on end end chip drivers/usb/acpi - register "desc" = ""Integrated CnVi bluetooth"" + register "desc" = ""Bluetooth"" register "type" = "UPC_TYPE_INTERNAL" register "reset_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_LOW(GPP_C14)" device usb 2.9 on end diff --git a/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb b/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb index fe7869dd4b..373438cf8a 100644 --- a/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb +++ b/src/mainboard/google/hatch/variants/hatch_whl/overridetree.cb @@ -32,7 +32,24 @@ chip soc/intel/cannonlake # GPIO for SD card detect register "sdcard_cd_gpio" = "vSD3_CD_B" + # USB configuration + register "usb2_ports[4]" = "USB2_PORT_MID(OC_SKIP)" # Discrete BT + device domain 0 on + device pci 14.0 on + chip drivers/usb/acpi + register "desc" = ""Root Hub"" + register "type" = "UPC_TYPE_HUB" + device usb 0.0 on + chip drivers/usb/acpi + register "desc" = ""Discrete bluetooth"" + register "type" = "UPC_TYPE_INTERNAL" + register "reset_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_LOW(GPP_C14)" + device usb 2.4 on end + end + end + end + end # USB xHCI device pci 15.0 on chip drivers/i2c/generic register "hid" = ""ELAN0000"" From e48be35bca9a0656d1becb0c8a030a11eb8ffaa7 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Wed, 19 Jun 2019 11:01:27 +0200 Subject: [PATCH 061/221] southbridge/intel/common/smbus: Add do_i2c_block_write() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel Braswell supports i2c block writes using SMBus controller. This support is missing in actual smbus routines. Add do_i2c_block_write() which is a based on do_smbus_block_write() but also write first byte to SMBHSTDAT1. The caller needs to configure the SMBus controller in i2c mode. In i2c mode SMBus controller will send the next sequence: SMBXINTADD, SMBHSTDAT1, SMBBLKDAT .. SMBBLKDAT To ensure the the command is send over the bus the SMBHSTCMD register must be written also BUG=N/A TEST=Config eDP for LCD display on Facebook FBG-1701 Change-Id: I40f8c0f5257a62398189f36892b8159052481693 Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/30800 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/southbridge/intel/common/smbus.c | 45 ++++++++++++++++++++++++++++ src/southbridge/intel/common/smbus.h | 2 ++ 2 files changed, 47 insertions(+) diff --git a/src/southbridge/intel/common/smbus.c b/src/southbridge/intel/common/smbus.c index af1eb602a0..e575abc40e 100644 --- a/src/southbridge/intel/common/smbus.c +++ b/src/southbridge/intel/common/smbus.c @@ -4,6 +4,7 @@ * Copyright (C) 2005 Yinghai Lu * Copyright (C) 2009 coresystems GmbH * Copyright (C) 2013 Vladimir Serbinenko + * Copyright (C) 2018-2019 Eltan B.V. * * 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 @@ -410,3 +411,47 @@ int do_i2c_eeprom_read(unsigned int smbus_base, u8 device, return ret; } + +/* + * The caller is responsible of settings HOSTC I2C_EN bit prior to making this + * call! + */ +int do_i2c_block_write(unsigned int smbus_base, u8 device, + unsigned int bytes, u8 *buf) +{ + u8 cmd; + int ret; + + if (!CONFIG(SOC_INTEL_BRASWELL)) + return SMBUS_ERROR; + + if (!bytes || (bytes > SMBUS_BLOCK_MAXLEN)) + return SMBUS_ERROR; + + /* Set up for a block data write. */ + ret = setup_command(smbus_base, I801_BLOCK_DATA, XMIT_WRITE(device)); + if (ret < 0) + return ret; + + /* + * In i2c mode SMBus controller sequence on bus will be: + * .. + * The SMBHSTCMD must be written also to ensure the SMBUs controller + * will generate the i2c sequence. + */ + cmd = *buf++; + bytes--; + outb(cmd, smbus_base + SMBHSTCMD); + outb(cmd, smbus_base + SMBHSTDAT1); + + /* Execute block transaction. */ + ret = block_cmd_loop(smbus_base, buf, bytes, BLOCK_WRITE); + if (ret < 0) + return ret; + + if (ret < bytes) + return SMBUS_ERROR; + + ret++; /* 1st byte has been written using SMBHSTDAT1 */ + return ret; +} diff --git a/src/southbridge/intel/common/smbus.h b/src/southbridge/intel/common/smbus.h index ded31d0ae2..4875581573 100644 --- a/src/southbridge/intel/common/smbus.h +++ b/src/southbridge/intel/common/smbus.h @@ -43,4 +43,6 @@ int do_smbus_block_write(unsigned int smbus_base, u8 device, /* Only since ICH5 */ int do_i2c_eeprom_read(unsigned int smbus_base, u8 device, unsigned int offset, unsigned int bytes, u8 *buf); +int do_i2c_block_write(unsigned int smbus_base, u8 device, + unsigned int bytes, u8 *buf); #endif From 863853cd2d8e01db2045e73d96c502e4ecba8ad1 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Tue, 18 Jun 2019 12:18:55 +0200 Subject: [PATCH 062/221] soc/intel/braswell/smbus.c: Add support for i2c mode block write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel Braswell supports i2c block write using SMBus controller. smbus_i2c_block_write() is added to configure SMBus controller in i2c mode before calling do_i2c_block_write(). Add smbus.c to ramstage. BUG=N/A TEST=Verify LCD display is working on Facebook FBG-1701 Change-Id: I50c1a03f624b3ab3b987d4f3b1d15dac4374e48a Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33225 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/soc/intel/braswell/Makefile.inc | 1 + src/soc/intel/braswell/include/soc/smbus.h | 26 ++++++++++++++++++ src/soc/intel/braswell/smbus.c | 32 ++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 src/soc/intel/braswell/include/soc/smbus.h diff --git a/src/soc/intel/braswell/Makefile.inc b/src/soc/intel/braswell/Makefile.inc index 1017d80c65..cc111da485 100644 --- a/src/soc/intel/braswell/Makefile.inc +++ b/src/soc/intel/braswell/Makefile.inc @@ -35,6 +35,7 @@ ramstage-$(CONFIG_ELOG) += elog.c ramstage-y += emmc.c ramstage-y += gpio.c ramstage-y += gfx.c +ramstage-y += smbus.c ramstage-y += gpio_support.c ramstage-y += iosf.c diff --git a/src/soc/intel/braswell/include/soc/smbus.h b/src/soc/intel/braswell/include/soc/smbus.h new file mode 100644 index 0000000000..8bc62f7eec --- /dev/null +++ b/src/soc/intel/braswell/include/soc/smbus.h @@ -0,0 +1,26 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc. + * Copyright (C) 2015 Intel Corp. + * Copyright (C) 2019 Eltan B.V. + * + * 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 _SOC_SMBUS_H_ +#define _SOC_SMBUS_H_ + +/* PCI Configuration Space SMBus */ +#define HOSTC 0x40 +#define HOSTC_I2C_EN (1 << 2) + +int smbus_i2c_block_write(u8 addr, u8 bytes, u8 *buf); +#endif /* _SOC_SMBUS_H_ */ diff --git a/src/soc/intel/braswell/smbus.c b/src/soc/intel/braswell/smbus.c index 7e1b0dfbb0..1dfd4c7ecd 100644 --- a/src/soc/intel/braswell/smbus.c +++ b/src/soc/intel/braswell/smbus.c @@ -3,6 +3,7 @@ * * Copyright (C) 2017 Intel Corporation. * Copyright (C) 2019 3mdeb + * Copyright (C) 2019 Eltan B.V. * * 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 @@ -16,6 +17,11 @@ #include #include +#include +#include +#include +#include +#include #include u8 smbus_read_byte(u32 smbus_dev, u8 addr, u8 offset) @@ -27,3 +33,29 @@ u8 smbus_write_byte(u32 smbus_dev, u8 addr, u8 offset, u8 value) { return do_smbus_write_byte(SMBUS_BASE_ADDRESS, addr, offset, value); } + +int smbus_i2c_block_write(u8 addr, u8 bytes, u8 *buf) +{ +#ifdef __SIMPLE_DEVICE__ + pci_devfn_t dev = PCI_DEV(0, SMBUS_DEV, SMBUS_FUNC); +#else + struct device *dev = pcidev_on_root(SMBUS_DEV, SMBUS_FUNC); +#endif + u32 smbase; + u32 smb_ctrl_reg; + int status; + + /* SMBus I/O BAR */ + smbase = pci_read_config32(dev, PCI_BASE_ADDRESS_4) & 0xFFFFFFFE; + + /* Enable I2C_EN bit in HOSTC register */ + smb_ctrl_reg = pci_read_config32(dev, HOSTC); + pci_write_config32(dev, HOSTC, smb_ctrl_reg | HOSTC_I2C_EN); + + status = do_i2c_block_write(smbase, addr, bytes, buf); + + /* Restore I2C_EN bit */ + pci_write_config32(dev, HOSTC, smb_ctrl_reg); + + return status; +} From c10af299aeed2a7d530fbabbaa55947d64712333 Mon Sep 17 00:00:00 2001 From: Hsin-Hsiung Wang Date: Tue, 26 Mar 2019 15:38:04 +0800 Subject: [PATCH 063/221] mediatek/mt8183: Calibrate vsim2 to 2.7 V The default voltage of vsim2 is set to 2.76V for sim card usage. In general, 2.76V of vsim2 is composed of 2.7V main voltage and 0.06V calibration voltage. However, vsim2 is used for the tx_ovdd power of display port IT6505 on the kukui board design which needs 2.7V. So we set it to 2.7V with modifying calibration value. BUG=b:126139364 BRANCH=none TEST=measure vsim2 voltage with multimeter Change-Id: I4dffdde89cbde91286d92e6c2b445f0b3d0ad2fe Signed-off-by: Hsin-Hsiung Wang Reviewed-on: https://review.coreboot.org/c/coreboot/+/32057 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/mainboard/google/kukui/romstage.c | 2 + src/soc/mediatek/mt8183/include/soc/mt6358.h | 2 + src/soc/mediatek/mt8183/mt6358.c | 41 ++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/src/mainboard/google/kukui/romstage.c b/src/mainboard/google/kukui/romstage.c index baaca43b90..1465243f07 100644 --- a/src/mainboard/google/kukui/romstage.c +++ b/src/mainboard/google/kukui/romstage.c @@ -29,6 +29,8 @@ void platform_romstage_main(void) mainboard_early_init(); mt6358_init(); + /* Adjust VSIM2 down to 2.7V because it is shared with IT6505. */ + pmic_set_vsim2_cali(2700); mt_pll_raise_ca53_freq(1989 * MHz); rtc_boot(); mt_mem_init(get_sdram_config()); diff --git a/src/soc/mediatek/mt8183/include/soc/mt6358.h b/src/soc/mediatek/mt8183/include/soc/mt6358.h index 02937bac9a..277ee9aa35 100644 --- a/src/soc/mediatek/mt8183/include/soc/mt6358.h +++ b/src/soc/mediatek/mt8183/include/soc/mt6358.h @@ -27,6 +27,7 @@ enum { PMIC_CPSDSA4 = 0x0a2e, PMIC_VDRAM1_VOSEL_SLEEP = 0x160a, PMIC_SMPS_ANA_CON0 = 0x1808, + PMIC_VSIM2_ANA_CON0 = 0x1e30, }; struct pmic_setting { @@ -38,5 +39,6 @@ struct pmic_setting { void mt6358_init(void); void pmic_set_power_hold(bool enable); +void pmic_set_vsim2_cali(unsigned int vsim2_mv); #endif /* __SOC_MEDIATEK_MT6358_H__ */ diff --git a/src/soc/mediatek/mt8183/mt6358.c b/src/soc/mediatek/mt8183/mt6358.c index 705424337f..ea4274f14b 100644 --- a/src/soc/mediatek/mt8183/mt6358.c +++ b/src/soc/mediatek/mt8183/mt6358.c @@ -13,6 +13,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -733,6 +734,46 @@ void pmic_set_power_hold(bool enable) pwrap_write_field(PMIC_PWRHOLD, (enable) ? 1 : 0, 0x1, 0); } +void pmic_set_vsim2_cali(unsigned int vsim2_mv) +{ + u16 vsim2_reg, cali_mv; + + cali_mv = vsim2_mv % 100; + assert(cali_mv % 10 == 0); + + switch (vsim2_mv - cali_mv) { + case 1700: + vsim2_reg = 0x3; + break; + + case 1800: + vsim2_reg = 0x4; + break; + + case 2700: + vsim2_reg = 0x8; + break; + + case 3000: + vsim2_reg = 0xb; + break; + + case 3100: + vsim2_reg = 0xc; + break; + + default: + assert(0); + return; + }; + + /* [11:8]=0x8, RG_VSIM2_VOSEL */ + pwrap_write_field(PMIC_VSIM2_ANA_CON0, vsim2_reg, 0xF, 8); + + /* [3:0], RG_VSIM2_VOCAL */ + pwrap_write_field(PMIC_VSIM2_ANA_CON0, cali_mv / 10, 0xF, 0); +} + static void pmic_wdt_set(void) { /* [5]=1, RG_WDTRSTB_DEB */ From a06cd6c29e5f2fb05210eb185b84c887791df989 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Sun, 16 Jun 2019 16:44:26 +0800 Subject: [PATCH 064/221] vboot: remove vboot_handoff_get_recovery_reason Two functions retrieve vboot recovery_reason: * vboot_handoff_get_recovery_reason * vboot_get_recovery_reason_shared_data Previously, when CBMEM comes online, a vboot_handoff data structure is created, and depending on the architecture, coreboot may eventually lose access to vboot_working_data. After implementing vboot_working_data CBMEM migration, vboot_working_data is always guaranteed to be accessible. vboot_get_recovery_reason_shared_data is corrected to also allow accessing vboot_working_data in ramstage and postcar. Now, vboot_handoff_get_recovery reason returning a valid recovery reason implies that vboot_get_recovery_reason_shared_data should *also* return a valid recovery reason. Thus we may remove the former. BUG=b:124141368, b:124192753 TEST=make clean && make test-abuild BRANCH=none Change-Id: Iac216dc968dd155d9d4f8bd0f2dfd5034762f9a0 Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/33532 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh Reviewed-by: Julius Werner --- src/security/vboot/bootmode.c | 28 ++++++---------------------- src/security/vboot/vboot_common.c | 13 ------------- src/security/vboot/vboot_common.h | 4 +--- 3 files changed, 7 insertions(+), 38 deletions(-) diff --git a/src/security/vboot/bootmode.c b/src/security/vboot/bootmode.c index 68749f008b..4d4dc0ddfd 100644 --- a/src/security/vboot/bootmode.c +++ b/src/security/vboot/bootmode.c @@ -26,10 +26,6 @@ static int vboot_get_recovery_reason_shared_data(void) { - /* Shared data does not exist for Ramstage and Post-CAR stage. */ - if (ENV_RAMSTAGE || ENV_POSTCAR) - return 0; - struct vb2_shared_data *sd = vboot_get_shared_data(); assert(sd); return sd->recovery_reason; @@ -96,11 +92,10 @@ static int vboot_possibly_executed(void) * VB2_RECOVERY_RO_MANUAL. * 2. Checks if recovery request is present in VBNV and returns the code read * from it. - * 3. Checks recovery request in handoff for stages post-cbmem. - * 4. For non-CBMEM stages, check if vboot verification is done and look-up - * selected region to identify if vboot_reference library has requested recovery - * path. If yes, return the reason code from shared data. - * 5. If nothing applies, return 0 indicating no recovery request. + * 3. Checks if vboot verification is done and looks up selected region + * to identify if vboot_reference library has requested recovery path. + * If yes, return the reason code from shared data. + * 4. If nothing applies, return 0 indicating no recovery request. */ int vboot_check_recovery_request(void) { @@ -115,19 +110,8 @@ int vboot_check_recovery_request(void) return reason; /* - * Check recovery flag in vboot_handoff for stages post CBMEM coming - * online. Since for some stages there is no way to know if cbmem has - * already come online, try looking up handoff anyways. If it fails, - * flow will fallback to looking up shared data. - */ - if (cbmem_possibly_online() && - ((reason = vboot_handoff_get_recovery_reason()) != 0)) - return reason; - - /* - * For stages where CBMEM might not be online, identify if vboot - * verification is already complete and no slot was selected - * i.e. recovery path was requested. + * Identify if vboot verification is already complete and no slot + * was selected i.e. recovery path was requested. */ if (vboot_possibly_executed() && vboot_logic_executed() && !vboot_is_slot_selected()) diff --git a/src/security/vboot/vboot_common.c b/src/security/vboot/vboot_common.c index ff8e6c896c..a18bf23f92 100644 --- a/src/security/vboot/vboot_common.c +++ b/src/security/vboot/vboot_common.c @@ -93,19 +93,6 @@ int vboot_handoff_check_recovery_flag(void) return vboot_get_handoff_flag(VB_INIT_OUT_ENABLE_RECOVERY); } -int vboot_handoff_get_recovery_reason(void) -{ - struct vboot_handoff *vbho; - VbSharedDataHeader *sd; - - if (vboot_get_handoff_info((void **)&vbho, NULL)) - return 0; - - sd = (VbSharedDataHeader *)vbho->shared_data; - - return sd->recovery_reason; -} - /* ============================ VBOOT REBOOT ============================== */ void __weak vboot_platform_prepare_reboot(void) { diff --git a/src/security/vboot/vboot_common.h b/src/security/vboot/vboot_common.h index a785a8ba34..65a543c791 100644 --- a/src/security/vboot/vboot_common.h +++ b/src/security/vboot/vboot_common.h @@ -54,15 +54,13 @@ struct vboot_handoff { int vboot_get_handoff_info(void **addr, uint32_t *size); /* - * The following functions read vboot_handoff structure to obtain requested + * The following function reads vboot_handoff structure to obtain requested * information. If vboot handoff is not available, 0 is returned by default. * If vboot handoff is available: * Returns 1 for flag if true * Returns 0 for flag if false - * Returns value read for other fields */ int vboot_handoff_check_recovery_flag(void); -int vboot_handoff_get_recovery_reason(void); /* ============================ VBOOT REBOOT ============================== */ /* From b6bcb6cc8f8b217254ccdb81ef8b2d852047d5b8 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Sun, 16 Jun 2019 16:59:26 +0800 Subject: [PATCH 065/221] vboot: remove functions which read vboot_handoff.out_flags These functions are no longer used and may be removed: * vboot_handoff_check_recovery_flag * vboot_get_handoff_flag BUG=b:124141368, b:124192753 TEST=make clean && make test-abuild BRANCH=none Change-Id: Ie05652ef1288eef74bd2e7e8bea79fd29d523859 Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/33533 Reviewed-by: Julius Werner Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/security/vboot/vboot_common.c | 18 ------------------ src/security/vboot/vboot_common.h | 9 --------- 2 files changed, 27 deletions(-) diff --git a/src/security/vboot/vboot_common.c b/src/security/vboot/vboot_common.c index a18bf23f92..8456dcfc22 100644 --- a/src/security/vboot/vboot_common.c +++ b/src/security/vboot/vboot_common.c @@ -75,24 +75,6 @@ int vboot_get_handoff_info(void **addr, uint32_t *size) return 0; } -static int vboot_get_handoff_flag(uint32_t flag) -{ - struct vboot_handoff *vbho; - - /* - * If vboot_handoff cannot be found, return default value of flag as 0. - */ - if (vboot_get_handoff_info((void **)&vbho, NULL)) - return 0; - - return !!(vbho->out_flags & flag); -} - -int vboot_handoff_check_recovery_flag(void) -{ - return vboot_get_handoff_flag(VB_INIT_OUT_ENABLE_RECOVERY); -} - /* ============================ VBOOT REBOOT ============================== */ void __weak vboot_platform_prepare_reboot(void) { diff --git a/src/security/vboot/vboot_common.h b/src/security/vboot/vboot_common.h index 65a543c791..241dc90e95 100644 --- a/src/security/vboot/vboot_common.h +++ b/src/security/vboot/vboot_common.h @@ -53,15 +53,6 @@ struct vboot_handoff { */ int vboot_get_handoff_info(void **addr, uint32_t *size); -/* - * The following function reads vboot_handoff structure to obtain requested - * information. If vboot handoff is not available, 0 is returned by default. - * If vboot handoff is available: - * Returns 1 for flag if true - * Returns 0 for flag if false - */ -int vboot_handoff_check_recovery_flag(void); - /* ============================ VBOOT REBOOT ============================== */ /* * vboot_reboot handles the reboot requests made by vboot_reference library. It From 532e0c74e15bba27f1b91001e9427c5305f405c8 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Sun, 16 Jun 2019 17:23:03 +0800 Subject: [PATCH 066/221] vboot: relocate code to log and clear recovery mode switch Logging and clearing the recovery mode switch doesn't have anything to do with vboot_handoff. Move it to the main verstage logic file. BUG=b:124141368, b:124192753 TEST=make clean && make test-abuild BRANCH=none Change-Id: I2e74f3893463e43fe5fad4a8df8036560f34e0db Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/33534 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/security/vboot/Makefile.inc | 1 + src/security/vboot/vboot_handoff.c | 15 --------------- src/security/vboot/vboot_logic.c | 26 ++++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/security/vboot/Makefile.inc b/src/security/vboot/Makefile.inc index 9ce724ed54..3306f41a0b 100644 --- a/src/security/vboot/Makefile.inc +++ b/src/security/vboot/Makefile.inc @@ -88,6 +88,7 @@ else verstage-y += secdata_tpm.c romstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += secdata_tpm.c endif +romstage-y += vboot_logic.c romstage-y += vboot_handoff.c common.c ramstage-y += common.c diff --git a/src/security/vboot/vboot_handoff.c b/src/security/vboot/vboot_handoff.c index 8a6b3d61e8..19773c5438 100644 --- a/src/security/vboot/vboot_handoff.c +++ b/src/security/vboot/vboot_handoff.c @@ -122,21 +122,6 @@ void vboot_fill_handoff(void) /* needed until we finish transtion to vboot2 for kernel verification */ fill_vboot_handoff(vh, sd); - - - /* Log the recovery mode switches if required, before clearing them. */ - log_recovery_mode_switch(); - - /* - * The recovery mode switch is cleared (typically backed by EC) here - * to allow multiple queries to get_recovery_mode_switch() and have - * them return consistent results during the verified boot path as well - * as dram initialization. x86 systems ignore the saved dram settings - * in the recovery path in order to start from a clean slate. Therefore - * clear the state here since this function is called when memory - * is known to be up. - */ - clear_recovery_mode_switch(); } /* diff --git a/src/security/vboot/vboot_logic.c b/src/security/vboot/vboot_logic.c index 7b98be28e4..62e033a0de 100644 --- a/src/security/vboot/vboot_logic.c +++ b/src/security/vboot/vboot_logic.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -281,6 +282,26 @@ static uint32_t extend_pcrs(struct vb2_context *ctx) vboot_extend_pcr(ctx, 1, HWID_DIGEST_PCR); } +static void vboot_log_and_clear_recovery_mode_switch(int unused) +{ + /* Log the recovery mode switches if required, before clearing them. */ + log_recovery_mode_switch(); + + /* + * The recovery mode switch is cleared (typically backed by EC) here + * to allow multiple queries to get_recovery_mode_switch() and have + * them return consistent results during the verified boot path as well + * as dram initialization. x86 systems ignore the saved dram settings + * in the recovery path in order to start from a clean slate. Therefore + * clear the state here since this function is called when memory + * is known to be up. + */ + clear_recovery_mode_switch(); +} +#if !CONFIG(VBOOT_STARTS_IN_ROMSTAGE) +ROMSTAGE_CBMEM_INIT_HOOK(vboot_log_and_clear_recovery_mode_switch) +#endif + /** * Verify and select the firmware in the RW image * @@ -448,6 +469,11 @@ void verstage_main(void) vboot_set_selected_region(region_device_region(&fw_main)); verstage_main_exit: + /* If CBMEM is not up yet, let the ROMSTAGE_CBMEM_INIT_HOOK take care + of running this function. */ + if (ENV_ROMSTAGE && CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) + vboot_log_and_clear_recovery_mode_switch(0); + vboot_finalize_work_context(&ctx); timestamp_add_now(TS_END_VBOOT); } From 86d8c4279d9446826f3f6578793baa5eb2156783 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Thu, 6 Jun 2019 11:49:50 -0600 Subject: [PATCH 067/221] nb/amd/amdmct/mct_ddr3: Remove duplicate code This conditional is exactly the same as the one right below it, except the operations are reorganized slightly. Change-Id: I00c19a467d23a0736bc2a33b516f97080039e634 Signed-off-by: Jacob Garber Found-by: Coverity CID 1347321 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33267 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c index 5be456695e..945ae8274b 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c @@ -3090,12 +3090,6 @@ void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, if (pDCTstat->DIMMValidDCT[0] && pDCTstat->DIMMValidDCT[1] && mctGet_NVbits(NV_Unganged)) interleave_channels = 1; - dword = (Get_NB32_DCT(dev, dct, 0x240) >> 4) & 0xf; - if (dword > 6) - read_odt_delay = dword - 6; - else - read_odt_delay = 0; - dword = Get_NB32_DCT(dev, dct, 0x240); delay = (dword >> 4) & 0xf; if (delay > 6) From 19cbe03534b955cc3c3e3505e66f852184005140 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Thu, 6 Jun 2019 11:35:43 -0600 Subject: [PATCH 068/221] nb/amd/amdmct/mct_ddr3: Remove duplicate conditional This check is already performed at the beginning of dct_ddr_voltage_index(). Change-Id: Ia73025333c152f14249afb16d05f66791e69e7cb Signed-off-by: Jacob Garber Found-by: Coverity CID 1347322, 1347323 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33264 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c index 945ae8274b..fa8c71447b 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c @@ -3071,11 +3071,6 @@ void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, */ uint8_t dimm_event_l_pin_support = 0; - if (pDCTstat->DIMMValidDCT[dct] == 0) - ddr_voltage_index = 1; - else - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); max_dimms_installable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); From 31755adc5ac77e1396e04f88a8c020bebea32461 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Tue, 4 Jun 2019 11:54:44 -0600 Subject: [PATCH 069/221] nb/amd/amdmct/mct: Remove duplicate if condition The case when Speed == 5 is already dealt with on line 111. Change-Id: Icc41c00fb333a51001568f588c17f7b6c6a3a923 Signed-off-by: Jacob Garber Found-by: Coverity CID 1229626 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33213 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Patrick Georgi Reviewed-by: Paul Menzel Reviewed-by: Angel Pons --- src/northbridge/amd/amdmct/mct/mctardk4.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/northbridge/amd/amdmct/mct/mctardk4.c b/src/northbridge/amd/amdmct/mct/mctardk4.c index d112c4664b..2e16a80002 100644 --- a/src/northbridge/amd/amdmct/mct/mctardk4.c +++ b/src/northbridge/amd/amdmct/mct/mctardk4.c @@ -128,8 +128,6 @@ static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload, *AddrTmgCTL = 0x002F2F00; } else if (Speed == 1) { *AddrTmgCTL = 0x002F2F00; - } else if (Speed == 5) { - *AddrTmgCTL = 0x002F2020; } else { *AddrTmgCTL = 0x002F2F2F; } From 176670e31a156358cd8f2ac6ee4a5eb0dd74f54f Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Tue, 4 Jun 2019 15:13:46 -0600 Subject: [PATCH 070/221] drivers/amd/agesa: Assert that StdHeader is non-null MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverity believes there is a path where StdHeader is possibly null. This *should* be incorrect, since the header is actually initialized through the module dispatch framework, though Coverity can't see it due to the extensive type-punning. However, the control flow is so dizzingly complicated that I'm not even completely sure, so adding an extra assert to be careful won't hurt anyway. Change-Id: If3d7c5d5c5bba846e7453b3dbc824e2208d749fb Signed-off-by: Jacob Garber Found-by: Coverity CID 1379932 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33214 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: Kyösti Mälkki --- src/drivers/amd/agesa/state_machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/amd/agesa/state_machine.c b/src/drivers/amd/agesa/state_machine.c index c8529c5e04..750d192325 100644 --- a/src/drivers/amd/agesa/state_machine.c +++ b/src/drivers/amd/agesa/state_machine.c @@ -272,7 +272,7 @@ int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func) /* Must call the function buffer was allocated for.*/ AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr; - ASSERT(StdHeader->Func == func); + ASSERT(StdHeader != NULL && StdHeader->Func == func); if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_entry_id) timestamp_add_now(task.ts_entry_id); From 698d83a7c8a93b347c03ff31362866e7a0f92cb7 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Fri, 7 Jun 2019 10:28:54 -0600 Subject: [PATCH 071/221] lib: Prevent memory leak on error path Free the tree before returning to prevent a leak. Change-Id: I1132c0e7404eec1af3adc19a83257f28563f8a58 Signed-off-by: Jacob Garber Found-by: Coverity CID 1401799 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33298 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/lib/device_tree.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/device_tree.c b/src/lib/device_tree.c index a5021ca8fd..ed878a25a3 100644 --- a/src/lib/device_tree.c +++ b/src/lib/device_tree.c @@ -259,11 +259,13 @@ struct device_tree *fdt_unflatten(const void *blob) if (magic != FDT_HEADER_MAGIC) { printk(BIOS_DEBUG, "Invalid device tree magic %#.8x!\n", magic); + free(tree); return NULL; } if (last_comp_version > FDT_SUPPORTED_VERSION) { printk(BIOS_DEBUG, "Unsupported device tree version %u(>=%u)\n", version, last_comp_version); + free(tree); return NULL; } if (version > FDT_SUPPORTED_VERSION) From 77b3a91bba5c9a0f5dd3144b38ba5308971103ec Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 9 Jun 2019 12:57:12 +0200 Subject: [PATCH 072/221] arch/x86/rdrand.c: Remove unneeded 'else' 'else' is not needed after a 'break' or 'return'. Change-Id: Ib7bdefb0027a35de42f6a665b98f9e5a2791061f Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33331 Tested-by: build bot (Jenkins) Reviewed-by: Vlado Cibic Reviewed-by: Angel Pons --- src/arch/x86/rdrand.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/arch/x86/rdrand.c b/src/arch/x86/rdrand.c index 35aac710a8..c9090df1fd 100644 --- a/src/arch/x86/rdrand.c +++ b/src/arch/x86/rdrand.c @@ -75,7 +75,6 @@ int get_random_number_64(uint64_t *rand) #if ENV_X86_64 if (rdrand_64(rand)) return 0; - else #endif if (rdrand_32(&rand_high) && rdrand_32(&rand_low)) { *rand = ((uint64_t)rand_high << 32) | From 561e11d6f872f6b6ab5fe79df0cbbf8dcd836297 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 9 Jun 2019 13:09:13 +0200 Subject: [PATCH 073/221] drivers/intel/fsp1_0/fastboot_cache: Remove unneeded 'else' 'else' is not needed after a 'break' or 'return'. Change-Id: I109f5aaa87afde61a36fff884305b43c1de2c680 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33332 Tested-by: build bot (Jenkins) Reviewed-by: Vlado Cibic Reviewed-by: Angel Pons --- src/drivers/intel/fsp1_0/fastboot_cache.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/drivers/intel/fsp1_0/fastboot_cache.c b/src/drivers/intel/fsp1_0/fastboot_cache.c index 088c292e8d..34761a05be 100644 --- a/src/drivers/intel/fsp1_0/fastboot_cache.c +++ b/src/drivers/intel/fsp1_0/fastboot_cache.c @@ -65,13 +65,12 @@ static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr) } *mrc_region_ptr = NULL; return 0; - } else { - *mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache", - CBFS_TYPE_MRC_CACHE, - ®ion_size); - - return region_size; } + *mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache", + CBFS_TYPE_MRC_CACHE, + ®ion_size); + + return region_size; } /* From b53427156c8ccaa33b92a1cb73200cae11de7e58 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 9 Jun 2019 13:11:49 +0200 Subject: [PATCH 074/221] ec/google/chromeec/ec_lpc: Remove unneeded 'else' 'else' is not needed after a 'break' or 'return'. Change-Id: I98d0ab0d139186b312e8c1086c475ba6ef0b7d3b Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33333 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/ec/google/chromeec/ec_lpc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ec/google/chromeec/ec_lpc.c b/src/ec/google/chromeec/ec_lpc.c index 7293cffcd3..b7d183ebb0 100644 --- a/src/ec/google/chromeec/ec_lpc.c +++ b/src/ec/google/chromeec/ec_lpc.c @@ -188,11 +188,9 @@ static int google_chromeec_command_version(void) return EC_HOST_CMD_FLAG_VERSION_3; } else if (flags & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) { return EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED; - } else { - printk(BIOS_ERR, - "Chromium EC command version unsupported\n"); - return -1; } + printk(BIOS_ERR, "Chromium EC command version unsupported\n"); + return -1; } static int google_chromeec_command_v3(struct chromeec_command *cec_command) From 1ba0da17c831eb0b02b863d3a5e2df993a3962aa Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 9 Jun 2019 13:15:25 +0200 Subject: [PATCH 075/221] ec/kontron/kempld/kempld_i2c.c: Remove unneeded 'else' 'else' is not needed after a 'break' or 'return'. Change-Id: I0843bebe48e4b91fc76c440ae33bbca838621de9 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33334 Tested-by: build bot (Jenkins) Reviewed-by: Vlado Cibic Reviewed-by: Angel Pons --- src/ec/kontron/kempld/kempld_i2c.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ec/kontron/kempld/kempld_i2c.c b/src/ec/kontron/kempld/kempld_i2c.c index fdc0b50dfc..ab41097782 100644 --- a/src/ec/kontron/kempld/kempld_i2c.c +++ b/src/ec/kontron/kempld/kempld_i2c.c @@ -166,10 +166,9 @@ static int kempld_i2c_process(struct kempld_i2c_data *const i2c) if (!(msg->flags & I2C_M_NOSTART)) { i2c->state = STATE_ADDR; return 0; - } else { - i2c->state = (msg->flags & I2C_M_RD) - ? STATE_READ : STATE_WRITE; } + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; } else { i2c->state = STATE_DONE; kempld_write8(KEMPLD_I2C_CMD, I2C_CMD_STOP); From c166071beb95f8bcef65284b73e0a431a53e9033 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 9 Jun 2019 13:29:26 +0200 Subject: [PATCH 076/221] mb/google/snappy: Remove unneeded 'else' 'else' is not needed after a 'break' or 'return'. Change-Id: I7b6c319a58b9f4f47de19336d18d00b73d3d3772 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33335 Tested-by: build bot (Jenkins) Reviewed-by: Vlado Cibic Reviewed-by: Angel Pons --- src/mainboard/google/reef/variants/snappy/mainboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/reef/variants/snappy/mainboard.c b/src/mainboard/google/reef/variants/snappy/mainboard.c index 950a029459..b34b8e2c92 100644 --- a/src/mainboard/google/reef/variants/snappy/mainboard.c +++ b/src/mainboard/google/reef/variants/snappy/mainboard.c @@ -70,8 +70,8 @@ uint8_t variant_board_sku(void) if ((ch < '0') || (ch > '9')) { vpd_sku_num = -1; break; - } else - vpd_sku_num = vpd_sku_num * 10 + (ch - '0'); + } + vpd_sku_num = vpd_sku_num * 10 + (ch - '0'); } if (vpd_sku_num != -1) From 283b438f5ceaa88eb4860a5e1438b03c875bdf03 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 9 Jun 2019 13:31:36 +0200 Subject: [PATCH 077/221] soc/intel/common/block/pcr: Remove unneded 'else' 'else' is not needed after a 'break' or 'return'. Change-Id: Ib3371ef6edb85a47ed734dd2ff9ce94008aa4e65 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33336 Reviewed-by: Patrick Georgi Reviewed-by: Vlado Cibic Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- src/soc/intel/common/block/pcr/pcr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/soc/intel/common/block/pcr/pcr.c b/src/soc/intel/common/block/pcr/pcr.c index 4a35a03ff1..f3971c238f 100644 --- a/src/soc/intel/common/block/pcr/pcr.c +++ b/src/soc/intel/common/block/pcr/pcr.c @@ -394,10 +394,9 @@ int pcr_execute_sideband_msg(struct pcr_sbi_msg *msg, uint32_t *data, break; } return 0; - } else { - printk(BIOS_ERR, "SBI Failure: Transaction Status = %x\n", - *response); - return -1; } + printk(BIOS_ERR, "SBI Failure: Transaction Status = %x\n", + *response); + return -1; } #endif From adc3235eb7457ee1bed18817c1770627a8251ff4 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Thu, 6 Jun 2019 16:59:34 +0200 Subject: [PATCH 078/221] cpu/amd/family_10h-family_15h: Fix 'if' condition identical branches Change-Id: I1c937a62388c38090ee2cc3228973cfb8361bac7 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33257 Tested-by: build bot (Jenkins) Reviewed-by: Marshall Dawson --- src/cpu/amd/family_10h-family_15h/init_cpus.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cpu/amd/family_10h-family_15h/init_cpus.c b/src/cpu/amd/family_10h-family_15h/init_cpus.c index d6a4725e2e..f416d9ccdb 100644 --- a/src/cpu/amd/family_10h-family_15h/init_cpus.c +++ b/src/cpu/amd/family_10h-family_15h/init_cpus.c @@ -504,10 +504,9 @@ u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo) if (is_fam15h()) { /* core 1 on node 0 is special; to avoid corrupting the * BSP do not alter MTRRs on that core */ + fam15_bsp_core1_apicid = 1; if (CONFIG(ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0)) - fam15_bsp_core1_apicid = CONFIG_APIC_ID_OFFSET + 1; - else - fam15_bsp_core1_apicid = 1; + fam15_bsp_core1_apicid += CONFIG_APIC_ID_OFFSET; if (apicid == fam15_bsp_core1_apicid) set_mtrrs = 0; From 8d83c662c335c5c2961aabcf49d55ad47e9237ae Mon Sep 17 00:00:00 2001 From: Hung-Te Lin Date: Thu, 6 Jun 2019 09:40:57 +0800 Subject: [PATCH 079/221] google/kukui: Revise FMAP firmware layout Adjust FMAP sections that - ELOG only needs 4K (by driver limitation) - SHARED_DATA only needs 4K or less (for netboot params) - SMMSTORE is probably not needed since UEFI@ARM is not available yet - VPD can be smaller (most x86 devices have only 16/8K for RO/RW) - Increase RW_LEGACY to 1M (recommended value) - Move all new saved space to CBFS BUG=b:134624821 TEST=Built Kukui image and boots on Rev2 units. Change-Id: Id2910df73ea47bfa32e056d631d1c3e5f1eed0d1 Signed-off-by: Hung-Te Lin Reviewed-on: https://review.coreboot.org/c/coreboot/+/33239 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/mainboard/google/kukui/chromeos.fmd | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/mainboard/google/kukui/chromeos.fmd b/src/mainboard/google/kukui/chromeos.fmd index 23e55766c6..d183273549 100644 --- a/src/mainboard/google/kukui/chromeos.fmd +++ b/src/mainboard/google/kukui/chromeos.fmd @@ -1,30 +1,30 @@ FLASH@0x0 0x800000 { WP_RO@0x0 0x200000 { - RO_SECTION@0x0 0x1f0000 { + RO_SECTION@0x0 0x1f8000 { BOOTBLOCK@0 32K FMAP@0x8000 0x1000 - COREBOOT(CBFS)@0x9000 0x1e4000 - GBB@0x1ed000 0x2f00 - RO_FRID@0x1eff00 0x100 + COREBOOT(CBFS)@0x9000 0x1ec000 + GBB 0x2f00 + RO_FRID 0x100 } - RO_VPD(PRESERVE)@0x1f0000 0x10000 + RO_VPD(PRESERVE)@0x1f8000 0x8000 } - RW_SECTION_A@0x200000 0x78000 { + RW_SECTION_A@0x200000 0x7c000 { VBLOCK_A@0x0 0x2000 - FW_MAIN_A(CBFS)@0x2000 0x75f00 - RW_FWID_A@0x77f00 0x100 + FW_MAIN_A(CBFS) 0x79f00 + RW_FWID_A 0x100 } - RW_SHARED@0x278000 0x2000 { - SHARED_DATA@0x0 0x2000 + RW_SHARED@0x27c000 0x1000 { + SHARED_DATA@0x0 0x1000 } - RW_NVRAM(PRESERVE)@0x27a000 0x2000 - RW_ELOG(PRESERVE)@0x27c000 0x4000 - RW_SECTION_B@0x280000 0x78000 { + RW_NVRAM(PRESERVE)@0x27d000 0x2000 + # ELOG driver has hard-coded the size to 4k. + RW_ELOG(PRESERVE)@0x27f000 0x1000 + RW_SECTION_B@0x280000 0x7c000 { VBLOCK_B@0x0 0x2000 - FW_MAIN_B(CBFS)@0x2000 0x75f00 - RW_FWID_B@0x77f00 0x100 + FW_MAIN_B(CBFS) 0x79f00 + RW_FWID_B 0x100 } - RW_VPD(PRESERVE)@0x2f8000 0x8000 - SMMSTORE(PRESERVE)@0x300000 0x20000 - RW_LEGACY(CBFS)@0x320000 0xe0000 + RW_VPD(PRESERVE)@0x2fc000 0x4000 + RW_LEGACY(CBFS)@0x300000 0x100000 } From a2c6a0998599812de3e0413a0d86acf7fcbe7865 Mon Sep 17 00:00:00 2001 From: jg_poxu Date: Wed, 15 May 2019 11:36:45 +0800 Subject: [PATCH 080/221] mediatek/mt8183: Add efuse calibration in auxadc The values from auxadc may be incorrect if not calibrated by efuse. Without calibration, the value error range is about +/-50mv, and after being calibrated the error range is about +/-10mv. BUG=b:131391176 TEST=make clean && make test-abuild; boots on Kukui rev 2 units. BRANCH=none Change-Id: Iccd6ea0ad810c993f9b62c0974279c960f890e52 Signed-off-by: Po Xu Reviewed-on: https://review.coreboot.org/c/coreboot/+/32800 Reviewed-by: Julius Werner Reviewed-by: JG Poxu Tested-by: build bot (Jenkins) --- src/soc/mediatek/mt8183/auxadc.c | 37 ++++++++++++++++++- .../mediatek/mt8183/include/soc/addressmap.h | 1 + src/soc/mediatek/mt8183/include/soc/efuse.h | 30 +++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/soc/mediatek/mt8183/include/soc/efuse.h diff --git a/src/soc/mediatek/mt8183/auxadc.c b/src/soc/mediatek/mt8183/auxadc.c index a167d2b58e..5460486709 100644 --- a/src/soc/mediatek/mt8183/auxadc.c +++ b/src/soc/mediatek/mt8183/auxadc.c @@ -18,11 +18,37 @@ #include #include #include +#include #include #include static struct mtk_auxadc_regs *const mtk_auxadc = (void *)AUXADC_BASE; +#define ADC_GE_A_SHIFT 10 +#define ADC_GE_A_MASK (0x3ff << ADC_GE_A_SHIFT) +#define ADC_OE_A_SHIFT 0 +#define ADC_OE_A_MASK (0x3ff << ADC_OE_A_SHIFT) +#define ADC_CALI_EN_A_SHIFT 20 +#define ADC_CALI_EN_A_MASK (0x1 << ADC_CALI_EN_A_SHIFT) + +static int cali_oe; +static int cali_ge; +static int calibrated = 0; +static void mt_auxadc_update_cali(void) +{ + uint32_t cali_reg; + int cali_ge_a; + int cali_oe_a; + + cali_reg = read32(&mtk_efuse->adc_cali_reg); + + if ((cali_reg & ADC_CALI_EN_A_MASK) != 0) { + cali_oe_a = (cali_reg & ADC_OE_A_MASK) >> ADC_OE_A_SHIFT; + cali_ge_a = (cali_reg & ADC_GE_A_MASK) >> ADC_GE_A_SHIFT; + cali_ge = cali_ge_a - 512; + cali_oe = cali_oe_a - 512; + } +} static uint32_t auxadc_get_rawdata(int channel) { setbits_le32(&mt8183_infracfg->module_sw_cg_1_clr, 1 << 10); @@ -44,8 +70,17 @@ static uint32_t auxadc_get_rawdata(int channel) int auxadc_get_voltage(unsigned int channel) { + uint32_t raw_value; assert(channel < 16); + if (!calibrated) { + mt_auxadc_update_cali(); + calibrated = 1; + } + /* 1.5V in 4096 steps */ - return (int)((int64_t)auxadc_get_rawdata(channel) * 1500000 / 4096); + raw_value = auxadc_get_rawdata(channel); + + raw_value = raw_value - cali_oe; + return (int)((int64_t)raw_value * 1500000 / (4096 + cali_ge)); } diff --git a/src/soc/mediatek/mt8183/include/soc/addressmap.h b/src/soc/mediatek/mt8183/include/soc/addressmap.h index d41b2b942e..e9f80d1607 100644 --- a/src/soc/mediatek/mt8183/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8183/include/soc/addressmap.h @@ -50,6 +50,7 @@ enum { IOCFG_LB_BASE = IO_PHYS + 0x01E70000, IOCFG_LM_BASE = IO_PHYS + 0x01E80000, IOCFG_BL_BASE = IO_PHYS + 0x01E90000, + EFUSEC_BASE = IO_PHYS + 0x01F10000, IOCFG_LT_BASE = IO_PHYS + 0x01F20000, IOCFG_TL_BASE = IO_PHYS + 0x01F30000, SSUSB_SIF_BASE = IO_PHYS + 0x01F40300, diff --git a/src/soc/mediatek/mt8183/include/soc/efuse.h b/src/soc/mediatek/mt8183/include/soc/efuse.h new file mode 100644 index 0000000000..32126abc4e --- /dev/null +++ b/src/soc/mediatek/mt8183/include/soc/efuse.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 MediaTek 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. + */ + +#ifndef _MTK_EFUSE_H +#define _MTK_EFUSE_H + +#include +#include + +struct efuse_regs { + uint32_t rserved[109]; + uint32_t adc_cali_reg; +}; + +check_member(efuse_regs, adc_cali_reg, 0x1b4); +static struct efuse_regs *const mtk_efuse = (void *)EFUSEC_BASE; + +#endif From 10494c497f009721d09c5838e8a2fcb0e261128c Mon Sep 17 00:00:00 2001 From: You-Cheng Syu Date: Mon, 10 Jun 2019 17:17:49 +0800 Subject: [PATCH 081/221] mediatek/mt8183: Support RTC in ramstage We need to support RTC in ramstage so that we can see correct timestamp in ChromiumOS eventlog. BUG=b:134461866 TEST='mosys eventlog list' shows correct timestamp on Kukui Change-Id: Idb0fe5c05e4ecdf0e6398e3c781c71d14f85f19b Signed-off-by: You-Cheng Syu Reviewed-on: https://review.coreboot.org/c/coreboot/+/33355 Tested-by: build bot (Jenkins) Reviewed-by: Hung-Te Lin Reviewed-by: Julius Werner --- src/soc/mediatek/mt8183/Makefile.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/soc/mediatek/mt8183/Makefile.inc b/src/soc/mediatek/mt8183/Makefile.inc index 5392a9e635..d35a07ed59 100644 --- a/src/soc/mediatek/mt8183/Makefile.inc +++ b/src/soc/mediatek/mt8183/Makefile.inc @@ -45,6 +45,8 @@ ramstage-y += ../common/cbmem.c emi.c ramstage-y += ../common/gpio.c gpio.c ramstage-y += ../common/mmu_operations.c mmu_operations.c ramstage-y += ../common/mtcmos.c mtcmos.c +ramstage-y += ../common/pmic_wrap.c +ramstage-y += ../common/rtc.c rtc.c ramstage-y += soc.c ramstage-$(CONFIG_SPI_FLASH) += ../common/spi.c spi.c ramstage-y += ../common/timer.c From 4b47e5a851c5b21acb8d9ef6af245ccb332b14a7 Mon Sep 17 00:00:00 2001 From: You-Cheng Syu Date: Mon, 10 Jun 2019 17:17:51 +0800 Subject: [PATCH 082/221] google/kukui: Enable RTC Enable RTC so that we can see correct timestamp in CrOS eventlogs. BUG=b:134461866 TEST='mosys eventlog list' shows correct timestamp on Kukui Change-Id: Ie9ef7c9343c781e348429cd5376a4a5519641e16 Signed-off-by: You-Cheng Syu Reviewed-on: https://review.coreboot.org/c/coreboot/+/33356 Tested-by: build bot (Jenkins) Reviewed-by: Hung-Te Lin --- src/mainboard/google/kukui/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mainboard/google/kukui/Kconfig b/src/mainboard/google/kukui/Kconfig index 6831d1e729..7719506421 100644 --- a/src/mainboard/google/kukui/Kconfig +++ b/src/mainboard/google/kukui/Kconfig @@ -25,6 +25,7 @@ config VBOOT config BOARD_SPECIFIC_OPTIONS def_bool y + select RTC select SOC_MEDIATEK_MT8183 select BOARD_ROMSIZE_KB_8192 select MAINBOARD_HAS_CHROMEOS From 89b1753c2289edacca05ef46e840f212f2a3025d Mon Sep 17 00:00:00 2001 From: Mengqi Zhang Date: Wed, 24 Apr 2019 10:14:52 +0800 Subject: [PATCH 083/221] mediatek/mt8183: Add SPI GPIO driving setting Set SPI GPIO driving to support SPI FLASH. BUG=b:80501386 BRANCH=none TEST=emerge-kukui coreboot; emerge-elm coreboot Change-Id: I95002ec71abd751c33c089185db04ed4a8686699 Signed-off-by: Mengqi Zhang Reviewed-on: https://review.coreboot.org/c/coreboot/+/32460 Reviewed-by: Hung-Te Lin Reviewed-by: Julius Werner Tested-by: build bot (Jenkins) --- src/mainboard/google/kukui/bootblock.c | 3 ++ src/soc/mediatek/mt8183/gpio.c | 55 ++++++++++++++++++++++ src/soc/mediatek/mt8183/include/soc/gpio.h | 3 ++ 3 files changed, 61 insertions(+) diff --git a/src/mainboard/google/kukui/bootblock.c b/src/mainboard/google/kukui/bootblock.c index 9d6c38ba64..9a7e71c292 100644 --- a/src/mainboard/google/kukui/bootblock.c +++ b/src/mainboard/google/kukui/bootblock.c @@ -15,9 +15,12 @@ #include #include +#include void bootblock_mainboard_init(void) { mtk_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, SPI_PAD0_MASK, 6 * MHz); mtk_spi_init(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, SPI_PAD0_MASK, 26 * MHz); + gpio_set_spi_driving(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, SPI_PAD0_MASK, + 10); } diff --git a/src/soc/mediatek/mt8183/gpio.c b/src/soc/mediatek/mt8183/gpio.c index 327d389eb2..3eccfbd50d 100644 --- a/src/soc/mediatek/mt8183/gpio.c +++ b/src/soc/mediatek/mt8183/gpio.c @@ -15,11 +15,15 @@ #include #include +#include +#include enum { EN_OFFSET = 0x60, SEL_OFFSET = 0x80, EH_RSEL_OFFSET = 0xF0, + GPIO_DRV0_OFFSET = 0xA0, + GPIO_DRV1_OFFSET = 0XB0, }; static void gpio_set_pull_pupd(gpio_t gpio, enum pull_enable enable, @@ -128,3 +132,54 @@ void gpio_set_i2c_eh_rsel(void) I2C_EH_RSL_MASK(SCL5) | I2C_EH_RSL_MASK(SDA5), I2C_EH_RSL_VAL(SCL5) | I2C_EH_RSL_VAL(SDA5)); } + +void gpio_set_spi_driving(unsigned int bus, enum spi_pad_mask pad_select, + unsigned int milliamps) +{ + void *reg = NULL; + unsigned int reg_val = milliamps / 2 - 1, offset = 0; + + assert(bus < SPI_BUS_NUMBER); + assert(milliamps >= 2 && milliamps <= 16); + assert(pad_select <= SPI_PAD1_MASK); + + switch (bus) { + case 0: + reg = (void *)(IOCFG_RB_BASE + GPIO_DRV1_OFFSET); + offset = 0; + break; + case 1: + if (pad_select == SPI_PAD0_MASK) { + reg = (void *)(IOCFG_LM_BASE + GPIO_DRV0_OFFSET); + offset = 0; + } else if (pad_select == SPI_PAD1_MASK) { + clrsetbits_le32((void *)IOCFG_RM_BASE + + GPIO_DRV0_OFFSET, 0xf | 0xf << 20, + reg_val | reg_val << 20); + clrsetbits_le32((void *)IOCFG_RM_BASE + + GPIO_DRV1_OFFSET, 0xf << 16, + reg_val << 16); + return; + } + break; + case 2: + clrsetbits_le32((void *)IOCFG_RM_BASE + GPIO_DRV0_OFFSET, + 0xf << 8 | 0xf << 12, + reg_val << 8 | reg_val << 12); + return; + case 3: + reg = (void *)(IOCFG_LM_BASE + GPIO_DRV0_OFFSET); + offset = 16; + break; + case 4: + reg = (void *)(IOCFG_LM_BASE + GPIO_DRV0_OFFSET); + offset = 12; + break; + case 5: + reg = (void *)(IOCFG_LM_BASE + GPIO_DRV0_OFFSET); + offset = 8; + break; + } + + clrsetbits_le32(reg, 0xf << offset, reg_val << offset); +} diff --git a/src/soc/mediatek/mt8183/include/soc/gpio.h b/src/soc/mediatek/mt8183/include/soc/gpio.h index 5a98953974..a0d6262abb 100644 --- a/src/soc/mediatek/mt8183/include/soc/gpio.h +++ b/src/soc/mediatek/mt8183/include/soc/gpio.h @@ -19,6 +19,7 @@ #include #include #include +#include enum { MAX_GPIO_REG_BITS = 32, @@ -617,5 +618,7 @@ check_member(gpio_regs, mode[22].val, 0x460); static struct gpio_regs *const mtk_gpio = (void *)(GPIO_BASE); void gpio_set_i2c_eh_rsel(void); +void gpio_set_spi_driving(unsigned int bus, enum spi_pad_mask pad_select, + unsigned int milliamps); #endif From 026be3d76f3934eb901485acd98e0d84f137068f Mon Sep 17 00:00:00 2001 From: Mengqi Zhang Date: Wed, 24 Apr 2019 11:11:52 +0800 Subject: [PATCH 084/221] mediatek: Add SPI tick_dly setting Add spi tick_dly setting for high-speed spi xfer. BUG=b:80501386 BRANCH=none TEST=emerge-kukui coreboot; emerge-elm coreboot Change-Id: Ie49fc3efe2a4a6dcdf2a2fc4c91b47e35d4f086e Signed-off-by: Mengqi Zhang Reviewed-on: https://review.coreboot.org/c/coreboot/+/32461 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/mainboard/google/kukui/bootblock.c | 7 +++++-- src/mainboard/google/kukui/early_init.c | 2 +- src/mainboard/google/oak/bootblock.c | 3 ++- src/soc/mediatek/common/include/soc/spi_common.h | 5 +++-- src/soc/mediatek/common/spi.c | 4 ++-- src/soc/mediatek/mt8173/include/soc/spi.h | 5 +++++ src/soc/mediatek/mt8173/spi.c | 7 +++++-- src/soc/mediatek/mt8183/include/soc/spi.h | 5 +++++ src/soc/mediatek/mt8183/spi.c | 7 +++++-- 9 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/mainboard/google/kukui/bootblock.c b/src/mainboard/google/kukui/bootblock.c index 9a7e71c292..ebd1e18d15 100644 --- a/src/mainboard/google/kukui/bootblock.c +++ b/src/mainboard/google/kukui/bootblock.c @@ -19,8 +19,11 @@ void bootblock_mainboard_init(void) { - mtk_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, SPI_PAD0_MASK, 6 * MHz); - mtk_spi_init(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, SPI_PAD0_MASK, 26 * MHz); + mtk_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, SPI_PAD0_MASK, 6 * MHz, + 0); + mtk_spi_init(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, SPI_PAD0_MASK, 26 * MHz, + 0); gpio_set_spi_driving(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, SPI_PAD0_MASK, 10); + } diff --git a/src/mainboard/google/kukui/early_init.c b/src/mainboard/google/kukui/early_init.c index 1193bb3fe9..7eee080412 100644 --- a/src/mainboard/google/kukui/early_init.c +++ b/src/mainboard/google/kukui/early_init.c @@ -34,6 +34,6 @@ void mainboard_early_init(void) gpio_set_mode(AP_IN_SLEEP_L, PAD_SRCLKENA0_FUNC_SRCLKENA0); - mtk_spi_init(CONFIG_DRIVER_TPM_SPI_BUS, SPI_PAD0_MASK, 1 * MHz); + mtk_spi_init(CONFIG_DRIVER_TPM_SPI_BUS, SPI_PAD0_MASK, 1 * MHz, 0); gpio_eint_configure(CR50_IRQ, IRQ_TYPE_EDGE_RISING); } diff --git a/src/mainboard/google/oak/bootblock.c b/src/mainboard/google/oak/bootblock.c index 3c50389914..89169ef0bf 100644 --- a/src/mainboard/google/oak/bootblock.c +++ b/src/mainboard/google/oak/bootblock.c @@ -89,7 +89,8 @@ void bootblock_mainboard_init(void) if (CONFIG(OAK_HAS_TPM2)) gpio_eint_configure(CR50_IRQ, IRQ_TYPE_EDGE_RISING); - mtk_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, SPI_PAD1_MASK, 6*MHz); + mtk_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, SPI_PAD1_MASK, 6*MHz, + 0); setup_chromeos_gpios(); diff --git a/src/soc/mediatek/common/include/soc/spi_common.h b/src/soc/mediatek/common/include/soc/spi_common.h index 162db59f94..81a9098180 100644 --- a/src/soc/mediatek/common/include/soc/spi_common.h +++ b/src/soc/mediatek/common/include/soc/spi_common.h @@ -84,8 +84,9 @@ extern struct mtk_spi_bus spi_bus[]; void mtk_spi_set_gpio_pinmux(unsigned int bus, enum spi_pad_mask pad_select); -void mtk_spi_set_timing(struct mtk_spi_regs *regs, u32 sck_ticks, u32 cs_ticks); +void mtk_spi_set_timing(struct mtk_spi_regs *regs, u32 sck_ticks, u32 cs_ticks, + unsigned int tick_dly); void mtk_spi_init(unsigned int bus, enum spi_pad_mask pad_select, - unsigned int speed_hz); + unsigned int speed_hz, unsigned int tick_dly); #endif diff --git a/src/soc/mediatek/common/spi.c b/src/soc/mediatek/common/spi.c index 71ed95a228..1af6f105c3 100644 --- a/src/soc/mediatek/common/spi.c +++ b/src/soc/mediatek/common/spi.c @@ -53,7 +53,7 @@ static void spi_sw_reset(struct mtk_spi_regs *regs) } void mtk_spi_init(unsigned int bus, enum spi_pad_mask pad_select, - unsigned int speed_hz) + unsigned int speed_hz, unsigned int tick_dly) { u32 div, sck_ticks, cs_ticks; @@ -73,7 +73,7 @@ void mtk_spi_init(unsigned int bus, enum spi_pad_mask pad_select, printk(BIOS_DEBUG, "SPI%u(PAD%u) initialized at %u Hz\n", bus, pad_select, SPI_HZ / (sck_ticks * 2)); - mtk_spi_set_timing(regs, sck_ticks, cs_ticks); + mtk_spi_set_timing(regs, sck_ticks, cs_ticks, tick_dly); clrsetbits_le32(®s->spi_cmd_reg, (SPI_CMD_CPHA_EN | SPI_CMD_CPOL_EN | diff --git a/src/soc/mediatek/mt8173/include/soc/spi.h b/src/soc/mediatek/mt8173/include/soc/spi.h index aaef3aa25c..58bf517f9d 100644 --- a/src/soc/mediatek/mt8173/include/soc/spi.h +++ b/src/soc/mediatek/mt8173/include/soc/spi.h @@ -43,4 +43,9 @@ enum { SPI_CFG0_CS_SETUP_SHIFT = 24, }; +enum { + SPI_CFG1_TICK_DLY_SHIFT = 30, + SPI_CFG1_TICK_DLY_MASK = 0x3 << SPI_CFG1_TICK_DLY_SHIFT, +}; + #endif diff --git a/src/soc/mediatek/mt8173/spi.c b/src/soc/mediatek/mt8173/spi.c index 0cc8377ff4..d0094418b8 100644 --- a/src/soc/mediatek/mt8173/spi.c +++ b/src/soc/mediatek/mt8173/spi.c @@ -38,14 +38,17 @@ void mtk_spi_set_gpio_pinmux(unsigned int bus, gpio_set_mode(GPIO(MSDC2_CMD), PAD_MSDC2_CMD_FUNC_SPI_CS_1); } -void mtk_spi_set_timing(struct mtk_spi_regs *regs, u32 sck_ticks, u32 cs_ticks) +void mtk_spi_set_timing(struct mtk_spi_regs *regs, u32 sck_ticks, u32 cs_ticks, + unsigned int tick_dly) { write32(®s->spi_cfg0_reg, ((sck_ticks - 1) << SPI_CFG0_SCK_HIGH_SHIFT) | ((sck_ticks - 1) << SPI_CFG0_SCK_LOW_SHIFT) | ((cs_ticks - 1) << SPI_CFG0_CS_HOLD_SHIFT) | ((cs_ticks - 1) << SPI_CFG0_CS_SETUP_SHIFT)); - clrsetbits_le32(®s->spi_cfg1_reg, SPI_CFG1_CS_IDLE_MASK, + clrsetbits_le32(®s->spi_cfg1_reg, SPI_CFG1_CS_IDLE_MASK | + SPI_CFG1_TICK_DLY_MASK, + (tick_dly << SPI_CFG1_TICK_DLY_SHIFT) | ((cs_ticks - 1) << SPI_CFG1_CS_IDLE_SHIFT)); } diff --git a/src/soc/mediatek/mt8183/include/soc/spi.h b/src/soc/mediatek/mt8183/include/soc/spi.h index 9bc7121847..f718081f67 100644 --- a/src/soc/mediatek/mt8183/include/soc/spi.h +++ b/src/soc/mediatek/mt8183/include/soc/spi.h @@ -49,5 +49,10 @@ enum { SPI_CFG2_SCK_HIGH_SHIFT = 16, }; +enum { + SPI_CFG1_TICK_DLY_SHIFT = 29, + SPI_CFG1_TICK_DLY_MASK = 0x7 << SPI_CFG1_TICK_DLY_SHIFT, + +}; #endif diff --git a/src/soc/mediatek/mt8183/spi.c b/src/soc/mediatek/mt8183/spi.c index a79dafba94..982f6439ed 100644 --- a/src/soc/mediatek/mt8183/spi.c +++ b/src/soc/mediatek/mt8183/spi.c @@ -109,7 +109,8 @@ void mtk_spi_set_gpio_pinmux(unsigned int bus, enum spi_pad_mask pad_select) gpio_set_mode((gpio_t){.id = ptr[i].pin_id}, ptr[i].func); } -void mtk_spi_set_timing(struct mtk_spi_regs *regs, u32 sck_ticks, u32 cs_ticks) +void mtk_spi_set_timing(struct mtk_spi_regs *regs, u32 sck_ticks, u32 cs_ticks, + unsigned int tick_dly) { write32(®s->spi_cfg0_reg, ((cs_ticks - 1) << SPI_CFG0_CS_HOLD_SHIFT) | @@ -119,7 +120,9 @@ void mtk_spi_set_timing(struct mtk_spi_regs *regs, u32 sck_ticks, u32 cs_ticks) ((sck_ticks - 1) << SPI_CFG2_SCK_HIGH_SHIFT) | ((sck_ticks - 1) << SPI_CFG2_SCK_LOW_SHIFT)); - clrsetbits_le32(®s->spi_cfg1_reg, SPI_CFG1_CS_IDLE_MASK, + clrsetbits_le32(®s->spi_cfg1_reg, SPI_CFG1_TICK_DLY_MASK | + SPI_CFG1_CS_IDLE_MASK, + (tick_dly << SPI_CFG1_TICK_DLY_SHIFT) | ((cs_ticks - 1) << SPI_CFG1_CS_IDLE_SHIFT)); } From fbeec122c03af689631b64c13f947f871963b79a Mon Sep 17 00:00:00 2001 From: Mengqi Zhang Date: Wed, 24 Apr 2019 11:26:30 +0800 Subject: [PATCH 085/221] google/kukui: Increase SPI flash speed to boot faster Increase SPI flash speed from 26MHz to 56MHz and set correct tick_dly to get faster boot process. BUG=b:80501386 BRANCH=none TEST=emerge-kukui coreboot; emerge-elm coreboot Change-Id: I8f44883b4f4a198146330caf5420dc39d5592a0a Signed-off-by: Mengqi Zhang Reviewed-on: https://review.coreboot.org/c/coreboot/+/32462 Reviewed-by: Hung-Te Lin Reviewed-by: Patrick Georgi Tested-by: build bot (Jenkins) --- src/mainboard/google/kukui/bootblock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/kukui/bootblock.c b/src/mainboard/google/kukui/bootblock.c index ebd1e18d15..61f30aff44 100644 --- a/src/mainboard/google/kukui/bootblock.c +++ b/src/mainboard/google/kukui/bootblock.c @@ -21,8 +21,8 @@ void bootblock_mainboard_init(void) { mtk_spi_init(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS, SPI_PAD0_MASK, 6 * MHz, 0); - mtk_spi_init(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, SPI_PAD0_MASK, 26 * MHz, - 0); + mtk_spi_init(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, SPI_PAD0_MASK, 56 * MHz, + 2); gpio_set_spi_driving(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, SPI_PAD0_MASK, 10); From 37fedc0414af6e5e2daccef5caa4b37632699f15 Mon Sep 17 00:00:00 2001 From: Mario Scheithauer Date: Mon, 3 Jun 2019 16:35:25 +0200 Subject: [PATCH 086/221] siemens/mc_apl5: Enable TPM support This patch enables TPM on SPI and adds the needed devicetree entry for mc_apl5. TEST=Build coreboot for mc_apl5 board and check the TPM console output. In addition the TPM was correctly verified by our Linux driver. Change-Id: Iafc967c7a2bfee9bdb9b6591d12328620e2887cc Signed-off-by: Mario Scheithauer Reviewed-on: https://review.coreboot.org/c/coreboot/+/33173 Reviewed-by: Patrick Georgi Reviewed-by: Werner Zeh Tested-by: build bot (Jenkins) --- src/mainboard/siemens/mc_apl1/variants/mc_apl5/Kconfig | 3 +++ .../siemens/mc_apl1/variants/mc_apl5/devicetree.cb | 6 +++++- src/mainboard/siemens/mc_apl1/variants/mc_apl5/gpio.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/mainboard/siemens/mc_apl1/variants/mc_apl5/Kconfig b/src/mainboard/siemens/mc_apl1/variants/mc_apl5/Kconfig index 196176c4fd..4a4b6cc604 100644 --- a/src/mainboard/siemens/mc_apl1/variants/mc_apl5/Kconfig +++ b/src/mainboard/siemens/mc_apl1/variants/mc_apl5/Kconfig @@ -8,5 +8,8 @@ config BOARD_SPECIFIC_OPTIONS select DRIVER_SIEMENS_NC_FPGA select NC_FPGA_NOTIFY_CB_READY select APL_SKIP_SET_POWER_LIMITS + select MAINBOARD_HAS_TPM2 + select MAINBOARD_HAS_LPC_TPM + select TPM_ON_FAST_SPI endif # BOARD_SIEMENS_MC_APL5 diff --git a/src/mainboard/siemens/mc_apl1/variants/mc_apl5/devicetree.cb b/src/mainboard/siemens/mc_apl1/variants/mc_apl5/devicetree.cb index f1ed5d2e15..5f1c9857d4 100644 --- a/src/mainboard/siemens/mc_apl1/variants/mc_apl5/devicetree.cb +++ b/src/mainboard/siemens/mc_apl1/variants/mc_apl5/devicetree.cb @@ -104,7 +104,11 @@ chip soc/intel/apollolake device pci 1c.0 on end # - eMMC device pci 1d.0 off end # - UFS device pci 1e.0 off end # - SDIO - device pci 1f.0 on end # - LPC + device pci 1f.0 on # - LPC + chip drivers/pc80/tpm + device pnp 0c31.0 on end + end + end device pci 1f.1 on end # - SMBUS end end diff --git a/src/mainboard/siemens/mc_apl1/variants/mc_apl5/gpio.c b/src/mainboard/siemens/mc_apl1/variants/mc_apl5/gpio.c index 7a424d131e..f9b258d199 100644 --- a/src/mainboard/siemens/mc_apl1/variants/mc_apl5/gpio.c +++ b/src/mainboard/siemens/mc_apl1/variants/mc_apl5/gpio.c @@ -254,7 +254,7 @@ static const struct pad_config gpio_table[] = { /* SIO_SPI_0 -- unused */ PAD_CFG_GPI(GPIO_104, DN_20K, DEEP), /* GP_SSP_0_CLK */ PAD_CFG_GPI(GPIO_105, DN_20K, DEEP), /* GP_SSP_0_FS0 */ - PAD_CFG_GPI(GPIO_106, UP_20K, DEEP), /* GP_SSP_0_FS1 */ + PAD_CFG_NF(GPIO_106, NATIVE, DEEP, NF3), /* FST_SPI_CS2_N */ PAD_CFG_GPI(GPIO_109, DN_20K, DEEP), /* GP_SSP_0_RXD */ PAD_CFG_GPI(GPIO_110, DN_20K, DEEP), /* GP_SSP_0_TXD */ From aa5e8e099e83647cd6347bcbc82e2c11a6cac1d7 Mon Sep 17 00:00:00 2001 From: Mario Scheithauer Date: Tue, 4 Jun 2019 13:43:32 +0200 Subject: [PATCH 087/221] siemens/mc_apl5: Change PTN interface settings Switch the default clock output for single LVDS mode to odd bus only. Change-Id: I278e761566a112d95cbd6c79e09c076d70b93e8f Signed-off-by: Mario Scheithauer Reviewed-on: https://review.coreboot.org/c/coreboot/+/33196 Tested-by: build bot (Jenkins) Reviewed-by: Werner Zeh --- src/mainboard/siemens/mc_apl1/variants/mc_apl5/ptn3460.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mainboard/siemens/mc_apl1/variants/mc_apl5/ptn3460.c b/src/mainboard/siemens/mc_apl1/variants/mc_apl5/ptn3460.c index c0770f3124..f6fed97551 100644 --- a/src/mainboard/siemens/mc_apl1/variants/mc_apl5/ptn3460.c +++ b/src/mainboard/siemens/mc_apl1/variants/mc_apl5/ptn3460.c @@ -76,7 +76,8 @@ int ptn3460_init(const char *hwi_block) return (PTN_BUS_ERROR | status); /* Set up configuration data according to the hwinfo block we get. */ cfg.dp_interface_ctrl = 0; - cfg.lvds_interface_ctrl1 = 0x00; + /* Drive LVDS clock for single mode on odd bus per default. */ + cfg.lvds_interface_ctrl1 = 0x01; if (disp_con == PF_DISPLCON_LVDS_DUAL) /* Turn on dual LVDS lane and clock. */ cfg.lvds_interface_ctrl1 |= 0x0b; From f6317b4892d8d295312ffd7a8b4caccf2610c25e Mon Sep 17 00:00:00 2001 From: Hung-Te Lin Date: Wed, 12 Jun 2019 16:59:24 +0800 Subject: [PATCH 088/221] src/driver/vpd: Update vpd_decode from upstream The upstream vpd_decode.c has been revised to prevent overrun of decoded contents. BUG=chromium:967209 TEST=select VPD config on kukui; make; boots on at least kukui boards. Change-Id: I1a50670a66b7b174d2a432c29d90152b86c32982 Signed-off-by: Hung-Te Lin Reviewed-on: https://review.coreboot.org/c/coreboot/+/33414 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/drivers/vpd/vpd_decode.c | 51 ++++++++++++++++++++---------------- src/drivers/vpd/vpd_decode.h | 21 ++------------- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/src/drivers/vpd/vpd_decode.c b/src/drivers/vpd/vpd_decode.c index 0eab704ca8..527c50818e 100644 --- a/src/drivers/vpd/vpd_decode.c +++ b/src/drivers/vpd/vpd_decode.c @@ -8,7 +8,7 @@ */ #include "vpd_decode.h" -int vpd_decode_len( +static int vpd_decode_len( const u32 max_len, const u8 *in, u32 *length, u32 *decoded_len) { u8 more; @@ -32,15 +32,36 @@ int vpd_decode_len( return VPD_DECODE_OK; } +static int vpd_decode_entry( + const u32 max_len, const u8 *input_buf, u32 *consumed, + const u8 **entry, u32 *entry_len) +{ + u32 decoded_len; + + if (vpd_decode_len(max_len - *consumed, &input_buf[*consumed], + entry_len, &decoded_len) != VPD_DECODE_OK) + return VPD_DECODE_FAIL; + if (max_len - *consumed < decoded_len) + return VPD_DECODE_FAIL; + + *consumed += decoded_len; + *entry = input_buf + *consumed; + + /* entry_len is untrusted data and must be checked again. */ + if (max_len - *consumed < *entry_len) + return VPD_DECODE_FAIL; + + *consumed += *entry_len; + return VPD_DECODE_OK; +} + int vpd_decode_string( const u32 max_len, const u8 *input_buf, u32 *consumed, vpd_decode_callback callback, void *callback_arg) { int type; - int res; u32 key_len; u32 value_len; - u32 decoded_len; const u8 *key; const u8 *value; @@ -55,30 +76,14 @@ int vpd_decode_string( case VPD_TYPE_STRING: (*consumed)++; - /* key */ - res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed], - &key_len, &decoded_len); - /* key name cannot be empty, and must be followed by value. */ - if (res != VPD_DECODE_OK || key_len < 1 || - *consumed + decoded_len + key_len >= max_len) + if (vpd_decode_entry(max_len, input_buf, consumed, &key, + &key_len) != VPD_DECODE_OK) return VPD_DECODE_FAIL; - *consumed += decoded_len; - key = &input_buf[*consumed]; - *consumed += key_len; - - /* value */ - res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed], - &value_len, &decoded_len); - /* value can be empty (value_len = 0). */ - if (res != VPD_DECODE_OK || - *consumed + decoded_len + value_len > max_len) + if (vpd_decode_entry(max_len, input_buf, consumed, &value, + &value_len) != VPD_DECODE_OK) return VPD_DECODE_FAIL; - *consumed += decoded_len; - value = &input_buf[*consumed]; - *consumed += value_len; - if (type == VPD_TYPE_STRING) return callback(key, key_len, value, value_len, callback_arg); diff --git a/src/drivers/vpd/vpd_decode.h b/src/drivers/vpd/vpd_decode.h index 99ca7efa81..5d595f367f 100644 --- a/src/drivers/vpd/vpd_decode.h +++ b/src/drivers/vpd/vpd_decode.h @@ -29,29 +29,12 @@ typedef int vpd_decode_callback( const u8 *key, u32 key_len, const u8 *value, u32 value_len, void *arg); -/* - * vpd_decode_len - * - * Given an encoded string, this function extracts the length of content - * (either key or value). The *consumed will contain the number of bytes - * consumed. - * - * The input_buf points to the first byte of the input buffer. - * - * The *consumed starts from 0, which is actually the next byte to be decoded. - * It can be non-zero to be used in multiple calls. - * - * Returns VPD_DECODE_OK on success, otherwise VPD_DECODE_FAIL. - */ -int vpd_decode_len( - const u32 max_len, const u8 *in, u32 *length, u32 *decoded_len); - /* * vpd_decode_string * * Given the encoded string, this function invokes callback with extracted - * (key, value). The *consumed will be plused the number of bytes consumed in - * this function. + * (key, value). The *consumed will be incremented by the number of bytes + * consumed in this function. * * The input_buf points to the first byte of the input buffer. * From e621d8f11a2bdad4920cbb7c4293fdfd98adf4bd Mon Sep 17 00:00:00 2001 From: Weiyi Lu Date: Tue, 19 Mar 2019 13:39:12 +0800 Subject: [PATCH 089/221] mediatek/mt8183: Add infra group DCM setting Add infra group DCM (Dynamic Clock Management) settings, which slows down OR gate clocks while hardware is in idle state. BUG=b:80501386 BRANCH=none TEST=Boots correctly on Kukui. Change-Id: I4741dfb7b984deb92171f370e5fb2593829d74c2 Signed-off-by: Weiyi Lu Reviewed-on: https://review.coreboot.org/c/coreboot/+/31977 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner Reviewed-by: You-Cheng Syu --- src/soc/mediatek/mt8183/include/soc/pll.h | 9 +++++++++ src/soc/mediatek/mt8183/pll.c | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/src/soc/mediatek/mt8183/include/soc/pll.h b/src/soc/mediatek/mt8183/include/soc/pll.h index 2a72e2c61c..3807e0087e 100644 --- a/src/soc/mediatek/mt8183/include/soc/pll.h +++ b/src/soc/mediatek/mt8183/include/soc/pll.h @@ -270,4 +270,13 @@ enum { SPI_HZ = MAINPLL_D5_D2_HZ, }; +enum { + DCM_INFRA_BUS_MASK = 0x40907ffb, + DCM_INFRA_BUS_ON = 0x40904203, + DCM_INFRA_MEM_ON = 0x1 << 27, + DCM_INFRA_P2PRX_MASK = 0xf, + DCM_INFRA_PERI_MASK = 0xf03ffffb, + DCM_INFRA_PERI_ON = 0xf03f83e3, +}; + #endif /* SOC_MEDIATEK_MT8183_PLL_H */ diff --git a/src/soc/mediatek/mt8183/pll.c b/src/soc/mediatek/mt8183/pll.c index 07ce6603f6..5368077318 100644 --- a/src/soc/mediatek/mt8183/pll.c +++ b/src/soc/mediatek/mt8183/pll.c @@ -344,6 +344,12 @@ void mt_pll_init(void) /* enable infrasys DCM */ setbits_le32(&mt8183_infracfg->infra_bus_dcm_ctrl, 0x3 << 21); + clrsetbits_le32(&mt8183_infracfg->infra_bus_dcm_ctrl, + DCM_INFRA_BUS_MASK, DCM_INFRA_BUS_ON); + setbits_le32(&mt8183_infracfg->mem_dcm_ctrl, DCM_INFRA_MEM_ON); + clrbits_le32(&mt8183_infracfg->p2p_rx_clk_on, DCM_INFRA_P2PRX_MASK); + clrsetbits_le32(&mt8183_infracfg->peri_bus_dcm_ctrl, + DCM_INFRA_PERI_MASK, DCM_INFRA_PERI_ON); /* enable [11] for change i2c module source clock to TOPCKGEN */ setbits_le32(&mt8183_infracfg->module_clk_sel, 0x1 << 11); From 7c05d2a6411ed11fa98fb7e85725c0b5dc82c442 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Thu, 13 Jun 2019 15:46:12 +0200 Subject: [PATCH 090/221] security/tpm/Makefile.inc: Remove VBOOT dependency for tss files in postcar tss_marshaling.c and tss.c depends on VBOOT for postcar. Eltan vendorcode used function in these file, but has VBOOT disabled. Remove depency of VBOOT for postcar fo tss/tcg-2.0/tss-marshaling.c and tss/tcg-2.0/tss.c BUG=N/A TEST=Created binary and verify logging on Facebook FBG-1701 Change-Id: I195c79283abf403208f406518372bf52289772ed Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33444 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/security/tpm/Makefile.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/security/tpm/Makefile.inc b/src/security/tpm/Makefile.inc index c05fb55a88..a2d32cff89 100644 --- a/src/security/tpm/Makefile.inc +++ b/src/security/tpm/Makefile.inc @@ -36,8 +36,8 @@ romstage-y += tss/tcg-2.0/tss.c verstage-$(CONFIG_VBOOT) += tss/tcg-2.0/tss_marshaling.c verstage-$(CONFIG_VBOOT) += tss/tcg-2.0/tss.c -postcar-$(CONFIG_VBOOT) += tss/tcg-2.0/tss_marshaling.c -postcar-$(CONFIG_VBOOT) += tss/tcg-2.0/tss.c +postcar-y += tss/tcg-2.0/tss_marshaling.c +postcar-y += tss/tcg-2.0/tss.c ## TSPI From 04326aabcdccabf83064d585758c6d635b9f1a3b Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 28 May 2019 10:00:05 +0200 Subject: [PATCH 091/221] sb/intel/ibexpeak/smihandler: Move finalizing to a common location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO: There is no reason to do this in SMM. Change-Id: I8bbb2f65bbe674bd1bc4ae8a4086bd1f5e9a79fa Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33139 Reviewed-by: Kyösti Mälkki Reviewed-by: HAOUAS Elyes Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- src/mainboard/lenovo/x201/smihandler.c | 19 ------------------- src/mainboard/packardbell/ms2290/smihandler.c | 19 ------------------- src/southbridge/intel/ibexpeak/smihandler.c | 7 +++++++ 3 files changed, 7 insertions(+), 38 deletions(-) diff --git a/src/mainboard/lenovo/x201/smihandler.c b/src/mainboard/lenovo/x201/smihandler.c index fc6a0e9670..9043f8e18c 100644 --- a/src/mainboard/lenovo/x201/smihandler.c +++ b/src/mainboard/lenovo/x201/smihandler.c @@ -20,10 +20,7 @@ #include #include #include -#include -#include #include -#include #include #include #include @@ -135,25 +132,9 @@ void mainboard_smi_gpi(u32 gpi_sts) mainboard_smi_handle_ec_sci(); } -static int mainboard_finalized = 0; - int mainboard_smi_apmc(u8 data) { switch (data) { - case APM_CNT_FINALIZE: - printk(BIOS_DEBUG, "APMC: FINALIZE\n"); - if (mainboard_finalized) { - printk(BIOS_DEBUG, "APMC#: Already finalized\n"); - return 0; - } - - intel_me_finalize_smm(); - intel_pch_finalize_smm(); - intel_nehalem_finalize_smm(); - intel_model_2065x_finalize_smm(); - - mainboard_finalized = 1; - break; case APM_CNT_ACPI_ENABLE: /* use 0x1600/0x1604 to prevent races with userspace */ ec_set_ports(0x1604, 0x1600); diff --git a/src/mainboard/packardbell/ms2290/smihandler.c b/src/mainboard/packardbell/ms2290/smihandler.c index 83562be921..dfc66f98cf 100644 --- a/src/mainboard/packardbell/ms2290/smihandler.c +++ b/src/mainboard/packardbell/ms2290/smihandler.c @@ -18,11 +18,8 @@ #include #include #include -#include -#include #include #include -#include #include static void mainboard_smm_init(void) @@ -54,26 +51,10 @@ void mainboard_smi_gpi(u32 gpi_sts) { } -static int mainboard_finalized = 0; - int mainboard_smi_apmc(u8 data) { u8 tmp; switch (data) { - case APM_CNT_FINALIZE: - printk(BIOS_DEBUG, "APMC: FINALIZE\n"); - if (mainboard_finalized) { - printk(BIOS_DEBUG, "APMC#: Already finalized\n"); - return 0; - } - - intel_me_finalize_smm(); - intel_pch_finalize_smm(); - intel_nehalem_finalize_smm(); - intel_model_2065x_finalize_smm(); - - mainboard_finalized = 1; - break; case APM_CNT_ACPI_ENABLE: tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb); tmp &= ~0x03; diff --git a/src/southbridge/intel/ibexpeak/smihandler.c b/src/southbridge/intel/ibexpeak/smihandler.c index dbc412c072..208075bbea 100644 --- a/src/southbridge/intel/ibexpeak/smihandler.c +++ b/src/southbridge/intel/ibexpeak/smihandler.c @@ -24,7 +24,10 @@ #include #include #include +#include +#include #include +#include #include "pch.h" #include "nvs.h" @@ -182,4 +185,8 @@ void southbridge_update_gnvs(u8 apm_cnt, int *smm_done) void southbridge_finalize_all(void) { + intel_me_finalize_smm(); + intel_pch_finalize_smm(); + intel_nehalem_finalize_smm(); + intel_model_2065x_finalize_smm(); } From 4c0d5cbb87df54897601d1b19dd5d2f7f4907eb4 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 28 May 2019 10:04:20 +0200 Subject: [PATCH 092/221] mb/*/{x201,packardbell}: Remove unused C-state generation functions Those are copied from Lenovo X60 code, but are unused. NOTE: No ACPI C-state are generated on this platform but Linux has a separate driver for that. Change-Id: Ie9b49f5451d8cde9c36672cac1f0f14cb3f0095e Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33140 Reviewed-by: Patrick Georgi Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- src/mainboard/lenovo/x201/mainboard.c | 13 ------------- src/mainboard/packardbell/ms2290/mainboard.c | 15 --------------- 2 files changed, 28 deletions(-) diff --git a/src/mainboard/lenovo/x201/mainboard.c b/src/mainboard/lenovo/x201/mainboard.c index 0e20afe610..01dba57c30 100644 --- a/src/mainboard/lenovo/x201/mainboard.c +++ b/src/mainboard/lenovo/x201/mainboard.c @@ -28,19 +28,6 @@ #include #include #include -#include - -static acpi_cstate_t cst_entries[] = { - {1, 1, 1000, {0x7f, 1, 2, 0, 1, 0} }, - {2, 1, 500, {0x01, 8, 0, 0, DEFAULT_PMBASE + LV2, 0} }, - {2, 17, 250, {0x01, 8, 0, 0, DEFAULT_PMBASE + LV3, 0} }, -}; - -int get_cst_entries(acpi_cstate_t **entries) -{ - *entries = cst_entries; - return ARRAY_SIZE(cst_entries); -} static void mainboard_init(struct device *dev) { diff --git a/src/mainboard/packardbell/ms2290/mainboard.c b/src/mainboard/packardbell/ms2290/mainboard.c index 09310aef72..28d3bb0958 100644 --- a/src/mainboard/packardbell/ms2290/mainboard.c +++ b/src/mainboard/packardbell/ms2290/mainboard.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -32,20 +31,6 @@ #include #include -static acpi_cstate_t cst_entries[] = { - {1, 1, 1000, {0x7f, 1, 2, 0, 1, 0} }, - {2, 1, 500, {0x01, 8, 0, 0, DEFAULT_PMBASE + LV2, 0} }, - {2, 17, 250, {0x01, 8, 0, 0, DEFAULT_PMBASE + LV3, 0} }, -}; - -int get_cst_entries(acpi_cstate_t ** entries) -{ - *entries = cst_entries; - return ARRAY_SIZE(cst_entries); -} - - - static void mainboard_enable(struct device *dev) { u16 pmbase; From 2c0ecc1f83dd1dee808d4ebfdfb1525fc9d1d529 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sat, 15 Jun 2019 18:55:48 +0200 Subject: [PATCH 093/221] mb/packardbell/ms2290/Kconfig: Remove ARCH_x options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those are already selected in cpu/intel/model_2065x/Kconfig. Change-Id: I7421faa24b8a95d2780bce0651cde0bfeb357833 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33507 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki Reviewed-by: Angel Pons --- src/mainboard/packardbell/ms2290/Kconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mainboard/packardbell/ms2290/Kconfig b/src/mainboard/packardbell/ms2290/Kconfig index c6a1e1256a..631559157f 100644 --- a/src/mainboard/packardbell/ms2290/Kconfig +++ b/src/mainboard/packardbell/ms2290/Kconfig @@ -3,9 +3,6 @@ if BOARD_PACKARDBELL_MS2290 config BOARD_SPECIFIC_OPTIONS def_bool y select SYSTEM_TYPE_LAPTOP - select ARCH_BOOTBLOCK_X86_32 - select ARCH_ROMSTAGE_X86_32 - select ARCH_RAMSTAGE_X86_32 select NORTHBRIDGE_INTEL_NEHALEM select SOUTHBRIDGE_INTEL_IBEXPEAK select HAVE_OPTION_TABLE From c82d7e76d5583c89434a57553fefa6ba8f464c73 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sat, 15 Jun 2019 19:00:17 +0200 Subject: [PATCH 094/221] mb/lenovo/x201/smihandler.c: Remove useless smihandler code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code to handle the brightness from SMM is copied from the Lenovo Thinkpad X60 code, but does not work on later generation. The PCI device it tries to address does not even exist on those devices. Change-Id: I0c25c3e5bec651b27158a84cc91289639a04ceb6 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33508 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/mainboard/lenovo/x201/smihandler.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/mainboard/lenovo/x201/smihandler.c b/src/mainboard/lenovo/x201/smihandler.c index 9043f8e18c..e80782acf6 100644 --- a/src/mainboard/lenovo/x201/smihandler.c +++ b/src/mainboard/lenovo/x201/smihandler.c @@ -15,7 +15,6 @@ */ #include -#include #include #include #include @@ -71,23 +70,6 @@ int mainboard_io_trap_handler(int smif) return 1; } -static void mainboard_smi_brightness_up(void) -{ - u8 value; - - if ((value = pci_read_config8(PCI_DEV(0, 2, 1), 0xf4)) < 0xf0) - pci_write_config8(PCI_DEV(0, 2, 1), 0xf4, (value + 0x10) | 0xf); -} - -static void mainboard_smi_brightness_down(void) -{ - u8 value; - - if ((value = pci_read_config8(PCI_DEV(0, 2, 1), 0xf4)) > 0x10) - pci_write_config8(PCI_DEV(0, 2, 1), 0xf4, - (value - 0x10) & 0xf0); -} - static void mainboard_smi_handle_ec_sci(void) { u8 status = inb(EC_SC); @@ -100,14 +82,6 @@ static void mainboard_smi_handle_ec_sci(void) printk(BIOS_DEBUG, "EC event %02x\n", event); switch (event) { - case 0x14: - /* brightness up */ - mainboard_smi_brightness_up(); - break; - case 0x15: - /* brightness down */ - mainboard_smi_brightness_down(); - break; case 0x18: /* Fn-F9 key */ case 0x27: From 6d7564cdfebfd6bfab34eadc805b3f926acf0518 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Tue, 18 Jun 2019 16:38:29 +0200 Subject: [PATCH 095/221] Move -Wlogical-op into xcompile Clang doesn't know `-Wlogical-op`, so let's move it into xcompile where we can easily distinguish between the two. However, this requires us to split out `GCC_ADAFLAGS*` from `GCC_CFLAGS*`. Change-Id: I6a50de0bc5372f61337f237383d32645ba86b0fd Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/33579 Reviewed-by: Patrick Georgi Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- Makefile.inc | 2 +- toolchain.inc | 2 +- util/xcompile/xcompile | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index 48879bc9fd..7ac0a829e2 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -401,7 +401,7 @@ endif CFLAGS_common += -pipe -g -nostdinc -std=gnu11 CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes -CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -Wlogical-op +CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie diff --git a/toolchain.inc b/toolchain.inc index 0486287444..875cb20387 100644 --- a/toolchain.inc +++ b/toolchain.inc @@ -131,7 +131,7 @@ OBJDUMP_$(1) := $(OBJDUMP_$(2)) STRIP_$(1) := $(STRIP_$(2)) READELF_$(1) := $(READELF_$(2)) CFLAGS_$(1) = $$(CFLAGS_common) $$(CFLAGS_$(2)) -ADAFLAGS_$(1) = --RTS=$$(obj)/libgnat-$(2)/ $$(ADAFLAGS_common) $$(GCC_CFLAGS_$(2)) +ADAFLAGS_$(1) = --RTS=$$(obj)/libgnat-$(2)/ $$(ADAFLAGS_common) $$(GCC_ADAFLAGS_$(2)) CPPFLAGS_$(1) = $$(CPPFLAGS_common) $$(CPPFLAGS_$(2)) -D__ARCH_$(2)__ COMPILER_RT_$(1) := $$(COMPILER_RT_$(2)) COMPILER_RT_FLAGS_$(1) := $$(COMPILER_RT_FLAGS_$(2)) diff --git a/util/xcompile/xcompile b/util/xcompile/xcompile index 050cc59827..e8d6677994 100755 --- a/util/xcompile/xcompile +++ b/util/xcompile/xcompile @@ -225,6 +225,9 @@ SUBARCH_SUPPORTED+=${TSUPP-${TARCH}} # GCC GCC_CC_${TARCH}:=${GCC} GCC_CFLAGS_${TARCH}:=${CFLAGS_GCC} +# Generally available for GCC's cc1: +GCC_CFLAGS_${TARCH}+=-Wlogical-op +GCC_ADAFLAGS_${TARCH}:=${CFLAGS_GCC} GCC_COMPILER_RT_${TARCH}:=${CC_RT_GCC} GCC_COMPILER_RT_FLAGS_${TARCH}:=${CC_RT_EXTRA_GCC} From fd54acf098895dd92b7722cf4020893174f3dcbd Mon Sep 17 00:00:00 2001 From: Hsin-Hsiung Wang Date: Mon, 3 Jun 2019 15:38:53 +0800 Subject: [PATCH 096/221] mediatek/mt8183: set vproc12 voltage correctly The correct address for vproc12 register of sw mode is 0x1426 instead of 0x140a. BUG=b:80501386 BRANCH=none Test=Boots correctly on Kukui and see that regulator is not stuck to 1.05V anymore: grep vproc12 /sys/kernel/debug/regulator/regulator_summary Change-Id: I13867b11c44019875e0ed607343197950a3b38b2 Signed-off-by: Hsin-Hsiung Wang Reviewed-on: https://review.coreboot.org/c/coreboot/+/33168 Reviewed-by: Hung-Te Lin Reviewed-by: Nicolas Boichat Tested-by: build bot (Jenkins) --- src/soc/mediatek/mt8183/mt6358.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/soc/mediatek/mt8183/mt6358.c b/src/soc/mediatek/mt8183/mt6358.c index ea4274f14b..53d2a43803 100644 --- a/src/soc/mediatek/mt8183/mt6358.c +++ b/src/soc/mediatek/mt8183/mt6358.c @@ -497,8 +497,10 @@ static struct pmic_setting init_setting[] = { {0x1B6C, 0x6, 0x6, 0}, /* Vproc11/Vproc12 to 1.05V */ + /* [6:0]: RG_BUCK_VPROC11_VOSEL */ {0x13a6, 0x58, 0x7F, 0}, - {0x140a, 0x58, 0x7F, 0}, + /* [6:0]: RG_BUCK_VPROC12_VOSEL */ + {0x1426, 0x58, 0x7F, 0}, }; static struct pmic_setting lp_setting[] = { From bf1da4b4491455cee03e770a89711ac308da83bb Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sat, 29 Dec 2018 13:09:26 +0100 Subject: [PATCH 097/221] x86/smmstub: Fix compiling with external toolchains This copies the makefile code from the smm/smm.o. Now works with clang version 7.0.1 from my OS using CONFIG_ANY_TOOLCHAIN. Change-Id: I298d24d54b8fb27da96257ccda65b7fbee988ebb Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/30504 Reviewed-by: Paul Menzel Reviewed-by: Aaron Durbin Tested-by: build bot (Jenkins) --- src/cpu/x86/smm/Makefile.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/x86/smm/Makefile.inc b/src/cpu/x86/smm/Makefile.inc index 32f5ea713d..e6add1d0d0 100644 --- a/src/cpu/x86/smm/Makefile.inc +++ b/src/cpu/x86/smm/Makefile.inc @@ -47,8 +47,8 @@ ramstage-srcs += $(obj)/cpu/x86/smm/smmstub.manual # SMM Stub Module. The stub is used as a trampoline for relocation and normal # SMM handling. -$(obj)/smmstub/smmstub.o: $$(smmstub-objs) - $(CC_smmstub) $(CFLAGS_smmstub) -nostdlib -r -o $@ $^ +$(obj)/smmstub/smmstub.o: $$(smmstub-objs) $(COMPILER_RT_smmstub) + $(LD_smmstub) -nostdlib -r -o $@ $(COMPILER_RT_FLAGS_smmstub) --whole-archive --start-group $(smmstub-objs) --no-whole-archive $(COMPILER_RT_smmstub) --end-group # Link the SMM stub module with a 0-byte heap. ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y) From f70cb8bf968af75669325104756464ce6f4b824b Mon Sep 17 00:00:00 2001 From: Christian Walter Date: Thu, 13 Jun 2019 10:54:30 +0200 Subject: [PATCH 098/221] soc/intel/skylake/romstage: Increase size of postcar stack I increase the size oof the postcar stack to prevent a stack overflow during the measured boot feature. After common string functions have been moved from inline into .c file (https://review.coreboot.org/c/coreboot/+/32901), I experienced a stack overflow in the postcar stage while verifiying the romstage during measured boot. To prevent this, the stack size should be increased. To play it safe, it should be increased to 8 KiB - though this is open for discussion. Change-Id: I6f1a4631bcadfb8c7d1de5bf0919e40990a65606 Signed-off-by: Christian Walter Reviewed-on: https://review.coreboot.org/c/coreboot/+/33434 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans --- src/soc/intel/skylake/romstage/romstage_fsp20.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c index 2819c6f260..0eff793ac2 100644 --- a/src/soc/intel/skylake/romstage/romstage_fsp20.c +++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c @@ -156,7 +156,7 @@ asmlinkage void car_stage_entry(void) pmc_set_disb(); if (!s3wake) save_dimm_info(); - if (postcar_frame_init(&pcf, 1*KiB)) + if (postcar_frame_init(&pcf, 8*KiB)) die("Unable to initialize postcar frame.\n"); /* From 3970a9d9645f265c34353ba24c0c436b02e69838 Mon Sep 17 00:00:00 2001 From: Philip Chen Date: Tue, 18 Jun 2019 12:48:34 -0700 Subject: [PATCH 099/221] mb/google/hatch: Do not pull down GPP_F2 internally There is already an external pull-up/down resistor tied to this pin to identify if the board is single-channel or dual-channel memory SKU. BUG=b:135496271 BRANCH=none TEST=build Signed-off-by: Philip Chen Change-Id: Ie218657fd9dde113ab26cf5551d1dff1b6e392b6 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33583 Tested-by: build bot (Jenkins) Reviewed-by: David Wu Reviewed-by: Furquan Shaikh --- src/mainboard/google/hatch/variants/baseboard/gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/hatch/variants/baseboard/gpio.c b/src/mainboard/google/hatch/variants/baseboard/gpio.c index 0b6607595d..e309175d03 100644 --- a/src/mainboard/google/hatch/variants/baseboard/gpio.c +++ b/src/mainboard/google/hatch/variants/baseboard/gpio.c @@ -284,7 +284,7 @@ static const struct pad_config gpio_table[] = { /* F1 : WWAN_RESET_1V8_ODL */ PAD_CFG_GPO(GPP_F1, 1, DEEP), /* F2 : MEM_CH_SEL */ - PAD_CFG_GPI(GPP_F2, DN_20K, PLTRST), + PAD_CFG_GPI(GPP_F2, NONE, PLTRST), /* F3 : GPP_F3 ==> NC */ PAD_NC(GPP_F3, NONE), /* F4 : CNV_BRI_DT */ @@ -460,7 +460,7 @@ static const struct pad_config early_gpio_table[] = { /* C23 : WLAN_PE_RST# */ PAD_CFG_GPO(GPP_C23, 1, DEEP), /* F2 : MEM_CH_SEL */ - PAD_CFG_GPI(GPP_F2, DN_20K, PLTRST), + PAD_CFG_GPI(GPP_F2, NONE, PLTRST), /* F11 : PCH_MEM_STRAP2 */ PAD_CFG_GPI(GPP_F11, NONE, PLTRST), /* F20 : PCH_MEM_STRAP0 */ From f371b051b0221e9f391f197d0960a201aefa39b8 Mon Sep 17 00:00:00 2001 From: Nitheesh Sekar Date: Fri, 31 May 2019 22:47:43 +0530 Subject: [PATCH 100/221] qcs405: Update bootblock size Increase the size of bootblock from 96K to 128K. Change-Id: Ifc6e7239ed2978a8490fa229945ebd5ed9182298 Signed-off-by: Nitheesh Sekar Reviewed-on: https://review.coreboot.org/c/coreboot/+/33159 Reviewed-by: Patrick Georgi Reviewed-by: Stefan Reinauer Tested-by: build bot (Jenkins) --- src/mainboard/google/mistral/chromeos.fmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/google/mistral/chromeos.fmd b/src/mainboard/google/mistral/chromeos.fmd index 76cdd50d91..4d5f666ce8 100644 --- a/src/mainboard/google/mistral/chromeos.fmd +++ b/src/mainboard/google/mistral/chromeos.fmd @@ -16,7 +16,7 @@ FLASH@0x0 8M { WP_RO 4M { RO_SECTION 0x204000 { - BOOTBLOCK 96K + BOOTBLOCK 128K COREBOOT(CBFS) FMAP@0x200000 0x1000 GBB 0x2f00 From eb1dea8faf3ead8599848f1f85cebe8756704b06 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 16 Jun 2019 15:45:36 +0200 Subject: [PATCH 101/221] security/vboot: Remove useless 'const' Change-Id: I3b5ca272abffe46c6a63251cf4905780f87a6836 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33540 Reviewed-by: Angel Pons Reviewed-by: Aaron Durbin Reviewed-by: Joel Kitching Tested-by: build bot (Jenkins) --- src/security/vboot/common.c | 2 +- src/security/vboot/misc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/security/vboot/common.c b/src/security/vboot/common.c index 8f8165a7c5..bd72683e00 100644 --- a/src/security/vboot/common.c +++ b/src/security/vboot/common.c @@ -24,7 +24,7 @@ #include #include -struct vboot_working_data * const vboot_get_working_data(void) +struct vboot_working_data *vboot_get_working_data(void) { struct vboot_working_data *wd = NULL; diff --git a/src/security/vboot/misc.h b/src/security/vboot/misc.h index acb6dbbd02..725f5fd436 100644 --- a/src/security/vboot/misc.h +++ b/src/security/vboot/misc.h @@ -53,7 +53,7 @@ struct vboot_working_data { /* * Source: security/vboot/common.c */ -struct vboot_working_data * const vboot_get_working_data(void); +struct vboot_working_data *vboot_get_working_data(void); void vboot_init_work_context(struct vb2_context *ctx); void vboot_finalize_work_context(struct vb2_context *ctx); struct vb2_shared_data *vboot_get_shared_data(void); From e07eb5f173b26f44d7779c8030d59f4d295e28fa Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 17 Jun 2019 12:23:32 +0200 Subject: [PATCH 102/221] soc/intel/skylake: Remove ROMCCFLAGS This is never used. Change-Id: I414acc38f72e206eb48cfd98214985c320862c91 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33556 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/soc/intel/skylake/Makefile.inc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index 129586a233..05e4c968e8 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -108,6 +108,4 @@ endif # Currently used for microcode path. CPPFLAGS_common += -I3rdparty/blobs/mainboard/$(MAINBOARDDIR) -ROMCCFLAGS := -mcpu=p4 -fno-simplify-phi -O2 - endif From 4c7979a24179f93306ce177b80c6b38cccfadc2c Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 17 Jun 2019 14:30:10 +0200 Subject: [PATCH 103/221] soc/intel/skylake: Clean up Kconfig This does the following: - select MAINBOARD_USES_FSP2_0 on Kabylake (does not support FSP1.1) - Remove stale Kconfig option on intel/saddlebrook - select SOC_INTEL_KABYLAKE on intel/kblrvp Change-Id: I64f48eeb00150aea039d533b0ac471fdd8483b90 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33561 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/mainboard/asrock/h110m/Kconfig | 1 - src/mainboard/google/eve/Kconfig | 1 - src/mainboard/google/fizz/Kconfig | 1 - src/mainboard/google/poppy/Kconfig | 1 - src/mainboard/intel/kblrvp/Kconfig | 3 +-- src/mainboard/intel/saddlebrook/Kconfig | 4 ---- src/soc/intel/skylake/Kconfig | 10 +++++++--- src/soc/intel/skylake/Makefile.inc | 2 +- 8 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/mainboard/asrock/h110m/Kconfig b/src/mainboard/asrock/h110m/Kconfig index 3d2111309e..487c90ed13 100644 --- a/src/mainboard/asrock/h110m/Kconfig +++ b/src/mainboard/asrock/h110m/Kconfig @@ -11,7 +11,6 @@ config BOARD_SPECIFIC_OPTIONS select INTEL_INT15 select SOC_INTEL_KABYLAKE select SKYLAKE_SOC_PCH_H - select MAINBOARD_USES_FSP2_0 select GENERIC_SPD_BIN select SUPERIO_NUVOTON_NCT6791D select SUPERIO_NUVOTON_NCT6776_COM_A diff --git a/src/mainboard/google/eve/Kconfig b/src/mainboard/google/eve/Kconfig index f7fb9c6516..022493c35f 100644 --- a/src/mainboard/google/eve/Kconfig +++ b/src/mainboard/google/eve/Kconfig @@ -19,7 +19,6 @@ config BOARD_SPECIFIC_OPTIONS select MAINBOARD_HAS_CHROMEOS select MAINBOARD_HAS_I2C_TPM_CR50 select MAINBOARD_HAS_TPM2 - select MAINBOARD_USES_FSP2_0 select SOC_INTEL_KABYLAKE config VBOOT diff --git a/src/mainboard/google/fizz/Kconfig b/src/mainboard/google/fizz/Kconfig index acaf8a6dc2..b05cb6c16d 100644 --- a/src/mainboard/google/fizz/Kconfig +++ b/src/mainboard/google/fizz/Kconfig @@ -17,7 +17,6 @@ config BOARD_GOOGLE_BASEBOARD_FIZZ select INTEL_GMA_HAVE_VBT select INTEL_LPSS_UART_FOR_CONSOLE select MAINBOARD_HAS_CHROMEOS - select MAINBOARD_USES_FSP2_0 select NO_FADT_8042 select SOC_INTEL_KABYLAKE select MAINBOARD_HAS_SPI_TPM_CR50 diff --git a/src/mainboard/google/poppy/Kconfig b/src/mainboard/google/poppy/Kconfig index 6bc8269aa7..e2ffe714c5 100644 --- a/src/mainboard/google/poppy/Kconfig +++ b/src/mainboard/google/poppy/Kconfig @@ -13,7 +13,6 @@ config BOARD_GOOGLE_BASEBOARD_POPPY select INTEL_GMA_HAVE_VBT if BOARD_GOOGLE_NAMI select INTEL_LPSS_UART_FOR_CONSOLE select MAINBOARD_HAS_CHROMEOS - select MAINBOARD_USES_FSP2_0 select SOC_INTEL_KABYLAKE select MAINBOARD_HAS_TPM2 diff --git a/src/mainboard/intel/kblrvp/Kconfig b/src/mainboard/intel/kblrvp/Kconfig index 52cee2dfd3..c0737cbce6 100644 --- a/src/mainboard/intel/kblrvp/Kconfig +++ b/src/mainboard/intel/kblrvp/Kconfig @@ -9,9 +9,8 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_ACPI_TABLES select HAVE_OPTION_TABLE select SOC_INTEL_COMMON_BLOCK_HDA_VERB if !BOARD_INTEL_KBLRVP8 - select SOC_INTEL_SKYLAKE + select SOC_INTEL_KABYLAKE select SKYLAKE_SOC_PCH_H if BOARD_INTEL_KBLRVP8 || BOARD_INTEL_KBLRVP11 - select MAINBOARD_USES_FSP2_0 select MAINBOARD_HAS_CHROMEOS select GENERIC_SPD_BIN select MAINBOARD_HAS_LPC_TPM diff --git a/src/mainboard/intel/saddlebrook/Kconfig b/src/mainboard/intel/saddlebrook/Kconfig index f2b7344aaa..934c15affd 100644 --- a/src/mainboard/intel/saddlebrook/Kconfig +++ b/src/mainboard/intel/saddlebrook/Kconfig @@ -29,14 +29,10 @@ config BOARD_SPECIFIC_OPTIONS select SOC_INTEL_SKYLAKE select SUPERIO_NUVOTON_NCT6776 select SUPERIO_NUVOTON_NCT6776_COM_A - select SADDLEBROOK_USES_FSP1_1 select HAVE_CMOS_DEFAULT select MAINBOARD_USES_IFD_GBE_REGION select USE_INTEL_FSP_MP_INIT -config SADDLEBROOK_USES_FSP1_1 - bool "FSP driver 1.1" - config IRQ_SLOT_COUNT int default 18 diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig index 626b5f80f0..fb455d2392 100644 --- a/src/soc/intel/skylake/Kconfig +++ b/src/soc/intel/skylake/Kconfig @@ -1,16 +1,20 @@ +config SOC_INTEL_COMMON_SKYLAKE_BASE + bool + config SOC_INTEL_SKYLAKE bool + select SOC_INTEL_COMMON_SKYLAKE_BASE help Intel Skylake support config SOC_INTEL_KABYLAKE bool - default n - select SOC_INTEL_SKYLAKE + select SOC_INTEL_COMMON_SKYLAKE_BASE + select MAINBOARD_USES_FSP2_0 help Intel Kabylake support -if SOC_INTEL_SKYLAKE +if SOC_INTEL_COMMON_SKYLAKE_BASE config CPU_SPECIFIC_OPTIONS def_bool y diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index 05e4c968e8..985acdf135 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -1,4 +1,4 @@ -ifeq ($(CONFIG_SOC_INTEL_SKYLAKE),y) +ifeq ($(CONFIG_SOC_INTEL_COMMON_SKYLAKE_BASE),y) subdirs-y += nhlt subdirs-y += romstage From d309f5b8e2c76cb87b8a008469e39484b7e138fd Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Wed, 12 Jun 2019 15:32:17 +0200 Subject: [PATCH 104/221] mainboard/facebook/fbg1701/fadt.c: Use asl_revision Fix value of 1 is used for asl_compiler_revision. Use asl_revision for this. BUG=N/A TEST=booting Linux 4.20 kernel on Facebook FBG1701 Change-Id: Iffd8fe637d4669b7099fb6eafc9873560502bf80 Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33423 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Lance Zhao --- src/mainboard/facebook/fbg1701/fadt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mainboard/facebook/fbg1701/fadt.c b/src/mainboard/facebook/fbg1701/fadt.c index 60dd5b9a73..544d24ba55 100644 --- a/src/mainboard/facebook/fbg1701/fadt.c +++ b/src/mainboard/facebook/fbg1701/fadt.c @@ -16,6 +16,7 @@ */ #include +#include void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt) { @@ -28,7 +29,7 @@ void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt) memcpy(header->oem_id, OEM_ID, 6); memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8); memcpy(header->asl_compiler_id, ASLC, 4); - header->asl_compiler_revision = 1; + header->asl_compiler_revision = asl_revision; fadt->firmware_ctrl = (unsigned long) facs; fadt->dsdt = (unsigned long) dsdt; From 5778f772b59d50f2ac8d730893c5bdc3581d951b Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Tue, 18 Jun 2019 12:36:48 +0200 Subject: [PATCH 105/221] mainboard/facebook/fbg1701: Remove unused includes Files onboard.h and mainboard.h are not used for building. Remove these files as include. BUG=N/A TEST=Build and boot embedded Linux 4.20 on Facebook FBG-1701 Change-Id: Ifeb0047357e641cbe1affbbaf5402213802c774c Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33574 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes --- src/mainboard/facebook/fbg1701/mainboard.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mainboard/facebook/fbg1701/mainboard.c b/src/mainboard/facebook/fbg1701/mainboard.c index ff2564d67a..8524b24000 100644 --- a/src/mainboard/facebook/fbg1701/mainboard.c +++ b/src/mainboard/facebook/fbg1701/mainboard.c @@ -17,8 +17,6 @@ */ #include -#include "onboard.h" -#include "mainboard.h" /* * Declare the resources we are using From e951e8ec7f8a5a9d7b9b681526c3b16b67be15d4 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sat, 15 Jun 2019 11:03:00 +0200 Subject: [PATCH 106/221] nb/x4x: Rename {ddr,fsb}2{mhz,ps} as {ddr,fsb}_to_{mhz,ps} Change-Id: I0442cc5bc54efd7e2c4e5496182c8df85acbcf91 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33491 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans --- src/northbridge/intel/x4x/raminit.c | 4 ++-- src/northbridge/intel/x4x/raminit_ddr23.c | 18 +++++++++--------- src/northbridge/intel/x4x/x4x.h | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c index bd6536ab6f..8013af9d51 100644 --- a/src/northbridge/intel/x4x/raminit.c +++ b/src/northbridge/intel/x4x/raminit.c @@ -461,9 +461,9 @@ static void print_selected_timings(struct sysinfo *s) { printk(BIOS_DEBUG, "Selected timings:\n"); printk(BIOS_DEBUG, "\tFSB: %dMHz\n", - fsb2mhz(s->selected_timings.fsb_clk)); + fsb_to_mhz(s->selected_timings.fsb_clk)); printk(BIOS_DEBUG, "\tDDR: %dMHz\n", - ddr2mhz(s->selected_timings.mem_clk)); + ddr_to_mhz(s->selected_timings.mem_clk)); printk(BIOS_DEBUG, "\tCAS: %d\n", s->selected_timings.CAS); printk(BIOS_DEBUG, "\ttRAS: %d\n", s->selected_timings.tRAS); diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c index 422b0ffa16..32618e8c88 100644 --- a/src/northbridge/intel/x4x/raminit_ddr23.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -32,12 +32,12 @@ #define ME_UMA_SIZEMB 0 -u32 fsb2mhz(u32 speed) +u32 fsb_to_mhz(u32 speed) { return (speed * 267) + 800; } -u32 ddr2mhz(u32 speed) +u32 ddr_to_mhz(u32 speed) { static const u16 mhz[] = { 0, 0, 667, 800, 1067, 1333 }; @@ -413,13 +413,13 @@ static void program_timings(struct sysinfo *s) adjusted_cas = s->selected_timings.CAS - 3; - u16 fsb2ps[3] = { + u16 fsb_to_ps[3] = { 5000, // 800 3750, // 1067 3000 // 1333 }; - u16 ddr2ps[6] = { + u16 ddr_to_ps[6] = { 5000, // 400 3750, // 533 3000, // 667 @@ -573,13 +573,13 @@ static void program_timings(struct sysinfo *s) MCHBAR8_AND_OR(0x400*i + 0x246, ~0x1f, (reg8 << 2) | 1); - fsb = fsb2ps[s->selected_timings.fsb_clk]; - ddr = ddr2ps[s->selected_timings.mem_clk]; + fsb = fsb_to_ps[s->selected_timings.fsb_clk]; + ddr = ddr_to_ps[s->selected_timings.mem_clk]; reg32 = (u32)((s->selected_timings.CAS + 7 + reg8) * ddr); reg32 = (u32)((reg32 / fsb) << 8); reg32 |= 0x0e000000; - if ((fsb2mhz(s->selected_timings.fsb_clk) / - ddr2mhz(s->selected_timings.mem_clk)) > 2) { + if ((fsb_to_mhz(s->selected_timings.fsb_clk) / + ddr_to_mhz(s->selected_timings.mem_clk)) > 2) { reg32 |= 1 << 24; } MCHBAR32_AND_OR(0x400*i + 0x248, ~0x0f001f00, reg32); @@ -671,7 +671,7 @@ static void program_timings(struct sysinfo *s) if (s->spd_type == DDR3) { MCHBAR8(0x114) = 0x42; reg16 = (512 - MAX(5, s->selected_timings.tRFC + 10000 - / ddr2ps[s->selected_timings.mem_clk])) + / ddr_to_ps[s->selected_timings.mem_clk])) / 2; reg16 &= 0x1ff; reg32 = (reg16 << 22) | (0x80 << 14) | (0xa << 9); diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index a7efb172c5..57723364ab 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -378,8 +378,8 @@ u8 decode_pciebar(u32 *const base, u32 *const len); void sdram_initialize(int boot_path, const u8 *spd_map); void do_raminit(struct sysinfo *, int fast_boot); void rcven(struct sysinfo *s); -u32 fsb2mhz(u32 speed); -u32 ddr2mhz(u32 speed); +u32 fsb_to_mhz(u32 speed); +u32 ddr_to_mhz(u32 speed); u32 test_address(int channel, int rank); void dqsset(u8 ch, u8 lane, const struct dll_setting *setting); void dqset(u8 ch, u8 lane, const struct dll_setting *setting); From 3286848a7a013b4d4effc4e50b4b7b552236cf73 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Fri, 1 Feb 2019 13:07:42 +0100 Subject: [PATCH 107/221] cpu/x86/msr: Move IA32_MISC_ENABLE bits to common place Change-Id: I51aa300358013cb0e76704feb2115d2a7e260f8a Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/31193 Reviewed-by: Angel Pons Reviewed-by: David Guckian Reviewed-by: Vanny E Tested-by: build bot (Jenkins) --- src/include/cpu/x86/msr.h | 2 ++ src/soc/intel/denverton_ns/include/soc/msr.h | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/include/cpu/x86/msr.h b/src/include/cpu/x86/msr.h index 5c6cae3a0e..8c558ce8ac 100644 --- a/src/include/cpu/x86/msr.h +++ b/src/include/cpu/x86/msr.h @@ -37,6 +37,8 @@ #define IA32_PERF_CTL 0x199 #define IA32_THERM_INTERRUPT 0x19b #define IA32_MISC_ENABLE 0x1a0 +#define FAST_STRINGS_ENABLE_BIT (1 << 0) +#define SPEED_STEP_ENABLE_BIT (1 << 16) #define IA32_ENERGY_PERF_BIAS 0x1b0 #define ENERGY_POLICY_PERFORMANCE 0 #define ENERGY_POLICY_NORMAL 6 diff --git a/src/soc/intel/denverton_ns/include/soc/msr.h b/src/soc/intel/denverton_ns/include/soc/msr.h index 1b27eefcaa..0d469c4871 100644 --- a/src/soc/intel/denverton_ns/include/soc/msr.h +++ b/src/soc/intel/denverton_ns/include/soc/msr.h @@ -96,10 +96,6 @@ #define SMRR_SUPPORTED (1 << 11) #define PRMRR_SUPPORTED (1 << 12) -/* IA32_MISC_ENABLE bits */ -#define FAST_STRINGS_ENABLE_BIT (1 << 0) -#define SPEED_STEP_ENABLE_BIT (1 << 16) - /* Read BCLK from MSR */ unsigned int bus_freq_khz(void); From a6a396ddb6f866c5a675dff5c1aa0b4cbaf44039 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 26 May 2019 13:25:30 +0200 Subject: [PATCH 108/221] cpu/intel/{haswell,model_206{5,a}x}: Use MSR_CORE_THREAD_COUNT for msr at 0x35 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regarding 64 and IA-32 Architectures Software Developer’s Manual, the register name of the msr at 0x35 is MSR_CORE_THREAD_COUNT. Change-Id: I5134619dc3a42187ddd5f46c85873c4278229e27 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33015 Reviewed-by: Arthur Heymans Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- src/cpu/intel/haswell/haswell.h | 2 +- src/cpu/intel/haswell/haswell_init.c | 2 +- src/cpu/intel/model_2065x/model_2065x.h | 2 +- src/cpu/intel/model_2065x/model_2065x_init.c | 2 +- src/cpu/intel/model_206ax/model_206ax.h | 2 +- src/cpu/intel/model_206ax/model_206ax_init.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h index 3dfdd8d071..4ebbe183b7 100644 --- a/src/cpu/intel/haswell/haswell.h +++ b/src/cpu/intel/haswell/haswell.h @@ -34,7 +34,7 @@ /* Haswell bus clock is fixed at 100MHz */ #define HASWELL_BCLK 100 -#define CORE_THREAD_COUNT_MSR 0x35 +#define MSR_CORE_THREAD_COUNT 0x35 #define MSR_FEATURE_CONFIG 0x13c #define MSR_FLEX_RATIO 0x194 #define FLEX_RATIO_LOCK (1 << 20) diff --git a/src/cpu/intel/haswell/haswell_init.c b/src/cpu/intel/haswell/haswell_init.c index 25cf243aca..95d719c2f1 100644 --- a/src/cpu/intel/haswell/haswell_init.c +++ b/src/cpu/intel/haswell/haswell_init.c @@ -732,7 +732,7 @@ static int get_cpu_count(void) int num_threads; int num_cores; - msr = rdmsr(CORE_THREAD_COUNT_MSR); + msr = rdmsr(MSR_CORE_THREAD_COUNT); num_threads = (msr.lo >> 0) & 0xffff; num_cores = (msr.lo >> 16) & 0xffff; printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n", diff --git a/src/cpu/intel/model_2065x/model_2065x.h b/src/cpu/intel/model_2065x/model_2065x.h index e7ba2a771b..eab2dd5c50 100644 --- a/src/cpu/intel/model_2065x/model_2065x.h +++ b/src/cpu/intel/model_2065x/model_2065x.h @@ -20,7 +20,7 @@ /* Nehalem bus clock is fixed at 133MHz */ #define NEHALEM_BCLK 133 -#define CORE_THREAD_COUNT_MSR 0x35 +#define MSR_CORE_THREAD_COUNT 0x35 #define MSR_FEATURE_CONFIG 0x13c #define MSR_FLEX_RATIO 0x194 #define FLEX_RATIO_LOCK (1 << 20) diff --git a/src/cpu/intel/model_2065x/model_2065x_init.c b/src/cpu/intel/model_2065x/model_2065x_init.c index d8de7c055f..289d4471e6 100644 --- a/src/cpu/intel/model_2065x/model_2065x_init.c +++ b/src/cpu/intel/model_2065x/model_2065x_init.c @@ -287,7 +287,7 @@ static int get_cpu_count(void) int num_threads; int num_cores; - msr = rdmsr(CORE_THREAD_COUNT_MSR); + msr = rdmsr(MSR_CORE_THREAD_COUNT); num_threads = (msr.lo >> 0) & 0xffff; num_cores = (msr.lo >> 16) & 0xffff; printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n", diff --git a/src/cpu/intel/model_206ax/model_206ax.h b/src/cpu/intel/model_206ax/model_206ax.h index f4c5d9323a..c0d2434fe6 100644 --- a/src/cpu/intel/model_206ax/model_206ax.h +++ b/src/cpu/intel/model_206ax/model_206ax.h @@ -22,7 +22,7 @@ /* SandyBridge/IvyBridge bus clock is fixed at 100MHz */ #define SANDYBRIDGE_BCLK 100 -#define CORE_THREAD_COUNT_MSR 0x35 +#define MSR_CORE_THREAD_COUNT 0x35 #define MSR_FEATURE_CONFIG 0x13c #define MSR_FLEX_RATIO 0x194 #define FLEX_RATIO_LOCK (1 << 20) diff --git a/src/cpu/intel/model_206ax/model_206ax_init.c b/src/cpu/intel/model_206ax/model_206ax_init.c index 524e49c5c6..80d85f3347 100644 --- a/src/cpu/intel/model_206ax/model_206ax_init.c +++ b/src/cpu/intel/model_206ax/model_206ax_init.c @@ -513,7 +513,7 @@ static int get_cpu_count(void) int num_threads; int num_cores; - msr = rdmsr(CORE_THREAD_COUNT_MSR); + msr = rdmsr(MSR_CORE_THREAD_COUNT); num_threads = (msr.lo >> 0) & 0xffff; num_cores = (msr.lo >> 16) & 0xffff; printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n", From 4821a0e135ff2d60f552203d2724ae2d44850623 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 18 Jun 2019 13:19:29 +0200 Subject: [PATCH 109/221] soc/intel/cannonlake: Rename SOC_INTEL_COMMON_CANNONLAKE_BASE What it really means to do is to use different FSP headers. Change-Id: I3c75d4aac8525ab2639608fb9c1b3a9afef0e943 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33575 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/soc/intel/cannonlake/Kconfig | 10 +++++----- src/soc/intel/cannonlake/chip.h | 2 +- src/soc/intel/cannonlake/cpu.c | 2 +- src/soc/intel/cannonlake/romstage/fsp_params.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index dac3522d0a..7b4282c934 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -3,7 +3,7 @@ config SOC_INTEL_CANNONLAKE help Intel Cannonlake support -config SOC_INTEL_COMMON_CANNONLAKE_BASE +config SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS bool default n select SOC_INTEL_CANNONLAKE @@ -11,7 +11,7 @@ config SOC_INTEL_COMMON_CANNONLAKE_BASE Single Kconfig option to select common base Cannonlake support. This Kconfig will help to select majority of CNL SoC features. Major difference that exist today between - SOC_INTEL_COMMON_CANNONLAKE_BASE and SOC_INTEL_CANNONLAKE Kconfig + SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS and SOC_INTEL_CANNONLAKE Kconfig are in FSP Header Files. Hence this Kconfig might help to select required SoC support FSP headers. Any future Intel SoC would like to make use of CNL support might just select this Kconfig. @@ -19,21 +19,21 @@ config SOC_INTEL_COMMON_CANNONLAKE_BASE config SOC_INTEL_COFFEELAKE bool default n - select SOC_INTEL_COMMON_CANNONLAKE_BASE + select SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS help Intel Coffeelake support config SOC_INTEL_WHISKEYLAKE bool default n - select SOC_INTEL_COMMON_CANNONLAKE_BASE + select SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS help Intel Whiskeylake support config SOC_INTEL_COMETLAKE bool default n - select SOC_INTEL_COMMON_CANNONLAKE_BASE + select SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS help Intel Cometlake support diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index 0d51c1ca5c..3b4c980e2d 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -111,7 +111,7 @@ struct soc_intel_cannonlake_config { enum { SaGv_Disabled, SaGv_FixedLow, -#if !CONFIG(SOC_INTEL_COMMON_CANNONLAKE_BASE) +#if !CONFIG(SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS) SaGv_FixedMid, #endif SaGv_FixedHigh, diff --git a/src/soc/intel/cannonlake/cpu.c b/src/soc/intel/cannonlake/cpu.c index d98e2f5486..7dae615350 100644 --- a/src/soc/intel/cannonlake/cpu.c +++ b/src/soc/intel/cannonlake/cpu.c @@ -500,7 +500,7 @@ int soc_skip_ucode_update(u32 current_patch_id, u32 new_patch_id) * have this check, where CNL CPU die is not based on KBL CPU * so skip this check for CNL. */ - if (!CONFIG(SOC_INTEL_COMMON_CANNONLAKE_BASE)) + if (!CONFIG(SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS)) return 0; /* diff --git a/src/soc/intel/cannonlake/romstage/fsp_params.c b/src/soc/intel/cannonlake/romstage/fsp_params.c index 77bad8f627..a1e3d76b4a 100644 --- a/src/soc/intel/cannonlake/romstage/fsp_params.c +++ b/src/soc/intel/cannonlake/romstage/fsp_params.c @@ -69,7 +69,7 @@ static void soc_memory_init_params(FSP_M_CONFIG *m_cfg, const config_t *config) /* Change VmxEnable UPD value according to ENABLE_VMX Kconfig */ m_cfg->VmxEnable = CONFIG(ENABLE_VMX); -#if CONFIG(SOC_INTEL_COMMON_CANNONLAKE_BASE) +#if CONFIG(SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS) m_cfg->SkipMpInit = !CONFIG_USE_INTEL_FSP_MP_INIT; #endif From 6beaef983aee5d886f6f8571855a92d608d98a17 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Sun, 16 Jun 2019 23:29:23 +0200 Subject: [PATCH 110/221] sb/intel/bd82x6x: Set up io_gen_dec in romstage based on devicetree Set up generic decode ranges based on the devicetree settings. Change-Id: Ie59b8272c69231d6dffccee30b4d3c84a7e83e8f Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33548 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: Patrick Rudolph --- src/mainboard/apple/macbookair4_2/romstage.c | 4 ---- src/mainboard/compulab/intense_pc/romstage.c | 6 ----- src/mainboard/gigabyte/ga-b75m-d3h/romstage.c | 1 - src/mainboard/google/butterfly/romstage.c | 7 ------ src/mainboard/google/link/romstage.c | 16 -------------- src/mainboard/google/parrot/romstage.c | 6 ----- src/mainboard/google/stout/romstage.c | 3 --- src/mainboard/hp/2570p/devicetree.cb | 1 + src/mainboard/hp/2570p/romstage.c | 2 -- src/mainboard/hp/2760p/devicetree.cb | 1 + src/mainboard/hp/2760p/romstage.c | 2 -- src/mainboard/hp/8460p/devicetree.cb | 1 + src/mainboard/hp/8460p/romstage.c | 2 -- src/mainboard/hp/8470p/devicetree.cb | 1 + src/mainboard/hp/8470p/romstage.c | 2 -- src/mainboard/hp/8770w/devicetree.cb | 1 + src/mainboard/hp/8770w/romstage.c | 2 -- src/mainboard/hp/folio_9470m/devicetree.cb | 1 + src/mainboard/hp/folio_9470m/romstage.c | 2 -- src/mainboard/hp/revolve_810_g1/devicetree.cb | 1 + src/mainboard/hp/revolve_810_g1/romstage.c | 2 -- .../intel/emeraldlake2/devicetree.cb | 5 ++++- src/mainboard/intel/emeraldlake2/romstage.c | 6 ----- src/mainboard/lenovo/l520/romstage.c | 4 ---- src/mainboard/lenovo/s230u/romstage.c | 3 --- src/mainboard/lenovo/t420/romstage.c | 4 ---- src/mainboard/lenovo/t420s/romstage.c | 4 ---- src/mainboard/lenovo/t430/romstage.c | 3 --- src/mainboard/lenovo/t430s/romstage.c | 4 ---- src/mainboard/lenovo/t520/romstage.c | 4 ---- src/mainboard/lenovo/t530/romstage.c | 4 ---- src/mainboard/lenovo/x131e/romstage.c | 5 ----- .../lenovo/x1_carbon_gen1/romstage.c | 4 ---- src/mainboard/lenovo/x220/romstage.c | 4 ---- src/mainboard/lenovo/x230/romstage.c | 4 ---- src/mainboard/samsung/lumpy/devicetree.cb | 1 + src/mainboard/samsung/lumpy/romstage.c | 3 --- src/mainboard/samsung/stumpy/devicetree.cb | 1 + src/mainboard/samsung/stumpy/romstage.c | 3 --- .../sapphire/pureplatinumh61/romstage.c | 4 ---- src/southbridge/intel/bd82x6x/early_pch.c | 22 +++++++++++++++++++ util/autoport/bd82x6x.go | 10 +++------ 42 files changed, 38 insertions(+), 128 deletions(-) diff --git a/src/mainboard/apple/macbookair4_2/romstage.c b/src/mainboard/apple/macbookair4_2/romstage.c index 6fee17ab0c..d04582d1ed 100644 --- a/src/mainboard/apple/macbookair4_2/romstage.c +++ b/src/mainboard/apple/macbookair4_2/romstage.c @@ -23,10 +23,6 @@ void pch_enable_lpc(void) { pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x3f0f); - pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x84, 0x000c0681); - pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x88, 0x000c1641); - pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x8c, 0x001c0301); - pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x90, 0x00fc0701); pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0070); pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xac, 0x80000000); } diff --git a/src/mainboard/compulab/intense_pc/romstage.c b/src/mainboard/compulab/intense_pc/romstage.c index 6d0b3af8c0..6c3d980b65 100644 --- a/src/mainboard/compulab/intense_pc/romstage.c +++ b/src/mainboard/compulab/intense_pc/romstage.c @@ -33,12 +33,6 @@ void pch_enable_lpc(void) u16 lpc_config = CNF1_LPC_EN | CNF2_LPC_EN; pci_write_config16(dev, LPC_EN, lpc_config); - /* Map 1 byte to the LPC bus. */ - pci_write_config32(dev, LPC_GEN1_DEC, 0x00164d); - - /* Map a range for the runtime_port registers to the LPC bus. */ - pci_write_config32(dev, LPC_GEN2_DEC, 0xc0181); - #if CONFIG(DRIVERS_UART_8250IO) /* Enable COM1 */ if (sio1007_enable_uart_at(SIO_PORT)) { diff --git a/src/mainboard/gigabyte/ga-b75m-d3h/romstage.c b/src/mainboard/gigabyte/ga-b75m-d3h/romstage.c index 67bcbcb8c9..b35a8b4af9 100644 --- a/src/mainboard/gigabyte/ga-b75m-d3h/romstage.c +++ b/src/mainboard/gigabyte/ga-b75m-d3h/romstage.c @@ -30,7 +30,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, KBC_LPC_EN | CNF1_LPC_EN | CNF2_LPC_EN | COMA_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x3c0a01); pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x10); pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); diff --git a/src/mainboard/google/butterfly/romstage.c b/src/mainboard/google/butterfly/romstage.c index d34b1e4574..844f754cfc 100644 --- a/src/mainboard/google/butterfly/romstage.c +++ b/src/mainboard/google/butterfly/romstage.c @@ -33,13 +33,6 @@ void pch_enable_lpc(void) /* EC Decode Range Port60/64 and Port62/66 */ /* Enable EC and PS/2 Keyboard/Mouse*/ pci_write_config16(PCH_LPC_DEV, LPC_EN, KBC_LPC_EN | MC_LPC_EN); - - /* EC Decode Range Port68/6C */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, (0x68 & ~3) | 0x40001); - - /* EC Decode Range Port 380-387 */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0x380 | 0x40001); - } void mainboard_rcba_config(void) diff --git a/src/mainboard/google/link/romstage.c b/src/mainboard/google/link/romstage.c index 8da13080b3..2f3f07cdce 100644 --- a/src/mainboard/google/link/romstage.c +++ b/src/mainboard/google/link/romstage.c @@ -34,28 +34,12 @@ void pch_enable_lpc(void) { - const struct device *lpc; - const struct southbridge_intel_bd82x6x_config *config = NULL; - - lpc = pcidev_on_root(0x1f, 0); - if (!lpc) - return; - if (lpc->chip_info) - config = lpc->chip_info; - if (!config) - return; - /* Set COM1/COM2 decode range */ pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010); /* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */ pci_write_config16(PCH_LPC_DEV, LPC_EN, KBC_LPC_EN | MC_LPC_EN | \ GAMEL_LPC_EN | COMA_LPC_EN); - - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, config->gen1_dec); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, config->gen2_dec); - pci_write_config32(PCH_LPC_DEV, LPC_GEN3_DEC, config->gen3_dec); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, config->gen4_dec); } void mainboard_rcba_config(void) diff --git a/src/mainboard/google/parrot/romstage.c b/src/mainboard/google/parrot/romstage.c index 76a4b4b677..ac06fbc83e 100644 --- a/src/mainboard/google/parrot/romstage.c +++ b/src/mainboard/google/parrot/romstage.c @@ -31,12 +31,6 @@ void pch_enable_lpc(void) /* Parrot EC Decode Range Port60/64, Port62/66 */ /* Enable EC, PS/2 Keyboard/Mouse */ pci_write_config16(PCH_LPC_DEV, LPC_EN, KBC_LPC_EN | MC_LPC_EN); - - /* Map EC_IO decode to the LPC bus */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, (EC_IO & ~3) | 0x00040001); - - /* Map EC registers 68/6C decode to the LPC bus */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, (68 & ~3) | 0x00040001); } void mainboard_rcba_config(void) diff --git a/src/mainboard/google/stout/romstage.c b/src/mainboard/google/stout/romstage.c index 7539dd7f51..6690c6863c 100644 --- a/src/mainboard/google/stout/romstage.c +++ b/src/mainboard/google/stout/romstage.c @@ -41,9 +41,6 @@ void pch_enable_lpc(void) */ pci_write_config16(PCH_LPC_DEV, LPC_EN, KBC_LPC_EN | MC_LPC_EN | CNF1_LPC_EN | FDD_LPC_EN); - - /* Stout EC Decode Range Port68/6C */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, (0x68 | 0x40001)); } void mainboard_rcba_config(void) diff --git a/src/mainboard/hp/2570p/devicetree.cb b/src/mainboard/hp/2570p/devicetree.cb index 585d61d134..79a84b73c2 100644 --- a/src/mainboard/hp/2570p/devicetree.cb +++ b/src/mainboard/hp/2570p/devicetree.cb @@ -46,6 +46,7 @@ chip northbridge/intel/sandybridge chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH register "c2_latency" = "0x0065" register "docking_supported" = "0" + # mailbox at 0x200/0x201 and PM1 at 0x220 register "gen1_dec" = "0x007c0201" register "gen2_dec" = "0x000c0101" register "gen3_dec" = "0x00fcfe01" diff --git a/src/mainboard/hp/2570p/romstage.c b/src/mainboard/hp/2570p/romstage.c index 21e3ceaa3d..6401909dd5 100644 --- a/src/mainboard/hp/2570p/romstage.c +++ b/src/mainboard/hp/2570p/romstage.c @@ -28,8 +28,6 @@ void pch_enable_lpc(void) */ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - /* Enable mailbox at 0x200/0x201 and PM1 at 0x220 */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x007c0201); } void mainboard_rcba_config(void) diff --git a/src/mainboard/hp/2760p/devicetree.cb b/src/mainboard/hp/2760p/devicetree.cb index 515d20f761..a301857b7a 100644 --- a/src/mainboard/hp/2760p/devicetree.cb +++ b/src/mainboard/hp/2760p/devicetree.cb @@ -55,6 +55,7 @@ chip northbridge/intel/sandybridge chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH register "c2_latency" = "0x0065" register "docking_supported" = "0" + # mailbox at 0x200/0x201 and PM1 at 0x220 register "gen1_dec" = "0x007c0201" register "gen2_dec" = "0x000c0101" register "gen3_dec" = "0x00fcfe01" diff --git a/src/mainboard/hp/2760p/romstage.c b/src/mainboard/hp/2760p/romstage.c index 68af61ba22..ba6f9566cf 100644 --- a/src/mainboard/hp/2760p/romstage.c +++ b/src/mainboard/hp/2760p/romstage.c @@ -27,8 +27,6 @@ void pch_enable_lpc(void) */ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - /* Enable mailbox at 0x200/0x201 and PM1 at 0x220 */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x007c0201); } void mainboard_rcba_config(void) diff --git a/src/mainboard/hp/8460p/devicetree.cb b/src/mainboard/hp/8460p/devicetree.cb index 79259b4def..a06aea9669 100644 --- a/src/mainboard/hp/8460p/devicetree.cb +++ b/src/mainboard/hp/8460p/devicetree.cb @@ -54,6 +54,7 @@ chip northbridge/intel/sandybridge chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH register "c2_latency" = "0x0065" register "docking_supported" = "0" + # mailbox at 0x200/0x201 and PM1 at 0x220 register "gen1_dec" = "0x007c0201" register "gen2_dec" = "0x000c0101" register "gen3_dec" = "0x00fcfe01" diff --git a/src/mainboard/hp/8460p/romstage.c b/src/mainboard/hp/8460p/romstage.c index a3fb5f095f..f30c3a8d27 100644 --- a/src/mainboard/hp/8460p/romstage.c +++ b/src/mainboard/hp/8460p/romstage.c @@ -34,8 +34,6 @@ void pch_enable_lpc(void) CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN | LPT_LPC_EN | COMA_LPC_EN); pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010); - /* Enable mailbox at 0x200/0x201 and PM1 at 0x220 */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x007c0201); } void mainboard_rcba_config(void) diff --git a/src/mainboard/hp/8470p/devicetree.cb b/src/mainboard/hp/8470p/devicetree.cb index 2a115cc62a..471537218e 100644 --- a/src/mainboard/hp/8470p/devicetree.cb +++ b/src/mainboard/hp/8470p/devicetree.cb @@ -55,6 +55,7 @@ chip northbridge/intel/sandybridge chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH register "c2_latency" = "0x0065" register "docking_supported" = "0" + # mailbox at 0x200/0x201 and PM1 at 0x220 register "gen1_dec" = "0x007c0201" register "gen2_dec" = "0x000c0101" register "gen3_dec" = "0x00fcfe01" diff --git a/src/mainboard/hp/8470p/romstage.c b/src/mainboard/hp/8470p/romstage.c index a8761739d5..b1375e815b 100644 --- a/src/mainboard/hp/8470p/romstage.c +++ b/src/mainboard/hp/8470p/romstage.c @@ -33,8 +33,6 @@ void pch_enable_lpc(void) CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN | LPT_LPC_EN | COMA_LPC_EN); pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010); - /* Enable mailbox at 0x200/0x201 and PM1 at 0x220 */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x007c0201); } void mainboard_rcba_config(void) diff --git a/src/mainboard/hp/8770w/devicetree.cb b/src/mainboard/hp/8770w/devicetree.cb index 7d74c940de..d98402c540 100644 --- a/src/mainboard/hp/8770w/devicetree.cb +++ b/src/mainboard/hp/8770w/devicetree.cb @@ -43,6 +43,7 @@ chip northbridge/intel/sandybridge chip southbridge/intel/bd82x6x # Intel Series 7 Panther Point PCH register "c2_latency" = "0x0065" register "docking_supported" = "0" + # mailbox at 0x200/0x201 and PM1 at 0x220 register "gen1_dec" = "0x007c0201" register "gen2_dec" = "0x000c0101" register "gen3_dec" = "0x00fcfe01" diff --git a/src/mainboard/hp/8770w/romstage.c b/src/mainboard/hp/8770w/romstage.c index a7f6b22aa3..8956b08b7b 100644 --- a/src/mainboard/hp/8770w/romstage.c +++ b/src/mainboard/hp/8770w/romstage.c @@ -34,8 +34,6 @@ void pch_enable_lpc(void) CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN | LPT_LPC_EN | COMA_LPC_EN); pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010); - /* Enable mailbox at 0x200/0x201 and PM1 at 0x220 */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x007c0201); } void mainboard_rcba_config(void) diff --git a/src/mainboard/hp/folio_9470m/devicetree.cb b/src/mainboard/hp/folio_9470m/devicetree.cb index 5d4e5b8ea2..d626934343 100644 --- a/src/mainboard/hp/folio_9470m/devicetree.cb +++ b/src/mainboard/hp/folio_9470m/devicetree.cb @@ -46,6 +46,7 @@ chip northbridge/intel/sandybridge # FIXME: check gfx.ndid and gfx.did chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH register "c2_latency" = "0x0065" register "docking_supported" = "0" + # mailbox at 0x200/0x201 and PM1 at 0x220 register "gen1_dec" = "0x007c0201" register "gen2_dec" = "0x000c0101" register "gen3_dec" = "0x00fcfe01" diff --git a/src/mainboard/hp/folio_9470m/romstage.c b/src/mainboard/hp/folio_9470m/romstage.c index db3296c457..8ff7813cd9 100644 --- a/src/mainboard/hp/folio_9470m/romstage.c +++ b/src/mainboard/hp/folio_9470m/romstage.c @@ -30,8 +30,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010); - /* Enable mailbox at 0x200/0x201 and PM1 at 0x220 */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x007c0201); } void mainboard_rcba_config(void) diff --git a/src/mainboard/hp/revolve_810_g1/devicetree.cb b/src/mainboard/hp/revolve_810_g1/devicetree.cb index 4d0d6395eb..ad69ca27e4 100644 --- a/src/mainboard/hp/revolve_810_g1/devicetree.cb +++ b/src/mainboard/hp/revolve_810_g1/devicetree.cb @@ -46,6 +46,7 @@ chip northbridge/intel/sandybridge # FIXME: check gfx.ndid and gfx.did chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH register "c2_latency" = "0x0065" register "docking_supported" = "0" + # mailbox at 0x200/0x201 and PM1 at 0x220 register "gen1_dec" = "0x007c0201" register "gen2_dec" = "0x000c0101" register "gen3_dec" = "0x00fcfe01" diff --git a/src/mainboard/hp/revolve_810_g1/romstage.c b/src/mainboard/hp/revolve_810_g1/romstage.c index f62024c3e6..5f8df63f5c 100644 --- a/src/mainboard/hp/revolve_810_g1/romstage.c +++ b/src/mainboard/hp/revolve_810_g1/romstage.c @@ -33,8 +33,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x0010); - /* Enable mailbox at 0x200/0x201 and PM1 at 0x220 */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x007c0201); } void mainboard_rcba_config(void) diff --git a/src/mainboard/intel/emeraldlake2/devicetree.cb b/src/mainboard/intel/emeraldlake2/devicetree.cb index 60072b0995..4ed1f3c694 100644 --- a/src/mainboard/intel/emeraldlake2/devicetree.cb +++ b/src/mainboard/intel/emeraldlake2/devicetree.cb @@ -44,8 +44,11 @@ chip northbridge/intel/sandybridge register "sata_port_map" = "0x3f" + register "gen1_dec" = "0x00fc1601" + # runtime_port registers + register "gen2_dec" = "0x000c0181" # SuperIO range is 0x700-0x73f - register "gen2_dec" = "0x003c0701" + register "gen3_dec" = "0x003c0701" register "c2_latency" = "1" register "p_cnt_throttling_supported" = "0" diff --git a/src/mainboard/intel/emeraldlake2/romstage.c b/src/mainboard/intel/emeraldlake2/romstage.c index 9a9fc24677..a28ae78f28 100644 --- a/src/mainboard/intel/emeraldlake2/romstage.c +++ b/src/mainboard/intel/emeraldlake2/romstage.c @@ -39,12 +39,6 @@ void pch_enable_lpc(void) u16 lpc_config = CNF1_LPC_EN | CNF2_LPC_EN | KBC_LPC_EN; pci_write_config16(dev, LPC_EN, lpc_config); - /* Map 256 bytes at 0x1600 to the LPC bus. */ - pci_write_config32(dev, LPC_GEN1_DEC, 0xfc1601); - - /* Map a range for the runtime_port registers to the LPC bus. */ - pci_write_config32(dev, LPC_GEN2_DEC, 0xc0181); - /* Enable COM1 */ if (sio1007_enable_uart_at(SIO_PORT)) { pci_write_config16(dev, LPC_EN, diff --git a/src/mainboard/lenovo/l520/romstage.c b/src/mainboard/lenovo/l520/romstage.c index c8003ae0a6..426ac4e6fa 100644 --- a/src/mainboard/lenovo/l520/romstage.c +++ b/src/mainboard/lenovo/l520/romstage.c @@ -29,10 +29,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN | LPT_LPC_EN); - - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1611); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0x040069); - pci_write_config32(PCH_LPC_DEV, LPC_GEN3_DEC, 0x0c0701); } void mainboard_rcba_config(void) diff --git a/src/mainboard/lenovo/s230u/romstage.c b/src/mainboard/lenovo/s230u/romstage.c index 32a3cc2c7d..dd8fc17268 100644 --- a/src/mainboard/lenovo/s230u/romstage.c +++ b/src/mainboard/lenovo/s230u/romstage.c @@ -30,9 +30,6 @@ void pch_enable_lpc(void) { pci_write_config16(PCH_LPC_DEV, LPC_EN, MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc0701); - pci_write_config32(PCH_LPC_DEV, LPC_GEN3_DEC, 0xc0069); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0xc06a1); pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); /* Memory map KB9012 EC registers */ diff --git a/src/mainboard/lenovo/t420/romstage.c b/src/mainboard/lenovo/t420/romstage.c index 806c72a3be..ebf5aed0f1 100644 --- a/src/mainboard/lenovo/t420/romstage.c +++ b/src/mainboard/lenovo/t420/romstage.c @@ -56,10 +56,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x0c06a1); - pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); } diff --git a/src/mainboard/lenovo/t420s/romstage.c b/src/mainboard/lenovo/t420s/romstage.c index 9c5171371c..49de58d8d1 100644 --- a/src/mainboard/lenovo/t420s/romstage.c +++ b/src/mainboard/lenovo/t420s/romstage.c @@ -56,10 +56,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x0c06a1); - pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); } diff --git a/src/mainboard/lenovo/t430/romstage.c b/src/mainboard/lenovo/t430/romstage.c index db50bb3017..1f4b90d7f9 100644 --- a/src/mainboard/lenovo/t430/romstage.c +++ b/src/mainboard/lenovo/t430/romstage.c @@ -55,9 +55,6 @@ void pch_enable_lpc(void) /* Enable TPM, EC, PS/2 Keyboard/Mouse */ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, - (0x0c << 16) | EC_LENOVO_PMH7_BASE | 1); } void mainboard_rcba_config(void) diff --git a/src/mainboard/lenovo/t430s/romstage.c b/src/mainboard/lenovo/t430s/romstage.c index 4edd5c6131..e590bb6c67 100644 --- a/src/mainboard/lenovo/t430s/romstage.c +++ b/src/mainboard/lenovo/t430s/romstage.c @@ -26,10 +26,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x0c06a1); - pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); } diff --git a/src/mainboard/lenovo/t520/romstage.c b/src/mainboard/lenovo/t520/romstage.c index ebff37ff9c..5c23b8e06f 100644 --- a/src/mainboard/lenovo/t520/romstage.c +++ b/src/mainboard/lenovo/t520/romstage.c @@ -58,10 +58,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x0c06a1); - pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); } diff --git a/src/mainboard/lenovo/t530/romstage.c b/src/mainboard/lenovo/t530/romstage.c index 24e2d9cde0..67cf97c486 100644 --- a/src/mainboard/lenovo/t530/romstage.c +++ b/src/mainboard/lenovo/t530/romstage.c @@ -58,10 +58,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x0c06a1); - pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); } diff --git a/src/mainboard/lenovo/x131e/romstage.c b/src/mainboard/lenovo/x131e/romstage.c index ea550aa143..79a2276fd0 100644 --- a/src/mainboard/lenovo/x131e/romstage.c +++ b/src/mainboard/lenovo/x131e/romstage.c @@ -26,11 +26,6 @@ void pch_enable_lpc(void) /* Enable TPM, EC, PS/2 Keyboard/Mouse */ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x007c1611); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0x00040069); - pci_write_config32(PCH_LPC_DEV, LPC_GEN3_DEC, 0x000c0701); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x000c06a1); } void mainboard_rcba_config(void) diff --git a/src/mainboard/lenovo/x1_carbon_gen1/romstage.c b/src/mainboard/lenovo/x1_carbon_gen1/romstage.c index a951fbc72e..f666671dd6 100644 --- a/src/mainboard/lenovo/x1_carbon_gen1/romstage.c +++ b/src/mainboard/lenovo/x1_carbon_gen1/romstage.c @@ -35,10 +35,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x0c06a1); - pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); } diff --git a/src/mainboard/lenovo/x220/romstage.c b/src/mainboard/lenovo/x220/romstage.c index 5f9a931340..9ecb8a3e1e 100644 --- a/src/mainboard/lenovo/x220/romstage.c +++ b/src/mainboard/lenovo/x220/romstage.c @@ -34,10 +34,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x0c06a1); - pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); } diff --git a/src/mainboard/lenovo/x230/romstage.c b/src/mainboard/lenovo/x230/romstage.c index 3f31141583..10cddebda3 100644 --- a/src/mainboard/lenovo/x230/romstage.c +++ b/src/mainboard/lenovo/x230/romstage.c @@ -31,10 +31,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF2_LPC_EN | CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0x7c1601); - pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, 0xc15e1); - pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, 0x0c06a1); - pci_write_config32(PCH_LPC_DEV, ETR3, 0x10000); } diff --git a/src/mainboard/samsung/lumpy/devicetree.cb b/src/mainboard/samsung/lumpy/devicetree.cb index 719947310b..feae5bf1e8 100644 --- a/src/mainboard/samsung/lumpy/devicetree.cb +++ b/src/mainboard/samsung/lumpy/devicetree.cb @@ -61,6 +61,7 @@ chip northbridge/intel/sandybridge # EC range is 0xa00-0xa3f register "gen1_dec" = "0x003c0a01" register "gen2_dec" = "0x003c0b01" + register "gen3_dec" = "0x00fc1601" register "c2_latency" = "1" register "p_cnt_throttling_supported" = "0" diff --git a/src/mainboard/samsung/lumpy/romstage.c b/src/mainboard/samsung/lumpy/romstage.c index a77149d927..d4b6dd834b 100644 --- a/src/mainboard/samsung/lumpy/romstage.c +++ b/src/mainboard/samsung/lumpy/romstage.c @@ -43,9 +43,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN | CNF2_LPC_EN | COMA_LPC_EN); - /* map full 256 bytes at 0x1600 to the LPC bus */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0xfc1601); - try_enabling_LPC47N207_uart(); #else /* Enable SuperIO + EC + KBC */ diff --git a/src/mainboard/samsung/stumpy/devicetree.cb b/src/mainboard/samsung/stumpy/devicetree.cb index 192e63d4d9..060fc40bb6 100644 --- a/src/mainboard/samsung/stumpy/devicetree.cb +++ b/src/mainboard/samsung/stumpy/devicetree.cb @@ -50,6 +50,7 @@ chip northbridge/intel/sandybridge register "c2_latency" = "1" register "p_cnt_throttling_supported" = "0" + register "gen1_dec" = "0x00fc1601" # SuperIO range is 0x700-0x73f register "gen2_dec" = "0x003c0701" diff --git a/src/mainboard/samsung/stumpy/romstage.c b/src/mainboard/samsung/stumpy/romstage.c index a8e28d67ac..77fd16016d 100644 --- a/src/mainboard/samsung/stumpy/romstage.c +++ b/src/mainboard/samsung/stumpy/romstage.c @@ -55,9 +55,6 @@ void pch_enable_lpc(void) pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | KBC_LPC_EN |\ CNF2_LPC_EN | COMA_LPC_EN); - /* map full 256 bytes at 0x1600 to the LPC bus */ - pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, 0xfc1601); - try_enabling_LPC47N207_uart(); #else /* Enable SuperIO + PS/2 Keyboard/Mouse */ diff --git a/src/mainboard/sapphire/pureplatinumh61/romstage.c b/src/mainboard/sapphire/pureplatinumh61/romstage.c index 9a67ab295b..c7d8f0f724 100644 --- a/src/mainboard/sapphire/pureplatinumh61/romstage.c +++ b/src/mainboard/sapphire/pureplatinumh61/romstage.c @@ -24,10 +24,6 @@ void pch_enable_lpc(void) { pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x2400); - pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x84, 0x000c0291); - pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x88, 0x000c0a01); - pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x8c, 0x00000000); - pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x90, 0x00000000); pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0000); pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xac, 0x00010000); } diff --git a/src/southbridge/intel/bd82x6x/early_pch.c b/src/southbridge/intel/bd82x6x/early_pch.c index e74c3043f0..4f9cd325c6 100644 --- a/src/southbridge/intel/bd82x6x/early_pch.c +++ b/src/southbridge/intel/bd82x6x/early_pch.c @@ -27,6 +27,7 @@ #include #include "pch.h" +#include "chip.h" #define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0) @@ -258,10 +259,31 @@ static void pch_generic_setup(void) write_pmbase16(TCO1_CNT, 1 << 11); /* halt timer */ } +static void pch_enable_lpc_gen_decode(void) +{ + const struct device *dev = pcidev_on_root(0x1f, 0); + const struct southbridge_intel_bd82x6x_config *config = NULL; + + /* Set up generic decode ranges */ + if (!dev) + return; + if (dev->chip_info) + config = dev->chip_info; + if (!config) + return; + + pci_write_config32(PCH_LPC_DEV, LPC_GEN1_DEC, config->gen1_dec); + pci_write_config32(PCH_LPC_DEV, LPC_GEN2_DEC, config->gen2_dec); + pci_write_config32(PCH_LPC_DEV, LPC_GEN3_DEC, config->gen3_dec); + pci_write_config32(PCH_LPC_DEV, LPC_GEN4_DEC, config->gen4_dec); +} + void early_pch_init(void) { pch_enable_lpc(); + pch_enable_lpc_gen_decode(); + pch_enable_bars(); pch_generic_setup(); diff --git a/util/autoport/bd82x6x.go b/util/autoport/bd82x6x.go index e93704ec4a..141ec5c7ae 100644 --- a/util/autoport/bd82x6x.go +++ b/util/autoport/bd82x6x.go @@ -28,7 +28,7 @@ func (b bd82x6x) writeGPIOSet(ctx Context, sb *os.File, } for i := uint(0); i < max; i++ { - if ((constraint>>i)&1 == 1) { + if (constraint>>i)&1 == 1 { fmt.Fprintf(sb, " .gpio%d = %s,\n", (set-1)*32+i, bits[partno][(val>>i)&1]) @@ -236,8 +236,8 @@ func (b bd82x6x) Scan(ctx Context, addr PCIDevData) { "p_cnt_throttling_supported": (FormatBool(FADT[104] == 1 && FADT[105] == 3)), "c2_latency": FormatHexLE16(FADT[96:98]), "docking_supported": (FormatBool((FADT[113] & (1 << 1)) != 0)), - "spi_uvscc": fmt.Sprintf("0x%x", inteltool.RCBA[0x38c8]), - "spi_lvscc": fmt.Sprintf("0x%x", inteltool.RCBA[0x38c4] &^ (1 << 23)), + "spi_uvscc": fmt.Sprintf("0x%x", inteltool.RCBA[0x38c8]), + "spi_lvscc": fmt.Sprintf("0x%x", inteltool.RCBA[0x38c4]&^(1<<23)), }, PCISlots: []PCISlot{ PCISlot{PCIAddr: PCIAddr{Dev: 0x14, Func: 0}, writeEmpty: false, additionalComment: "USB 3.0 Controller"}, @@ -315,10 +315,6 @@ void pch_enable_lpc(void) { `) RestorePCI16Simple(sb, addr, 0x82) - RestorePCI32Simple(sb, addr, 0x84) - RestorePCI32Simple(sb, addr, 0x88) - RestorePCI32Simple(sb, addr, 0x8c) - RestorePCI32Simple(sb, addr, 0x90) RestorePCI16Simple(sb, addr, 0x80) From 019a253b34029342da8451616b88877ba08b3786 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sat, 25 May 2019 11:13:43 +0200 Subject: [PATCH 111/221] nb/intel/nehalem/raminit.c: Remove variable set but not used Change-Id: I5d3a04970fa57f07ca7dd748f114ac0cd6955522 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33004 Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- src/northbridge/intel/nehalem/raminit.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/northbridge/intel/nehalem/raminit.c b/src/northbridge/intel/nehalem/raminit.c index 15d6abb67b..686089fdd0 100644 --- a/src/northbridge/intel/nehalem/raminit.c +++ b/src/northbridge/intel/nehalem/raminit.c @@ -2235,26 +2235,11 @@ train_ram_at_178(struct raminfo *info, u8 channel, int slot, int rank, u8 lower_usable[8]; u8 upper_usable[8]; unsigned short num_successfully_checked[8]; - u8 secondary_total_rank; u8 reg1b3; + int i; - if (info->populated_ranks_mask[1]) { - if (channel == 1) - secondary_total_rank = - info->populated_ranks[1][0][0] + - info->populated_ranks[1][0][1] - + info->populated_ranks[1][1][0] + - info->populated_ranks[1][1][1]; - else - secondary_total_rank = 0; - } else - secondary_total_rank = total_rank; - - { - int i; - for (i = 0; i < 8; i++) - state[i] = BEFORE_USABLE; - } + for (i = 0; i < 8; i++) + state[i] = BEFORE_USABLE; if (!first_run) { int is_all_ok = 1; @@ -2270,7 +2255,6 @@ train_ram_at_178(struct raminfo *info, u8 channel, int slot, int rank, is_all_ok = 0; } if (is_all_ok) { - int i; for (i = 0; i < 8; i++) state[i] = COMPLETE; } @@ -2336,7 +2320,6 @@ train_ram_at_178(struct raminfo *info, u8 channel, int slot, int rank, do { u8 failmask = 0; - int i; for (i = 0; i < niter; i++) { if (failmask == 0xFF) break; @@ -2437,7 +2420,6 @@ train_ram_at_178(struct raminfo *info, u8 channel, int slot, int rank, do { int failmask = 0; - int i; for (i = 0; i < niter; i++) { if (failmask == 0xFF) break; From 3c3f836d7e27f5dbd396d367ceb09908045ec230 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 22 May 2019 20:31:48 +0200 Subject: [PATCH 112/221] sb/intel/bd82x6x/early_pch.c: Remove variable set but not used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: If359eaa010949427dbff1e3a83528c0ad399dc9d Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32943 Reviewed-by: Patrick Georgi Reviewed-by: Kyösti Mälkki Tested-by: build bot (Jenkins) --- src/southbridge/intel/bd82x6x/early_pch.c | 35 ++++++++++------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/southbridge/intel/bd82x6x/early_pch.c b/src/southbridge/intel/bd82x6x/early_pch.c index 4f9cd325c6..c1631f4229 100644 --- a/src/southbridge/intel/bd82x6x/early_pch.c +++ b/src/southbridge/intel/bd82x6x/early_pch.c @@ -41,7 +41,6 @@ wait_iobp(void) static u32 read_iobp(u32 address) { - volatile u32 tmp; u32 ret; RCBA32(IOBPIRI) = address; @@ -49,14 +48,13 @@ read_iobp(u32 address) wait_iobp(); ret = RCBA32(IOBPD); wait_iobp(); - tmp = RCBA8(IOBPS); // call wait_iobp() instead here? + RCBA8(IOBPS); // call wait_iobp() instead here? return ret; } static void write_iobp(u32 address, u32 val) { - volatile u32 tmp; /* this function was probably pch_iobp_update with the andvalue * being 0. So either the IOBP read can be removed or this function * and the pch_iobp_update function in ramstage could be merged */ @@ -68,7 +66,7 @@ write_iobp(u32 address, u32 val) wait_iobp(); RCBA16(IOBPS) = (RCBA16(IOBPS) & 0x1ff) | 0x600; - tmp = RCBA8(IOBPS); // call wait_iobp() instead here? + RCBA8(IOBPS); // call wait_iobp() instead here? } void early_pch_init_native_dmi_pre(void) @@ -85,14 +83,12 @@ void early_pch_init_native_dmi_pre(void) void early_pch_init_native_dmi_post(void) { - volatile u32 tmp; - - tmp = RCBA32(0x0050); // !!! = 0x01200654 + RCBA32(0x0050); // !!! = 0x01200654 RCBA32(0x0050) = 0x01200654; - tmp = RCBA32(0x0050); // !!! = 0x01200654 + RCBA32(0x0050); // !!! = 0x01200654 RCBA32(0x0050) = 0x012a0654; - tmp = RCBA32(0x0050); // !!! = 0x012a0654 - tmp = RCBA8(0x1114); // !!! = 0x00 + RCBA32(0x0050); // !!! = 0x012a0654 + RCBA8(0x1114); // !!! = 0x00 RCBA8(0x1114) = 0x05; /* @@ -119,7 +115,7 @@ void early_pch_init_native_dmi_post(void) */ RCBA32(0x2020) = (1 << 31) | (1 << 24) | (0x11 << 1); /* Read back register */ - tmp = RCBA32(0x2020); + RCBA32(0x2020); /* Virtual Channel private Resource Control Register. * Enable channel. @@ -128,7 +124,7 @@ void early_pch_init_native_dmi_post(void) */ RCBA32(0x2030) = (1 << 31) | (2 << 24) | (0x22 << 1); /* Read back register */ - tmp = RCBA32(0x2030); + RCBA32(0x2030); /* Virtual Channel ME Resource Control Register. * Enable channel. @@ -140,7 +136,7 @@ void early_pch_init_native_dmi_post(void) /* Lock Virtual Channel Resource control register. */ RCBA32(0x0050) |= 0x80000000; /* Read back register */ - tmp = RCBA32(0x0050); + RCBA32(0x0050); /* Wait for virtual channels negotiation pending */ while (RCBA16(0x201a) & VCNEGPND) @@ -156,24 +152,23 @@ void early_pch_init_native_dmi_post(void) void early_pch_init_native (void) { - volatile u32 tmp; pci_write_config8 (SOUTHBRIDGE, 0xa6, pci_read_config8 (SOUTHBRIDGE, 0xa6) | 2); RCBA32(0x2088) = 0x00109000; - tmp = RCBA32(0x20ac); // !!! = 0x00000000 + RCBA32(0x20ac); // !!! = 0x00000000 RCBA32(0x20ac) = 0x40000000; RCBA32(0x100c) = 0x01110000; RCBA8(0x2340) = 0x1b; - tmp = RCBA32(0x2314); // !!! = 0x0a080000 + RCBA32(0x2314); // !!! = 0x0a080000 RCBA32(0x2314) = 0x0a280000; - tmp = RCBA32(0x2310); // !!! = 0xc809605b + RCBA32(0x2310); // !!! = 0xc809605b RCBA32(0x2310) = 0xa809605b; RCBA32(0x2324) = 0x00854c74; - tmp = RCBA8(0x0400); // !!! = 0x00 - tmp = RCBA32(0x2310); // !!! = 0xa809605b + RCBA8(0x0400); // !!! = 0x00 + RCBA32(0x2310); // !!! = 0xa809605b RCBA32(0x2310) = 0xa809605b; - tmp = RCBA32(0x2310); // !!! = 0xa809605b + RCBA32(0x2310); // !!! = 0xa809605b RCBA32(0x2310) = 0xa809605b; write_iobp(0xea007f62, 0x00590133); From 97642c28f6e562617f20330bb7e8a334ac507073 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 22 May 2019 20:53:25 +0200 Subject: [PATCH 113/221] nb/intel/nehalem/raminit.c: Remove variable set but not used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I216d4d00375fcff9e740583b9e17013e0495360c Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32944 Reviewed-by: Patrick Georgi Reviewed-by: Kyösti Mälkki Tested-by: build bot (Jenkins) --- src/northbridge/intel/nehalem/raminit.c | 29 ++++++++++--------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/northbridge/intel/nehalem/raminit.c b/src/northbridge/intel/nehalem/raminit.c index 686089fdd0..2b71c81825 100644 --- a/src/northbridge/intel/nehalem/raminit.c +++ b/src/northbridge/intel/nehalem/raminit.c @@ -3722,11 +3722,6 @@ void raminit(const int s3resume, const u8 *spd_addrmap) u16 deven; int cbmem_wasnot_inited; - /* only used for dummy reads */ - volatile u8 tmp8; - volatile u16 tmp16; - volatile u32 tmp32; - x2ca8 = MCHBAR8(0x2ca8); deven = pci_read_config16(NORTHBRIDGE, D0F0_DEVEN); @@ -4040,10 +4035,10 @@ void raminit(const int s3resume, const u8 *spd_addrmap) pci_read_config8(PCI_DEV (0, 0x2, 0x0), 0x4c); pci_read_config8(PCI_DEV (0, 0x2, 0x0), 0x4e); - tmp8 = MCHBAR8(0x1150); - tmp8 = MCHBAR8(0x1151); - tmp8 = MCHBAR8(0x1022); - tmp8 = MCHBAR8(0x16d0); + MCHBAR8(0x1150); + MCHBAR8(0x1151); + MCHBAR8(0x1022); + MCHBAR8(0x16d0); MCHBAR32(0x1300) = 0x60606060; MCHBAR32(0x1304) = 0x60606060; MCHBAR32(0x1308) = 0x78797a7b; @@ -4231,10 +4226,10 @@ void raminit(const int s3resume, const u8 *spd_addrmap) } MCHBAR32_AND_OR(0x2c80, 0, 0x1053688); // !!!! - tmp32 = MCHBAR32(0x1c04); // !!!! + MCHBAR32(0x1c04); // !!!! MCHBAR32(0x1804) = 0x406080; - tmp8 = MCHBAR8(0x2ca8); + MCHBAR8(0x2ca8); if (x2ca8 == 0) { MCHBAR8_AND(0x2ca8, ~3); @@ -4246,9 +4241,9 @@ void raminit(const int s3resume, const u8 *spd_addrmap) MCHBAR8(0x2ca8) = MCHBAR8(0x2ca8); MCHBAR32_AND_OR(0x2c80, 0, 0x53688); // !!!! pci_write_config32(PCI_DEV (0xff, 0, 0), 0x60, 0x20220); - tmp16 = MCHBAR16(0x2c20); // !!!! - tmp16 = MCHBAR16(0x2c10); // !!!! - tmp16 = MCHBAR16(0x2c00); // !!!! + MCHBAR16(0x2c20); // !!!! + MCHBAR16(0x2c10); // !!!! + MCHBAR16(0x2c00); // !!!! MCHBAR16(0x2c00) = 0x8c0; udelay(1000); write_1d0(0, 0x33d, 0, 0); @@ -4354,7 +4349,7 @@ void raminit(const int s3resume, const u8 *spd_addrmap) MCHBAR32_AND_OR(0x1f4, 0, 0x20000); // !!!! MCHBAR32(0x1f0) = 0x1d000200; MCHBAR8_AND_OR(0x1f0, 0, 0x1); // !!!! - tmp8 = MCHBAR8(0x1f0); // !!!! + MCHBAR8(0x1f0); // !!!! program_board_delay(&info); @@ -4413,7 +4408,7 @@ void raminit(const int s3resume, const u8 *spd_addrmap) info.populated_ranks[channel][0][0] ? 9 : 1); rmw_1d0(0x116, 0xe, 1, 4, 1); // = 0x4040432 // !!!! - tmp32 = MCHBAR32(0x144); // !!!! + MCHBAR32(0x144); // !!!! write_1d0(2, 0xae, 6, 1); write_1d0(2, 0x300, 6, 1); write_1d0(2, 0x121, 3, 1); @@ -4663,7 +4658,7 @@ void raminit(const int s3resume, const u8 *spd_addrmap) reg1c = read32p(DEFAULT_EPBAR | 0x01c); // = 0x8001 // OK pci_read_config32(NORTHBRIDGE, 0x40); // = DEFAULT_EPBAR | 0x001 // OK write32p(DEFAULT_EPBAR | 0x01c, reg1c); // OK - tmp8 = MCHBAR8(0xe08); // = 0x0 + MCHBAR8(0xe08); // = 0x0 pci_read_config32(NORTHBRIDGE, 0xe4); // = 0x316126 MCHBAR8_OR(0x1210, 2); MCHBAR32(0x1200) = 0x8800440; From 44245693ec5ad007f526cc7c333f2f59badf7b18 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sat, 25 May 2019 20:33:03 +0200 Subject: [PATCH 114/221] nb/amd/amdfam10/northbridge.c: Remove variable set but not used Change-Id: I62a51b794dedcf320b8054125e75aa041035ce33 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33013 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- src/northbridge/amd/amdfam10/northbridge.c | 31 ++-------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c index a681961be2..0c594b9f62 100644 --- a/src/northbridge/amd/amdfam10/northbridge.c +++ b/src/northbridge/amd/amdfam10/northbridge.c @@ -209,15 +209,6 @@ static void amd_g34_fixup(struct bus *link, struct device *dev) */ f3xe8 = pci_read_config32(get_node_pci(nodeid, 3), 0xe8); uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30); - uint8_t defective_link_number_1; - uint8_t defective_link_number_2; - if (is_fam15h()) { - defective_link_number_1 = 4; /* Link 0 Sublink 1 */ - defective_link_number_2 = 7; /* Link 3 Sublink 1 */ - } else { - defective_link_number_1 = 6; /* Link 2 Sublink 1 */ - defective_link_number_2 = 5; /* Link 1 Sublink 1 */ - } if (internal_node_number == 0) { /* Node 0 */ if (link->link_num == 6) /* Link 2 Sublink 1 */ @@ -745,7 +736,6 @@ static void amdfam10_domain_read_resources(struct device *dev) uint8_t node; uint8_t interleaved; int8_t range; - int8_t max_range; uint8_t max_node; uint64_t max_range_limit; uint32_t dword; @@ -756,7 +746,6 @@ static void amdfam10_domain_read_resources(struct device *dev) /* Find highest DRAM range (DramLimitAddr) */ num_nodes = 0; max_node = 0; - max_range = -1; interleaved = 0; max_range_limit = 0; struct device *node_dev; @@ -782,7 +771,6 @@ static void amdfam10_domain_read_resources(struct device *dev) qword |= (((uint64_t)dword2) & 0xff) << 40; if (qword > max_range_limit) { - max_range = range; max_range_limit = qword; max_node = dword & 0x7; } @@ -904,7 +892,6 @@ static void amdfam10_domain_set_resources(struct device *dev) struct bus *link; #if CONFIG_HW_MEM_HOLE_SIZEK != 0 struct hw_mem_hole_info mem_hole; - u32 reset_memhole = 1; #endif pci_tolm = 0xffffffffUL; @@ -935,7 +922,6 @@ static void amdfam10_domain_set_resources(struct device *dev) // Use hole_basek as mmio_basek, and we don't need to reset hole anymore if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) { mmio_basek = mem_hole.hole_startk; - reset_memhole = 0; } #endif @@ -1542,7 +1528,6 @@ static void cpu_bus_scan(struct device *dev) uint8_t rev_gte_d = 0; uint8_t dual_node = 0; uint32_t f3xe8; - uint32_t family; uint32_t model; busn = CONFIG_CBB; @@ -1583,7 +1568,7 @@ static void cpu_bus_scan(struct device *dev) f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8); - family = model = cpuid_eax(0x80000001); + model = cpuid_eax(0x80000001); model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); if (is_fam15h()) { @@ -1691,17 +1676,14 @@ static void detect_and_enable_probe_filter(struct device *dev) uint8_t fam15h = 0; uint8_t rev_gte_d = 0; - unsigned nb_cfg_54; - uint32_t family; uint32_t model; - family = model = cpuid_eax(0x80000001); + model = cpuid_eax(0x80000001); model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); if (is_fam15h()) { /* Family 15h or later */ fam15h = 1; - nb_cfg_54 = 1; } if ((model >= 0x8) || fam15h) @@ -1862,20 +1844,11 @@ static void detect_and_enable_cache_partitioning(struct device *dev) uint8_t cu_enabled; uint8_t compute_unit_count = 0; - uint32_t f3xe8; - uint8_t dual_node = 0; - for (i = 0; i < sysconf.nodes; i++) { struct device *f3x_dev = pcidev_on_root(0x18 + i, 3); struct device *f4x_dev = pcidev_on_root(0x18 + i, 4); struct device *f5x_dev = pcidev_on_root(0x18 + i, 5); - f3xe8 = pci_read_config32(f3x_dev, 0xe8); - - /* Check for dual node capability */ - if (f3xe8 & 0x20000000) - dual_node = 1; - /* Determine the number of active compute units on this node */ f5x80 = pci_read_config32(f5x_dev, 0x80); cu_enabled = f5x80 & 0xf; From 49bfc0e9e076c16b6bb6f11ec664963202defa22 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 29 May 2019 13:02:47 +0200 Subject: [PATCH 115/221] sb/nvidia/ck804/lpc.c: Remove variable set but not used Change-Id: I19b16bc2052440ca191cf3e30810ddc58a485a60 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33063 Reviewed-by: Patrick Georgi Tested-by: build bot (Jenkins) --- src/southbridge/nvidia/ck804/lpc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/southbridge/nvidia/ck804/lpc.c b/src/southbridge/nvidia/ck804/lpc.c index 21235548a0..8caa8ed1ee 100644 --- a/src/southbridge/nvidia/ck804/lpc.c +++ b/src/southbridge/nvidia/ck804/lpc.c @@ -124,10 +124,9 @@ static void lpc_init(struct device *dev) get_option(&on, "slow_cpu"); if (on) { u16 pm10_bar; - u32 dword; pm10_bar = (pci_read_config16(dev, 0x60) & 0xff00); outl(((on << 1) + 0x10), (pm10_bar + 0x10)); - dword = inl(pm10_bar + 0x10); + inl(pm10_bar + 0x10); on = 8 - on; printk(BIOS_DEBUG, "Throttling CPU %2d.%1.1d percent.\n", (on * 12) + (on >> 1), (on & 1) * 5); From 8de6cb975f8cf5cd7a4a98b5784fea3d36ce8fec Mon Sep 17 00:00:00 2001 From: Jinke Fan Date: Sat, 18 May 2019 18:07:56 +0800 Subject: [PATCH 116/221] arch/x86/cpu: Add define and strings for Hygon Chengdu Haiguang IC Design Co., Ltd (Hygon) is a Joint Venture between AMD and Haiguang Information Technology Co.,Ltd., aims at providing high performance x86 processor for China server market. Its first generation processor codename is Dhyana, which originates from AMD technology and shares most of the architecture with AMD's family 17h, but with different CPU Vendor ID ("HygonGenuine") /Family series number (Family 18h). More details can be found on: http://lkml.kernel.org/r/5ce86123a7b9dad925ac583d88d2f921040e859b.1538583282.git.puwen@hygon.cn Change-Id: I8af8b0f0675f978ac07522029696e43651a3153f Signed-off-by: Jinke Fan Reviewed-on: https://review.coreboot.org/c/coreboot/+/32876 Reviewed-by: Angel Pons Reviewed-by: Lance Zhao Reviewed-by: Philipp Deppenwiese Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/arch/x86/cpu.c | 2 ++ src/arch/x86/include/arch/cpu.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/arch/x86/cpu.c b/src/arch/x86/cpu.c index e6c9435503..cfab21956b 100644 --- a/src/arch/x86/cpu.c +++ b/src/arch/x86/cpu.c @@ -113,6 +113,7 @@ static struct { { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, { X86_VENDOR_NSC, "Geode by NSC", }, { X86_VENDOR_SIS, "SiS SiS SiS ", }, + { X86_VENDOR_HYGON, "HygonGenuine", }, }; static const char *const x86_vendor_name[] = { @@ -126,6 +127,7 @@ static const char *const x86_vendor_name[] = { [X86_VENDOR_TRANSMETA] = "Transmeta", [X86_VENDOR_NSC] = "NSC", [X86_VENDOR_SIS] = "SiS", + [X86_VENDOR_HYGON] = "Hygon", }; static const char *cpu_vendor_name(int vendor) diff --git a/src/arch/x86/include/arch/cpu.h b/src/arch/x86/include/arch/cpu.h index 078ea1748b..ff1a33b9ea 100644 --- a/src/arch/x86/include/arch/cpu.h +++ b/src/arch/x86/include/arch/cpu.h @@ -152,6 +152,7 @@ static inline unsigned int cpuid_edx(unsigned int op) #define X86_VENDOR_TRANSMETA 8 #define X86_VENDOR_NSC 9 #define X86_VENDOR_SIS 10 +#define X86_VENDOR_HYGON 11 #define X86_VENDOR_ANY 0xfe #define X86_VENDOR_UNKNOWN 0xff From 09c31d557fb731cac17821e547cdb644ee817463 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Tue, 4 Jun 2019 10:30:41 -0600 Subject: [PATCH 117/221] nb/amd/amdfam10: Use 64 bits in multiplication The literal needs to be cast to a uint64 to prevent num_nodes from being implicitly promoted to a signed int. Change-Id: Id2fa328fb8d0a9827c7c78157c024736e9b26dc4 Signed-off-by: Jacob Garber Found-by: Coverity CID 1347343 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33210 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth Reviewed-by: HAOUAS Elyes --- src/northbridge/amd/amdfam10/northbridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c index 0c594b9f62..e28b89b8e4 100644 --- a/src/northbridge/amd/amdfam10/northbridge.c +++ b/src/northbridge/amd/amdfam10/northbridge.c @@ -779,7 +779,7 @@ static void amdfam10_domain_read_resources(struct device *dev) /* Calculate CC6 storage area size */ if (interleaved) - qword = (0x1000000 * num_nodes); + qword = (uint64_t)0x1000000 * num_nodes; else qword = 0x1000000; From 493d36684c105d89372598bd4a937e97b2bdf05e Mon Sep 17 00:00:00 2001 From: David Wu Date: Wed, 19 Jun 2019 19:46:37 +0800 Subject: [PATCH 118/221] mb/google/hatch/variants/kindred: Update memory strap GPIOs According to the latest schematic (b:127996858#comment38), MEM_CONFIG_0 --> GPP_H19 MEM_CONFIG_1 --> GPP_H22 MEM_CONFIG_2 --> GPP_F10 MEM_CONFIG_3 --> GPP_F3 BUG=none BRANCH=none TEST=Boot kindred proto board Change-Id: Ib79f9454116583a94fe1fd53a37ed928d32988d5 Signed-off-by: David Wu Reviewed-on: https://review.coreboot.org/c/coreboot/+/33617 Tested-by: build bot (Jenkins) Reviewed-by: Paul Fagerburg --- .../hatch/variants/kindred/Makefile.inc | 3 ++ .../google/hatch/variants/kindred/gpio.c | 54 +++++++++++++++++++ .../variants/kindred/include/variant/gpio.h | 8 +-- 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 src/mainboard/google/hatch/variants/kindred/gpio.c diff --git a/src/mainboard/google/hatch/variants/kindred/Makefile.inc b/src/mainboard/google/hatch/variants/kindred/Makefile.inc index 8173ca4389..563275dd19 100644 --- a/src/mainboard/google/hatch/variants/kindred/Makefile.inc +++ b/src/mainboard/google/hatch/variants/kindred/Makefile.inc @@ -18,3 +18,6 @@ SPD_SOURCES += 8G_2400 # 0b010 SPD_SOURCES += 8G_2666 # 0b011 SPD_SOURCES += 16G_2400 # 0b100 SPD_SOURCES += 16G_2666 # 0b101 + +bootblock-y += gpio.c +ramstage-y += gpio.c diff --git a/src/mainboard/google/hatch/variants/kindred/gpio.c b/src/mainboard/google/hatch/variants/kindred/gpio.c new file mode 100644 index 0000000000..43948a35f8 --- /dev/null +++ b/src/mainboard/google/hatch/variants/kindred/gpio.c @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2019 Google 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 +#include +#include +#include + +static const struct pad_config gpio_table[] = { + /* F3 : MEM_STRAP_3 */ + PAD_CFG_GPI(GPP_F3, NONE, PLTRST), + /* F10 : MEM_STRAP_2 */ + PAD_CFG_GPI(GPP_F10, NONE, PLTRST), + /* H19 : MEM_STRAP_0 */ + PAD_CFG_GPI(GPP_H19, NONE, PLTRST), + /* H22 : MEM_STRAP_1 */ + PAD_CFG_GPI(GPP_H22, NONE, PLTRST), +}; + +const struct pad_config *override_gpio_table(size_t *num) +{ + *num = ARRAY_SIZE(gpio_table); + return gpio_table; +} + +/* GPIOs configured before ramstage */ +static const struct pad_config early_gpio_table[] = { + /* F3 : MEM_STRAP_3 */ + PAD_CFG_GPI(GPP_F3, NONE, PLTRST), + /* F10 : MEM_STRAP_2 */ + PAD_CFG_GPI(GPP_F10, NONE, PLTRST), + /* H19 : MEM_STRAP_0 */ + PAD_CFG_GPI(GPP_H19, NONE, PLTRST), + /* H22 : MEM_STRAP_1 */ + PAD_CFG_GPI(GPP_H22, NONE, PLTRST), +}; + +const struct pad_config *override_early_gpio_table(size_t *num) +{ + *num = ARRAY_SIZE(early_gpio_table); + return early_gpio_table; +} diff --git a/src/mainboard/google/hatch/variants/kindred/include/variant/gpio.h b/src/mainboard/google/hatch/variants/kindred/include/variant/gpio.h index 29e590422f..92f9d412fd 100644 --- a/src/mainboard/google/hatch/variants/kindred/include/variant/gpio.h +++ b/src/mainboard/google/hatch/variants/kindred/include/variant/gpio.h @@ -19,9 +19,9 @@ #include /* Memory configuration board straps */ -#define GPIO_MEM_CONFIG_0 GPP_F20 -#define GPIO_MEM_CONFIG_1 GPP_F21 -#define GPIO_MEM_CONFIG_2 GPP_F11 -#define GPIO_MEM_CONFIG_3 GPP_F22 +#define GPIO_MEM_CONFIG_0 GPP_H19 +#define GPIO_MEM_CONFIG_1 GPP_H22 +#define GPIO_MEM_CONFIG_2 GPP_F10 +#define GPIO_MEM_CONFIG_3 GPP_F3 #endif From f69c96dd8d857a90143f1c2f38efd19e26b68039 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Thu, 13 Jun 2019 14:33:20 -0600 Subject: [PATCH 119/221] sb/amd/sr5650: Use 32 bit integers when disabling ports This function attempts to set bits in the 20s of state and state_save, which won't work since those variables are only 16 bits wide. Extend them to 32 bits to capture all the bit operations. Change-Id: I5616a2d879a85ff5f57af5af20384516659c62d6 Signed-off-by: Jacob Garber Found-by: Coverity CID 1347384 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33457 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- src/southbridge/amd/sr5650/pcie.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/southbridge/amd/sr5650/pcie.c b/src/southbridge/amd/sr5650/pcie.c index f87fadbb08..6c42fdde4d 100644 --- a/src/southbridge/amd/sr5650/pcie.c +++ b/src/southbridge/amd/sr5650/pcie.c @@ -59,11 +59,11 @@ static void PciePowerOffGppPorts(struct device *nb_dev, struct device *dev, u32 { printk(BIOS_DEBUG, "PciePowerOffGppPorts() port %d\n", port); u32 reg; - u16 state_save; + u32 state_save; uint8_t i; struct southbridge_amd_sr5650_config *cfg = (struct southbridge_amd_sr5650_config *)nb_dev->chip_info; - u16 state = cfg->port_enable; + u32 state = cfg->port_enable; if (!(AtiPcieCfg.Config & PCIE_DISABLE_HIDE_UNUSED_PORTS)) state &= AtiPcieCfg.PortDetect; From 7d881b5189efea7e9ee3f64e36964c951001e1a1 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Thu, 6 Jun 2019 12:13:14 -0600 Subject: [PATCH 120/221] nb/amd/amdmct/mct_ddr3: Remove unused code As described in the comment, the BKDG-recommended algorithm causes problems and isn't being used, so just delete it. Change-Id: Ib3d4eba7ea2d7f6545613af5670b243bc011275f Signed-off-by: Jacob Garber Found-by: Coverity CID 1347325, 1347326 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33269 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: Patrick Georgi --- src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c index ab16887f1d..42f313ab92 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c @@ -1213,13 +1213,6 @@ void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui Seed_Fine = (SeedTotal[ByteLane] % 32) + 32; } - if (Seed_Gross == 0) - Seed_PreGross = 0; - else if (Seed_Gross & 0x1) - Seed_PreGross = 1; - else - Seed_PreGross = 2; - /* The BKDG-recommended algorithm causes problems with registered DIMMs on some systems * due to the long register delays causing premature total delay wrap-around. * Attempt to work around this... From d97591c34571b66157c540355457c4fea794a611 Mon Sep 17 00:00:00 2001 From: Asami Doi Date: Fri, 7 Jun 2019 16:22:03 +0900 Subject: [PATCH 121/221] payloads/libpayload: Update a Makefile for sample libpayload and make a configuraton for QEMU/ARM. This CL allows building a sample libpayload for QEMU/ARM. Change-Id: Ia32872c43a99357aa966de3582f6fdb2e2652517 Signed-off-by: Asami Doi Reviewed-on: https://review.coreboot.org/c/coreboot/+/33287 Tested-by: build bot (Jenkins) Reviewed-by: Raul Rangel Reviewed-by: Julius Werner --- payloads/libpayload/README | 12 +++++++++--- .../libpayload/configs/config.emulation-qemu-arm | 6 ++++++ payloads/libpayload/sample/Makefile | 11 ++++++----- 3 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 payloads/libpayload/configs/config.emulation-qemu-arm diff --git a/payloads/libpayload/README b/payloads/libpayload/README index fdf9b1840d..d35f685fd5 100644 --- a/payloads/libpayload/README +++ b/payloads/libpayload/README @@ -22,12 +22,18 @@ Installation $ make - $ sudo make install (optional, will install into /opt per default) + $ make install (optional, will install into ./install per default) -As libpayload is for 32bit x86 systems only, you might have to install the -32bit libgcc version, otherwise your payloads will fail to compile. +On x86 systems, libpayload will always be 32-bit even if your host OS runs +in 64-bit, so you might have to install the 32-bit libgcc version. On Debian systems you'd do 'apt-get install gcc-multilib' for example. +Run 'make distclean' before switching boards. This command will remove +your current .config file, so you need 'make menuconfig' again or +'make defconfig' in order to set up configuration. Default configuration +is based on 'configs/defconfig'. See the configs/ directory for examples +of configuration. + Usage ----- diff --git a/payloads/libpayload/configs/config.emulation-qemu-arm b/payloads/libpayload/configs/config.emulation-qemu-arm new file mode 100644 index 0000000000..4b69caf737 --- /dev/null +++ b/payloads/libpayload/configs/config.emulation-qemu-arm @@ -0,0 +1,6 @@ +CONFIG_LP_ARCH_ARM=y +CONFIG_LP_STACK_SIZE=64000 +CONFIG_LP_BASE_ADDRESS=0x62030000 +CONFIG_LP_TINYCURSES=y +CONFIG_LP_8250_SERIAL_CONSOLE=y +CONFIG_LP_TIMER_GENERIC_HZ=1000000 diff --git a/payloads/libpayload/sample/Makefile b/payloads/libpayload/sample/Makefile index 5931d5eb11..18121dfe80 100644 --- a/payloads/libpayload/sample/Makefile +++ b/payloads/libpayload/sample/Makefile @@ -28,19 +28,20 @@ ## # Sample libpayload Makefile. -include ../.xcompile include ../.config +include ../.xcompile -ARCH-$(CONFIG_LP_ARCH_ARMV) := arm -ARCH-$(CONFIG_LP_ARCH_POWERPC) := powerpc -ARCH-$(CONFIG_LP_ARCH_X86) := i386 +ARCH-$(CONFIG_LP_ARCH_ARM) := arm +ARCH-$(CONFIG_LP_ARCH_X86) := x86_32 +ARCH-$(CONFIG_LP_ARCH_ARM64) := arm64 +ARCH-$(CONFIG_LP_ARCH_MIPS) := mips CC := $(CC_$(ARCH-y)) AS := $(AS_$(ARCH-y)) LIBPAYLOAD_DIR := ../install/libpayload XCC := CC="$(CC)" $(LIBPAYLOAD_DIR)/bin/lpgcc XAS := AS="$(AS)" $(LIBPAYLOAD_DIR)/bin/lpas -CFLAGS := -Wall -Werror -Os +CFLAGS := -fno-builtin -Wall -Werror -Os TARGET := hello OBJS := $(TARGET).o From 1a86cda6dbacfbae285fa3d44b3f67bea95367e3 Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Mon, 10 Jun 2019 14:00:56 -0700 Subject: [PATCH 122/221] soc/intel: Provide SPD manufacturer ID and module type to SMBIOS The DIMM manufacturing ID was not being initialized and so the DIMMs were not described in SMBIOS tables properly. The module type can also be provided, but the SMBIOS code expects SPD module type values from DDR2 so the DDR3/4 values are adjusted before sending to SMBIOS. BUG=b:134897498 BRANCH=sarien TEST=dump and compare with dmidecode BEFORE: Type: DDR4 Manufacturer: Unknown (0) Form Factor: Unknown AFTER: Type: DDR4 Manufacturer: Hynix/Hyundai Form Factor: SODIMM Change-Id: Id673e08aa6e3dad196009c3c21a3dda2f40c9e42 Signed-off-by: Duncan Laurie Reviewed-on: https://review.coreboot.org/c/coreboot/+/33379 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/soc/intel/apollolake/meminit_util_apl.c | 2 ++ src/soc/intel/apollolake/meminit_util_glk.c | 4 ++- src/soc/intel/cannonlake/romstage/romstage.c | 4 ++- src/soc/intel/common/smbios.c | 26 ++++++++++++++++++- src/soc/intel/common/smbios.h | 2 +- src/soc/intel/icelake/romstage/romstage.c | 4 ++- .../intel/skylake/romstage/romstage_fsp20.c | 4 ++- 7 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/soc/intel/apollolake/meminit_util_apl.c b/src/soc/intel/apollolake/meminit_util_apl.c index 16d14d945f..1dc5ceeb2c 100644 --- a/src/soc/intel/apollolake/meminit_util_apl.c +++ b/src/soc/intel/apollolake/meminit_util_apl.c @@ -93,6 +93,8 @@ void save_lpddr4_dimm_info_part_num(const char *dram_part_num) NULL, /* SPD not available */ memory_info_hob->DataWidth, 0, + 0, + src_dimm->MfgId, 0); index++; } diff --git a/src/soc/intel/apollolake/meminit_util_glk.c b/src/soc/intel/apollolake/meminit_util_glk.c index 59e133076a..0fbab0b177 100644 --- a/src/soc/intel/apollolake/meminit_util_glk.c +++ b/src/soc/intel/apollolake/meminit_util_glk.c @@ -99,7 +99,9 @@ void save_lpddr4_dimm_info_part_num(const char *dram_part_num) src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL, memory_info_hob->DataWidth, 0, - 0); + 0, + src_dimm->MfgId, + src_dimm->SpdModuleType); index++; } } diff --git a/src/soc/intel/cannonlake/romstage/romstage.c b/src/soc/intel/cannonlake/romstage/romstage.c index fa530a29a6..9dadb2d14e 100644 --- a/src/soc/intel/cannonlake/romstage/romstage.c +++ b/src/soc/intel/cannonlake/romstage/romstage.c @@ -116,7 +116,9 @@ static void save_dimm_info(void) src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL, memory_info_hob->DataWidth, memory_info_hob->VddVoltage[memProfNum], - memory_info_hob->EccSupport); + memory_info_hob->EccSupport, + src_dimm->MfgId, + src_dimm->SpdModuleType); index++; } } diff --git a/src/soc/intel/common/smbios.c b/src/soc/intel/common/smbios.c index e3ed3a2e69..d315e15f28 100644 --- a/src/soc/intel/common/smbios.c +++ b/src/soc/intel/common/smbios.c @@ -17,14 +17,38 @@ #include "smbios.h" #include #include +#include /* Fill the SMBIOS memory information from FSP MEM_INFO_DATA_HOB in CBMEM.*/ void dimm_info_fill(struct dimm_info *dimm, u32 dimm_capacity, u8 ddr_type, u32 frequency, u8 rank_per_dimm, u8 channel_id, u8 dimm_id, const char *module_part_num, size_t module_part_number_size, const u8 *module_serial_num, u16 data_width, u32 vdd_voltage, - bool ecc_support) + bool ecc_support, u16 mod_id, u8 mod_type) { + dimm->mod_id = mod_id; + /* Translate to DDR2 module type field that SMBIOS code expects. */ + switch (mod_type) { + case SPD_DIMM_TYPE_SO_DIMM: + dimm->mod_type = SPD_SODIMM; + break; + case SPD_DIMM_TYPE_72B_SO_CDIMM: + dimm->mod_type = SPD_72B_SO_CDIMM; + break; + case SPD_DIMM_TYPE_72B_SO_RDIMM: + dimm->mod_type = SPD_72B_SO_RDIMM; + break; + case SPD_DIMM_TYPE_UDIMM: + dimm->mod_type = SPD_UDIMM; + break; + case SPD_DIMM_TYPE_RDIMM: + dimm->mod_type = SPD_RDIMM; + break; + case SPD_DIMM_TYPE_UNDEFINED: + default: + dimm->mod_type = SPD_UNDEFINED; + break; + } dimm->dimm_size = dimm_capacity; dimm->ddr_type = ddr_type; dimm->ddr_frequency = frequency; diff --git a/src/soc/intel/common/smbios.h b/src/soc/intel/common/smbios.h index 12b8da0d85..97437eef45 100644 --- a/src/soc/intel/common/smbios.h +++ b/src/soc/intel/common/smbios.h @@ -27,6 +27,6 @@ void dimm_info_fill(struct dimm_info *dimm, u32 dimm_capacity, u8 ddr_type, u32 frequency, u8 rank_per_dimm, u8 channel_id, u8 dimm_id, const char *module_part_num, size_t module_part_number_size, const u8 *module_serial_num, u16 data_width, u32 vdd_voltage, - bool ecc_support); + bool ecc_support, u16 mod_id, u8 mod_type); #endif /* _COMMON_SMBIOS_H_ */ diff --git a/src/soc/intel/icelake/romstage/romstage.c b/src/soc/intel/icelake/romstage/romstage.c index a09641cf44..b0eeb2e959 100644 --- a/src/soc/intel/icelake/romstage/romstage.c +++ b/src/soc/intel/icelake/romstage/romstage.c @@ -101,7 +101,9 @@ static void save_dimm_info(void) src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL, memory_info_hob->DataWidth, memory_info_hob->VddVoltage[memProfNum], - memory_info_hob->EccSupport); + memory_info_hob->EccSupport, + src_dimm->MfgId, + src_dimm->SpdModuleType); index++; } } diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c index 0eff793ac2..83fc27eaa5 100644 --- a/src/soc/intel/skylake/romstage/romstage_fsp20.c +++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c @@ -129,7 +129,9 @@ static void save_dimm_info(void) src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL, memory_info_hob->DataWidth, memory_info_hob->VddVoltage[memProfNum], - memory_info_hob->EccSupport); + memory_info_hob->EccSupport, + src_dimm->MfgId, + src_dimm->SpdModuleType); index++; } } From 319f0370bfe99ce47ea8b883696ad89d19b7c4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 25 Oct 2018 15:48:54 +0200 Subject: [PATCH 123/221] src/cpu/amd/pi/00730F01: Add microcode update infrastructure for fam16h PI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code is based on microcode update procedure from fam10-15h with necessary microcode blob structure updates for fam16h. Currently updating microcode in romstage seem to be impossible. AGESA is overriding the microcode patch regardles of the current microcode revision patched on CPU. Use ramstage CPU init procedures to update microcode easily. Tested with microcode blob 07030106 released 2018-02-09 from platomav/CPUMicrocodes GitHub repository on apu2 platform. TEST=boot Linux kernel 4.14.50 on PC Engines apu2 and run dmesg to see patch_level=0x07030106 on all cores Change-Id: Ic15cba06f3cd9cfbc538b6764b158fa699f0ecf6 Signed-off-by: Michał Żygowski Reviewed-on: https://review.coreboot.org/c/coreboot/+/29272 Reviewed-by: Kyösti Mälkki Tested-by: build bot (Jenkins) --- src/cpu/amd/pi/00730F01/Kconfig | 2 + src/cpu/amd/pi/00730F01/Makefile.inc | 4 + src/cpu/amd/pi/00730F01/microcode_fam16h.c | 169 +++++++++++++++++++++ src/cpu/amd/pi/00730F01/model_16_init.c | 3 + src/cpu/amd/pi/00730F01/update_microcode.c | 58 +++++++ 5 files changed, 236 insertions(+) create mode 100644 src/cpu/amd/pi/00730F01/microcode_fam16h.c create mode 100644 src/cpu/amd/pi/00730F01/update_microcode.c diff --git a/src/cpu/amd/pi/00730F01/Kconfig b/src/cpu/amd/pi/00730F01/Kconfig index 054523ee37..f3f488d2dd 100644 --- a/src/cpu/amd/pi/00730F01/Kconfig +++ b/src/cpu/amd/pi/00730F01/Kconfig @@ -16,6 +16,8 @@ config CPU_AMD_PI_00730F01 bool select X86_AMD_FIXED_MTRRS + select SUPPORT_CPU_UCODE_IN_CBFS + select MICROCODE_BLOB_UNDISCLOSED if CPU_AMD_PI_00730F01 diff --git a/src/cpu/amd/pi/00730F01/Makefile.inc b/src/cpu/amd/pi/00730F01/Makefile.inc index 9367b458a3..99b6ef33a9 100644 --- a/src/cpu/amd/pi/00730F01/Makefile.inc +++ b/src/cpu/amd/pi/00730F01/Makefile.inc @@ -14,10 +14,14 @@ # romstage-y += fixme.c +romstage-y += update_microcode.c +romstage-y += microcode_fam16h.c ramstage-y += fixme.c ramstage-y += chip_name.c ramstage-y += model_16_init.c +ramstage-y += update_microcode.c +ramstage-y += microcode_fam16h.c subdirs-y += ../../mtrr subdirs-y += ../../../x86/tsc diff --git a/src/cpu/amd/pi/00730F01/microcode_fam16h.c b/src/cpu/amd/pi/00730F01/microcode_fam16h.c new file mode 100644 index 0000000000..ad951242a7 --- /dev/null +++ b/src/cpu/amd/pi/00730F01/microcode_fam16h.c @@ -0,0 +1,169 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Copyright (C) 2015 Raptor Engineering + * Copyright (C) 2019 PC Engines 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Values and header structure from: + * BKDG for AMD Family 16h Models 30h-3Fh Processors + * 52740 Rev 3.06 - March 18, 2016 + */ + +#define F16H_MPB_MAX_SIZE 3458 +#define F16H_MPB_DATA_OFFSET 32 + + /* + * STRUCTURE OF A MICROCODE (UCODE) FILE FOR FAM16h + * Microcode Patch Block + * Microcode Header + * Microcode "Blob" + * ... + * ... + * (end of file) + * + * + * MICROCODE HEADER (offset 0 bytes from start of file) + * Total size = 32 bytes + * [0:3] Date code (32 bits) + * [4:7] Patch level (32 bits) + * [8:9] Microcode patch data ID (16 bits) + * [10:15] Reserved (48 bits) + * [16:19] Chipset 1 device ID (32 bits) + * [20:23] Chipset 2 device ID (32 bits) + * [24:25] Processor Revisions ID (16 bits) + * [26] Chipset 1 revision ID (8 bits) + * [27] Chipset 2 revision ID (8 bits) + * [28:31] Reserved (32 bits) + * + * MICROCODE BLOB (offset += 32) + * Total size = m bytes + * + */ + +struct microcode { + uint32_t date_code; + uint32_t patch_id; + + uint16_t mc_patch_data_id; + uint8_t reserved1[6]; + + uint32_t chipset1_dev_id; + uint32_t chipset2_dev_id; + + uint16_t processor_rev_id; + + uint8_t chipset1_rev_id; + uint8_t chipset2_rev_id; + + uint8_t reserved2[4]; + + uint8_t m_patch_data[F16H_MPB_MAX_SIZE-F16H_MPB_DATA_OFFSET]; + +}; + +static void apply_microcode_patch(const struct microcode *m) +{ + uint32_t new_patch_id; + msr_t msr; + + /* apply patch */ + msr.hi = 0; + msr.lo = (uint32_t)m; + + wrmsr(0xc0010020, msr); + + printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n", + m->patch_id); + + /* patch authentication */ + msr = rdmsr(0x8b); + new_patch_id = msr.lo; + + printk(BIOS_DEBUG, "microcode: updated to patch id = 0x%08x %s\n", + new_patch_id, + (new_patch_id == m->patch_id) ? "success" : "fail"); +} + +static void amd_update_microcode(const void *ucode, size_t ucode_len, + uint32_t equivalent_processor_rev_id) +{ + const struct microcode *m; + const uint8_t *c = ucode; + + m = (struct microcode *)c; + + if (m->processor_rev_id == equivalent_processor_rev_id) + apply_microcode_patch(m); +} + +void amd_update_microcode_from_cbfs(uint32_t equivalent_processor_rev_id) +{ + const void *ucode; + size_t ucode_len; + + if (equivalent_processor_rev_id == 0) { + printk(BIOS_DEBUG, "microcode: rev id not found. " + "Skipping microcode patch!\n"); + return; + } +#ifdef __PRE_RAM__ +#if CONFIG(HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK) + spin_lock(romstage_microcode_cbfs_lock()); +#endif +#endif + ucode = cbfs_boot_map_with_leak("cpu_microcode_blob.bin", + CBFS_TYPE_MICROCODE, + &ucode_len); + if (!ucode) { + printk(BIOS_DEBUG, "cpu_microcode_blob.bin not found. " + "Skipping updates.\n"); +#ifdef __PRE_RAM__ +#if CONFIG(HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK) + spin_unlock(romstage_microcode_cbfs_lock()); +#endif +#endif + return; + } + + if (ucode_len > F16H_MPB_MAX_SIZE || + ucode_len < F16H_MPB_DATA_OFFSET) { + printk(BIOS_DEBUG, "microcode file invalid. Skipping " + "updates.\n"); +#ifdef __PRE_RAM__ +#if CONFIG(HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK) + spin_unlock(romstage_microcode_cbfs_lock()); +#endif +#endif + return; + } + + amd_update_microcode(ucode, ucode_len, + equivalent_processor_rev_id); + +#ifdef __PRE_RAM__ +#if CONFIG(HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK) + spin_unlock(romstage_microcode_cbfs_lock()); +#endif +#endif + +} diff --git a/src/cpu/amd/pi/00730F01/model_16_init.c b/src/cpu/amd/pi/00730F01/model_16_init.c index fe828900fc..b0449a73b2 100644 --- a/src/cpu/amd/pi/00730F01/model_16_init.c +++ b/src/cpu/amd/pi/00730F01/model_16_init.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -98,6 +99,8 @@ static void model_16_init(struct device *dev) msr = rdmsr(HWCR_MSR); msr.lo |= (1 << 0); wrmsr(HWCR_MSR, msr); + + update_microcode(cpuid_eax(1)); } static struct device_operations cpu_dev_ops = { diff --git a/src/cpu/amd/pi/00730F01/update_microcode.c b/src/cpu/amd/pi/00730F01/update_microcode.c new file mode 100644 index 0000000000..6acf13a6ef --- /dev/null +++ b/src/cpu/amd/pi/00730F01/update_microcode.c @@ -0,0 +1,58 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Timothy Pearson , Raptor Engineering + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Copyright (C) 2019 PC Engines 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. + */ + +#include +#include + +struct id_mapping { + uint32_t orig_id; + uint16_t new_id; +}; + +static u16 get_equivalent_processor_rev_id(u32 orig_id) +{ + static const struct id_mapping id_mapping_table[] = { + /* Family 16h */ + + /* TODO This equivalent processor revisions ID needs verification */ + { 0x730f01, 0x7301 }, + + /* Array terminator */ + { 0xffffff, 0x0000 }, + }; + + u32 new_id; + int i; + + new_id = 0; + + for (i = 0; id_mapping_table[i].orig_id != 0xffffff; i++) { + if (id_mapping_table[i].orig_id == orig_id) { + new_id = id_mapping_table[i].new_id; + break; + } + } + + return new_id; +} + +void update_microcode(u32 cpu_deviceid) +{ + u32 equivalent_processor_rev_id = + get_equivalent_processor_rev_id(cpu_deviceid); + amd_update_microcode_from_cbfs(equivalent_processor_rev_id); +} From fb626dcd78a2a61af728b5479d3babb3ea7e5b36 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 3 Jun 2019 19:37:45 +0200 Subject: [PATCH 124/221] cpu/intel/haswell: Link tsc_freq.c in the bootblock This provides tsc_freq_mhz implementation. Change-Id: Ic6a84336f89a37aa412a9cc8c375fbd41dc09cf2 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33176 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes --- src/cpu/intel/haswell/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/intel/haswell/Makefile.inc b/src/cpu/intel/haswell/Makefile.inc index f83d5db970..1e7d226c51 100644 --- a/src/cpu/intel/haswell/Makefile.inc +++ b/src/cpu/intel/haswell/Makefile.inc @@ -25,6 +25,7 @@ bootblock-y += ../car/non-evict/cache_as_ram.S bootblock-y += ../car/bootblock.c bootblock-y += ../../x86/early_reset.S bootblock-y += bootblock.c +bootblock-y += tsc_freq.c postcar-y += ../car/non-evict/exit_car.S From 09ccd418f40bad87098e71411e408bf9b5c69881 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 3 Jun 2019 19:36:25 +0200 Subject: [PATCH 125/221] sb/intel/common: Link SPI code in bootblock Change-Id: I2874bc37c6bceb2b22115a09ed1501ce917b4623 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33177 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/southbridge/intel/common/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/southbridge/intel/common/Makefile.inc b/src/southbridge/intel/common/Makefile.inc index 4cf6e6f57e..deab85ff97 100644 --- a/src/southbridge/intel/common/Makefile.inc +++ b/src/southbridge/intel/common/Makefile.inc @@ -45,6 +45,7 @@ romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_GPIO) += gpio.c +bootblock-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c postcar-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c From 2ea1c9b29e0549149905833e66bea875e932c5bf Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Tue, 4 Jun 2019 10:42:24 +0200 Subject: [PATCH 126/221] cpu/intel/haswell: Link monotonic_timer.c in early stages This is needed for SPI flash console in bootblock/romstage/postcar. Change-Id: I18253cc028e87cd31879d722a6d788917e9c97b3 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33191 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- src/cpu/intel/haswell/Makefile.inc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpu/intel/haswell/Makefile.inc b/src/cpu/intel/haswell/Makefile.inc index 1e7d226c51..fa467e5a8b 100644 --- a/src/cpu/intel/haswell/Makefile.inc +++ b/src/cpu/intel/haswell/Makefile.inc @@ -17,6 +17,9 @@ smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c ifneq ($(CONFIG_TSC_MONOTONIC_TIMER),y) +bootblock-y += monotonic_timer.c +romstage-y += monotonic_timer.c +postcar-y += monotonic_timer.c ramstage-y += monotonic_timer.c smm-y += monotonic_timer.c endif From 735ddc930f77950e1f292c574067106cf38e2e87 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 7 May 2019 17:05:28 -0700 Subject: [PATCH 127/221] device_tree: Add overlay support This patch adds support for merging a device tree overlay (as defined in Documentation/dt-object-internal.txt in the dtc repository) into a base device tree. It was adapted from depthcharge's http://crosreview.com/1536387. Change-Id: Ibec833cd471201bcc7a79eebf360d5f12adb8ff9 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32869 Reviewed-by: Hung-Te Lin Tested-by: build bot (Jenkins) --- src/include/device_tree.h | 4 + src/lib/device_tree.c | 471 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 475 insertions(+) diff --git a/src/include/device_tree.h b/src/include/device_tree.h index d9d9613f96..8d86bc5acb 100644 --- a/src/include/device_tree.h +++ b/src/include/device_tree.h @@ -180,6 +180,10 @@ void dt_find_bin_prop(const struct device_tree_node *node, const char *name, const char *dt_find_string_prop(const struct device_tree_node *node, const char *name); +/* Apply an overlay to a base device tree. Ownership of the overlay data passes + to the newly combined base tree -- do not free() or access it afterwards! */ +int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay); + /* * Fixups to apply to a kernel's device tree before booting it. */ diff --git a/src/lib/device_tree.c b/src/lib/device_tree.c index ed878a25a3..a68e1b74c5 100644 --- a/src/lib/device_tree.c +++ b/src/lib/device_tree.c @@ -1100,3 +1100,474 @@ struct device_tree_node *dt_init_reserved_memory_node(struct device_tree *tree) return reserved; } + +/* + * Increment a single phandle in prop at a given offset by a given adjustment. + * + * @param prop Property whose phandle should be adjusted. + * @param adjustment Value that should be added to the existing phandle. + * @param offset Byte offset of the phandle in the property data. + * + * @return New phandle value, or 0 on error. + */ +static uint32_t dt_adjust_phandle(struct device_tree_property *prop, + uint32_t adjustment, uint32_t offset) +{ + if (offset + 4 > prop->prop.size) + return 0; + + uint32_t phandle = be32dec(prop->prop.data + offset); + if (phandle == 0 || + phandle == FDT_PHANDLE_ILLEGAL || + phandle == 0xffffffff) + return 0; + + phandle += adjustment; + if (phandle >= FDT_PHANDLE_ILLEGAL) + return 0; + + be32enc(prop->prop.data + offset, phandle); + return phandle; +} + +/* + * Adjust all phandles in subtree by adding a new base offset. + * + * @param node Root node of the subtree to work on. + * @param base New phandle base to be added to all phandles. + * + * @return New highest phandle in the subtree, or 0 on error. + */ +static uint32_t dt_adjust_all_phandles(struct device_tree_node *node, + uint32_t base) +{ + uint32_t new_max = MAX(base, 1); // make sure we don't return 0 + struct device_tree_property *prop; + struct device_tree_node *child; + + if (!node) + return new_max; + + list_for_each(prop, node->properties, list_node) + if (dt_prop_is_phandle(prop)) { + node->phandle = dt_adjust_phandle(prop, base, 0); + if (!node->phandle) + return 0; + new_max = MAX(new_max, node->phandle); + } // no break -- can have more than one phandle prop + + list_for_each(child, node->children, list_node) + new_max = MAX(new_max, dt_adjust_all_phandles(child, base)); + + return new_max; +} + +/* + * Apply a /__local_fixup__ subtree to the corresponding overlay subtree. + * + * @param node Root node of the overlay subtree to fix up. + * @param node Root node of the /__local_fixup__ subtree. + * @param base Adjustment that was added to phandles in the overlay. + * + * @return 0 on success, -1 on error. + */ +static int dt_fixup_locals(struct device_tree_node *node, + struct device_tree_node *fixup, uint32_t base) +{ + struct device_tree_property *prop; + struct device_tree_property *fixup_prop; + struct device_tree_node *child; + struct device_tree_node *fixup_child; + int i; + + // For local fixups the /__local_fixup__ subtree contains the same node + // hierarchy as the main tree we're fixing up. Each property contains + // the fixup offsets for the respective property in the main tree. For + // each property in the fixup node, find the corresponding property in + // the base node and apply fixups to all offsets it specifies. + list_for_each(fixup_prop, fixup->properties, list_node) { + struct device_tree_property *base_prop = NULL; + list_for_each(prop, node->properties, list_node) + if (!strcmp(prop->prop.name, fixup_prop->prop.name)) { + base_prop = prop; + break; + } + + // We should always find a corresponding base prop for a fixup, + // and fixup props contain a list of 32-bit fixup offsets. + if (!base_prop || fixup_prop->prop.size % sizeof(uint32_t)) + return -1; + + for (i = 0; i < fixup_prop->prop.size; i += sizeof(uint32_t)) + if (!dt_adjust_phandle(base_prop, base, be32dec( + fixup_prop->prop.data + i))) + return -1; + } + + // Now recursively descend both the base tree and the /__local_fixups__ + // subtree in sync to apply all fixups. + list_for_each(fixup_child, fixup->children, list_node) { + struct device_tree_node *base_child = NULL; + list_for_each(child, node->children, list_node) + if (!strcmp(child->name, fixup_child->name)) { + base_child = child; + break; + } + + // All fixup nodes should have a corresponding base node. + if (!base_child) + return -1; + + if (dt_fixup_locals(base_child, fixup_child, base) < 0) + return -1; + } + + return 0; +} + +/* + * Update all /__symbols__ properties in an overlay that start with + * "/fragment@X/__overlay__" with corresponding path prefix in the base tree. + * + * @param symbols /__symbols__ done to update. + * @param fragment /fragment@X node that references to should be updated. + * @param base_path Path of base tree node that the fragment overlaid. + */ +static void dt_fix_symbols(struct device_tree_node *symbols, + struct device_tree_node *fragment, + const char *base_path) +{ + struct device_tree_property *prop; + char buf[512]; // Should be enough for maximum DT path length? + char node_path[64]; // easily enough for /fragment@XXXX/__overlay__ + + if (!symbols) // If the overlay has no /__symbols__ node, we're done! + return; + + int len = snprintf(node_path, sizeof(node_path), "/%s/__overlay__", + fragment->name); + + list_for_each(prop, symbols->properties, list_node) + if (!strncmp(prop->prop.data, node_path, len)) { + prop->prop.size = snprintf(buf, sizeof(buf), "%s%s", + base_path, (char *)prop->prop.data + len) + 1; + free(prop->prop.data); + prop->prop.data = strdup(buf); + } +} + +/* + * Fix up overlay according to a property in /__fixup__. If the fixed property + * is a /fragment@X:target, also update /__symbols__ references to fragment. + * + * @params overlay Overlay to fix up. + * @params fixup /__fixup__ property. + * @params phandle phandle value to insert where the fixup points to. + * @params base_path Path to the base DT node that the fixup points to. + * @params overlay_symbols /__symbols__ node of the overlay. + * + * @return 0 on success, -1 on error. + */ +static int dt_fixup_external(struct device_tree *overlay, + struct device_tree_property *fixup, + uint32_t phandle, const char *base_path, + struct device_tree_node *overlay_symbols) +{ + struct device_tree_property *prop; + + // External fixup properties are encoded as "::". + char *entry = fixup->prop.data; + while ((void *)entry < fixup->prop.data + fixup->prop.size) { + // okay to destroy fixup property value, won't be needed again + char *node_path = entry; + entry = strchr(node_path, ':'); + if (!entry) + return -1; + *entry++ = '\0'; + + char *prop_name = entry; + entry = strchr(prop_name, ':'); + if (!entry) + return -1; + *entry++ = '\0'; + + struct device_tree_node *ovl_node = dt_find_node_by_path( + overlay, node_path, NULL, NULL, 0); + if (!ovl_node || !isdigit(*entry)) + return -1; + + struct device_tree_property *ovl_prop = NULL; + list_for_each(prop, ovl_node->properties, list_node) + if (!strcmp(prop->prop.name, prop_name)) { + ovl_prop = prop; + break; + } + + // Move entry to first char after number, must be a '\0'. + uint32_t offset = skip_atoi(&entry); + if (!ovl_prop || offset + 4 > ovl_prop->prop.size || entry[0]) + return -1; + entry++; // jump over '\0' to potential next fixup + + be32enc(ovl_prop->prop.data + offset, phandle); + + // If this is a /fragment@X:target property, update + // references to this fragment in the overlay __symbols__ now. + if (offset == 0 && !strcmp(prop_name, "target") && + !strchr(node_path + 1, '/')) // only toplevel nodes + dt_fix_symbols(overlay_symbols, ovl_node, base_path); + } + + return 0; +} + +/* + * Apply all /__fixup__ properties in the overlay. This will destroy the + * property data in /__fixup__ and it should not be accessed again. + * + * @params tree Base device tree that the overlay updates. + * @params symbols /__symbols__ node of the base device tree. + * @params overlay Overlay to fix up. + * @params fixups /__fixup__ node in the overlay. + * @params overlay_symbols /__symbols__ node of the overlay. + * + * @return 0 on success, -1 on error. + */ +static int dt_fixup_all_externals(struct device_tree *tree, + struct device_tree_node *symbols, + struct device_tree *overlay, + struct device_tree_node *fixups, + struct device_tree_node *overlay_symbols) +{ + struct device_tree_property *fix; + + // If we have any external fixups, the base tree must have /__symbols__. + if (!symbols) + return -1; + + // Unlike /__local_fixups__, /__fixups__ is not a whole subtree that + // mirrors the node hierarchy. It's just a directory of fixup properties + // that each directly contain all information necessary to apply them. + list_for_each(fix, fixups->properties, list_node) { + // The name of a fixup property is the label of the node we want + // a property to phandle-reference. Look it up in /__symbols__. + const char *path = dt_find_string_prop(symbols, fix->prop.name); + if (!path) + return -1; + + // Find the node the label pointed to to figure out its phandle. + struct device_tree_node *node = dt_find_node_by_path(tree, path, + NULL, NULL, 0); + if (!node) + return -1; + + // Write it into the overlay property(s) pointing to that node. + if (dt_fixup_external(overlay, fix, node->phandle, + path, overlay_symbols) < 0) + return -1; + } + + return 0; +} + +/* + * Copy all nodes and properties from one DT subtree into another. This is a + * shallow copy so both trees will point to the same property data afterwards. + * + * @params dst Destination subtree to copy into. + * @params src Source subtree to copy from. + * @params upd 1 to overwrite same-name properties, 0 to discard them. + */ +static void dt_copy_subtree(struct device_tree_node *dst, + struct device_tree_node *src, int upd) +{ + struct device_tree_property *prop; + struct device_tree_property *src_prop; + list_for_each(src_prop, src->properties, list_node) { + if (dt_prop_is_phandle(src_prop) || + !strcmp(src_prop->prop.name, "name")) { + printk(BIOS_DEBUG, + "WARNING: ignoring illegal overlay prop '%s'\n", + src_prop->prop.name); + continue; + } + + struct device_tree_property *dst_prop = NULL; + list_for_each(prop, dst->properties, list_node) + if (!strcmp(prop->prop.name, src_prop->prop.name)) { + dst_prop = prop; + break; + } + + if (dst_prop) { + if (!upd) { + printk(BIOS_DEBUG, + "WARNING: ignoring prop update '%s'\n", + src_prop->prop.name); + continue; + } + } else { + dst_prop = xzalloc(sizeof(*dst_prop)); + list_insert_after(&dst_prop->list_node, + &dst->properties); + } + + dst_prop->prop = src_prop->prop; + } + + struct device_tree_node *node; + struct device_tree_node *src_node; + list_for_each(src_node, src->children, list_node) { + struct device_tree_node *dst_node = NULL; + list_for_each(node, dst->children, list_node) + if (!strcmp(node->name, src_node->name)) { + dst_node = node; + break; + } + + if (!dst_node) { + dst_node = xzalloc(sizeof(*dst_node)); + *dst_node = *src_node; + list_insert_after(&dst_node->list_node, &dst->children); + } else { + dt_copy_subtree(dst_node, src_node, upd); + } + } +} + +/* + * Apply an overlay /fragment@X node to a base device tree. + * + * @param tree Base device tree. + * @param fragment /fragment@X node. + * @params overlay_symbols /__symbols__ node of the overlay. + * + * @return 0 on success, -1 on error. + */ +static int dt_import_fragment(struct device_tree *tree, + struct device_tree_node *fragment, + struct device_tree_node *overlay_symbols) +{ + // The actually overlaid nodes/props are in an __overlay__ child node. + static const char *overlay_path[] = { "__overlay__", NULL }; + struct device_tree_node *overlay = dt_find_node(fragment, overlay_path, + NULL, NULL, 0); + + // If it doesn't have an __overlay__ child, it's not a fragment. + if (!overlay) + return 0; + + // The target node of the fragment can be given by path or by phandle. + struct device_tree_property *prop; + struct device_tree_property *phandle = NULL; + struct device_tree_property *path = NULL; + list_for_each(prop, fragment->properties, list_node) { + if (!strcmp(prop->prop.name, "target")) { + phandle = prop; + break; // phandle target has priority, stop looking here + } + if (!strcmp(prop->prop.name, "target-path")) + path = prop; + } + + struct device_tree_node *target = NULL; + if (phandle) { + if (phandle->prop.size != sizeof(uint32_t)) + return -1; + target = dt_find_node_by_phandle(tree->root, + be32dec(phandle->prop.data)); + // Symbols already updated as part of dt_fixup_external(target). + } else if (path) { + target = dt_find_node_by_path(tree, path->prop.data, + NULL, NULL, 0); + dt_fix_symbols(overlay_symbols, fragment, path->prop.data); + } + if (!target) + return -1; + + dt_copy_subtree(target, overlay, 1); + return 0; +} + +/* + * Apply a device tree overlay to a base device tree. This will + * destroy/incorporate the overlay data, so it should not be freed or reused. + * See dtc.git/Documentation/dt-object-internal.txt for overlay format details. + * + * @param tree Unflattened base device tree to add the overlay into. + * @param overlay Unflattened overlay device tree to apply to the base. + * + * @return 0 on success, -1 on error. + */ +int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay) +{ + // First, we need to make sure phandles inside the overlay don't clash + // with those in the base tree. We just define the highest phandle value + // in the base tree as the "phandle offset" for this overlay and + // increment all phandles in it by that value. + uint32_t phandle_base = tree->max_phandle; + uint32_t new_max = dt_adjust_all_phandles(overlay->root, phandle_base); + if (!new_max) { + printk(BIOS_DEBUG, "ERROR: invalid phandles in overlay\n"); + return -1; + } + tree->max_phandle = new_max; + + // Now that we changed phandles in the overlay, we need to update any + // nodes referring to them. Those are listed in /__local_fixups__. + struct device_tree_node *local_fixups = dt_find_node_by_path(overlay, + "/__local_fixups__", NULL, NULL, 0); + if (local_fixups && dt_fixup_locals(overlay->root, local_fixups, + phandle_base) < 0) { + printk(BIOS_DEBUG, "ERROR: invalid local fixups in overlay\n"); + return -1; + } + + // Besides local phandle references (from nodes within the overlay to + // other nodes within the overlay), the overlay may also contain phandle + // references to the base tree. These are stored with invalid values and + // must be updated now. /__symbols__ contains a list of all labels in + // the base tree, and /__fixups__ describes all nodes in the overlay + // that contain external phandle references. + // We also take this opportunity to update all /fragment@X/__overlay__/ + // prefixes in the overlay's /__symbols__ node to the correct path that + // the fragment will be placed in later, since this is the only step + // where we have all necessary information for that easily available. + struct device_tree_node *symbols = dt_find_node_by_path(tree, + "/__symbols__", NULL, NULL, 0); + struct device_tree_node *fixups = dt_find_node_by_path(overlay, + "/__fixups__", NULL, NULL, 0); + struct device_tree_node *overlay_symbols = dt_find_node_by_path(overlay, + "/__symbols__", NULL, NULL, 0); + if (fixups && dt_fixup_all_externals(tree, symbols, overlay, + fixups, overlay_symbols) < 0) { + printk(BIOS_DEBUG, + "ERROR: cannot match external fixups from overlay\n"); + return -1; + } + + // After all this fixing up, we can finally merge the overlay into the + // tree (one fragment at a time, because for some reason it's split up). + struct device_tree_node *fragment; + list_for_each(fragment, overlay->root->children, list_node) + if (dt_import_fragment(tree, fragment, overlay_symbols) < 0) { + printk(BIOS_DEBUG, "ERROR: bad DT fragment '%s'\n", + fragment->name); + return -1; + } + + // We need to also update /__symbols__ to include labels from this + // overlay, in case we want to load further overlays with external + // phandle references to it. If the base tree already has a /__symbols__ + // we merge them together, otherwise we just insert the overlay's + // /__symbols__ node into the base tree root. + if (overlay_symbols) { + if (symbols) + dt_copy_subtree(symbols, overlay_symbols, 0); + else + list_insert_after(&overlay_symbols->list_node, + &tree->root->children); + } + + return 0; +} From b379f1964ec6b0a59b7d869154a8bc739eb55fc0 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Mon, 13 May 2019 16:34:16 -0700 Subject: [PATCH 128/221] fit: Refactor config node handling This patch makes some minor refactoring to the way the FIT parser handles config nodes. A lot of this code was written in the dawn age of depthcharge when its device tree library wasn't as well-stocked yet, so some of it can be rewritten nicer with more high-level primitives. There's no point in storing both the string name and the actual FDT node of a FIT image node separately, since the latter also contains the former, so remove that. Also eliminate code for the case of not having an FDT (which makes no sense), and move some more FDT validity/compat checking into fit_update_compat() (mostly in anticipation of later changes). This patch was adapted from depthcharge's http://crosreview.com/1553456 with a couple of modifications specific to coreboot's custom FIT loading code. Change-Id: Ia79e0fd0e1159c4aca64c453b82a0379b133350d Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32870 Reviewed-by: Hung-Te Lin Tested-by: build bot (Jenkins) --- src/arch/arm64/fit_payload.c | 10 +-- src/include/fit.h | 11 ++- src/lib/fit.c | 128 ++++++++++++++++------------------- src/lib/fit_payload.c | 59 ++++++++-------- 4 files changed, 92 insertions(+), 116 deletions(-) diff --git a/src/arch/arm64/fit_payload.c b/src/arch/arm64/fit_payload.c index c4bbceee4c..fd1bae171a 100644 --- a/src/arch/arm64/fit_payload.c +++ b/src/arch/arm64/fit_payload.c @@ -184,20 +184,14 @@ bool fit_payload_arch(struct prog *payload, struct fit_config_node *config, bool place_anywhere; void *arg = NULL; - if (!config->fdt || !fdt) { - printk(BIOS_CRIT, "CRIT: Providing a valid FDT is mandatory to " - "boot an ARM64 kernel!\n"); - return false; - } - - if (!decompress_kernel_header(config->kernel_node)) { + if (!decompress_kernel_header(config->kernel)) { printk(BIOS_CRIT, "CRIT: Payload doesn't look like an ARM64" " kernel Image.\n"); return false; } /* Update kernel size from image header, if possible */ - kernel->size = get_kernel_size(config->kernel_node); + kernel->size = get_kernel_size(config->kernel); printk(BIOS_DEBUG, "FIT: Using kernel size of 0x%zx bytes\n", kernel->size); diff --git a/src/include/fit.h b/src/include/fit.h index 6e0667f6cf..758ee70c9c 100644 --- a/src/include/fit.h +++ b/src/include/fit.h @@ -27,7 +27,7 @@ struct fit_image_node { const char *name; - const void *data; + void *data; uint32_t size; int compression; @@ -37,12 +37,9 @@ struct fit_image_node struct fit_config_node { const char *name; - const char *kernel; - struct fit_image_node *kernel_node; - const char *fdt; - struct fit_image_node *fdt_node; - const char *ramdisk; - struct fit_image_node *ramdisk_node; + struct fit_image_node *kernel; + struct fit_image_node *fdt; + struct fit_image_node *ramdisk; struct fdt_property compat; int compat_rank; int compat_pos; diff --git a/src/lib/fit.c b/src/lib/fit.c index c98ba2f802..5fbcd77407 100644 --- a/src/lib/fit.c +++ b/src/lib/fit.c @@ -85,6 +85,17 @@ static void fit_add_default_compat_strings(void) fit_add_compat_string(compat_string); } +static struct fit_image_node *find_image(const char *name) +{ + struct fit_image_node *image; + list_for_each(image, image_nodes, list_node) { + if (!strcmp(image->name, name)) + return image; + } + printk(BIOS_ERR, "ERROR: Cannot find image node %s!\n", name); + return NULL; +} + static void image_node(struct device_tree_node *node) { struct fit_image_node *image = xzalloc(sizeof(*image)); @@ -120,11 +131,11 @@ static void config_node(struct device_tree_node *node) struct device_tree_property *prop; list_for_each(prop, node->properties, list_node) { if (!strcmp("kernel", prop->prop.name)) - config->kernel = prop->prop.data; + config->kernel = find_image(prop->prop.data); else if (!strcmp("fdt", prop->prop.name)) - config->fdt = prop->prop.data; + config->fdt = find_image(prop->prop.data); else if (!strcmp("ramdisk", prop->prop.name)) - config->ramdisk = prop->prop.data; + config->ramdisk = find_image(prop->prop.data); } list_insert_after(&config->list_node, &config_nodes); @@ -132,40 +143,22 @@ static void config_node(struct device_tree_node *node) static void fit_unpack(struct device_tree *tree, const char **default_config) { - assert(tree && tree->root); + struct device_tree_node *child; + struct device_tree_node *images = dt_find_node_by_path(tree, "/images", + NULL, NULL, 0); + if (images) + list_for_each(child, images->children, list_node) + image_node(child); - struct device_tree_node *top; - list_for_each(top, tree->root->children, list_node) { - struct device_tree_node *child; - if (!strcmp("images", top->name)) { - - list_for_each(child, top->children, list_node) - image_node(child); - - } else if (!strcmp("configurations", top->name)) { - struct device_tree_property *prop; - list_for_each(prop, top->properties, list_node) { - if (!strcmp("default", prop->prop.name) && - default_config) - *default_config = prop->prop.data; - } - - list_for_each(child, top->children, list_node) - config_node(child); - } + struct device_tree_node *configs = dt_find_node_by_path(tree, + "/configurations", NULL, NULL, 0); + if (configs) { + *default_config = dt_find_string_prop(configs, "default"); + list_for_each(child, configs->children, list_node) + config_node(child); } } -static struct fit_image_node *find_image(const char *name) -{ - struct fit_image_node *image; - list_for_each(image, image_nodes, list_node) { - if (!strcmp(image->name, name)) - return image; - } - return NULL; -} - static int fdt_find_compat(const void *blob, uint32_t start_offset, struct fdt_property *prop) { @@ -393,18 +386,27 @@ void fit_update_memory(struct device_tree *tree) /* * Finds a compat string and updates the compat position and rank. - * @param fdt_blob Pointer to FDT * @param config The current config node to operate on + * @return 0 if compat updated, -1 if this FDT cannot be used. */ -static void fit_update_compat(const void *fdt_blob, - struct fit_config_node *config) +static int fit_update_compat(struct fit_config_node *config) { + if (config->fdt->compression != CBFS_COMPRESS_NONE) { + printk(BIOS_ERR, + "FDT compression not yet supported, skipping %s.\n", + config->name); + return -1; + } + + void *fdt_blob = config->fdt->data; struct compat_string_entry *compat_node; const struct fdt_header *fdt_header = (const struct fdt_header *)fdt_blob; uint32_t fdt_offset = be32_to_cpu(fdt_header->structure_offset); size_t i = 0; + config->compat_pos = -1; + config->compat_rank = -1; if (!fdt_find_compat(fdt_blob, fdt_offset, &config->compat)) { list_for_each(compat_node, compat_strings, list_node) { int pos = fit_check_compat(&config->compat, @@ -419,6 +421,8 @@ static void fit_update_compat(const void *fdt_blob, i++; } } + + return 0; } struct fit_config_node *fit_load(void *fit) @@ -457,55 +461,41 @@ struct fit_config_node *fit_load(void *fit) printk(BIOS_DEBUG, "\n"); /* Process and list the configs. */ list_for_each(config, config_nodes, list_node) { - if (config->kernel) - config->kernel_node = find_image(config->kernel); - if (config->fdt) - config->fdt_node = find_image(config->fdt); - if (config->ramdisk) - config->ramdisk_node = find_image(config->ramdisk); + if (!config->kernel) { + printk(BIOS_ERR, + "ERROR: config %s has no kernel, skipping.\n", + config->name); + continue; + } + if (!config->fdt) { + printk(BIOS_ERR, + "ERROR: config %s has no FDT, skipping.\n", + config->name); + continue; + } - if (config->ramdisk_node && - config->ramdisk_node->compression < 0) { + if (config->ramdisk && + config->ramdisk->compression < 0) { printk(BIOS_WARNING, "WARN: Ramdisk is compressed with " "an unsupported algorithm, discarding config %s." "\n", config->name); - list_remove(&config->list_node); continue; } - if (!config->kernel_node || - (config->fdt && !config->fdt_node)) { - printk(BIOS_DEBUG, "FIT: Missing image, discarding " - "config %s.\n", config->name); - list_remove(&config->list_node); + if (fit_update_compat(config)) continue; - } - if (config->fdt_node) { - if (config->fdt_node->compression != - CBFS_COMPRESS_NONE) { - printk(BIOS_DEBUG, - "FIT: FDT compression not yet supported," - " skipping config %s.\n", config->name); - list_remove(&config->list_node); - continue; - } - - config->compat_pos = -1; - config->compat_rank = -1; - - fit_update_compat(config->fdt_node->data, config); - } printk(BIOS_DEBUG, "FIT: config %s", config->name); if (default_config_name && !strcmp(config->name, default_config_name)) { printk(BIOS_DEBUG, " (default)"); default_config = config; } - if (config->fdt) - printk(BIOS_DEBUG, ", fdt %s", config->fdt); + printk(BIOS_DEBUG, ", kernel %s", config->kernel->name); + printk(BIOS_DEBUG, ", fdt %s", config->fdt->name); if (config->ramdisk) - printk(BIOS_DEBUG, ", ramdisk %s", config->ramdisk); + printk(BIOS_DEBUG, ", ramdisk %s", + config->ramdisk->name); if (config->compat.name) { printk(BIOS_DEBUG, ", compat"); int bytes = config->compat.size; diff --git a/src/lib/fit_payload.c b/src/lib/fit_payload.c index e0158f2129..4bc6622b19 100644 --- a/src/lib/fit_payload.c +++ b/src/lib/fit_payload.c @@ -176,37 +176,34 @@ void fit_payload(struct prog *payload) struct fit_config_node *config = fit_load(data); - if (!config || !config->kernel_node) { + if (!config) { printk(BIOS_ERR, "ERROR: Could not load FIT\n"); rdev_munmap(prog_rdev(payload), data); return; } - if (config->fdt_node) { - dt = fdt_unflatten(config->fdt_node->data); - if (!dt) { - printk(BIOS_ERR, - "ERROR: Failed to unflatten the FDT.\n"); - rdev_munmap(prog_rdev(payload), data); - return; - } - - dt_apply_fixups(dt); - - /* Insert coreboot specific information */ - add_cb_fdt_data(dt); - - /* Update device_tree */ -#if defined(CONFIG_LINUX_COMMAND_LINE) - fit_update_chosen(dt, (char *)CONFIG_LINUX_COMMAND_LINE); -#endif - fit_update_memory(dt); + dt = fdt_unflatten(config->fdt->data); + if (!dt) { + printk(BIOS_ERR, "ERROR: Failed to unflatten the FDT.\n"); + rdev_munmap(prog_rdev(payload), data); + return; } + dt_apply_fixups(dt); + + /* Insert coreboot specific information */ + add_cb_fdt_data(dt); + + /* Update device_tree */ +#if defined(CONFIG_LINUX_COMMAND_LINE) + fit_update_chosen(dt, (char *)CONFIG_LINUX_COMMAND_LINE); +#endif + fit_update_memory(dt); + /* Collect infos for fit_payload_arch */ - kernel.size = config->kernel_node->size; + kernel.size = config->kernel->size; fdt.size = dt ? dt_flat_size(dt) : 0; - initrd.size = config->ramdisk_node ? config->ramdisk_node->size : 0; + initrd.size = config->ramdisk ? config->ramdisk->size : 0; /* Invoke arch specific payload placement and fixups */ if (!fit_payload_arch(payload, config, &kernel, &fdt, &initrd)) { @@ -216,17 +213,15 @@ void fit_payload(struct prog *payload) return; } - /* Load the images to given position */ - if (config->fdt_node) { - /* Update device_tree */ - if (config->ramdisk_node) - fit_add_ramdisk(dt, (void *)initrd.offset, initrd.size); + /* Update ramdisk location in FDT */ + if (config->ramdisk) + fit_add_ramdisk(dt, (void *)initrd.offset, initrd.size); - pack_fdt(&fdt, dt); - } + /* Repack FDT for handoff to kernel */ + pack_fdt(&fdt, dt); - if (config->ramdisk_node && - extract(&initrd, config->ramdisk_node)) { + if (config->ramdisk && + extract(&initrd, config->ramdisk)) { printk(BIOS_ERR, "ERROR: Failed to extract initrd\n"); prog_set_entry(payload, NULL, NULL); rdev_munmap(prog_rdev(payload), data); @@ -235,7 +230,7 @@ void fit_payload(struct prog *payload) timestamp_add_now(TS_KERNEL_DECOMPRESSION); - if (extract(&kernel, config->kernel_node)) { + if (extract(&kernel, config->kernel)) { printk(BIOS_ERR, "ERROR: Failed to extract kernel\n"); prog_set_entry(payload, NULL, NULL); rdev_munmap(prog_rdev(payload), data); From 2855a0c14dc1e390a13fbaecf14e888d1339a0b9 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Thu, 16 May 2019 13:51:31 -0700 Subject: [PATCH 129/221] fit_payload: Don't call prog_segment_loaded() on extracted images Kernel handoff on all architectures supporting FIT images already includes flushing and disabling the cache. No need to waste any more time flushing individual components (especially since in the case of compressed DT overlays they will still get accessed again afterwards). Change-Id: I7b483e920c5a71663b024b5b50804ffc84939830 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32871 Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/lib/fit_payload.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/fit_payload.c b/src/lib/fit_payload.c index 4bc6622b19..c977903534 100644 --- a/src/lib/fit_payload.c +++ b/src/lib/fit_payload.c @@ -88,12 +88,11 @@ static bool extract(struct region *region, struct fit_image_node *node) } if (!true_size) { - printk(BIOS_ERR, "ERROR: %s node failed!\n", comp_name); + printk(BIOS_ERR, "ERROR: %s decompression failed!\n", + comp_name); return true; } - prog_segment_loaded(region->offset, true_size, 0); - return false; } From fec4206299aefba05cae3bb82421635543ca1a2b Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Thu, 16 May 2019 16:04:19 -0700 Subject: [PATCH 130/221] fit: Add device tree compression This patch adds support for compressing individual device trees in the FIT image. In order to make this efficient, we'll have to pull the compatible property out of the FDT and store it directly in the config node of the FIT image, so that we don't have to scan (and therefore decompress) every single FDT on boot. Device tree compression is only supported for FIT images that have this external compatible property. For older images with no compression, we still support fallback to scanning the FDT for the property. This patch was adapted from depthcharge's http://crosreview.com/1553458 Change-Id: Ifcb6997782c480c8ef6692df17b66ad96264e623 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32872 Reviewed-by: Hung-Te Lin Tested-by: build bot (Jenkins) --- src/lib/fit.c | 60 ++++++++++++++++++++++++++----------------- src/lib/fit_payload.c | 20 ++++++++++++++- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/lib/fit.c b/src/lib/fit.c index 5fbcd77407..befedde9cf 100644 --- a/src/lib/fit.c +++ b/src/lib/fit.c @@ -136,6 +136,8 @@ static void config_node(struct device_tree_node *node) config->fdt = find_image(prop->prop.data); else if (!strcmp("ramdisk", prop->prop.name)) config->ramdisk = find_image(prop->prop.data); + else if (!strcmp("compatible", prop->prop.name)) + config->compat = prop->prop; } list_insert_after(&config->list_node, &config_nodes); @@ -391,35 +393,45 @@ void fit_update_memory(struct device_tree *tree) */ static int fit_update_compat(struct fit_config_node *config) { - if (config->fdt->compression != CBFS_COMPRESS_NONE) { - printk(BIOS_ERR, - "FDT compression not yet supported, skipping %s.\n", - config->name); - return -1; - } + // If there was no "compatible" property in config node, this is a + // legacy FIT image. Must extract compat prop from FDT itself. + if (!config->compat.name) { + void *fdt_blob = config->fdt->data; + const struct fdt_header *fdt_header = fdt_blob; + uint32_t fdt_offset = be32_to_cpu(fdt_header->structure_offset); - void *fdt_blob = config->fdt->data; - struct compat_string_entry *compat_node; - const struct fdt_header *fdt_header = - (const struct fdt_header *)fdt_blob; - uint32_t fdt_offset = be32_to_cpu(fdt_header->structure_offset); - size_t i = 0; + if (config->fdt->compression != CBFS_COMPRESS_NONE) { + printk(BIOS_ERR, + "ERROR: config %s has a compressed FDT without " + "external compatible property, skipping.\n", + config->name); + return -1; + } + + if (fdt_find_compat(fdt_blob, fdt_offset, &config->compat)) { + printk(BIOS_ERR, + "ERROR: Can't find compat string in FDT %s " + "for config %s, skipping.\n", + config->fdt->name, config->name); + return -1; + } + } config->compat_pos = -1; config->compat_rank = -1; - if (!fdt_find_compat(fdt_blob, fdt_offset, &config->compat)) { - list_for_each(compat_node, compat_strings, list_node) { - int pos = fit_check_compat(&config->compat, - compat_node->compat_string); - if (pos >= 0) { - config->compat_pos = pos; - config->compat_rank = i; - config->compat_string = - compat_node->compat_string; - break; - } - i++; + size_t i = 0; + struct compat_string_entry *compat_node; + list_for_each(compat_node, compat_strings, list_node) { + int pos = fit_check_compat(&config->compat, + compat_node->compat_string); + if (pos >= 0) { + config->compat_pos = pos; + config->compat_rank = i; + config->compat_string = + compat_node->compat_string; + break; } + i++; } return 0; diff --git a/src/lib/fit_payload.c b/src/lib/fit_payload.c index c977903534..b0491889c9 100644 --- a/src/lib/fit_payload.c +++ b/src/lib/fit_payload.c @@ -96,6 +96,24 @@ static bool extract(struct region *region, struct fit_image_node *node) return false; } +static struct device_tree *unpack_fdt(struct fit_image_node *image_node) +{ + void *data = image_node->data; + + if (image_node->compression != CBFS_COMPRESS_NONE) { + /* TODO: This is an ugly heuristic for how much the size will + expand on decompression, fix once FIT images support storing + the real uncompressed size. */ + struct region r = { .offset = 0, .size = image_node->size * 5 }; + data = malloc(r.size); + r.offset = (uintptr_t)data; + if (!data || extract(&r, image_node)) + return NULL; + } + + return fdt_unflatten(data); +} + /** * Add coreboot tables, CBMEM information and optional board specific strapping * IDs to the device tree loaded via FIT. @@ -181,7 +199,7 @@ void fit_payload(struct prog *payload) return; } - dt = fdt_unflatten(config->fdt->data); + dt = unpack_fdt(config->fdt); if (!dt) { printk(BIOS_ERR, "ERROR: Failed to unflatten the FDT.\n"); rdev_munmap(prog_rdev(payload), data); From 21b0b1adec23d2f67e51a47207e691fb41f576dd Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Thu, 16 May 2019 16:12:04 -0700 Subject: [PATCH 131/221] fit: Add overlay support This patch adds support to boot FIT image configurations consisting of a base device tree and one or more overlays. Since extracting the right compatible string from overlay FDTs is problematic, we'll only support this for FIT images that have the compatible string pulled out into the config node. This patch was adapted from depthcharge's http://crosreview.com/1555293 Change-Id: I0943f9a1869c9e416887c7ff16e33f7d91b74989 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32873 Reviewed-by: Hung-Te Lin Tested-by: build bot (Jenkins) --- src/include/fit.h | 12 ++++++++---- src/lib/fit.c | 39 ++++++++++++++++++++++++++++++++++++++- src/lib/fit_payload.c | 9 +++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/include/fit.h b/src/include/fit.h index 758ee70c9c..1c90aca1ff 100644 --- a/src/include/fit.h +++ b/src/include/fit.h @@ -24,8 +24,7 @@ #include #include -struct fit_image_node -{ +struct fit_image_node { const char *name; void *data; uint32_t size; @@ -34,11 +33,11 @@ struct fit_image_node struct list_node list_node; }; -struct fit_config_node -{ +struct fit_config_node { const char *name; struct fit_image_node *kernel; struct fit_image_node *fdt; + struct list_node overlays; struct fit_image_node *ramdisk; struct fdt_property compat; int compat_rank; @@ -48,6 +47,11 @@ struct fit_config_node struct list_node list_node; }; +struct fit_overlay_chain { + struct fit_image_node *overlay; + struct list_node list_node; +}; + /* * Updates the cmdline in the devicetree. */ diff --git a/src/lib/fit.c b/src/lib/fit.c index befedde9cf..6ac0a8917e 100644 --- a/src/lib/fit.c +++ b/src/lib/fit.c @@ -96,6 +96,31 @@ static struct fit_image_node *find_image(const char *name) return NULL; } +static struct fit_image_node *find_image_with_overlays(const char *name, + int bytes, struct list_node *prev) +{ + struct fit_image_node *base = find_image(name); + if (!base) + return NULL; + + int len = strnlen(name, bytes) + 1; + bytes -= len; + name += len; + while (bytes > 0) { + struct fit_overlay_chain *next = xzalloc(sizeof(*next)); + next->overlay = find_image(name); + if (!next->overlay) + return NULL; + list_insert_after(&next->list_node, prev); + prev = &next->list_node; + len = strnlen(name, bytes) + 1; + bytes -= len; + name += len; + } + + return base; +} + static void image_node(struct device_tree_node *node) { struct fit_image_node *image = xzalloc(sizeof(*image)); @@ -133,7 +158,8 @@ static void config_node(struct device_tree_node *node) if (!strcmp("kernel", prop->prop.name)) config->kernel = find_image(prop->prop.data); else if (!strcmp("fdt", prop->prop.name)) - config->fdt = find_image(prop->prop.data); + config->fdt = find_image_with_overlays(prop->prop.data, + prop->prop.size, &config->overlays); else if (!strcmp("ramdisk", prop->prop.name)) config->ramdisk = find_image(prop->prop.data); else if (!strcmp("compatible", prop->prop.name)) @@ -408,6 +434,14 @@ static int fit_update_compat(struct fit_config_node *config) return -1; } + // FDT overlays are not supported in legacy FIT images. + if (config->overlays.next) { + printk(BIOS_ERR, + "ERROR: config %s has overlay but no compat!\n", + config->name); + return -1; + } + if (fdt_find_compat(fdt_blob, fdt_offset, &config->compat)) { printk(BIOS_ERR, "ERROR: Can't find compat string in FDT %s " @@ -442,6 +476,7 @@ struct fit_config_node *fit_load(void *fit) struct fit_image_node *image; struct fit_config_node *config; struct compat_string_entry *compat_node; + struct fit_overlay_chain *overlay_chain; printk(BIOS_DEBUG, "FIT: Loading FIT from %p\n", fit); @@ -505,6 +540,8 @@ struct fit_config_node *fit_load(void *fit) } printk(BIOS_DEBUG, ", kernel %s", config->kernel->name); printk(BIOS_DEBUG, ", fdt %s", config->fdt->name); + list_for_each(overlay_chain, config->overlays, list_node) + printk(BIOS_DEBUG, " %s", overlay_chain->overlay->name); if (config->ramdisk) printk(BIOS_DEBUG, ", ramdisk %s", config->ramdisk->name); diff --git a/src/lib/fit_payload.c b/src/lib/fit_payload.c index b0491889c9..8e75915806 100644 --- a/src/lib/fit_payload.c +++ b/src/lib/fit_payload.c @@ -206,6 +206,15 @@ void fit_payload(struct prog *payload) return; } + struct fit_overlay_chain *chain; + list_for_each(chain, config->overlays, list_node) { + struct device_tree *overlay = unpack_fdt(chain->overlay); + if (!overlay || dt_apply_overlay(dt, overlay)) { + printk(BIOS_ERR, "ERROR: Failed to apply overlay %s!\n", + chain->overlay->name); + } + } + dt_apply_fixups(dt); /* Insert coreboot specific information */ From 80f3ac63f2d73c96ae394ec26361f16ab7724687 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Fri, 17 May 2019 22:29:25 -0700 Subject: [PATCH 132/221] fit: Check all compat strings for highest match The compat string matching code was mostly copied from depthcharge. One of the few differences is that we now store the list of compat strings we're willing to match in a list rather than an array. Since our lists insert at the front, that means the strings are now ordered lowest to highest (not highest to lowest like in depthcharge). We did rewrite the compat_rank matching code to accomodate for that... however, what we didn't do is remove the break-statement in the loop that matches all compat strings. When we search the lowest priority first, we can't abort the search as soon as we found a match -- we have to keep looking because we might find a higher priority match later. This patch fixes the issue so that my Kevin can actually match for google,kevin-rev5 (and doesn't just jump at the first best google,kevin match). Change-Id: Ibe3d84bbce6de3cd49c746a667ae1ccfdc843105 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32874 Reviewed-by: Hung-Te Lin Tested-by: build bot (Jenkins) --- src/lib/fit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/fit.c b/src/lib/fit.c index 6ac0a8917e..37dfc8de98 100644 --- a/src/lib/fit.c +++ b/src/lib/fit.c @@ -463,7 +463,6 @@ static int fit_update_compat(struct fit_config_node *config) config->compat_rank = i; config->compat_string = compat_node->compat_string; - break; } i++; } From 23df47724d792207fc99864acabf2cd234ac0d9d Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Fri, 17 May 2019 22:50:18 -0700 Subject: [PATCH 133/221] device_tree: Update comment style to C89 This code was copied from depthcharge which uses C99 comment style, but coreboot uses C89 comment style. Update to match coreboot. Change-Id: Ib67bb9ff17b7688826071453ab58894a0835ce10 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/32875 Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/include/device_tree.h | 44 +++++----- src/lib/device_tree.c | 178 ++++++++++++++++++++------------------ src/lib/fit.c | 6 +- 3 files changed, 119 insertions(+), 109 deletions(-) diff --git a/src/include/device_tree.h b/src/include/device_tree.h index 8d86bc5acb..56a9361bd8 100644 --- a/src/include/device_tree.h +++ b/src/include/device_tree.h @@ -74,9 +74,9 @@ struct device_tree_node const char *name; uint32_t phandle; - // List of struct device_tree_property-s. + /* List of struct device_tree_property-s. */ struct list_node properties; - // List of struct device_tree_nodes. + /* List of struct device_tree_nodes. */ struct list_node children; struct list_node list_node; @@ -108,18 +108,18 @@ struct device_tree * which were consumed reading the requested value. */ -// Read the property, if any, at offset offset. +/* Read the property, if any, at offset offset. */ int fdt_next_property(const void *blob, uint32_t offset, struct fdt_property *prop); -// Read the name of the node, if any, at offset offset. +/* Read the name of the node, if any, at offset offset. */ int fdt_node_name(const void *blob, uint32_t offset, const char **name); void fdt_print_node(const void *blob, uint32_t offset); int fdt_skip_node(const void *blob, uint32_t offset); -// Read a flattened device tree into a heirarchical structure which refers to -// the contents of the flattened tree in place. Modifying the flat tree -// invalidates the unflattened one. +/* Read a flattened device tree into a heirarchical structure which refers to + the contents of the flattened tree in place. Modifying the flat tree + invalidates the unflattened one. */ struct device_tree *fdt_unflatten(const void *blob); @@ -128,42 +128,42 @@ struct device_tree *fdt_unflatten(const void *blob); * Unflattened device tree functions. */ -// Figure out how big a device tree would be if it were flattened. +/* Figure out how big a device tree would be if it were flattened. */ uint32_t dt_flat_size(const struct device_tree *tree); -// Flatten a device tree into the buffer pointed to by dest. +/* Flatten a device tree into the buffer pointed to by dest. */ void dt_flatten(const struct device_tree *tree, void *dest); void dt_print_node(const struct device_tree_node *node); -// Read #address-cells and #size-cells properties from a node. +/* Read #address-cells and #size-cells properties from a node. */ void dt_read_cell_props(const struct device_tree_node *node, u32 *addrcp, u32 *sizecp); -// Look up or create a node relative to a parent node, through its path -// represented as an array of strings. +/* Look up or create a node relative to a parent node, through its path + represented as an array of strings. */ struct device_tree_node *dt_find_node(struct device_tree_node *parent, const char **path, u32 *addrcp, u32 *sizecp, int create); struct device_tree_node *dt_find_node_by_phandle(struct device_tree_node *root, uint32_t phandle); -// Look up or create a node in the tree, through its path -// represented as a string of '/' separated node names. +/* Look up or create a node in the tree, through its path + represented as a string of '/' separated node names. */ struct device_tree_node *dt_find_node_by_path(struct device_tree *tree, const char *path, u32 *addrcp, u32 *sizecp, int create); -// Look up a node through an alias. +/* Look up a node through an alias. */ struct device_tree_node *dt_find_node_by_alias(struct device_tree *tree, const char *alias); -// Look up a node relative to a parent node, through its compatible string. +/* Look up a node relative to a parent node, through its compatible string. */ struct device_tree_node *dt_find_compat(struct device_tree_node *parent, const char *compatible); -// Look up the next child of a parent node, through its compatible string. It -// uses child pointer as the marker to find next. +/* Look up the next child of a parent node, through its compatible string. It + uses child pointer as the marker to find next. */ struct device_tree_node *dt_find_next_compat_child(struct device_tree_node *parent, struct device_tree_node *child, const char *compat); -// Look up a node relative to a parent node, through its property value. +/* Look up a node relative to a parent node, through its property value. */ struct device_tree_node *dt_find_prop_value(struct device_tree_node *parent, const char *name, void *data, size_t size); -// Write src into *dest as a 'length'-byte big-endian integer. +/* Write src into *dest as a 'length'-byte big-endian integer. */ void dt_write_int(u8 *dest, u64 src, size_t length); -// Delete a property +/* Delete a property */ void dt_delete_prop(struct device_tree_node *node, const char *name); -// Add different kinds of properties to a node, or update existing ones. +/* Add different kinds of properties to a node, or update existing ones. */ void dt_add_bin_prop(struct device_tree_node *node, const char *name, void *data, size_t size); void dt_add_string_prop(struct device_tree_node *node, const char *name, diff --git a/src/lib/device_tree.c b/src/lib/device_tree.c index a68e1b74c5..2e81a08779 100644 --- a/src/lib/device_tree.c +++ b/src/lib/device_tree.c @@ -133,7 +133,7 @@ static int print_flat_node(const void *blob, uint32_t start_offset, int depth) offset += size; } - printk(BIOS_DEBUG, "\n"); // empty line between props and nodes + printk(BIOS_DEBUG, "\n"); /* empty line between props and nodes */ while ((size = print_flat_node(blob, offset, depth + 1))) offset += size; @@ -279,9 +279,9 @@ struct device_tree *fdt_unflatten(const void *blob) uint32_t min_offset = 0; min_offset = MIN(struct_offset, strings_offset); min_offset = MIN(min_offset, reserve_offset); - // Assume everything up to the first non-header component is part of - // the header and needs to be preserved. This will protect us against - // new elements being added in the future. + /* Assume everything up to the first non-header component is part of + the header and needs to be preserved. This will protect us against + new elements being added in the future. */ tree->header_size = min_offset; struct device_tree_reserve_map_entry *entry; @@ -309,25 +309,25 @@ struct device_tree *fdt_unflatten(const void *blob) static void dt_flat_prop_size(struct device_tree_property *prop, uint32_t *struct_size, uint32_t *strings_size) { - // Starting token. + /* Starting token. */ *struct_size += sizeof(uint32_t); - // Size. + /* Size. */ *struct_size += sizeof(uint32_t); - // Name offset. + /* Name offset. */ *struct_size += sizeof(uint32_t); - // Property value. + /* Property value. */ *struct_size += ALIGN_UP(prop->prop.size, sizeof(uint32_t)); - // Property name. + /* Property name. */ *strings_size += strlen(prop->prop.name) + 1; } static void dt_flat_node_size(struct device_tree_node *node, uint32_t *struct_size, uint32_t *strings_size) { - // Starting token. + /* Starting token. */ *struct_size += sizeof(uint32_t); - // Node name. + /* Node name. */ *struct_size += ALIGN_UP(strlen(node->name) + 1, sizeof(uint32_t)); struct device_tree_property *prop; @@ -338,7 +338,7 @@ static void dt_flat_node_size(struct device_tree_node *node, list_for_each(child, node->children, list_node) dt_flat_node_size(child, struct_size, strings_size); - // End token. + /* End token. */ *struct_size += sizeof(uint32_t); } @@ -355,7 +355,7 @@ uint32_t dt_flat_size(const struct device_tree *tree) dt_flat_node_size(tree->root, &struct_size, &strings_size); size += struct_size; - // End token. + /* End token. */ size += sizeof(uint32_t); size += strings_size; @@ -480,7 +480,7 @@ void dt_flatten(const struct device_tree *tree, void *start_dest) static void print_node(const struct device_tree_node *node, int depth) { print_indent(depth); - if (depth == 0) // root node has no name, print a starting slash + if (depth == 0) /* root node has no name, print a starting slash */ printk(BIOS_DEBUG, "/"); printk(BIOS_DEBUG, "%s {\n", node->name); @@ -488,7 +488,7 @@ static void print_node(const struct device_tree_node *node, int depth) list_for_each(prop, node->properties, list_node) print_property(&prop->prop, depth + 1); - printk(BIOS_DEBUG, "\n"); // empty line between props and nodes + printk(BIOS_DEBUG, "\n"); /* empty line between props and nodes */ struct device_tree_node *child; list_for_each(child, node->children, list_node) @@ -548,13 +548,13 @@ struct device_tree_node *dt_find_node(struct device_tree_node *parent, { struct device_tree_node *node, *found = NULL; - // Update #address-cells and #size-cells for this level. + /* Update #address-cells and #size-cells for this level. */ dt_read_cell_props(parent, addrcp, sizecp); if (!*path) return parent; - // Find the next node in the path, if it exists. + /* Find the next node in the path, if it exists. */ list_for_each(node, parent->children, list_node) { if (!strcmp(node->name, *path)) { found = node; @@ -562,7 +562,7 @@ struct device_tree_node *dt_find_node(struct device_tree_node *parent, } } - // Otherwise create it or return NULL. + /* Otherwise create it or return NULL. */ if (!found) { if (!create) return NULL; @@ -609,8 +609,8 @@ struct device_tree_node *dt_find_node_by_path(struct device_tree *tree, int i; struct device_tree_node *node = NULL; - if (path[0] == '/') { // regular path - if (path[1] == '\0') { // special case: "/" is root node + if (path[0] == '/') { /* regular path */ + if (path[1] == '\0') { /* special case: "/" is root node */ dt_read_cell_props(tree->root, addrcp, sizecp); return tree->root; } @@ -620,7 +620,7 @@ struct device_tree_node *dt_find_node_by_path(struct device_tree *tree, return NULL; parent = tree->root; - } else { // alias + } else { /* alias */ char *alias; alias = duped_str = strdup(path); @@ -641,7 +641,7 @@ struct device_tree_node *dt_find_node_by_path(struct device_tree *tree, } if (!sub_path) { - // it's just the alias, no sub-path + /* it's just the alias, no sub-path */ free(duped_str); return parent; } @@ -756,7 +756,7 @@ static int dt_check_compat_match(struct device_tree_node *node, struct device_tree_node *dt_find_compat(struct device_tree_node *parent, const char *compat) { - // Check if the parent node itself is compatible. + /* Check if the parent node itself is compatible. */ if (dt_check_compat_match(parent, compat)) return parent; @@ -1091,11 +1091,11 @@ struct device_tree_node *dt_init_reserved_memory_node(struct device_tree *tree) if (!reserved) return NULL; - // Binding doc says this should have the same #{address,size}-cells as - // the root. + /* Binding doc says this should have the same #{address,size}-cells as + the root. */ dt_add_u32_prop(reserved, "#address-cells", addr); dt_add_u32_prop(reserved, "#size-cells", size); - // Binding doc says this should be empty (i.e., 1:1 mapping from root). + /* Binding doc says this should be empty (1:1 mapping from root). */ dt_add_bin_prop(reserved, "ranges", NULL, 0); return reserved; @@ -1141,7 +1141,7 @@ static uint32_t dt_adjust_phandle(struct device_tree_property *prop, static uint32_t dt_adjust_all_phandles(struct device_tree_node *node, uint32_t base) { - uint32_t new_max = MAX(base, 1); // make sure we don't return 0 + uint32_t new_max = MAX(base, 1); /* make sure we don't return 0 */ struct device_tree_property *prop; struct device_tree_node *child; @@ -1154,7 +1154,7 @@ static uint32_t dt_adjust_all_phandles(struct device_tree_node *node, if (!node->phandle) return 0; new_max = MAX(new_max, node->phandle); - } // no break -- can have more than one phandle prop + } /* no break -- can have more than one phandle prop */ list_for_each(child, node->children, list_node) new_max = MAX(new_max, dt_adjust_all_phandles(child, base)); @@ -1180,11 +1180,13 @@ static int dt_fixup_locals(struct device_tree_node *node, struct device_tree_node *fixup_child; int i; - // For local fixups the /__local_fixup__ subtree contains the same node - // hierarchy as the main tree we're fixing up. Each property contains - // the fixup offsets for the respective property in the main tree. For - // each property in the fixup node, find the corresponding property in - // the base node and apply fixups to all offsets it specifies. + /* + * For local fixups the /__local_fixup__ subtree contains the same node + * hierarchy as the main tree we're fixing up. Each property contains + * the fixup offsets for the respective property in the main tree. For + * each property in the fixup node, find the corresponding property in + * the base node and apply fixups to all offsets it specifies. + */ list_for_each(fixup_prop, fixup->properties, list_node) { struct device_tree_property *base_prop = NULL; list_for_each(prop, node->properties, list_node) @@ -1193,8 +1195,8 @@ static int dt_fixup_locals(struct device_tree_node *node, break; } - // We should always find a corresponding base prop for a fixup, - // and fixup props contain a list of 32-bit fixup offsets. + /* We should always find a corresponding base prop for a fixup, + and fixup props contain a list of 32-bit fixup offsets. */ if (!base_prop || fixup_prop->prop.size % sizeof(uint32_t)) return -1; @@ -1204,8 +1206,8 @@ static int dt_fixup_locals(struct device_tree_node *node, return -1; } - // Now recursively descend both the base tree and the /__local_fixups__ - // subtree in sync to apply all fixups. + /* Now recursively descend both the base tree and the /__local_fixups__ + subtree in sync to apply all fixups. */ list_for_each(fixup_child, fixup->children, list_node) { struct device_tree_node *base_child = NULL; list_for_each(child, node->children, list_node) @@ -1214,7 +1216,7 @@ static int dt_fixup_locals(struct device_tree_node *node, break; } - // All fixup nodes should have a corresponding base node. + /* All fixup nodes should have a corresponding base node. */ if (!base_child) return -1; @@ -1238,10 +1240,10 @@ static void dt_fix_symbols(struct device_tree_node *symbols, const char *base_path) { struct device_tree_property *prop; - char buf[512]; // Should be enough for maximum DT path length? - char node_path[64]; // easily enough for /fragment@XXXX/__overlay__ + char buf[512]; /* Should be enough for maximum DT path length? */ + char node_path[64]; /* easily enough for /fragment@XXXX/__overlay__ */ - if (!symbols) // If the overlay has no /__symbols__ node, we're done! + if (!symbols) /* If the overlay has no /__symbols__ node, we're done! */ return; int len = snprintf(node_path, sizeof(node_path), "/%s/__overlay__", @@ -1275,10 +1277,10 @@ static int dt_fixup_external(struct device_tree *overlay, { struct device_tree_property *prop; - // External fixup properties are encoded as "::". + /* External fixup properties are encoded as "::". */ char *entry = fixup->prop.data; while ((void *)entry < fixup->prop.data + fixup->prop.size) { - // okay to destroy fixup property value, won't be needed again + /* okay to destroy fixup property value, won't need it again */ char *node_path = entry; entry = strchr(node_path, ':'); if (!entry) @@ -1303,18 +1305,18 @@ static int dt_fixup_external(struct device_tree *overlay, break; } - // Move entry to first char after number, must be a '\0'. + /* Move entry to first char after number, must be a '\0'. */ uint32_t offset = skip_atoi(&entry); if (!ovl_prop || offset + 4 > ovl_prop->prop.size || entry[0]) return -1; - entry++; // jump over '\0' to potential next fixup + entry++; /* jump over '\0' to potential next fixup */ be32enc(ovl_prop->prop.data + offset, phandle); - // If this is a /fragment@X:target property, update - // references to this fragment in the overlay __symbols__ now. + /* If this is a /fragment@X:target property, update references + to this fragment in the overlay __symbols__ now. */ if (offset == 0 && !strcmp(prop_name, "target") && - !strchr(node_path + 1, '/')) // only toplevel nodes + !strchr(node_path + 1, '/')) /* only toplevel nodes */ dt_fix_symbols(overlay_symbols, ovl_node, base_path); } @@ -1341,27 +1343,29 @@ static int dt_fixup_all_externals(struct device_tree *tree, { struct device_tree_property *fix; - // If we have any external fixups, the base tree must have /__symbols__. + /* If we have any external fixups, base tree must have /__symbols__. */ if (!symbols) return -1; - // Unlike /__local_fixups__, /__fixups__ is not a whole subtree that - // mirrors the node hierarchy. It's just a directory of fixup properties - // that each directly contain all information necessary to apply them. + /* + * Unlike /__local_fixups__, /__fixups__ is not a whole subtree that + * mirrors the node hierarchy. It's just a directory of fixup properties + * that each directly contain all information necessary to apply them. + */ list_for_each(fix, fixups->properties, list_node) { - // The name of a fixup property is the label of the node we want - // a property to phandle-reference. Look it up in /__symbols__. + /* The name of a fixup property is the label of the node we want + a property to phandle-reference. Look up in /__symbols__. */ const char *path = dt_find_string_prop(symbols, fix->prop.name); if (!path) return -1; - // Find the node the label pointed to to figure out its phandle. + /* Find node the label pointed to to figure out its phandle. */ struct device_tree_node *node = dt_find_node_by_path(tree, path, NULL, NULL, 0); if (!node) return -1; - // Write it into the overlay property(s) pointing to that node. + /* Write into the overlay property(s) pointing to that node. */ if (dt_fixup_external(overlay, fix, node->phandle, path, overlay_symbols) < 0) return -1; @@ -1448,23 +1452,23 @@ static int dt_import_fragment(struct device_tree *tree, struct device_tree_node *fragment, struct device_tree_node *overlay_symbols) { - // The actually overlaid nodes/props are in an __overlay__ child node. + /* The actual overlaid nodes/props are in an __overlay__ child node. */ static const char *overlay_path[] = { "__overlay__", NULL }; struct device_tree_node *overlay = dt_find_node(fragment, overlay_path, NULL, NULL, 0); - // If it doesn't have an __overlay__ child, it's not a fragment. + /* If it doesn't have an __overlay__ child, it's not a fragment. */ if (!overlay) return 0; - // The target node of the fragment can be given by path or by phandle. + /* Target node of the fragment can be given by path or by phandle. */ struct device_tree_property *prop; struct device_tree_property *phandle = NULL; struct device_tree_property *path = NULL; list_for_each(prop, fragment->properties, list_node) { if (!strcmp(prop->prop.name, "target")) { phandle = prop; - break; // phandle target has priority, stop looking here + break; /* phandle target has priority, stop looking */ } if (!strcmp(prop->prop.name, "target-path")) path = prop; @@ -1476,7 +1480,7 @@ static int dt_import_fragment(struct device_tree *tree, return -1; target = dt_find_node_by_phandle(tree->root, be32dec(phandle->prop.data)); - // Symbols already updated as part of dt_fixup_external(target). + /* Symbols already updated as part of dt_fixup_external(). */ } else if (path) { target = dt_find_node_by_path(tree, path->prop.data, NULL, NULL, 0); @@ -1501,10 +1505,12 @@ static int dt_import_fragment(struct device_tree *tree, */ int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay) { - // First, we need to make sure phandles inside the overlay don't clash - // with those in the base tree. We just define the highest phandle value - // in the base tree as the "phandle offset" for this overlay and - // increment all phandles in it by that value. + /* + * First, we need to make sure phandles inside the overlay don't clash + * with those in the base tree. We just define the highest phandle value + * in the base tree as the "phandle offset" for this overlay and + * increment all phandles in it by that value. + */ uint32_t phandle_base = tree->max_phandle; uint32_t new_max = dt_adjust_all_phandles(overlay->root, phandle_base); if (!new_max) { @@ -1513,8 +1519,8 @@ int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay) } tree->max_phandle = new_max; - // Now that we changed phandles in the overlay, we need to update any - // nodes referring to them. Those are listed in /__local_fixups__. + /* Now that we changed phandles in the overlay, we need to update any + nodes referring to them. Those are listed in /__local_fixups__. */ struct device_tree_node *local_fixups = dt_find_node_by_path(overlay, "/__local_fixups__", NULL, NULL, 0); if (local_fixups && dt_fixup_locals(overlay->root, local_fixups, @@ -1523,16 +1529,18 @@ int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay) return -1; } - // Besides local phandle references (from nodes within the overlay to - // other nodes within the overlay), the overlay may also contain phandle - // references to the base tree. These are stored with invalid values and - // must be updated now. /__symbols__ contains a list of all labels in - // the base tree, and /__fixups__ describes all nodes in the overlay - // that contain external phandle references. - // We also take this opportunity to update all /fragment@X/__overlay__/ - // prefixes in the overlay's /__symbols__ node to the correct path that - // the fragment will be placed in later, since this is the only step - // where we have all necessary information for that easily available. + /* + * Besides local phandle references (from nodes within the overlay to + * other nodes within the overlay), the overlay may also contain phandle + * references to the base tree. These are stored with invalid values and + * must be updated now. /__symbols__ contains a list of all labels in + * the base tree, and /__fixups__ describes all nodes in the overlay + * that contain external phandle references. + * We also take this opportunity to update all /fragment@X/__overlay__/ + * prefixes in the overlay's /__symbols__ node to the correct path that + * the fragment will be placed in later, since this is the only step + * where we have all necessary information for that easily available. + */ struct device_tree_node *symbols = dt_find_node_by_path(tree, "/__symbols__", NULL, NULL, 0); struct device_tree_node *fixups = dt_find_node_by_path(overlay, @@ -1546,8 +1554,8 @@ int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay) return -1; } - // After all this fixing up, we can finally merge the overlay into the - // tree (one fragment at a time, because for some reason it's split up). + /* After all this fixing up, we can finally merge overlay into the tree + (one fragment at a time, because for some reason it's split up). */ struct device_tree_node *fragment; list_for_each(fragment, overlay->root->children, list_node) if (dt_import_fragment(tree, fragment, overlay_symbols) < 0) { @@ -1556,11 +1564,13 @@ int dt_apply_overlay(struct device_tree *tree, struct device_tree *overlay) return -1; } - // We need to also update /__symbols__ to include labels from this - // overlay, in case we want to load further overlays with external - // phandle references to it. If the base tree already has a /__symbols__ - // we merge them together, otherwise we just insert the overlay's - // /__symbols__ node into the base tree root. + /* + * We need to also update /__symbols__ to include labels from this + * overlay, in case we want to load further overlays with external + * phandle references to it. If the base tree already has a /__symbols__ + * we merge them together, otherwise we just insert the overlay's + * /__symbols__ node into the base tree root. + */ if (overlay_symbols) { if (symbols) dt_copy_subtree(symbols, overlay_symbols, 0); diff --git a/src/lib/fit.c b/src/lib/fit.c index 37dfc8de98..045f52f408 100644 --- a/src/lib/fit.c +++ b/src/lib/fit.c @@ -419,8 +419,8 @@ void fit_update_memory(struct device_tree *tree) */ static int fit_update_compat(struct fit_config_node *config) { - // If there was no "compatible" property in config node, this is a - // legacy FIT image. Must extract compat prop from FDT itself. + /* If there was no "compatible" property in config node, this is a + legacy FIT image. Must extract compat prop from FDT itself. */ if (!config->compat.name) { void *fdt_blob = config->fdt->data; const struct fdt_header *fdt_header = fdt_blob; @@ -434,7 +434,7 @@ static int fit_update_compat(struct fit_config_node *config) return -1; } - // FDT overlays are not supported in legacy FIT images. + /* FDT overlays are not supported in legacy FIT images. */ if (config->overlays.next) { printk(BIOS_ERR, "ERROR: config %s has overlay but no compat!\n", From c6ba36f0694c3fa9a7db2a61bc264bef851b4360 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Wed, 12 Jun 2019 09:48:31 +0200 Subject: [PATCH 134/221] mb/emulation/qemu-riscv: Support arbitrary ROM sizes Make the linker script dynamic to support non default ROM sizes. Prevents weird runtime issues due to stages overwriting parts of the CBFS while decompressing stages. Change-Id: I37b9187c719b907959f02a272ec0459aabbcda3c Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33412 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Hug --- src/mainboard/emulation/qemu-riscv/memlayout.ld | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/mainboard/emulation/qemu-riscv/memlayout.ld b/src/mainboard/emulation/qemu-riscv/memlayout.ld index 032fbddecf..7f8ec3dd6a 100644 --- a/src/mainboard/emulation/qemu-riscv/memlayout.ld +++ b/src/mainboard/emulation/qemu-riscv/memlayout.ld @@ -15,15 +15,18 @@ #include #include +#include -#define START 0x80000000 +//Stages start after CBFS in DRAM +#define STAGES_START (QEMU_VIRT_DRAM + CONFIG_ROM_SIZE) SECTIONS { - DRAM_START(START) - BOOTBLOCK(START, 64K) - STACK(START + 4M, 4K) - ROMSTAGE(START + 4M + 64K, 128K) - PRERAM_CBMEM_CONSOLE(START + 4M + 192K, 8K) - RAMSTAGE(START + 4M + 200K, 16M) + DRAM_START(QEMU_VIRT_DRAM) + BOOTBLOCK(QEMU_VIRT_DRAM, 64K) + // CBFS goes here + STACK(STAGES_START, 4K) + ROMSTAGE(STAGES_START + 64K, 128K) + PRERAM_CBMEM_CONSOLE(STAGES_START + 192K, 8K) + RAMSTAGE(STAGES_START + 200K, 16M) } From 5e45053d52665f70d2dbe098ec276d10d200dd9f Mon Sep 17 00:00:00 2001 From: Kevin Chiu Date: Fri, 14 Jun 2019 00:23:14 +0800 Subject: [PATCH 135/221] mb/google/octopus: expose get_board_sku as global BUG=b:134912735 BRANCH=octopus TEST=emerge-octopus coreboot chromeos-bootimage Change-Id: I1fb7b5eeac48f2cd9c24fa1d3ac3fe4b390762d2 Signed-off-by: Kevin Chiu Reviewed-on: https://review.coreboot.org/c/coreboot/+/33448 Reviewed-by: Aaron Durbin Reviewed-by: Karthik Ramasubramanian Tested-by: build bot (Jenkins) --- src/mainboard/google/octopus/mainboard.c | 2 +- .../octopus/variants/baseboard/include/baseboard/variants.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/octopus/mainboard.c b/src/mainboard/google/octopus/mainboard.c index 4316ffed23..91cf1e4b70 100644 --- a/src/mainboard/google/octopus/mainboard.c +++ b/src/mainboard/google/octopus/mainboard.c @@ -118,7 +118,7 @@ struct chip_operations mainboard_ops = { #define SKU_UNKNOWN 0xFFFFFFFF #define SKU_MAX 255 -static uint32_t get_board_sku(void) +uint32_t get_board_sku(void) { static uint32_t sku_id = SKU_UNKNOWN; diff --git a/src/mainboard/google/octopus/variants/baseboard/include/baseboard/variants.h b/src/mainboard/google/octopus/variants/baseboard/include/baseboard/variants.h index 96381183b8..5374ace795 100644 --- a/src/mainboard/google/octopus/variants/baseboard/include/baseboard/variants.h +++ b/src/mainboard/google/octopus/variants/baseboard/include/baseboard/variants.h @@ -34,7 +34,8 @@ extern const struct lpddr4_swizzle_cfg baseboard_lpddr4_swizzle; const struct lpddr4_cfg *variant_lpddr4_config(void); /* Return memory SKU for the board. */ size_t variant_memory_sku(void); - +/* Return board SKU */ +uint32_t get_board_sku(void); /* Return ChromeOS gpio table and fill in number of entries. */ const struct cros_gpio *variant_cros_gpios(size_t *num); From b6d6739b4003ae315caa616639001e11dd0923f2 Mon Sep 17 00:00:00 2001 From: Kevin Chiu Date: Tue, 11 Jun 2019 23:29:18 +0800 Subject: [PATCH 136/221] mb/google/octopus: Override VBT selection for Garg Garg proto build has 3 SKUs: garg 2A2C DB: SKU ID - 1 garg HDMI DB: SKU ID - 9 garg LTE DB: SKU ID - 17 For SKU#9, VBT will need to be overridden to enable DDI_C output to HDMI BUG=b:134912735 BRANCH=octopus TEST=emerge-octopus coreboot chromeos-bootimage Cq-Depend: chrome-internal:1380847 Change-Id: I6c0ec086496eaf217ea8e326f5084d886d0e698f Signed-off-by: Kevin Chiu Reviewed-on: https://review.coreboot.org/c/coreboot/+/33395 Tested-by: build bot (Jenkins) Reviewed-by: Karthik Ramasubramanian --- .../google/octopus/variants/garg/Makefile.inc | 1 + .../google/octopus/variants/garg/variant.c | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/mainboard/google/octopus/variants/garg/variant.c diff --git a/src/mainboard/google/octopus/variants/garg/Makefile.inc b/src/mainboard/google/octopus/variants/garg/Makefile.inc index 9fb63f5f43..ba865e9f82 100644 --- a/src/mainboard/google/octopus/variants/garg/Makefile.inc +++ b/src/mainboard/google/octopus/variants/garg/Makefile.inc @@ -1,3 +1,4 @@ bootblock-y += gpio.c ramstage-y += gpio.c +ramstage-y += variant.c diff --git a/src/mainboard/google/octopus/variants/garg/variant.c b/src/mainboard/google/octopus/variants/garg/variant.c new file mode 100644 index 0000000000..a3efe3f802 --- /dev/null +++ b/src/mainboard/google/octopus/variants/garg/variant.c @@ -0,0 +1,39 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2019 Google 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 +#include +#include +#include + +enum { + SKU_1_2A2C = 1, + SKU_9_HDMI = 9, + SKU_17_LTE = 17, +}; + +const char *mainboard_vbt_filename(void) +{ + uint32_t sku_id; + + sku_id = get_board_sku(); + + switch (sku_id) { + case SKU_9_HDMI: + return "vbt_garg_hdmi.bin"; + default: + return "vbt.bin"; + } +} From 3d5bb2a5df7c16d0faa5e6e84b42f3220ccf8405 Mon Sep 17 00:00:00 2001 From: Xiang Wang Date: Fri, 14 Jun 2019 11:16:13 +0800 Subject: [PATCH 137/221] Documentatioan: update stage handoff protocol Change-Id: I170fc16675c2701f6ea133cfce6e5fabdfb0e8d3 Signed-off-by: Xiang Wang Reviewed-on: https://review.coreboot.org/c/coreboot/+/33460 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph Reviewed-by: Philipp Hug --- Documentation/arch/riscv/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/arch/riscv/index.md b/Documentation/arch/riscv/index.md index 888651dba6..9a5de34f09 100644 --- a/Documentation/arch/riscv/index.md +++ b/Documentation/arch/riscv/index.md @@ -15,7 +15,7 @@ Payloads run from the ramstage are started in S mode, and trap delegation will have been done. These payloads rely on the SBI and can not replace it. ## Stage handoff protocol -On entry to a stage or payload, +On entry to a stage or payload (including SELF payloads), * all harts are running. * A0 is the hart ID. * A1 is the pointer to the Flattened Device Tree (FDT). From 16ad2d70caec5c0ec806b95c80128fd3213246d7 Mon Sep 17 00:00:00 2001 From: mtk11195 Date: Wed, 23 Jan 2019 11:41:19 +0800 Subject: [PATCH 138/221] mediatek/mt8183: enable DDR low power feature BUG=b:80501386 BRANCH=none TEST=Boots correctly and stress test pass on Kukui. Change-Id: Ic48580e7e5db25dc1c29dabf41c4e3816fb946d3 Signed-off-by: Huayang Duan Reviewed-on: https://review.coreboot.org/c/coreboot/+/32010 Tested-by: build bot (Jenkins) Reviewed-by: Hung-Te Lin Reviewed-by: Julius Werner Reviewed-by: Huayang Duan --- src/soc/mediatek/mt8183/dramc_pi_basic_api.c | 118 +++++++++++++++-- .../mt8183/dramc_pi_calibration_api.c | 119 ++++++++++++------ src/soc/mediatek/mt8183/emi.c | 12 +- .../mt8183/include/soc/dramc_pi_api.h | 4 +- .../mt8183/include/soc/dramc_register.h | 5 +- src/soc/mediatek/mt8183/include/soc/emi.h | 1 + 6 files changed, 206 insertions(+), 53 deletions(-) diff --git a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c index 3ca5c22fcc..cdba2af2df 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_basic_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_basic_api.c @@ -20,7 +20,7 @@ #include #include -static void sw_imp_cal_vref_sel(u8 term_option, u8 impcal_stage) +static void dramc_sw_imp_cal_vref_sel(u8 term_option, u8 impcal_stage) { u8 vref_sel = 0; @@ -56,7 +56,7 @@ void dramc_sw_impedance(const struct sdram_params *params) sw_impedance[ODT_OFF][3] = sw_impedance[ODT_ON][3]; clrsetbits_le32(&ch[0].phy.shu[0].ca_cmd[11], 0xff, 0x3); - sw_imp_cal_vref_sel(dq_term, IMPCAL_STAGE_DRVP); + dramc_sw_imp_cal_vref_sel(dq_term, IMPCAL_STAGE_DRVP); /* DQ */ clrsetbits_le32(&ch[0].ao.shu[0].drving[0], (0x1f << 5) | (0x1f << 0), @@ -154,9 +154,6 @@ static void dramc_rx_input_delay_tracking(u8 chn) for (size_t r = 0; r < 2; r++) for (size_t b = 0; b < 2; b++) { - /* Track rising and update rising/falling together */ - clrbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[2], - 0x1 << 29); clrsetbits_le32(&ch[chn].phy.r[r].b[b].rxdvs[7], (0x3f << 0) | (0x3f << 8) | (0x7f << 16) | (0x7f << 24), @@ -172,8 +169,6 @@ static void dramc_rx_input_delay_tracking(u8 chn) (0x3 << 18) | (0x3 << 16)); } - clrbits_le32(&ch[chn].phy.ca_cmd[10], (0x7 << 28) | (0x7 << 24)); - /* Rx DLY tracking setting (Static) */ clrsetbits_le32(&ch[chn].phy.b0_rxdvs[0], (0x1 << 29) | (0xf << 4) | (0x1 << 0), @@ -181,6 +176,7 @@ static void dramc_rx_input_delay_tracking(u8 chn) clrsetbits_le32(&ch[chn].phy.b1_rxdvs[0], (0x1 << 29) | (0xf << 4) | (0x1 << 0), (0x1 << 29) | (0x0 << 4) | (0x1 << 0)); + clrbits_le32(&ch[chn].phy.ca_cmd[10], (0x7 << 28) | (0x7 << 24)); for (u8 b = 0; b < 2; b++) { clrsetbits_le32(&ch[chn].phy.b[b].dq[9], @@ -201,10 +197,12 @@ static void dramc_rx_input_delay_tracking(u8 chn) static void dramc_hw_dqs_gating_tracking(u8 chn) { - setbits_le32(&ch[chn].ao.stbcal, (0x3 << 26) | (0x1 << 0)); + clrsetbits_le32(&ch[chn].ao.stbcal, + (0x1 << 21) | (0x3 << 15) | (0x1f << 8) | (0x1 << 4), + (0x3 << 26) | (0x1 << 0)); clrsetbits_le32(&ch[chn].ao.stbcal1, (0xffff << 16) | (0x1 << 8) | (0x1 << 6), - (0x1 << 16) | (0x1 << 8) | (0x0 << 6)); + (0x1 << 16) | (0x1 << 8) | (0x1 << 6)); clrsetbits_le32(&ch[chn].phy.misc_ctrl0, (0x1 << 24) | (0x1f << 11) | (0xf << 0), @@ -262,6 +260,63 @@ static void dramc_phy_low_power_enable(void) dramc_set_broadcast(broadcast_bak); } + +static void dramc_dummy_read_for_tracking_enable(u8 chn) +{ + setbits_le32(&ch[chn].ao.dummy_rd, 0x3 << 16); + + for (size_t r = 0; r < 2; r++) + for (size_t i = 0; i < 4; i++) + write32(&ch[chn].ao.rk[r].dummy_rd_wdata[i], + 0xaaaa5555); + + clrsetbits_le32(&ch[chn].ao.test2_4, 0x7 << 28, 0x4 << 28); + for (size_t r = 0; r < 2; r++) { + clrsetbits_le32(&ch[chn].ao.rk[r].dummy_rd_adr, + (0x1ffff << 0) | (0x7ff << 17) | (0xf << 28), + (0x7fff << 0) | (0x3f0 << 17)); + setbits_le32(&ch[chn].ao.rk[r].dummy_rd_bk, 0x7 << 0); + } + + clrbits_le32(&ch[chn].ao.dummy_rd, 0x1 << 25 | 0x1 << 20); +} + +static void dramc_set_CKE_2_rank_independent(u8 chn) +{ + clrsetbits_le32(&ch[chn].ao.rkcfg, (0x1 << 15) | (0x1 << 12), 0x1 << 2); + clrsetbits_le32(&ch[chn].ao.ckectrl, + (0x1 << 1) | (0xf << 8) | (0x7 << 13), + (0x4 << 8) | (0x2 << 13)); + + for (u8 shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + setbits_le32(&ch[chn].ao.shu[shu].conf[2], + (0x1 << 29) | (0x1 << 31)); + clrbits_le32(&ch[chn].ao.dramctrl, 0x1 << 9); +} + +static void dramc_pa_improve(u8 chn) +{ + clrbits_le32(&ch[chn].ao.clkar, 0xffff); + clrbits_le32(&ch[chn].ao.srefctrl, 0xf << 12); + clrbits_le32(&ch[chn].ao.zqcs, 0x1 << 19); + clrbits_le32(&ch[chn].ao.pre_tdqsck[0], 0x1 << 17); + clrbits_le32(&ch[chn].ao.zqcs, 0x1 << 19); + clrbits_le32(&ch[chn].ao.pre_tdqsck[0], 0x1 << 17); + + for (u8 shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + clrbits_le32(&ch[chn].ao.shu[shu].odtctrl, 0x3 << 2); +} + +static void dramc_enable_dramc_dcm(void) +{ + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + clrsetbits_le32(&ch[chn].ao.dramc_pd_ctrl, + (0x7 << 0) | (0x1 << 26) | (0x1 << 30) | (0x1 << 31), + (0x7 << 0) | (0x1 << 30) | (0x1 << 31)); + setbits_le32(&ch[chn].ao.clkar, 0x1 << 31); + } +} + void dramc_runtime_config(void) { clrbits_le32(&ch[0].ao.refctrl0, 0x1 << 29); @@ -270,39 +325,78 @@ void dramc_runtime_config(void) transfer_pll_to_spm_control(); setbits_le32(&mtk_spm->spm_power_on_val0, 0x3 << 25); + /* RX_TRACKING: ON */ for (u8 chn = 0; chn < CHANNEL_MAX; chn++) dramc_rx_input_delay_tracking(chn); + /* HW_GATING: ON */ dramc_hw_gating_init(); dramc_hw_gating_onoff(CHANNEL_A, true); + dramc_hw_gating_onoff(CHANNEL_B, true); + /* HW_GATING DBG: OFF */ for (size_t chn = 0; chn < CHANNEL_MAX; chn++) clrbits_le32(&ch[chn].ao.stbcal2, (0x3 << 4) | (0x3 << 8) | (0x1 << 28)); + /* DUMMY_READ_FOR_TRACKING: ON */ + for (u8 chn = 0; chn < CHANNEL_MAX; chn++) + dramc_dummy_read_for_tracking_enable(chn); + + /* ZQCS_ENABLE_LP4: ON */ clrbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 30); clrbits_le32(&ch[1].ao.spcmdctrl, 0x1 << 30); + /* LOWPOWER_GOLDEN_SETTINGS(DCM): ON */ dramc_phy_low_power_enable(); dramc_enable_phy_dcm(true); + /* DUMMY_READ_FOR_DQS_GATING_RETRY: OFF */ for (size_t chn = 0; chn < CHANNEL_MAX; chn++) for (size_t shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) clrbits_le32(&ch[chn].ao.shu[shu].dqsg_retry, (0x1 << 1) | (0x3 << 13)); + /* SPM_CONTROL_AFTERK: ON */ write32(&ch[0].phy.misc_spm_ctrl0, 0xfbffefff); write32(&ch[1].phy.misc_spm_ctrl0, 0xfbffefff); write32(&ch[0].phy.misc_spm_ctrl2, 0xffffffef); write32(&ch[1].phy.misc_spm_ctrl2, 0x7fffffef); + /* IMPEDANCE_TRACKING: ON */ dramc_impedance_tracking_enable(); for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + /* TEMP_SENSOR: ON */ clrbits_le32(&ch[chn].ao.spcmdctrl, 0x3 << 28); setbits_le32(&ch[chn].ao.hw_mrr_fun, (0x1 << 0) | (0x1 << 11)); - clrbits_le32(&ch[0].ao.refctrl0, 0x1 << 18); - setbits_le32(&ch[chn].phy.dvfs_emi_clk, 0x1 << 24); - setbits_le32(&ch[chn].ao.dvfsdll, 0x1 << 7); + + /* PER_BANK_REFRESH: ON */ + clrbits_le32(&ch[chn].ao.refctrl0, 0x1 << 18); + + /* HW_SAVE_FOR_SR: ON */ + clrbits_le32(&ch[chn].ao.rstmask, (0x1 << 25) | (0x1 << 28)); + setbits_le32(&ch[chn].ao.refctrl1, 0x1 << 0); + clrsetbits_le32(&ch[chn].ao.srefctrl, 0x1 << 20, 0x1 << 22); + + /* SET_CKE_2_RANK_INDEPENDENT_RUN_TIME: ON */ + dramc_set_CKE_2_rank_independent(chn); + + /* CLK_FREE_FUN_FOR_DRAMC_PSEL: ON */ + clrbits_le32(&ch[chn].ao.refctrl1, (0x1 << 6) | (0x3 << 2)); + clrbits_le32(&ch[chn].ao.clkar, 0x1 << 19); + + /* PA_IMPROVEMENT_FOR_DRAMC_ACTIVE_POWER: ON */ + dramc_pa_improve(chn); + + /* DRAM DRS DISABLE */ + clrsetbits_le32(&ch[chn].ao.drsctrl, + (0x1 << 21) | (0x3f << 12) | (0xf << 8) | (0x1 << 6), + (0x1 << 19) | (0x3 << 12) | (0x8 << 8) | + (0x3 << 4) | (0x1 << 2) | (0x1 << 0)); + setbits_le32(&ch[chn].ao.dummy_rd, 0x3 << 26); } + + enable_emi_dcm(); + dramc_enable_dramc_dcm(); } diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index f3c76a9273..6dc8fa6588 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -86,7 +86,7 @@ struct per_byte_dly { u16 final_dly; }; -static void auto_refresh_switch(u8 chn, bool option) +static void dramc_auto_refresh_switch(u8 chn, bool option) { clrsetbits_le32(&ch[chn].ao.refctrl0, 1 << REFCTRL0_REFDIS_SHIFT, (option ? 0 : 1) << REFCTRL0_REFDIS_SHIFT); @@ -157,7 +157,7 @@ static void dramc_write_leveling(u8 chn, u8 rank, } } -static void cmd_bus_training(u8 chn, u8 rank, +static void dramc_cmd_bus_training(u8 chn, u8 rank, const struct sdram_params *params) { u32 cbt_cs, mr12_value; @@ -257,7 +257,7 @@ void dramc_enable_phy_dcm(bool en) dramc_set_broadcast(broadcast_bak); } -static void reset_delay_chain_before_calibration(void) +static void dramc_reset_delay_chain_before_calibration(void) { for (size_t chn = 0; chn < CHANNEL_MAX; chn++) for (size_t rank = 0; rank < RANK_MAX; rank++) { @@ -290,10 +290,10 @@ static void dramc_rx_input_delay_tracking_init_by_freq(u8 chn) clrbits_le32(&shu->b[1].dq[7], (0x1 << 12) | (0x1 << 13)); } -void dramc_apply_pre_calibration_config(void) +void dramc_apply_config_before_calibration(void) { dramc_enable_phy_dcm(false); - reset_delay_chain_before_calibration(); + dramc_reset_delay_chain_before_calibration(); setbits_le32(&ch[0].ao.shu[0].conf[3], 0x1ff << 16); setbits_le32(&ch[0].ao.spcmdctrl, 0x1 << 24); @@ -344,7 +344,53 @@ void dramc_apply_pre_calibration_config(void) } } -static void rx_dqs_isi_pulse_cg_switch(u8 chn, bool flag) +static void dramc_set_mr13_vrcg_to_Normal(u8 chn) +{ + for (u8 rank = 0; rank < RANK_MAX; rank++) + dramc_mode_reg_write_by_rank(chn, rank, 13, 0xd0); + + for (u8 shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + clrbits_le32(&ch[chn].ao.shu[shu].hwset_vrcg, 0x1 << 19); +} + +void dramc_apply_config_after_calibration(void) +{ + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) { + setbits_le32(&ch[chn].phy.misc_cg_ctrl4, 0x11400000); + clrbits_le32(&ch[chn].ao.refctrl1, 0x1 << 7); + clrbits_le32(&ch[chn].ao.shuctrl, 0x1 << 2); + clrbits_le32(&ch[chn].phy.ca_cmd[6], 0x1 << 6); + dramc_set_mr13_vrcg_to_Normal(chn); + + clrbits_le32(&ch[chn].phy.b[0].dq[6], 0x3); + clrbits_le32(&ch[chn].phy.b[1].dq[6], 0x3); + clrbits_le32(&ch[chn].phy.ca_cmd[6], 0x3); + setbits_le32(&ch[chn].phy.b[0].dq[6], 0x1 << 5); + setbits_le32(&ch[chn].phy.b[1].dq[6], 0x1 << 5); + setbits_le32(&ch[chn].phy.ca_cmd[6], 0x1 << 5); + + clrbits_le32(&ch[chn].ao.impcal, 0x3 << 24); + clrbits_le32(&ch[chn].phy.misc_imp_ctrl0, 0x7); + + clrbits_le32(&ch[chn].phy.misc_ctrl0, 0x1 << 31); + clrbits_le32(&ch[chn].phy.misc_ctrl1, 0x1 << 25); + + setbits_le32(&ch[chn].ao.spcmdctrl, 1 << 29); + setbits_le32(&ch[chn].ao.dqsoscr, 1 << 24); + + for (u8 shu = 0; shu < DRAM_DFS_SHUFFLE_MAX; shu++) + clrbits_le32(&ch[chn].ao.shu[shu].scintv, 0x1 << 30); + + clrbits_le32(&ch[chn].ao.dummy_rd, (0x7 << 20) | (0x1 << 7)); + dramc_cke_fix_onoff(chn, false, false); + clrbits_le32(&ch[chn].ao.dramc_pd_ctrl, 0x1 << 26); + + clrbits_le32(&ch[chn].ao.eyescan, 0x7 << 8); + clrsetbits_le32(&ch[chn].ao.test2_4, 0x7 << 28, 0x4 << 28); + } +} + +static void dramc_rx_dqs_isi_pulse_cg_switch(u8 chn, bool flag) { for (size_t b = 0; b < 2; b++) clrsetbits_le32(&ch[chn].phy.b[b].dq[6], 1 << 5, @@ -468,7 +514,7 @@ static void dramc_engine2_end(u8 chn) clrbits_le32(&ch[chn].ao.test2_4, 0x1 << 17); } -static void find_gating_window(u32 result_r, u32 result_f, u32 *debug_cnt, +static void dramc_find_gating_window(u32 result_r, u32 result_f, u32 *debug_cnt, u8 dly_coarse_large, u8 dly_coarse_0p5t, u8 *pass_begin, u8 *pass_count, u8 *dly_fine_xt, u32 *coarse_tune, u8 *dqs_high) { @@ -509,7 +555,7 @@ static void find_gating_window(u32 result_r, u32 result_f, u32 *debug_cnt, } } -static void find_dly_tune(u8 chn, u8 dly_coarse_large, u8 dly_coarse_0p5t, +static void dramc_find_dly_tune(u8 chn, u8 dly_coarse_large, u8 dly_coarse_0p5t, u8 dly_fine_xt, u8 *dqs_high, u8 *dly_coarse_large_cnt, u8 *dly_coarse_0p5t_cnt, u8 *dly_fine_tune_cnt, u8 *dqs_trans) { @@ -577,7 +623,7 @@ static void dramc_set_gating_mode(u8 chn, bool mode) static void dramc_rx_dqs_gating_cal_pre(u8 chn, u8 rank) { - rx_dqs_isi_pulse_cg_switch(chn, false); + dramc_rx_dqs_isi_pulse_cg_switch(chn, false); clrbits_le32(&ch[chn].ao.refctrl0, 1 << REFCTRL0_PBREFEN_SHIFT); dramc_hw_gating_onoff(chn, false); @@ -606,7 +652,7 @@ static void dramc_write_dqs_gating_result(u8 chn, u8 rank, u8 best_coarse_rodt_p1[DQS_NUMBER]; u8 best_coarse_0p5t_rodt_p1[DQS_NUMBER]; - rx_dqs_isi_pulse_cg_switch(chn, true); + dramc_rx_dqs_isi_pulse_cg_switch(chn, true); write32(&ch[chn].ao.shu[0].rk[rank].selph_dqsg0, ((u32) best_coarse_tune2t[0] << @@ -807,9 +853,9 @@ static void dramc_rx_dqs_gating_cal(u8 chn, u8 rank) dramc_set_gating_mode(chn, 1); dramc_engine2_run(chn, TE_OP_READ_CHECK); - find_dly_tune(chn, dly_coarse_large, dly_coarse_0p5t, - dly_fine_xt, dqs_high, dly_coarse_large_cnt, - dly_coarse_0p5t_cnt, + dramc_find_dly_tune(chn, dly_coarse_large, + dly_coarse_0p5t, dly_fine_xt, dqs_high, + dly_coarse_large_cnt, dly_coarse_0p5t_cnt, dly_fine_tune_cnt, dqs_transition); dramc_dbg("%d %d %d |", dly_coarse_large, @@ -825,7 +871,7 @@ static void dramc_rx_dqs_gating_cal(u8 chn, u8 rank) } dramc_dbg("\n"); - find_gating_window(result_r, result_f, debug_cnt, + dramc_find_gating_window(result_r, result_f, debug_cnt, dly_coarse_large, dly_coarse_0p5t, pass_begin, pass_count, &dly_fine_xt, &coarse_tune, dqs_high); @@ -971,7 +1017,7 @@ static void dramc_transfer_dly_tune( dly_tune->coarse_tune_large_oen = tmp_val >> 3; } -static void set_rx_dly_factor(u8 chn, u8 rank, enum RX_TYPE type, u32 val) +static void dramc_set_rx_dly_factor(u8 chn, u8 rank, enum RX_TYPE type, u32 val) { u32 tmp, mask; @@ -1006,7 +1052,8 @@ static void set_rx_dly_factor(u8 chn, u8 rank, enum RX_TYPE type, u32 val) } } -static void set_tx_dly_factor(u8 chn, u8 rank, enum CAL_TYPE type, u32 val) +static void dramc_set_tx_dly_factor(u8 chn, u8 rank, + enum CAL_TYPE type, u32 val) { struct tx_dly_tune dly_tune = {0}; u32 coarse_tune_large = 0, coarse_tune_large_oen = 0; @@ -1203,19 +1250,18 @@ static void dramc_set_rx_dly(u8 chn, u8 rank, s32 dly) { if (dly <= 0) { /* Hold time calibration */ - set_rx_dly_factor(chn, rank, RX_DQS, -dly); + dramc_set_rx_dly_factor(chn, rank, RX_DQS, -dly); dram_phy_reset(chn); } else { /* Setup time calibration */ - set_rx_dly_factor(chn, rank, RX_DQS, 0); - set_rx_dly_factor(chn, rank, RX_DQM, dly); + dramc_set_rx_dly_factor(chn, rank, RX_DQS, 0); + dramc_set_rx_dly_factor(chn, rank, RX_DQM, dly); dram_phy_reset(chn); - set_rx_dly_factor(chn, rank, RX_DQ, dly); + dramc_set_rx_dly_factor(chn, rank, RX_DQ, dly); } - } -static void set_tx_best_dly_factor(u8 chn, u8 rank_start, +static void dramc_set_tx_best_dly_factor(u8 chn, u8 rank_start, struct per_byte_dly *tx_perbyte_dly, u16 dq_precal_result[]) { u32 coarse_tune_large = 0; @@ -1268,7 +1314,7 @@ static void set_tx_best_dly_factor(u8 chn, u8 rank_start, FINE_TUNE_DQM_SHIFT)); } -static void set_rx_best_dly_factor(u8 chn, u8 rank, +static void dramc_set_rx_best_dly_factor(u8 chn, u8 rank, struct dqdqs_perbit_dly *dqdqs_perbit_dly, u32 *max_dqsdly_byte, u32 *ave_dqm_dly) { @@ -1335,7 +1381,7 @@ static void dramc_set_dqdqs_dly(u8 chn, u8 rank, enum CAL_TYPE type, s32 dly) if ((type == RX_WIN_RD_DQC) || (type == RX_WIN_TEST_ENG)) dramc_set_rx_dly(chn, rank, dly); else - set_tx_dly_factor(chn, rank, type, dly); + dramc_set_tx_dly_factor(chn, rank, type, dly); } static void dramc_set_tx_best_dly(u8 chn, u8 rank, @@ -1380,7 +1426,8 @@ static void dramc_set_tx_best_dly(u8 chn, u8 rank, byte_dly_cell[i]); } - set_tx_best_dly_factor(chn, rank, tx_perbyte_dly, tx_dq_precal_result); + dramc_set_tx_best_dly_factor(chn, rank, tx_perbyte_dly, + tx_dq_precal_result); } static int dramc_set_rx_best_dly(u8 chn, u8 rank, @@ -1425,7 +1472,7 @@ static int dramc_set_rx_best_dly(u8 chn, u8 rank, return -1; } - set_rx_best_dly_factor(chn, rank, rx_dly, max_dqsdly_byte, + dramc_set_rx_best_dly_factor(chn, rank, rx_dly, max_dqsdly_byte, ave_dqmdly_byte); return 0; } @@ -1546,8 +1593,10 @@ static u8 dramc_window_perbit_cal(u8 chn, u8 rank, dramc_set_vref(chn, rank, type, vref_dly.vref); if ((type == RX_WIN_RD_DQC) || (type == RX_WIN_TEST_ENG)) { - set_rx_dly_factor(chn, rank, RX_DQM, FIRST_DQ_DELAY); - set_rx_dly_factor(chn, rank, RX_DQ, FIRST_DQ_DELAY); + dramc_set_rx_dly_factor(chn, rank, + RX_DQM, FIRST_DQ_DELAY); + dramc_set_rx_dly_factor(chn, rank, + RX_DQ, FIRST_DQ_DELAY); } dramc_get_dly_range(chn, rank, type, dq_precal_result, @@ -1625,7 +1674,7 @@ static u8 dramc_window_perbit_cal(u8 chn, u8 rank, return 0; } -static void dle_factor_handler(u8 chn, u8 val) +static void dramc_dle_factor_handler(u8 chn, u8 val) { val = MAX(val, 2); clrsetbits_le32(&ch[chn].ao.shu[0].conf[1], @@ -1650,7 +1699,7 @@ static u8 dramc_rx_datlat_cal(u8 chn, u8 rank) dramc_engine2_init(chn, rank, 0x400, false); for (datlat = 12; datlat < DATLAT_TAP_NUMBER; datlat++) { - dle_factor_handler(chn, datlat); + dramc_dle_factor_handler(chn, datlat); u32 err = dramc_engine2_run(chn, TE_OP_WRITE_READ_CHECK); @@ -1679,7 +1728,7 @@ static u8 dramc_rx_datlat_cal(u8 chn, u8 rank) assert(sum != 0); - dle_factor_handler(chn, best_step); + dramc_dle_factor_handler(chn, best_step); clrsetbits_le32(&ch[chn].ao.padctrl, PADCTRL_DQIENQKEND_MASK, (0x1 << PADCTRL_DQIENQKEND_SHIFT) | @@ -1691,7 +1740,7 @@ static u8 dramc_rx_datlat_cal(u8 chn, u8 rank) static void dramc_dual_rank_rx_datlat_cal(u8 chn, u8 datlat0, u8 datlat1) { u8 final_datlat = MAX(datlat0, datlat1); - dle_factor_handler(chn, final_datlat); + dramc_dle_factor_handler(chn, final_datlat); } static void dramc_rx_dqs_gating_post_process(u8 chn) @@ -1794,10 +1843,10 @@ void dramc_calibrate_all_channels(const struct sdram_params *pams) for (u8 chn = 0; chn < CHANNEL_MAX; chn++) { for (u8 rk = RANK_0; rk < RANK_MAX; rk++) { dramc_show("Start K ch:%d, rank:%d\n", chn, rk); - auto_refresh_switch(chn, false); - cmd_bus_training(chn, rk, pams); + dramc_auto_refresh_switch(chn, false); + dramc_cmd_bus_training(chn, rk, pams); dramc_write_leveling(chn, rk, pams->wr_level); - auto_refresh_switch(chn, true); + dramc_auto_refresh_switch(chn, true); dramc_rx_dqs_gating_cal(chn, rk); dramc_window_perbit_cal(chn, rk, RX_WIN_RD_DQC, pams); dramc_window_perbit_cal(chn, rk, TX_WIN_DQ_DQM, pams); diff --git a/src/soc/mediatek/mt8183/emi.c b/src/soc/mediatek/mt8183/emi.c index 757a453de9..937d06de37 100644 --- a/src/soc/mediatek/mt8183/emi.c +++ b/src/soc/mediatek/mt8183/emi.c @@ -292,11 +292,21 @@ static void init_dram(const struct sdram_params *params) emi_init2(params); } +void enable_emi_dcm(void) +{ + clrbits_le32(&emi_regs->conm, 0xff << 24); + clrbits_le32(&emi_regs->conn, 0xff << 24); + + for (size_t chn = 0; chn < CHANNEL_MAX; chn++) + clrbits_le32(&ch[chn].emi.chn_conb, 0xff << 24); +} + static void do_calib(const struct sdram_params *params) { - dramc_apply_pre_calibration_config(); + dramc_apply_config_before_calibration(); dramc_calibrate_all_channels(params); dramc_ac_timing_optimize(); + dramc_apply_config_after_calibration(); dramc_runtime_config(); } diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h index 781443a397..23b5cf032c 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_pi_api.h @@ -123,8 +123,10 @@ void dramc_set_broadcast(u32 onoff); u32 dramc_get_broadcast(void); void dramc_init(void); void dramc_sw_impedance(const struct sdram_params *params); -void dramc_apply_pre_calibration_config(void); +void dramc_apply_config_before_calibration(void); +void dramc_apply_config_after_calibration(void); void dramc_calibrate_all_channels(const struct sdram_params *params); void dramc_hw_gating_onoff(u8 chn, bool onoff); void dramc_enable_phy_dcm(bool bEn); + #endif /* _DRAMC_PI_API_MT8183_H */ diff --git a/src/soc/mediatek/mt8183/include/soc/dramc_register.h b/src/soc/mediatek/mt8183/include/soc/dramc_register.h index 2487504a28..f0720a7272 100644 --- a/src/soc/mediatek/mt8183/include/soc/dramc_register.h +++ b/src/soc/mediatek/mt8183/include/soc/dramc_register.h @@ -265,10 +265,7 @@ check_member(dramc_nao_regs, cmddrv2, 0x0474); struct dramc_ao_regs_rk { uint32_t dqsosc; uint32_t rsvd_1[5]; - uint32_t dummy_rd_wdata0; - uint32_t dummy_rd_wdata1; - uint32_t dummy_rd_wdata2; - uint32_t dummy_rd_wdata3; + uint32_t dummy_rd_wdata[4]; uint32_t dummy_rd_adr; uint32_t dummy_rd_bk; uint32_t pre_tdqsck[12]; diff --git a/src/soc/mediatek/mt8183/include/soc/emi.h b/src/soc/mediatek/mt8183/include/soc/emi.h index 81e3d91daa..2c04a50e9e 100644 --- a/src/soc/mediatek/mt8183/include/soc/emi.h +++ b/src/soc/mediatek/mt8183/include/soc/emi.h @@ -38,6 +38,7 @@ extern const u8 phy_mapping[CHANNEL_MAX][16]; int complex_mem_test(u8 *start, unsigned int len); size_t sdram_size(void); const struct sdram_params *get_sdram_config(void); +void enable_emi_dcm(void); void mt_set_emi(const struct sdram_params *params); void mt_mem_init(const struct sdram_params *params); From b8f65ad68a0ce722012ff4fac39e2b18f0025fbe Mon Sep 17 00:00:00 2001 From: Huayang Duan Date: Thu, 11 Apr 2019 19:27:39 +0800 Subject: [PATCH 139/221] mediatek/mt8183: fix mode register setting fail issue The mode register setting of DRAM may fail without some delay after each MR write. BUG=b:80501386 BRANCH=none TEST=Boots correctly and stress test pass on Kukui. Change-Id: I51785e90b2014994be5018bfe543245d44626242 Signed-off-by: Huayang Duan Reviewed-on: https://review.coreboot.org/c/coreboot/+/32284 Reviewed-by: Hung-Te Lin Reviewed-by: Huayang Duan Tested-by: build bot (Jenkins) --- src/soc/mediatek/mt8183/dramc_init_setting.c | 174 ++++++++++++++----- 1 file changed, 129 insertions(+), 45 deletions(-) diff --git a/src/soc/mediatek/mt8183/dramc_init_setting.c b/src/soc/mediatek/mt8183/dramc_init_setting.c index d275127978..09bec0108e 100644 --- a/src/soc/mediatek/mt8183/dramc_init_setting.c +++ b/src/soc/mediatek/mt8183/dramc_init_setting.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -24,7 +25,7 @@ struct reg_init_value { u32 value; }; -struct reg_init_value dramc_init_sequence[] = { +static struct reg_init_value dramc_init_sequence[] = { {&mt8183_infracfg->dramc_wbr, 0x00000000}, {&ch[0].ao.refctrl0, 0x20712000}, {&ch[1].ao.refctrl0, 0x20712000}, @@ -620,7 +621,52 @@ struct reg_init_value dramc_init_sequence[] = { {&ch[1].phy.shu[0].rk[1].b[1].dq[1], 0x22000000}, {&ch[1].phy.shu[0].b[0].dll[1], 0x00022501}, - /* dramc mode register init */ + /* update the ac timing */ + {&ch[0].ao.shu[0].actim[0], 0x06020c07}, + {&ch[0].ao.shu[0].actim[1], 0x10080501}, + {&ch[0].ao.shu[0].actim[2], 0x07070201}, + {&ch[0].ao.shu[0].actim[3], 0x6164002c}, + {&ch[0].ao.shu[0].actim[4], 0x22650077}, + {&ch[0].ao.shu[0].actim[5], 0x0a000c0b}, + {&ch[0].ao.shu[0].actim_xrt, 0x05030609}, + {&ch[0].ao.shu[0].ac_time_05t, 0x000106e1}, + {&ch[0].ao.catraining1, 0x0b000000}, + {&ch[0].ao.shu[0].rk[0].dqsctl, 0x00000004}, + {&ch[0].ao.shu[0].rk[1].dqsctl, 0x00000004}, + {&ch[0].ao.shu[0].odtctrl, 0xc001004f}, + {&ch[0].ao.shu[0].conf[1], 0x34000d0f}, + {&ch[0].ao.shu[0].conf[2], 0x9007640f}, + {&ch[0].ao.shu[0].scintv, 0x4e39eb36}, + {&ch[0].ao.shu[0].ckectrl, 0x33210000}, + {&ch[0].ao.ckectrl, 0x88d02440}, + {&ch[0].ao.shu[0].rankctl, 0x64300003}, + {&ch[0].ao.shu[0].rankctl, 0x64301203}, + {&ch[1].ao.shu[0].actim[0], 0x06020c07}, + {&ch[1].ao.shu[0].actim[1], 0x10080501}, + {&ch[1].ao.shu[0].actim[2], 0x07070201}, + {&ch[1].ao.shu[0].actim[3], 0x6164002c}, + {&ch[1].ao.shu[0].actim[4], 0x22650077}, + {&ch[1].ao.shu[0].actim[5], 0x0a000c0b}, + {&ch[1].ao.shu[0].actim_xrt, 0x05030609}, + {&ch[1].ao.shu[0].ac_time_05t, 0x000106e1}, + {&ch[1].ao.catraining1, 0x0b000000}, + {&ch[1].ao.shu[0].rk[0].dqsctl, 0x00000004}, + {&ch[1].ao.shu[0].rk[1].dqsctl, 0x00000004}, + {&ch[1].ao.shu[0].odtctrl, 0xc001004f}, + {&ch[1].ao.shu[0].conf[1], 0x34000d0f}, + {&ch[1].ao.shu[0].conf[2], 0x9007640f}, + {&ch[1].ao.shu[0].scintv, 0x4e39eb36}, + {&ch[1].ao.shu[0].ckectrl, 0x33210000}, + {&ch[1].ao.ckectrl, 0x88d02440}, + {&ch[1].ao.shu[0].rankctl, 0x64300003}, + {&ch[1].ao.shu[0].rankctl, 0x64301203}, + {&ch[0].ao.arbctl, 0x00000c80}, + {&ch[0].ao.rstmask, 0x00000000}, + {&ch[0].ao.arbctl, 0x00000c80}, +}; + +static struct reg_init_value dramc_mode_reg_init_sequence[] = { + /* dramc power on sequence */ {&ch[0].phy.misc_ctrl1, 0x8100908c}, {&ch[1].phy.misc_ctrl1, 0x8100908c}, {&ch[0].ao.ckectrl, 0x88d02480}, @@ -632,6 +678,8 @@ struct reg_init_value dramc_init_sequence[] = { {&ch[0].ao.ckectrl, 0x88d02440}, {&ch[1].ao.ckectrl, 0x88d02440}, {&ch[0].ao.mrs, 0x00000000}, + + /* CH0 dramc ZQ Calibration */ {&ch[0].ao.dramc_pd_ctrl, 0xc4000107}, {&ch[0].ao.ckectrl, 0x88d02440}, {&ch[0].ao.mrs, 0x00000000}, @@ -641,70 +689,104 @@ struct reg_init_value dramc_init_sequence[] = { {&ch[0].ao.mrs, 0x00000000}, {&ch[0].ao.dramc_pd_ctrl, 0xc4000107}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR13 */ {&ch[0].ao.mrs, 0x00000d18}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR12 */ {&ch[0].ao.mrs, 0x00000c5d}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR1 */ {&ch[0].ao.mrs, 0x00000156}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR2 */ {&ch[0].ao.mrs, 0x0000020b}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR11 */ {&ch[0].ao.mrs, 0x00000b00}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR22 */ {&ch[0].ao.mrs, 0x00001638}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR14 */ {&ch[0].ao.mrs, 0x00000e5d}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR3 */ {&ch[0].ao.mrs, 0x00000330}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR13 */ {&ch[0].ao.mrs, 0x00000d58}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR12 */ {&ch[0].ao.mrs, 0x00000c5d}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR1 */ {&ch[0].ao.mrs, 0x00000156}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR2 */ {&ch[0].ao.mrs, 0x0000022d}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR11 */ {&ch[0].ao.mrs, 0x00000b23}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR22 */ {&ch[0].ao.mrs, 0x00001634}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR14 */ {&ch[0].ao.mrs, 0x00000e10}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR3 */ {&ch[0].ao.mrs, 0x00000330}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* dramc ZQ Calibration */ {&ch[0].ao.mrs, 0x01000330}, {&ch[0].ao.dramc_pd_ctrl, 0xc4000107}, {&ch[0].ao.ckectrl, 0x88d02440}, @@ -715,76 +797,112 @@ struct reg_init_value dramc_init_sequence[] = { {&ch[0].ao.mrs, 0x01000330}, {&ch[0].ao.dramc_pd_ctrl, 0xc4000107}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR13 */ {&ch[0].ao.mrs, 0x01000d18}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR12 */ {&ch[0].ao.mrs, 0x01000c5d}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR1 */ {&ch[0].ao.mrs, 0x01000156}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR2 */ {&ch[0].ao.mrs, 0x0100020b}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR11 */ {&ch[0].ao.mrs, 0x01000b00}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR22 */ {&ch[0].ao.mrs, 0x01001638}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR14 */ {&ch[0].ao.mrs, 0x01000e5d}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR3 */ {&ch[0].ao.mrs, 0x01000330}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR13 */ {&ch[0].ao.mrs, 0x01000d58}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR12 */ {&ch[0].ao.mrs, 0x01000c5d}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR1 */ {&ch[0].ao.mrs, 0x01000156}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR2 */ {&ch[0].ao.mrs, 0x0100022d}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR11 */ {&ch[0].ao.mrs, 0x01000b23}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR22 */ {&ch[0].ao.mrs, 0x01001634}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR14 */ {&ch[0].ao.mrs, 0x01000e10}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR3 */ {&ch[0].ao.mrs, 0x01000330}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR13 */ {&ch[0].ao.mrs, 0x00000330}, {&ch[0].ao.ckectrl, 0x88d02440}, {&ch[0].ao.mrs, 0x00000dd8}, {&ch[0].ao.spcmd, 0x00000001}, {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, + + /* MR13 */ {&ch[0].ao.mrs, 0x01000dd8}, {&ch[0].ao.ckectrl, 0x88d02440}, {&ch[0].ao.mrs, 0x01000dd8}, @@ -792,9 +910,12 @@ struct reg_init_value dramc_init_sequence[] = { {&ch[0].ao.spcmd, 0x00000000}, {&ch[0].ao.ckectrl, 0x88d02440}, {&ch[0].ao.mrs, 0x01000dd8}, + {&ch[0].ao.shu[0].hwset_mr13, 0x00d8000d}, {&ch[0].ao.shu[0].hwset_vrcg, 0x00d8000d}, {&ch[0].ao.shu[0].hwset_mr2, 0x002d0002}, + + /* CH1 dramc ZQ Calibration */ {&ch[1].ao.mrs, 0x00000000}, {&ch[1].ao.dramc_pd_ctrl, 0xc4000107}, {&ch[1].ao.ckectrl, 0x88d02440}, @@ -961,49 +1082,6 @@ struct reg_init_value dramc_init_sequence[] = { {&ch[1].ao.shu[0].hwset_mr2, 0x002d0002}, {&ch[0].ao.mrs, 0x00000dd8}, {&ch[1].ao.mrs, 0x00000dd8}, - - /* update the ac timing */ - {&ch[0].ao.shu[0].actim[0], 0x06020c07}, - {&ch[0].ao.shu[0].actim[1], 0x10080501}, - {&ch[0].ao.shu[0].actim[2], 0x07070201}, - {&ch[0].ao.shu[0].actim[3], 0x6164002c}, - {&ch[0].ao.shu[0].actim[4], 0x22650077}, - {&ch[0].ao.shu[0].actim[5], 0x0a000c0b}, - {&ch[0].ao.shu[0].actim_xrt, 0x05030609}, - {&ch[0].ao.shu[0].ac_time_05t, 0x000106e1}, - {&ch[0].ao.catraining1, 0x0b000000}, - {&ch[0].ao.shu[0].rk[0].dqsctl, 0x00000004}, - {&ch[0].ao.shu[0].rk[1].dqsctl, 0x00000004}, - {&ch[0].ao.shu[0].odtctrl, 0xc001004f}, - {&ch[0].ao.shu[0].conf[1], 0x34000d0f}, - {&ch[0].ao.shu[0].conf[2], 0x9007640f}, - {&ch[0].ao.shu[0].scintv, 0x4e39eb36}, - {&ch[0].ao.shu[0].ckectrl, 0x33210000}, - {&ch[0].ao.ckectrl, 0x88d02440}, - {&ch[0].ao.shu[0].rankctl, 0x64300003}, - {&ch[0].ao.shu[0].rankctl, 0x64301203}, - {&ch[1].ao.shu[0].actim[0], 0x06020c07}, - {&ch[1].ao.shu[0].actim[1], 0x10080501}, - {&ch[1].ao.shu[0].actim[2], 0x07070201}, - {&ch[1].ao.shu[0].actim[3], 0x6164002c}, - {&ch[1].ao.shu[0].actim[4], 0x22650077}, - {&ch[1].ao.shu[0].actim[5], 0x0a000c0b}, - {&ch[1].ao.shu[0].actim_xrt, 0x05030609}, - {&ch[1].ao.shu[0].ac_time_05t, 0x000106e1}, - {&ch[1].ao.catraining1, 0x0b000000}, - {&ch[1].ao.shu[0].rk[0].dqsctl, 0x00000004}, - {&ch[1].ao.shu[0].rk[1].dqsctl, 0x00000004}, - {&ch[1].ao.shu[0].odtctrl, 0xc001004f}, - {&ch[1].ao.shu[0].conf[1], 0x34000d0f}, - {&ch[1].ao.shu[0].conf[2], 0x9007640f}, - {&ch[1].ao.shu[0].scintv, 0x4e39eb36}, - {&ch[1].ao.shu[0].ckectrl, 0x33210000}, - {&ch[1].ao.ckectrl, 0x88d02440}, - {&ch[1].ao.shu[0].rankctl, 0x64300003}, - {&ch[1].ao.shu[0].rankctl, 0x64301203}, - {&ch[0].ao.arbctl, 0x00000c80}, - {&ch[0].ao.rstmask, 0x00000000}, - {&ch[0].ao.arbctl, 0x00000c80}, }; void dramc_init(void) @@ -1011,4 +1089,10 @@ void dramc_init(void) for (int i = 0; i < ARRAY_SIZE(dramc_init_sequence); i++) write32(dramc_init_sequence[i].addr, dramc_init_sequence[i].value); + + for (int i = 0; i < ARRAY_SIZE(dramc_mode_reg_init_sequence); i++) { + write32(dramc_mode_reg_init_sequence[i].addr, + dramc_mode_reg_init_sequence[i].value); + udelay(2); + } } From 42b7b77571bd45f28850eb66a17f0ef91f995f28 Mon Sep 17 00:00:00 2001 From: Huayang Duan Date: Mon, 8 Apr 2019 20:10:23 +0800 Subject: [PATCH 140/221] mediatek/mt8183: support SAMSUNG and MICRON EMCP LPDDR4X DDR bootup Support SAMSUNG KMDP6001DA-B425 and MICRON MT29VZZZAD8DQKSL EMCP LPDDR4X DDR From the calibration log of MICRON MT29VZZZAD8DQKSL, we found the begin pass range of RX window earlier than with other DDR type. So need change the DQS starting offset to increase the scan range of RX window. BUG=b:80501386 BRANCH=none TEST=Boots correctly on EMCP DRAM Change-Id: I5fcc8673a2fbd7ec3a8776ab61c57f8903ddda20 Signed-off-by: Huayang Duan Reviewed-on: https://review.coreboot.org/c/coreboot/+/32243 Tested-by: build bot (Jenkins) Reviewed-by: Hung-Te Lin Reviewed-by: Julius Werner Reviewed-by: Huayang Duan --- src/mainboard/google/kukui/sdram_configs.c | 2 + .../google/kukui/sdram_params/Makefile.inc | 2 + .../sdram-lpddr4x-KMDP6001DA-B425-4GB.c | 41 +++++++++++++++++++ .../sdram-lpddr4x-MT29VZZZAD8DQKSL-4GB.c | 41 +++++++++++++++++++ .../mt8183/dramc_pi_calibration_api.c | 2 +- 5 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/mainboard/google/kukui/sdram_params/sdram-lpddr4x-KMDP6001DA-B425-4GB.c create mode 100644 src/mainboard/google/kukui/sdram_params/sdram-lpddr4x-MT29VZZZAD8DQKSL-4GB.c diff --git a/src/mainboard/google/kukui/sdram_configs.c b/src/mainboard/google/kukui/sdram_configs.c index cbfb08d5ce..5931c79ecd 100644 --- a/src/mainboard/google/kukui/sdram_configs.c +++ b/src/mainboard/google/kukui/sdram_configs.c @@ -21,6 +21,8 @@ static const char *const sdram_configs[] = { [1] = "sdram-lpddr4x-H9HCNNNCPMALHR-4GB", [2] = "sdram-lpddr4x-MT53E1G32D4NQ-4GB", + [3] = "sdram-lpddr4x-KMDP6001DA-B425-4GB", + [5] = "sdram-lpddr4x-MT29VZZZAD8DQKSL-4GB", }; static struct sdram_params params; diff --git a/src/mainboard/google/kukui/sdram_params/Makefile.inc b/src/mainboard/google/kukui/sdram_params/Makefile.inc index 1e11140873..77158a5c59 100644 --- a/src/mainboard/google/kukui/sdram_params/Makefile.inc +++ b/src/mainboard/google/kukui/sdram_params/Makefile.inc @@ -1,6 +1,8 @@ sdram-params := sdram-params += sdram-lpddr4x-H9HCNNNCPMALHR-4GB sdram-params += sdram-lpddr4x-MT53E1G32D4NQ-4GB +sdram-params += sdram-lpddr4x-KMDP6001DA-B425-4GB +sdram-params += sdram-lpddr4x-MT29VZZZAD8DQKSL-4GB $(foreach params,$(sdram-params), \ $(eval cbfs-files-y += $(params)) \ diff --git a/src/mainboard/google/kukui/sdram_params/sdram-lpddr4x-KMDP6001DA-B425-4GB.c b/src/mainboard/google/kukui/sdram_params/sdram-lpddr4x-KMDP6001DA-B425-4GB.c new file mode 100644 index 0000000000..1e0c3628fd --- /dev/null +++ b/src/mainboard/google/kukui/sdram_params/sdram-lpddr4x-KMDP6001DA-B425-4GB.c @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 MediaTek 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 + +struct sdram_params params = { + .impedance = { + [ODT_OFF] = {0x9, 0x7, 0x0, 0xF}, + [ODT_ON] = {0xA, 0x9, 0x0, 0xE} + }, + .wr_level = { + [CHANNEL_A] = { {0x21, 0x21}, {0x20, 0x20} }, + [CHANNEL_B] = { {0x1E, 0x1F}, {0x1D, 0x1E} } + }, + .cbt_cs = { + [CHANNEL_A] = {0x1, 0x1}, + [CHANNEL_B] = {0x2, 0x2} + }, + .cbt_mr12 = { + [CHANNEL_A] = {0x56, 0x56}, + [CHANNEL_B] = {0x58, 0x5C} + }, + .emi_cona_val = 0xF053F154, + .emi_conh_val = 0x44440003, + .emi_conf_val = 0x00421000, + .chn_emi_cona_val = {0x0444F051, 0x0444F051}, + .cbt_mode_extern = CBT_NORMAL_MODE, + .delay_cell_unit = 868, +}; diff --git a/src/mainboard/google/kukui/sdram_params/sdram-lpddr4x-MT29VZZZAD8DQKSL-4GB.c b/src/mainboard/google/kukui/sdram_params/sdram-lpddr4x-MT29VZZZAD8DQKSL-4GB.c new file mode 100644 index 0000000000..512023b35e --- /dev/null +++ b/src/mainboard/google/kukui/sdram_params/sdram-lpddr4x-MT29VZZZAD8DQKSL-4GB.c @@ -0,0 +1,41 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 MediaTek 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 + +struct sdram_params params = { + .impedance = { + [ODT_OFF] = {0x9, 0x7, 0x0, 0xF}, + [ODT_ON] = {0xA, 0x9, 0x0, 0xE} + }, + .wr_level = { + [CHANNEL_A] = { {0x21, 0x21}, {0x20, 0x20} }, + [CHANNEL_B] = { {0x21, 0x28}, {0x21, 0x29} } + }, + .cbt_cs = { + [CHANNEL_A] = {0x2, 0x2}, + [CHANNEL_B] = {0x2, 0x2} + }, + .cbt_mr12 = { + [CHANNEL_A] = {0x5E, 0x5E}, + [CHANNEL_B] = {0x5E, 0x5C} + }, + .emi_cona_val = 0xF053F154, + .emi_conh_val = 0x44440003, + .emi_conf_val = 0x00421000, + .chn_emi_cona_val = {0x0444F051, 0x0444F051}, + .cbt_mode_extern = CBT_NORMAL_MODE, + .delay_cell_unit = 868, +}; diff --git a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c index 6dc8fa6588..05f793ec4b 100644 --- a/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c +++ b/src/soc/mediatek/mt8183/dramc_pi_calibration_api.c @@ -32,7 +32,7 @@ enum { enum { FIRST_DQ_DELAY = 0, - FIRST_DQS_DELAY = -10, + FIRST_DQS_DELAY = -16, MAX_DQDLY_TAPS = 16, MAX_RX_DQDLY_TAPS = 63, }; From b3c344b8b80d397877e605a59cc55eeb637531a9 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 17 Jun 2019 15:28:09 +0200 Subject: [PATCH 141/221] mb/facebook/fbg1701: Remove unused Kconfig symbols Change-Id: Ifc61fd11c9d7a4d192eaae73c5421f643d27d817 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33562 Tested-by: build bot (Jenkins) Reviewed-by: Frans Hendriks Reviewed-by: Angel Pons --- src/mainboard/facebook/fbg1701/Kconfig | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/mainboard/facebook/fbg1701/Kconfig b/src/mainboard/facebook/fbg1701/Kconfig index 3f451945b4..b3c589dc2f 100644 --- a/src/mainboard/facebook/fbg1701/Kconfig +++ b/src/mainboard/facebook/fbg1701/Kconfig @@ -78,14 +78,6 @@ config FSP1_1_DISPLAY_LOGO bool default n -config BOOTBLOCK_LOC - hex - default 0xFFFF0000 - -config BOOTBLOCK_SIZE - hex - default 0x10000 - config SPI_FLASH_INCLUDE_ALL_DRIVERS bool default n From 3f17c3b33ff43cdc0879bc5b20d6526371e124b0 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Thu, 20 Jun 2019 11:03:53 +0200 Subject: [PATCH 142/221] mb/lenovo/x201: Remove duplicated include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0917f11091b8c93c21c0e25690440b7dd0e9c8ba Signed-off-by: Peter Lemenkov Reviewed-on: https://review.coreboot.org/c/coreboot/+/33626 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki Reviewed-by: Paul Menzel --- src/mainboard/lenovo/x201/mainboard.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mainboard/lenovo/x201/mainboard.c b/src/mainboard/lenovo/x201/mainboard.c index 01dba57c30..70b393cc18 100644 --- a/src/mainboard/lenovo/x201/mainboard.c +++ b/src/mainboard/lenovo/x201/mainboard.c @@ -26,7 +26,6 @@ #include "dock.h" #include #include -#include #include static void mainboard_init(struct device *dev) From fcbb3c5747180ffb1796608b3689d2ce4c7aa6e4 Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:01:54 +0200 Subject: [PATCH 143/221] arch-x86/smbios: use ALIGN_UP instead of ALIGN for better readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ALIGN_UP is an alias for ALIGN. Change-Id: Ie723ebe80f8f627021151413cb43adce6c88a0dc Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33628 Reviewed-by: Paul Menzel Reviewed-by: Kyösti Mälkki Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- src/arch/x86/smbios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c index 7865c7ef98..be090217ae 100644 --- a/src/arch/x86/smbios.c +++ b/src/arch/x86/smbios.c @@ -1150,12 +1150,12 @@ unsigned long smbios_write_tables(unsigned long current) int max_struct_size = 0; int handle = 0; - current = ALIGN(current, 16); + current = ALIGN_UP(current, 16); printk(BIOS_DEBUG, "%s: %08lx\n", __func__, current); se = (struct smbios_entry *)current; current += sizeof(struct smbios_entry); - current = ALIGN(current, 16); + current = ALIGN_UP(current, 16); tables = current; update_max(len, max_struct_size, smbios_write_type0(¤t, From 0f6b51b2de5e53166a7a1e21e5d3f73724219b86 Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:09:01 +0200 Subject: [PATCH 144/221] arch/x86/tables: use ALIGN_UP instead of ALIGN for better readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Idfb814abee87d52d0f5970ec0cd291f738631320 Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33629 Reviewed-by: Kyösti Mälkki Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- src/arch/x86/tables.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/arch/x86/tables.c b/src/arch/x86/tables.c index f17fb858b0..3cc385b530 100644 --- a/src/arch/x86/tables.c +++ b/src/arch/x86/tables.c @@ -36,7 +36,7 @@ static unsigned long write_pirq_table(unsigned long rom_table_end) /* This table must be between 0x0f0000 and 0x100000 */ rom_table_end = write_pirq_routing_table(rom_table_end); - rom_table_end = ALIGN(rom_table_end, 1024); + rom_table_end = ALIGN_UP(rom_table_end, 1024); /* And add a high table version for those payloads that * want to live in the F segment @@ -68,7 +68,7 @@ static unsigned long write_mptable(unsigned long rom_table_end) /* The smp table must be in 0-1K, 639K-640K, or 960K-1M */ rom_table_end = write_smp_table(rom_table_end); - rom_table_end = ALIGN(rom_table_end, 1024); + rom_table_end = ALIGN_UP(rom_table_end, 1024); high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_MPTABLE, MAX_MP_TABLE_SIZE); @@ -114,7 +114,7 @@ static unsigned long write_acpi_table(unsigned long rom_table_end) unsigned long acpi_start = high_table_pointer; unsigned long new_high_table_pointer; - rom_table_end = ALIGN(rom_table_end, 16); + rom_table_end = ALIGN_UP(rom_table_end, 16); new_high_table_pointer = write_acpi_tables(high_table_pointer); if (new_high_table_pointer > (high_table_pointer + MAX_ACPI_SIZE)) @@ -146,10 +146,10 @@ static unsigned long write_acpi_table(unsigned long rom_table_end) printk(BIOS_ERR, "ERROR: Didn't find RSDP in high table.\n"); } - rom_table_end = ALIGN(rom_table_end + sizeof(acpi_rsdp_t), 16); + rom_table_end = ALIGN_UP(rom_table_end + sizeof(acpi_rsdp_t), 16); } else { rom_table_end = write_acpi_tables(rom_table_end); - rom_table_end = ALIGN(rom_table_end, 1024); + rom_table_end = ALIGN_UP(rom_table_end, 1024); } return rom_table_end; @@ -168,7 +168,7 @@ static unsigned long write_smbios_table(unsigned long rom_table_end) new_high_table_pointer = smbios_write_tables(high_table_pointer); - rom_table_end = ALIGN(rom_table_end, 16); + rom_table_end = ALIGN_UP(rom_table_end, 16); memcpy((void *)rom_table_end, (void *)high_table_pointer, sizeof(struct smbios_entry)); rom_table_end += sizeof(struct smbios_entry); @@ -184,7 +184,7 @@ static unsigned long write_smbios_table(unsigned long rom_table_end) new_rom_table_end = smbios_write_tables(rom_table_end); printk(BIOS_DEBUG, "SMBIOS size %ld bytes\n", new_rom_table_end - rom_table_end); - rom_table_end = ALIGN(new_rom_table_end, 16); + rom_table_end = ALIGN_UP(new_rom_table_end, 16); } return rom_table_end; From 84b5aa3f50bf0874be9554be432ed91bed64802b Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:14:51 +0200 Subject: [PATCH 145/221] arch/x86: use ALIGN_UP instead of ALIGN for better readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch contains the rest of the fixes for this subtree; having one change for every area would create an unnecessary amouint of patches. Change-Id: Id92c11d58693292d58cba323c8468db858becfb5 Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33630 Reviewed-by: Kyösti Mälkki Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- src/arch/x86/gdt.c | 2 +- src/arch/x86/include/arch/early_variables.h | 2 +- src/arch/x86/pirq_routing.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/arch/x86/gdt.c b/src/arch/x86/gdt.c index c9aec6d111..d3ad01e1df 100644 --- a/src/arch/x86/gdt.c +++ b/src/arch/x86/gdt.c @@ -46,7 +46,7 @@ static void move_gdt(int is_recovery) newgdt = cbmem_find(CBMEM_ID_GDT); num_gdt_bytes = (uintptr_t)&gdt_end - (uintptr_t)&gdt; if (!newgdt) { - newgdt = cbmem_add(CBMEM_ID_GDT, ALIGN(num_gdt_bytes, 512)); + newgdt = cbmem_add(CBMEM_ID_GDT, ALIGN_UP(num_gdt_bytes, 512)); if (!newgdt) { printk(BIOS_ERR, "Error: Could not relocate GDT.\n"); return; diff --git a/src/arch/x86/include/arch/early_variables.h b/src/arch/x86/include/arch/early_variables.h index 9ea1537d81..b3042c34d2 100644 --- a/src/arch/x86/include/arch/early_variables.h +++ b/src/arch/x86/include/arch/early_variables.h @@ -69,7 +69,7 @@ int car_active(void); static inline size_t car_data_size(void) { size_t car_size = _car_relocatable_data_size; - return ALIGN(car_size, 64); + return ALIGN_UP(car_size, 64); } static inline size_t car_object_offset(void *ptr) diff --git a/src/arch/x86/pirq_routing.c b/src/arch/x86/pirq_routing.c index 194efb4ad2..70df201c99 100644 --- a/src/arch/x86/pirq_routing.c +++ b/src/arch/x86/pirq_routing.c @@ -191,7 +191,7 @@ unsigned long copy_pirq_routing_table(unsigned long addr, const struct irq_routing_table *routing_table) { /* Align the table to be 16 byte aligned. */ - addr = ALIGN(addr, 16); + addr = ALIGN_UP(addr, 16); /* This table must be between 0xf0000 & 0x100000 */ printk(BIOS_INFO, "Copying Interrupt Routing Table to 0x%08lx... ", From e1d57f7610921471d5fef0c78f7f9bb054a6ada1 Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:22:26 +0200 Subject: [PATCH 146/221] arch/arm/cpu: use ALIGN_UP instead of ALIGN for better readability Change-Id: Id0e281ece0a647721c18402029cd6980f75d5908 Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33631 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes --- src/arch/arm/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/arm/cpu.c b/src/arch/arm/cpu.c index fae1a37efc..93d5675f35 100644 --- a/src/arch/arm/cpu.c +++ b/src/arch/arm/cpu.c @@ -39,7 +39,7 @@ struct cpu_info *cpu_info(void) "feature, make sure you add the proper assertions " \ "(and maybe consider revising the whole thing to work closer to what " \ "arm64 is doing now)." - uintptr_t addr = ALIGN((uintptr_t)__builtin_frame_address(0), + uintptr_t addr = ALIGN_UP((uintptr_t)__builtin_frame_address(0), CONFIG_STACK_SIZE); addr -= sizeof(struct cpu_info); return (void *)addr; From 8d2ec86c5ed5f33fc121346db06dff69ea75e18e Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:26:09 +0200 Subject: [PATCH 147/221] commonlib/storage: use ALIGN_UP instead of ALIGN for better readability Change-Id: I76ec5ff107bc043d9457b3377e88226a96eb3f3c Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33632 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes --- src/commonlib/storage/bouncebuf.h | 2 +- src/commonlib/storage/storage.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commonlib/storage/bouncebuf.h b/src/commonlib/storage/bouncebuf.h index 27d92e826b..0d81be1faa 100644 --- a/src/commonlib/storage/bouncebuf.h +++ b/src/commonlib/storage/bouncebuf.h @@ -88,7 +88,7 @@ int bounce_buffer_stop(struct bounce_buffer *state); #define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \ char __##name[ROUND(size * sizeof(type), DMA_MINALIGN) + \ DMA_MINALIGN - 1]; \ - type *name = (type *) ALIGN((uintptr_t)__##name, DMA_MINALIGN) + type *name = (type *) ALIGN_UP((uintptr_t)__##name, DMA_MINALIGN) #ifndef ARCH_DMA_MINALIGN #define ARCH_DMA_MINALIGN (DMA_MINALIGN) #endif diff --git a/src/commonlib/storage/storage.h b/src/commonlib/storage/storage.h index 645b6c1abd..c71510dd19 100644 --- a/src/commonlib/storage/storage.h +++ b/src/commonlib/storage/storage.h @@ -23,7 +23,7 @@ #define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \ char __##name[ROUND(size * sizeof(type), DMA_MINALIGN) + \ DMA_MINALIGN - 1]; \ - type *name = (type *) ALIGN((uintptr_t)__##name, DMA_MINALIGN) + type *name = (type *) ALIGN_UP((uintptr_t)__##name, DMA_MINALIGN) /* NOOPs mirroring ARM's cache API, since x86 devices usually cache snoop */ #define dcache_invalidate_by_mva(addr, len) From d5a11ed6c82a7a3e6d8551e27feda96fb505498b Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:35:44 +0200 Subject: [PATCH 148/221] device/pci_rom: use ALIGN_UP instead of ALIGN for better readability Change-Id: Icb0b3fd22fa9b6ea73b7770079f81335e40fd0d3 Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33633 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes --- src/device/pci_rom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c index 2dbfb51b5f..3160c2041b 100644 --- a/src/device/pci_rom.c +++ b/src/device/pci_rom.c @@ -257,7 +257,7 @@ pci_rom_write_acpi_tables(struct device *device, unsigned long current, /* AMD/ATI uses VFCT */ if (device->vendor == PCI_VENDOR_ID_ATI) { - current = ALIGN(current, 8); + current = ALIGN_UP(current, 8); printk(BIOS_DEBUG, "ACPI: * VFCT at %lx\n", current); vfct = (struct acpi_vfct *)current; acpi_create_vfct(device, vfct, pci_rom_acpi_fill_vfct); From e56bf318243f1b541a06e0c52e040a943dbf62bf Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:42:35 +0200 Subject: [PATCH 149/221] cpu/amd: use ALIGN_UP instead of ALIGN for better readability Change-Id: Icef97ea764567a311b4cd63b65ad584ed0360152 Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33634 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes --- src/cpu/amd/car/post_cache_as_ram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu/amd/car/post_cache_as_ram.c b/src/cpu/amd/car/post_cache_as_ram.c index 18e7542e6d..f49c6765c6 100644 --- a/src/cpu/amd/car/post_cache_as_ram.c +++ b/src/cpu/amd/car/post_cache_as_ram.c @@ -45,7 +45,7 @@ static size_t backup_size(void) { size_t car_size = car_data_size(); - return ALIGN(car_size + 1024, 1024); + return ALIGN_UP(car_size + 1024, 1024); } static void memcpy_(void *d, const void *s, size_t len) From f0cbb09a624b8d7e06d744857331aa9c8810d72f Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:45:16 +0200 Subject: [PATCH 150/221] cpu/x86: use ALIGN_UP instead of ALIGN for better readability Change-Id: I0afb81740973a0c841ebe6cce984e135e5c395e6 Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33635 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes --- src/cpu/x86/mirror_payload.c | 2 +- src/cpu/x86/mp_init.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/x86/mirror_payload.c b/src/cpu/x86/mirror_payload.c index 5f0493a510..6da21646fc 100644 --- a/src/cpu/x86/mirror_payload.c +++ b/src/cpu/x86/mirror_payload.c @@ -42,7 +42,7 @@ void mirror_payload(struct prog *payload) alignment_diff = (intra_cacheline_mask & (uintptr_t)src); size += alignment_diff; - size = ALIGN(size, cacheline_size); + size = ALIGN_UP(size, cacheline_size); printk(BIOS_DEBUG, "Payload aligned size: 0x%zx\n", size); diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c index b7b8fe2afa..9528149627 100644 --- a/src/cpu/x86/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -321,7 +321,7 @@ static atomic_t *load_sipi_vector(struct mp_params *mp_params) module_size = rmodule_memory_size(&sipi_mod); /* Align to 4 bytes. */ - module_size = ALIGN(module_size, 4); + module_size = ALIGN_UP(module_size, 4); if (module_size > loc_size) { printk(BIOS_CRIT, "SIPI module size (%d) > region size (%d).\n", From 51ff9e8415263d5e3afb2aa3e85ca8bbccd166af Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 14:49:16 +0200 Subject: [PATCH 151/221] drivers/intel/fsp: use ALIGN_UP instead of ALIGN for better readability Change-Id: I41fd50dc1e30332261f80e99419dad2635b5a54a Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33636 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes --- src/drivers/intel/fsp1_0/fsp_util.c | 2 +- src/drivers/intel/fsp1_1/raminit.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/intel/fsp1_0/fsp_util.c b/src/drivers/intel/fsp1_0/fsp_util.c index 4e50abae4e..d787c7beca 100644 --- a/src/drivers/intel/fsp1_0/fsp_util.c +++ b/src/drivers/intel/fsp1_0/fsp_util.c @@ -275,7 +275,7 @@ int save_mrc_data(void *hob_start) printk(BIOS_DEBUG, "Memory Configure Data Hob at %p (size = 0x%x).\n", (void *)mrc_hob_data, mrc_hob_size); - output_len = ALIGN(mrc_hob_size, 16); + output_len = ALIGN_UP(mrc_hob_size, 16); /* Save the MRC S3/fast boot/ADR restore data to cbmem */ mrc_data = cbmem_add (CBMEM_ID_MRCDATA, diff --git a/src/drivers/intel/fsp1_1/raminit.c b/src/drivers/intel/fsp1_1/raminit.c index eff011aa62..a631fcae60 100644 --- a/src/drivers/intel/fsp1_1/raminit.c +++ b/src/drivers/intel/fsp1_1/raminit.c @@ -297,7 +297,7 @@ void raminit(struct romstage_params *params) else if (!vboot_recovery_mode_enabled()) { /* Do not save MRC data in recovery path */ params->data_to_save = GET_GUID_HOB_DATA(mrc_hob); - params->data_to_save_size = ALIGN( + params->data_to_save_size = ALIGN_UP( ((u32)GET_HOB_LENGTH(mrc_hob)), 16); } } From c469712166257da7b159773b42f067090b63e34e Mon Sep 17 00:00:00 2001 From: Felix Held Date: Thu, 20 Jun 2019 13:50:17 +0200 Subject: [PATCH 152/221] arch/x86/acpi: use ALIGN_UP instead of ALIGN The ALIGN_UP macro is basically an alias of the ALIGN macro; with this change it's more obvious in which direction the alignment happens. Change-Id: I6f1b9f9bbcafeb85a6ef5c10ce4b57edc0740e72 Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33627 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Lance Zhao --- src/arch/x86/acpi.c | 4 ++-- src/arch/x86/include/arch/acpi.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c index 1b8aaae64b..71fc4e208f 100644 --- a/src/arch/x86/acpi.c +++ b/src/arch/x86/acpi.c @@ -864,7 +864,7 @@ unsigned long acpi_write_hpet(struct device *device, unsigned long current, hpet = (acpi_hpet_t *) current; current += sizeof(acpi_hpet_t); - current = ALIGN(current, 16); + current = ALIGN_UP(current, 16); acpi_create_hpet(hpet); acpi_add_table(rsdp, hpet); @@ -1322,7 +1322,7 @@ unsigned long write_acpi_tables(unsigned long start) acpi_write_xsdt(xsdt, oem_id, oem_table_id); printk(BIOS_DEBUG, "ACPI: * FACS\n"); - current = (ALIGN(current, 64)); + current = ALIGN_UP(current, 64); facs = (acpi_facs_t *) current; current += sizeof(acpi_facs_t); current = acpi_align_current(current); diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h index e48b2da567..6251b98142 100644 --- a/src/arch/x86/include/arch/acpi.h +++ b/src/arch/x86/include/arch/acpi.h @@ -1004,7 +1004,7 @@ static inline int acpi_is_wakeup_s4(void) { return 0; } static inline uintptr_t acpi_align_current(uintptr_t current) { - return ALIGN(current, 16); + return ALIGN_UP(current, 16); } /* ACPI table revisions should match the revision of the ACPI spec From ffbc3b5f5fb0bdf57b6d5e3808e55e761241d8ba Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Thu, 6 Jun 2019 15:45:51 +0200 Subject: [PATCH 153/221] drivers/ipmi: Add chip ops * Add chips ops for IPMI KCS. * Get IPMI version over KCS. * Generates ACPI SPMI table for IPMI KCS. * Generates SMBIOS type 38 for IPMI KCS. * Generates ACPI SPMI device for IPMI KCS on LPC device. * Add documentation To use this driver on BMC that support KCS on I/O: 1. Add an entry to the devicetree.cb: chip drivers/ipmi device pnp ca2.0 on end # IPMI KCS end 2. Select IPMI_KCS in Kconfig. 3. (Optional) enable LPC I/O decode for the given address. Tested on Wedge100s. Change-Id: I73cbd2058ccdc5395baf244f31345a85eb0047d7 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33255 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- Documentation/drivers/index.md | 7 + Documentation/drivers/ipmi_kcs.md | 47 ++++++ Documentation/index.md | 1 + src/drivers/ipmi/Makefile.inc | 1 + src/drivers/ipmi/chip.h | 29 ++++ src/drivers/ipmi/ipmi_kcs.h | 24 +++ src/drivers/ipmi/ipmi_kcs_ops.c | 267 ++++++++++++++++++++++++++++++ 7 files changed, 376 insertions(+) create mode 100644 Documentation/drivers/index.md create mode 100644 Documentation/drivers/ipmi_kcs.md create mode 100644 src/drivers/ipmi/chip.h create mode 100644 src/drivers/ipmi/ipmi_kcs_ops.c diff --git a/Documentation/drivers/index.md b/Documentation/drivers/index.md new file mode 100644 index 0000000000..642ae1a5f3 --- /dev/null +++ b/Documentation/drivers/index.md @@ -0,0 +1,7 @@ +# Platform indenpendend drivers documentation + +The drivers can be found in `src/drivers`. They are intended for onboard +and plugin devices, significantly reducing integration complexity and +they allow to easily reuse existing code accross platforms. + +* [IPMI KCS](ipmi_kcs.md) diff --git a/Documentation/drivers/ipmi_kcs.md b/Documentation/drivers/ipmi_kcs.md new file mode 100644 index 0000000000..f6f0fb986a --- /dev/null +++ b/Documentation/drivers/ipmi_kcs.md @@ -0,0 +1,47 @@ +# IPMI KCS driver + +The driver can be found in `src/drivers/ipmi/`. It works with BMC that provide +a KCS I/O interface as specified in the [IPMI] standard. + +The driver detects the IPMI version, reserves the I/O space in coreboot's +resource allocator and writes the required ACPI and SMBIOS tables. + +## For developers + +To use the driver, select the `IPMI_KCS` Kconfig and add the following PNP +device under the LPC bridge device (in example for the KCS at 0xca2): + +``` + chip drivers/ipmi + device pnp ca2.0 on end # IPMI KCS + end +``` + +**Note:** The I/O base address needs to be aligned to 2. + +The following registers can be set: + +* `have_nv_storage` + * Boolean + * If true `nv_storage_device_address` will be added to SMBIOS type 38. +* `nv_storage_device_address` + * Integer + * The NV storage address as defined in SMBIOS spec for type 38. +* `bmc_i2c_address` + * Integer + * The i2c address of the BMC. zero if not applicable. +* `have_apic` + * Boolean + * If true the `apic_interrupt` will be added to SPMI table. +* `apic_interrupt` + * Integer + * The APIC interrupt used to notify about a change on the KCS. +* `have_gpe` + * Boolean + * If true the `gpe_interrupt` will be added to SPMI table. +* `gpe_interrupt` + * Integer + * The bit in GPE (SCI) used to notify about a change on the KCS. + + +[IPMI]: https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf diff --git a/Documentation/index.md b/Documentation/index.md index 76faffa497..a2c2878ddb 100644 --- a/Documentation/index.md +++ b/Documentation/index.md @@ -175,6 +175,7 @@ Contents: * [Native Graphics Initialization with libgfxinit](gfx/libgfxinit.md) * [Display panel-specific documentation](gfx/display-panel.md) * [Architecture-specific documentation](arch/index.md) +* [Platform independend drivers documentation](drivers/index.md) * [Northbridge-specific documentation](northbridge/index.md) * [System on Chip-specific documentation](soc/index.md) * [Mainboard-specific documentation](mainboard/index.md) diff --git a/src/drivers/ipmi/Makefile.inc b/src/drivers/ipmi/Makefile.inc index e9e7ff3bca..a29c2e2d0e 100644 --- a/src/drivers/ipmi/Makefile.inc +++ b/src/drivers/ipmi/Makefile.inc @@ -1 +1,2 @@ ramstage-$(CONFIG_IPMI_KCS) += ipmi_kcs.c +ramstage-$(CONFIG_IPMI_KCS) += ipmi_kcs_ops.c diff --git a/src/drivers/ipmi/chip.h b/src/drivers/ipmi/chip.h new file mode 100644 index 0000000000..eb8b4e6d34 --- /dev/null +++ b/src/drivers/ipmi/chip.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Patrick Rudolph + * + * 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 _IMPI_CHIP_H_ +#define _IPMI_CHIP_H_ + +struct drivers_ipmi_config { + u8 bmc_i2c_address; + u8 have_nv_storage; + u8 nv_storage_device_address; + u8 have_gpe; + u8 gpe_interrupt; + u8 have_apic; + u32 apic_interrupt; +}; + +#endif /* _IMPI_CHIP_H_ */ diff --git a/src/drivers/ipmi/ipmi_kcs.h b/src/drivers/ipmi/ipmi_kcs.h index 3cd7609039..a194dd22e9 100644 --- a/src/drivers/ipmi/ipmi_kcs.h +++ b/src/drivers/ipmi/ipmi_kcs.h @@ -20,6 +20,10 @@ #define IPMI_NETFN_BRIDGE 0x02 #define IPMI_NETFN_SENSOREVENT 0x04 #define IPMI_NETFN_APPLICATION 0x06 +#define IPMI_BMC_GET_DEVICE_ID 0x01 +#define IPMI_IPMI_VERSION_MINOR(x) ((x) >> 4) +#define IPMI_IPMI_VERSION_MAJOR(x) ((x) & 0xf) + #define IPMI_NETFN_FIRMWARE 0x08 #define IPMI_NETFN_STORAGE 0x0a #define IPMI_NETFN_TRANSPORT 0x0c @@ -29,4 +33,24 @@ extern int ipmi_kcs_message(int port, int netfn, int lun, int cmd, const unsigned char *inmsg, int inlen, unsigned char *outmsg, int outlen); + +struct ipmi_rsp { + uint8_t lun; + uint8_t cmd; + uint8_t completion_code; +} __packed; + +/* Get Device ID */ +struct ipmi_devid_rsp { + struct ipmi_rsp resp; + uint8_t device_id; + uint8_t device_revision; + uint8_t fw_rev1; + uint8_t fw_rev2; + uint8_t ipmi_version; + uint8_t additional_device_support; + uint8_t manufacturer_id[3]; + uint8_t product_id[2]; +} __packed; + #endif diff --git a/src/drivers/ipmi/ipmi_kcs_ops.c b/src/drivers/ipmi/ipmi_kcs_ops.c new file mode 100644 index 0000000000..0cc4e0a965 --- /dev/null +++ b/src/drivers/ipmi/ipmi_kcs_ops.c @@ -0,0 +1,267 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 9elements Agency 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. + * + * Place in devicetree.cb: + * + * chip drivers/ipmi + * device pnp ca2.0 on end # IPMI KCS + * end + */ + +#include +#include +#include +#if CONFIG(HAVE_ACPI_TABLES) +#include +#include +#endif +#if CONFIG(GENERATE_SMBIOS_TABLES) +#include +#endif +#include +#include +#include "ipmi_kcs.h" +#include "chip.h" + +/* 4 bit encoding */ +static u8 ipmi_revision_major = 0x1; +static u8 ipmi_revision_minor = 0x0; + +static int ipmi_get_device_id(struct device *dev, struct ipmi_devid_rsp *rsp) +{ + int ret; + + ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_APPLICATION, 0, + IPMI_BMC_GET_DEVICE_ID, NULL, 0, (u8 *)rsp, + sizeof(*rsp)); + if (ret < sizeof(struct ipmi_rsp) || rsp->resp.completion_code) { + printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n", + __func__, ret, rsp->resp.completion_code); + return 1; + } + if (ret != sizeof(*rsp)) { + printk(BIOS_ERR, "IPMI: %s response truncated\n", __func__); + return 1; + } + return 0; +} + +static void ipmi_kcs_init(struct device *dev) +{ + struct ipmi_devid_rsp rsp; + uint32_t man_id = 0, prod_id = 0; + + if (!dev->enabled) + return; + + /* Get IPMI version for ACPI and SMBIOS */ + if (!ipmi_get_device_id(dev, &rsp)) { + ipmi_revision_minor = IPMI_IPMI_VERSION_MINOR(rsp.ipmi_version); + ipmi_revision_major = IPMI_IPMI_VERSION_MAJOR(rsp.ipmi_version); + + memcpy(&man_id, rsp.manufacturer_id, + sizeof(rsp.manufacturer_id)); + + memcpy(&prod_id, rsp.product_id, sizeof(rsp.product_id)); + + printk(BIOS_INFO, "IPMI: Found man_id 0x%06x, prod_id 0x%04x\n", + man_id, prod_id); + + printk(BIOS_INFO, "IPMI: Version %01x.%01x\n", + ipmi_revision_major, ipmi_revision_minor); + } else { + /* Don't write tables if communication failed */ + dev->enabled = 0; + } +} + +#if CONFIG(HAVE_ACPI_TABLES) +static uint32_t uid_cnt = 0; + +static unsigned long +ipmi_write_acpi_tables(struct device *dev, unsigned long current, + struct acpi_rsdp *rsdp) +{ + struct drivers_ipmi_config *conf = NULL; + struct acpi_spmi *spmi; + s8 gpe_interrupt = -1; + u32 apic_interrupt = 0; + acpi_addr_t addr = { + .space_id = ACPI_ADDRESS_SPACE_IO, + .access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS, + .addrl = dev->path.pnp.port, + }; + + current = ALIGN_UP(current, 8); + printk(BIOS_DEBUG, "ACPI: * SPMI at %lx\n", current); + spmi = (struct acpi_spmi *)current; + + if (dev->chip_info) + conf = dev->chip_info; + + if (conf) { + if (conf->have_gpe) + gpe_interrupt = conf->gpe_interrupt; + if (conf->have_apic) + apic_interrupt = conf->apic_interrupt; + } + + /* Use command to get UID from ipmi_ssdt */ + acpi_create_ipmi(dev, spmi, (ipmi_revision_major << 8) | + (ipmi_revision_minor << 4), &addr, + IPMI_INTERFACE_KCS, gpe_interrupt, apic_interrupt, + dev->command); + + acpi_add_table(rsdp, spmi); + + current += spmi->header.length; + + return current; +} + +static void ipmi_ssdt(struct device *dev) +{ + const char *scope = acpi_device_scope(dev); + struct drivers_ipmi_config *conf = NULL; + + if (!scope) { + printk(BIOS_ERR, "IPMI: Missing ACPI scope for %s\n", + dev_path(dev)); + return; + } + + if (dev->chip_info) + conf = dev->chip_info; + + /* Use command to pass UID to ipmi_write_acpi_tables */ + dev->command = uid_cnt++; + + /* write SPMI device */ + acpigen_write_scope(scope); + acpigen_write_device("SPMI"); + acpigen_write_name_string("_HID", "IPI0001"); + acpigen_write_name_string("_STR", "IPMI_KCS"); + acpigen_write_name_byte("_UID", dev->command); + acpigen_write_STA(0xf); + acpigen_write_name("_CRS"); + acpigen_write_resourcetemplate_header(); + acpigen_write_io16(dev->path.pnp.port, dev->path.pnp.port, 1, 2, 1); + + if (conf) { + // FIXME: is that correct? + if (conf->have_apic) + acpigen_write_irq(1 << conf->apic_interrupt); + } + + acpigen_write_resourcetemplate_footer(); + + acpigen_write_method("_IFT", 0); + acpigen_write_return_byte(1); // KCS + acpigen_pop_len(); + + acpigen_write_method("_SRV", 0); + acpigen_write_return_integer((ipmi_revision_major << 8) | + (ipmi_revision_minor << 4)); + acpigen_pop_len(); + + acpigen_pop_len(); /* pop device */ + acpigen_pop_len(); /* pop scope */ +} +#endif + +#if CONFIG(GENERATE_SMBIOS_TABLES) +static int ipmi_smbios_data(struct device *dev, int *handle, + unsigned long *current) +{ + struct drivers_ipmi_config *conf = NULL; + u8 nv_storage = 0xff; + u8 i2c_address = 0; + int len = 0; + + if (dev->chip_info) + conf = dev->chip_info; + + if (conf) { + if (conf->have_nv_storage) + nv_storage = conf->nv_storage_device_address; + i2c_address = conf->bmc_i2c_address; + } + + // add IPMI Device Information + len += smbios_write_type38( + current, handle, + SMBIOS_BMC_INTERFACE_KCS, + ipmi_revision_minor | (ipmi_revision_major << 4), + i2c_address, // I2C address + nv_storage, // NV storage + dev->path.pnp.port | 1, // IO interface + 0, + 0); // no IRQ + + return len; +} +#endif + +static void ipmi_set_resources(struct device *dev) +{ + struct resource *res; + + for (res = dev->resource_list; res; res = res->next) { + if (!(res->flags & IORESOURCE_ASSIGNED)) + continue; + + res->flags |= IORESOURCE_STORED; + report_resource_stored(dev, res, ""); + } +} + +static void ipmi_read_resources(struct device *dev) +{ + struct resource *res = new_resource(dev, 0); + res->base = dev->path.pnp.port; + res->size = 2; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; +} + +static struct device_operations ops = { + .read_resources = ipmi_read_resources, + .set_resources = ipmi_set_resources, + .enable_resources = DEVICE_NOOP, + .init = ipmi_kcs_init, +#if CONFIG(HAVE_ACPI_TABLES) + .write_acpi_tables = ipmi_write_acpi_tables, + .acpi_fill_ssdt_generator = ipmi_ssdt, +#endif +#if CONFIG(GENERATE_SMBIOS_TABLES) + .get_smbios_data = ipmi_smbios_data, +#endif +}; + +static void enable_dev(struct device *dev) +{ + if (dev->path.type != DEVICE_PATH_PNP) + printk(BIOS_ERR, "%s: Unsupported device type\n", + dev_path(dev)); + else if (dev->path.pnp.port & 1) + printk(BIOS_ERR, "%s: Base address needs to be aligned to 2\n", + dev_path(dev)); + else + dev->ops = &ops; +} + +struct chip_operations drivers_ipmi_ops = { + CHIP_NAME("IPMI KCS") + .enable_dev = enable_dev, +}; From db86a35ab686937fc4e4eb9a4f7417595bd9b519 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Fri, 14 Jun 2019 18:54:32 +0200 Subject: [PATCH 154/221] mb/ocp/wedge100s: Use the new IPMI driver * Enable decoding the IPMI KCS to LPC * Select the IPMI driver * Add the PNP device that holds the IPMI KCS base address Tested on Wedge100s. Change-Id: I35634bbcbe6893bd72ec7e41f6ca7bba09d819a2 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33489 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/mainboard/ocp/wedge100s/Kconfig | 1 + src/mainboard/ocp/wedge100s/devicetree.cb | 3 +++ src/mainboard/ocp/wedge100s/romstage.c | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/src/mainboard/ocp/wedge100s/Kconfig b/src/mainboard/ocp/wedge100s/Kconfig index bd5e6655af..491829a084 100644 --- a/src/mainboard/ocp/wedge100s/Kconfig +++ b/src/mainboard/ocp/wedge100s/Kconfig @@ -16,6 +16,7 @@ config BOARD_SPECIFIC_OPTIONS select MAINBOARD_HAS_TPM1 select DRIVERS_UART_8250IO select SUPERIO_ITE_IT8528E + select IPMI_KCS config VBOOT select VBOOT_VBNV_CMOS diff --git a/src/mainboard/ocp/wedge100s/devicetree.cb b/src/mainboard/ocp/wedge100s/devicetree.cb index 48410bae08..3552a6db1b 100644 --- a/src/mainboard/ocp/wedge100s/devicetree.cb +++ b/src/mainboard/ocp/wedge100s/devicetree.cb @@ -60,6 +60,9 @@ chip soc/intel/fsp_broadwell_de device pnp 6e.18 off end device pnp 6e.19 off end end #superio/ite/it8528e + chip drivers/ipmi + device pnp ca2.0 on end # IPMI KCS + end end # LPC Bridge device pci 1f.2 on end # SATA Controller device pci 1f.3 on end # SMBus Controller diff --git a/src/mainboard/ocp/wedge100s/romstage.c b/src/mainboard/ocp/wedge100s/romstage.c index 7fdc981915..108d7a1c4d 100644 --- a/src/mainboard/ocp/wedge100s/romstage.c +++ b/src/mainboard/ocp/wedge100s/romstage.c @@ -38,6 +38,10 @@ void early_mainboard_romstage_entry(void) pci_write_config32(PCI_DEV(0x0, LPC_DEV, LPC_FUNC), LPC_GEN1_DEC, (0 << 16) | ALIGN_DOWN(SUPERIO_DEV, 4) | 1); + /* Decode IPMI KCS */ + pci_write_config32(PCI_DEV(0x0, LPC_DEV, LPC_FUNC), LPC_GEN2_DEC, + (0 << 16) | ALIGN_DOWN(0xca2, 4) | 1); + if (CONFIG(CONSOLE_SERIAL)) ite_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); From e2d152c118af73500d5c6162c0c1407712458742 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Fri, 21 Jun 2019 07:06:50 +0200 Subject: [PATCH 155/221] arch: Add missing #include ALIGN((a), b) and ALIGN_UP(a, b) needs 'helpers.h' Change-Id: I029c7c5cbb19c7e69997b3d84f929cb61e8e2b23 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33657 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/arch/arm/armv7/mmu.c | 1 + src/arch/arm/cpu.c | 1 + src/arch/arm64/fit_payload.c | 1 + src/arch/x86/acpi.c | 1 + src/arch/x86/acpi_s3.c | 1 + src/arch/x86/gdt.c | 1 + src/arch/x86/include/arch/early_variables.h | 1 + src/arch/x86/pirq_routing.c | 1 + src/arch/x86/smbios.c | 1 + src/arch/x86/tables.c | 1 + 10 files changed, 10 insertions(+) diff --git a/src/arch/arm/armv7/mmu.c b/src/arch/arm/armv7/mmu.c index ce9d3fd9d8..b3133a08b7 100644 --- a/src/arch/arm/armv7/mmu.c +++ b/src/arch/arm/armv7/mmu.c @@ -29,6 +29,7 @@ */ #include +#include #include #include #include diff --git a/src/arch/arm/cpu.c b/src/arch/arm/cpu.c index 93d5675f35..87fc6b17cc 100644 --- a/src/arch/arm/cpu.c +++ b/src/arch/arm/cpu.c @@ -29,6 +29,7 @@ */ #include #include +#include /* Return the CPU struct which is at the high memory address of the stack. */ diff --git a/src/arch/arm64/fit_payload.c b/src/arch/arm64/fit_payload.c index fd1bae171a..46bea23053 100644 --- a/src/arch/arm64/fit_payload.c +++ b/src/arch/arm64/fit_payload.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c index 71fc4e208f..80923e3edd 100644 --- a/src/arch/x86/acpi.c +++ b/src/arch/x86/acpi.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include diff --git a/src/arch/x86/acpi_s3.c b/src/arch/x86/acpi_s3.c index 4c573033da..049fb12e75 100644 --- a/src/arch/x86/acpi_s3.c +++ b/src/arch/x86/acpi_s3.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/src/arch/x86/gdt.c b/src/arch/x86/gdt.c index d3ad01e1df..81756ff568 100644 --- a/src/arch/x86/gdt.c +++ b/src/arch/x86/gdt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/src/arch/x86/include/arch/early_variables.h b/src/arch/x86/include/arch/early_variables.h index b3042c34d2..a69c230596 100644 --- a/src/arch/x86/include/arch/early_variables.h +++ b/src/arch/x86/include/arch/early_variables.h @@ -17,6 +17,7 @@ #define ARCH_EARLY_VARIABLES_H #include +#include #include #if ENV_CACHE_AS_RAM && !CONFIG(NO_CAR_GLOBAL_MIGRATION) diff --git a/src/arch/x86/pirq_routing.c b/src/arch/x86/pirq_routing.c index 70df201c99..15d7411b3f 100644 --- a/src/arch/x86/pirq_routing.c +++ b/src/arch/x86/pirq_routing.c @@ -16,6 +16,7 @@ */ #include #include +#include #include #include diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c index be090217ae..2f5c3a643e 100644 --- a/src/arch/x86/smbios.c +++ b/src/arch/x86/smbios.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/src/arch/x86/tables.c b/src/arch/x86/tables.c index 3cc385b530..0baa58eb2b 100644 --- a/src/arch/x86/tables.c +++ b/src/arch/x86/tables.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include From d26844ce823791acbc95fb3e109d948b9c36995c Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Fri, 21 Jun 2019 07:31:40 +0200 Subject: [PATCH 156/221] cpu: Add missing #include ALIGN and ALIGN_UP needs 'helpers.h' Change-Id: Ib3a9e0d6caff69f4b0adb54364b47cc6ac52a610 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33658 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/cpu/amd/car/post_cache_as_ram.c | 2 ++ src/cpu/intel/car/romstage.c | 1 + src/cpu/intel/haswell/romstage.c | 1 + src/cpu/intel/smm/gen1/smmrelocate.c | 1 + src/cpu/x86/mirror_payload.c | 1 + src/cpu/x86/mtrr/mtrr.c | 1 + src/cpu/x86/smm/smm_module_loader.c | 1 + 7 files changed, 8 insertions(+) diff --git a/src/cpu/amd/car/post_cache_as_ram.c b/src/cpu/amd/car/post_cache_as_ram.c index f49c6765c6..50ed657f42 100644 --- a/src/cpu/amd/car/post_cache_as_ram.c +++ b/src/cpu/amd/car/post_cache_as_ram.c @@ -16,10 +16,12 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ + #include #include #include #include +#include #include #include #include diff --git a/src/cpu/intel/car/romstage.c b/src/cpu/intel/car/romstage.c index a7daff4fb2..89052d6be6 100644 --- a/src/cpu/intel/car/romstage.c +++ b/src/cpu/intel/car/romstage.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c index 0426bb4cea..3cbdf44c1d 100644 --- a/src/cpu/intel/haswell/romstage.c +++ b/src/cpu/intel/haswell/romstage.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/src/cpu/intel/smm/gen1/smmrelocate.c b/src/cpu/intel/smm/gen1/smmrelocate.c index f3192bcd55..d52043f047 100644 --- a/src/cpu/intel/smm/gen1/smmrelocate.c +++ b/src/cpu/intel/smm/gen1/smmrelocate.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/src/cpu/x86/mirror_payload.c b/src/cpu/x86/mirror_payload.c index 6da21646fc..88c5e8183f 100644 --- a/src/cpu/x86/mirror_payload.c +++ b/src/cpu/x86/mirror_payload.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index 60eee319ce..e9efc8b1de 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/src/cpu/x86/smm/smm_module_loader.c b/src/cpu/x86/smm/smm_module_loader.c index 80b2c27c79..b3ffb3d318 100644 --- a/src/cpu/x86/smm/smm_module_loader.c +++ b/src/cpu/x86/smm/smm_module_loader.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #define FXSAVE_SIZE 512 From 78fa372ec9f7e26b8af715a90d44fb537bbd4425 Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Thu, 20 Jun 2019 20:12:40 +0200 Subject: [PATCH 157/221] superio/nuvoton/nct6791d: Add symbol to select COM port Like the NCT6776, the NCT6791D has muxed COMA/GPIO8 functions. Since it requires setting different bits, add a new Kconfig symbol to do it. Change-Id: I62dc18810026f9b1550da19950f66af605600ec8 Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/33640 Tested-by: build bot (Jenkins) Reviewed-by: Maxim Polyakov Reviewed-by: Felix Held --- src/superio/nuvoton/common/early_serial.c | 6 ++++++ src/superio/nuvoton/nct6791d/Kconfig | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/superio/nuvoton/common/early_serial.c b/src/superio/nuvoton/common/early_serial.c index b35ec9d8b9..7f22993cd0 100644 --- a/src/superio/nuvoton/common/early_serial.c +++ b/src/superio/nuvoton/common/early_serial.c @@ -64,9 +64,15 @@ void nuvoton_pnp_exit_conf_state(pnp_devfn_t dev) void nuvoton_enable_serial(pnp_devfn_t dev, u16 iobase) { nuvoton_pnp_enter_conf_state(dev); + if (CONFIG(SUPERIO_NUVOTON_NCT6776_COM_A)) /* Route GPIO8 pin group to COM A */ pnp_write_config(dev, 0x2a, 0x40); + + if (CONFIG(SUPERIO_NUVOTON_NCT6791D_COM_A)) + /* Route GPIO8 pin group to COM A */ + pnp_write_config(dev, 0x2a, 0x00); + pnp_set_logical_device(dev); pnp_set_enable(dev, 0); pnp_set_iobase(dev, PNP_IDX_IO0, iobase); diff --git a/src/superio/nuvoton/nct6791d/Kconfig b/src/superio/nuvoton/nct6791d/Kconfig index 6e39e462aa..55581fbcfe 100644 --- a/src/superio/nuvoton/nct6791d/Kconfig +++ b/src/superio/nuvoton/nct6791d/Kconfig @@ -16,3 +16,8 @@ config SUPERIO_NUVOTON_NCT6791D bool select SUPERIO_NUVOTON_COMMON_PRE_RAM + +config SUPERIO_NUVOTON_NCT6791D_COM_A + bool + depends on SUPERIO_NUVOTON_NCT6791D + default n From 8272405abb9a0c30253f384df90238d6681faea3 Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Thu, 13 Jun 2019 14:01:50 +0200 Subject: [PATCH 158/221] mb/asrock/h110m: Correct Kconfig symbol selection The asrock/h110m has a NCT6791D, but is selecting the NCT6776-specific SUPERIO_NUVOTON_NCT6776_COM_A symbol. Use the NCT6791D symbol instead. Change-Id: I9f3fde161844f919b070f2b6ce7e106411439a9a Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/33439 Tested-by: build bot (Jenkins) Reviewed-by: Maxim Polyakov Reviewed-by: Felix Held --- src/mainboard/asrock/h110m/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/asrock/h110m/Kconfig b/src/mainboard/asrock/h110m/Kconfig index 487c90ed13..eebce57d49 100644 --- a/src/mainboard/asrock/h110m/Kconfig +++ b/src/mainboard/asrock/h110m/Kconfig @@ -13,7 +13,7 @@ config BOARD_SPECIFIC_OPTIONS select SKYLAKE_SOC_PCH_H select GENERIC_SPD_BIN select SUPERIO_NUVOTON_NCT6791D - select SUPERIO_NUVOTON_NCT6776_COM_A + select SUPERIO_NUVOTON_NCT6791D_COM_A select REALTEK_8168_RESET select RT8168_SET_LED_MODE From 09b103a955a7168f416c1b21e27e409d281a3693 Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Thu, 13 Jun 2019 14:08:04 +0200 Subject: [PATCH 159/221] superio/nuvoton/nct6776: Make Kconfig symbol dependent The SUPERIO_NUVOTON_NCT6776_COM_A symbol should only be visible if SUPERIO_NUVOTON_NCT6776 is selected as well. Change-Id: I9c52d596080360bf3fc25265749ced66ec44f5dc Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/33440 Reviewed-by: Felix Held Tested-by: build bot (Jenkins) --- src/superio/nuvoton/nct6776/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/superio/nuvoton/nct6776/Kconfig b/src/superio/nuvoton/nct6776/Kconfig index 90d4d32555..441692bddd 100644 --- a/src/superio/nuvoton/nct6776/Kconfig +++ b/src/superio/nuvoton/nct6776/Kconfig @@ -20,4 +20,5 @@ config SUPERIO_NUVOTON_NCT6776 config SUPERIO_NUVOTON_NCT6776_COM_A bool + depends on SUPERIO_NUVOTON_NCT6776 default n From 6f9fcc64a170ec4348811dcb1cead2b1bcf2e3a0 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Fri, 21 Jun 2019 09:48:48 +0200 Subject: [PATCH 160/221] mainboard/facebook/fbg1701: Configure TC358860 eDP to MIPI controller FBG1701 contains a TC358860 eDP to MIPI Bridge controller which needs to be configured. Add mainboard_configure_edp_bridge() to program the controller. CPLD version is used to determine which table must be programmed. The eDP is an i2c slave which expects the next i2c bus data for block write: followed by data with LSB first. BUG=N/A TEST=Config eDP and verify LCD panels are working on Facebook FBG-1701 Change-Id: I262cb4376b86db94e3bb9522c556b5cc3ff38335 Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33433 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held Reviewed-by: Angel Pons --- src/mainboard/facebook/fbg1701/ramstage.c | 345 ++++++++++++++++++++++ 1 file changed, 345 insertions(+) diff --git a/src/mainboard/facebook/fbg1701/ramstage.c b/src/mainboard/facebook/fbg1701/ramstage.c index 91dfe3b2cf..3903a6474e 100644 --- a/src/mainboard/facebook/fbg1701/ramstage.c +++ b/src/mainboard/facebook/fbg1701/ramstage.c @@ -1,6 +1,7 @@ /* * This file is part of the coreboot project. * + * Copyright (C) 2018-2019 Facebook, Inc * Copyright (C) 2018-2019 Eltan B.V. * * This program is free software; you can redistribute it and/or modify @@ -13,11 +14,355 @@ * GNU General Public License for more details. */ +#include +#include #include +#include #include "mainboard.h" +#include "onboard.h" + +struct edp_data { + u8 payload_length; + u8 address; + /* data: reg[15:8],reg[7:0], data bytes starting with data[7:0] */ + u8 data[6]; +} __packed; + +static const struct edp_data tc348860_table[] = { + /* set eDP bridge to eDP 1920 */ + /* IO */ + { 6, 0x68, { 0x08, 0x00, 0x01, 0x00, 0x00, 0x00 } }, + /* Boot */ + { 6, 0x68, { 0x10, 0x00, 0x78, 0x69, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x04, 0x02, 0x08, 0x02, 0x00 } }, + { 6, 0x68, { 0x10, 0x08, 0x23, 0x00, 0x87, 0x02 } }, + { 6, 0x68, { 0x10, 0x0C, 0x19, 0x04, 0x00, 0x23 } }, + { 6, 0x68, { 0x10, 0x10, 0x06, 0x00, 0x67, 0x00 } }, + { 6, 0x68, { 0x10, 0x14, 0x01, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x18, 0xFF, 0xFF, 0xFF, 0xFF } }, + /* Internal */ + { 3, 0x68, { 0xB0, 0x05, 0x0A, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x06, 0x03, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x07, 0x16, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x08, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x09, 0x21, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x0A, 0x07, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x14, 0x03, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x18, 0xFF, 0xFF, 0xFF, 0xFF } }, + /* eDP */ + { 3, 0x68, { 0x80, 0x03, 0x41, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB4, 0x00, 0x0D, 0x00, 0x00, 0x00 } }, + /* DPRX */ + { 3, 0x68, { 0xB8, 0x8E, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8F, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x9A, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x9B, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x00, 0x0E, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x26, 0x02, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x01, 0x20, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC0, 0xF1, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC1, 0xF1, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC2, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC3, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC4, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC5, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC6, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC7, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x0B, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x33, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x5B, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x10, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x38, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x60, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x15, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x3D, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x65, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x1A, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x42, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x6A, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x1F, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x47, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x6F, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x24, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x4C, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x74, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x29, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x51, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x79, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x2E, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x56, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x7E, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x90, 0x10, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x91, 0x0F, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x92, 0xF6, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x93, 0x10, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x94, 0x0F, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x95, 0xF6, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x96, 0x10, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x97, 0x0F, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x98, 0xF6, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x99, 0x10, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x9A, 0x0F, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x9B, 0xF6, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8A, 0x03, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x96, 0x03, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0xD1, 0x07, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0xB0, 0x07, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8B, 0x04, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8C, 0x45, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8D, 0x05, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x97, 0x04, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x98, 0xE0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x99, 0x2E, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x14, 0x07, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x18, 0xFF, 0xFF, 0xFF, 0xFF } }, + /* Video size */ + { 6, 0x68, { 0x01, 0x48, 0xB0, 0x04, 0x00, 0x00 } }, + { 6, 0x68, { 0x29, 0x20, 0x10, 0x0E, 0x0B, 0x3E } }, + /* eDP */ + { 3, 0x68, { 0xB6, 0x31, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x80, 0x01, 0x14, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x80, 0x02, 0x02, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB6, 0x08, 0x0B, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x00, 0x1E, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x50, 0x10, 0x00, 0x00, 0x9D, 0x00 } }, + { 6, 0x68, { 0x00, 0x8C, 0x40, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x80, 0x02, 0x00, 0x00, 0x00 } }, + /* Link Training */ + { 3, 0x68, { 0x82, 0x02, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x82, 0x03, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x82, 0x04, 0xFF, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x21, 0x58, 0x09, 0x00, 0x28, 0x00 } }, + { 6, 0x68, { 0x21, 0x60, 0x07, 0x00, 0x0F, 0x00 } }, + { 6, 0x68, { 0x21, 0x64, 0x28, 0x23, 0x00, 0x00 } }, + { 6, 0x68, { 0x21, 0x68, 0x0E, 0x00, 0x00, 0x00 } }, + /* DSI */ + { 6, 0x68, { 0x20, 0x7C, 0x81, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x20, 0x50, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x20, 0x1C, 0x01, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x20, 0x60, 0xFF, 0xFF, 0xFF, 0xFF } }, + /* GPIO */ + { 6, 0x68, { 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x84, 0x0F, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x84, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x84, 0x0F, 0x00, 0x00, 0x00 } }, + /* DSI clock */ + { 6, 0x68, { 0x20, 0x50, 0x20, 0x00, 0x00, 0x00 } }, + /* LCD init */ + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x01, 0x00, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x8C, 0x80, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0xC7, 0x50, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0xC5, 0x50, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x85, 0x04, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x86, 0x08, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x83, 0xAA, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x84, 0x11, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x9C, 0x10, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0xA9, 0x4B, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x05, 0x11, 0x00, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x05, 0x29, 0x00, 0x81 } }, + { 6, 0x68, { 0x2A, 0x10, 0x10, 0x00, 0x04, 0x80 } }, + { 6, 0x68, { 0x2A, 0x04, 0x01, 0x00, 0x00, 0x00 } }, + /* Check Video */ + { 6, 0x68, { 0x01, 0x54, 0x01, 0x00, 0x00, 0x00 } }, + /* End of table */ + { 0, 0x00, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, +}; + +static const struct edp_data b101uan08_table[] = { + /* set eDP bridge to eDP 1920 */ + /* IO Voltage Setting */ + { 6, 0x68, { 0x08, 0x00, 0x01, 0x00, 0x00, 0x00 } }, + /* Boot Settings */ + { 6, 0x68, { 0x10, 0x00, 0x78, 0x69, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x04, 0x02, 0x08, 0x02, 0x00 } }, + { 6, 0x68, { 0x10, 0x08, 0x22, 0x00, 0xA0, 0x02 } }, + { 6, 0x68, { 0x10, 0x0C, 0x50, 0x04, 0x00, 0x03 } }, + { 6, 0x68, { 0x10, 0x10, 0x10, 0x0D, 0x06, 0x01 } }, + { 6, 0x68, { 0x10, 0x14, 0x01, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x18, 0xFF, 0xFF, 0xFF, 0xFF } }, + /* Internal PCLK settings for Non Present or REFCLK=26MHz */ + { 3, 0x68, { 0xB0, 0x05, 0x0A, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x06, 0x03, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x07, 0x16, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x08, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x09, 0x21, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB0, 0x0A, 0x07, 0x00, 0x00, 0x00 } }, + /* DSI Clock setting for Non Preset or REFCLK=26MHz */ + { 6, 0x68, { 0x41, 0xB0, 0xC1, 0x22, 0x04, 0x00 } }, + { 6, 0x68, { 0x41, 0xBC, 0x01, 0x0E, 0x00, 0x00 } }, + { 6, 0x68, { 0x41, 0xC0, 0x30, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x14, 0x03, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x18, 0xFF, 0xFF, 0xFF, 0xFF } }, + /* Additional Settng for eDP */ + { 3, 0x68, { 0x80, 0x03, 0x41, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB4, 0x00, 0x0D, 0x00, 0x00, 0x00 } }, + /* DPRX CAD Register Setting */ + { 3, 0x68, { 0xB8, 0x8E, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8F, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x9A, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x9B, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x00, 0x0E, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x26, 0x02, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x01, 0x20, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC0, 0xF1, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC1, 0xF1, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC2, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC3, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC4, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC5, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC6, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0xC7, 0xF0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x0B, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x33, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x5B, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x10, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x38, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x60, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x15, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x3D, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x65, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x1A, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x42, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x6A, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x1F, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x47, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x6F, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x24, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x4C, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x74, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x29, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x51, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x79, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x2E, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x56, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x7E, 0x00, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x90, 0x10, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x91, 0x0F, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x92, 0xF6, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x93, 0x10, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x94, 0x0F, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x95, 0xF6, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x96, 0x10, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x97, 0x0F, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x98, 0xF6, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x99, 0x10, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x9A, 0x0F, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0x9B, 0xF6, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8A, 0x03, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x96, 0x03, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0xD1, 0x07, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xBB, 0xB0, 0x07, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8B, 0x04, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8C, 0x45, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x8D, 0x05, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x97, 0x04, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x98, 0xE0, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x99, 0x2E, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x80, 0x0E, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x14, 0x07, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x10, 0x18, 0xFF, 0xFF, 0xFF, 0xFF } }, + /* Video size Related Settings for Non Present */ + { 6, 0x68, { 0x01, 0x48, 0xB0, 0x04, 0x00, 0x00 } }, + { 6, 0x68, { 0x29, 0x20, 0x10, 0x0E, 0x0B, 0x3E } }, + /* eDP Settings for Link Training*/ + { 3, 0x68, { 0xB6, 0x31, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x80, 0x01, 0x14, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x80, 0x02, 0x02, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB6, 0x08, 0x0B, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0xB8, 0x00, 0x1E, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x50, 0x10, 0x00, 0x00, 0x9D, 0x00 } }, + { 6, 0x68, { 0x00, 0x8C, 0x40, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x80, 0x02, 0x00, 0x00, 0x00 } }, + /* Link Training */ + { 3, 0x68, { 0x82, 0x02, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x82, 0x03, 0xFF, 0x00, 0x00, 0x00 } }, + { 3, 0x68, { 0x82, 0x04, 0xFF, 0x00, 0x00, 0x00 } }, + /* DSI Transition Time Setting for Non Preset */ + { 6, 0x68, { 0x21, 0x54, 0x0D, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x21, 0x58, 0x06, 0x00, 0x2A, 0x00 } }, + { 6, 0x68, { 0x21, 0x5C, 0x07, 0x00, 0x0E, 0x00 } }, + { 6, 0x68, { 0x21, 0x60, 0x07, 0x00, 0x10, 0x00 } }, + { 6, 0x68, { 0x21, 0x64, 0x10, 0x27, 0x00, 0x00 } }, + { 6, 0x68, { 0x21, 0x68, 0x0E, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x21, 0x6C, 0x0A, 0x00, 0x0E, 0x00 } }, + { 6, 0x68, { 0x21, 0x78, 0x0E, 0x00, 0x0D, 0x00 } }, + /* DSI Start */ + { 6, 0x68, { 0x20, 0x7C, 0x81, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x20, 0x50, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x20, 0x1C, 0x01, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x20, 0x60, 0xFF, 0xFF, 0xFF, 0xFF } }, + /* GPIO for LCD control*/ + { 6, 0x68, { 0x08, 0x04, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x84, 0x0F, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x84, 0x00, 0x00, 0x00, 0x00 } }, + { 6, 0x68, { 0x00, 0x84, 0x0F, 0x00, 0x00, 0x00 } }, + /* DSI Hs Clock Mode */ + { 6, 0x68, { 0x20, 0x50, 0x20, 0x00, 0x00, 0x00 } }, + /* LCD Initialization */ + { 6, 0x68, { 0x22, 0xFC, 0x15, 0xBF, 0xA5, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x01, 0x00, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x8F, 0xA5, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x83, 0xAA, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x84, 0x11, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0xA9, 0x48, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x83, 0x00, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x84, 0x00, 0x81 } }, + { 6, 0x68, { 0x22, 0xFC, 0x15, 0x8F, 0x00, 0x81 } }, + { 6, 0x68, { 0x2A, 0x10, 0x10, 0x00, 0x04, 0x80 } }, + { 6, 0x68, { 0x2A, 0x04, 0x01, 0x00, 0x00, 0x00 } }, + /* Check if eDP video is coming */ + { 6, 0x68, { 0x01, 0x54, 0x01, 0x00, 0x00, 0x00 } }, + /* End of table */ + { 0, 0x00, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, +}; + +static void mainboard_configure_edp_bridge(void) +{ + u8 cpld_version; + const struct edp_data *edptable; + unsigned int loops; + int status; + + cpld_version = (inb(CPLD_PCB_VERSION_PORT) & CPLD_PCB_VERSION_MASK) >> + CPLD_PCB_VERSION_BIT; + printk(BIOS_DEBUG, "CPLD version: %x\n", cpld_version); + if (cpld_version < 7) + edptable = tc348860_table; + else + edptable = b101uan08_table; + + /* reset bridge */ + outb(CPLD_CMD_RESET_DSI_BRIDGE_ACTIVE, CPLD_RESET_PORT); + outb(CPLD_CMD_RESET_DSI_BRIDGE_INACTIVE, CPLD_RESET_PORT); + + /* set eDP bridge to eDP 1920 */ + while (edptable->payload_length) { + loops = 5; + do { + status = smbus_i2c_block_write(edptable->address, + edptable->payload_length, + (u8 *)&edptable->data[0]); + } while (--loops && (status < 0)); + + if (loops == 0) { + printk(BIOS_ERR, "Writing eDP bridge failed!\n"); + return; + } + edptable++; + }; +} void mainboard_silicon_init_params(SILICON_INIT_UPD *params) { + /* Configure the eDP bridge to eDP 1920 */ + mainboard_configure_edp_bridge(); + if (CONFIG(FSP1_1_DISPLAY_LOGO)) { size_t logo_len; void *logo = NULL; From b8477797462fdb6dc3b5c5e28e7b34d83621299a Mon Sep 17 00:00:00 2001 From: Felix Held Date: Fri, 21 Jun 2019 19:23:13 +0200 Subject: [PATCH 161/221] nuvoton/early_serial: improve comments on serial pinmux settings Change-Id: I36c0d752df97810bd99d2eec27403545421ce533 Signed-off-by: Felix Held Reviewed-on: https://review.coreboot.org/c/coreboot/+/33665 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes --- src/superio/nuvoton/common/early_serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/superio/nuvoton/common/early_serial.c b/src/superio/nuvoton/common/early_serial.c index 7f22993cd0..eaa3c5af64 100644 --- a/src/superio/nuvoton/common/early_serial.c +++ b/src/superio/nuvoton/common/early_serial.c @@ -66,11 +66,11 @@ void nuvoton_enable_serial(pnp_devfn_t dev, u16 iobase) nuvoton_pnp_enter_conf_state(dev); if (CONFIG(SUPERIO_NUVOTON_NCT6776_COM_A)) - /* Route GPIO8 pin group to COM A */ + /* Route COM A to GPIO8 pin group */ pnp_write_config(dev, 0x2a, 0x40); if (CONFIG(SUPERIO_NUVOTON_NCT6791D_COM_A)) - /* Route GPIO8 pin group to COM A */ + /* Route COM A to GPIO8 pin group */ pnp_write_config(dev, 0x2a, 0x00); pnp_set_logical_device(dev); From 2195f7af23d7a34d546f1e3f00a0d3a34ee3a8c5 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Fri, 21 Jun 2019 07:20:12 +0200 Subject: [PATCH 162/221] drivers: Add missing #include ALIGN and ALIGN_UP needs 'helpers.h Change-Id: Ia18f69b58bae6d841d800dc38745ff27f51cec46 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33659 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/drivers/amd/agesa/mtrr_fixme.c | 1 + src/drivers/intel/fsp1_1/car.c | 1 + src/drivers/intel/fsp1_1/fsp_util.c | 1 + src/drivers/intel/fsp1_1/raminit.c | 1 + src/drivers/smmstore/store.c | 1 + 5 files changed, 5 insertions(+) diff --git a/src/drivers/amd/agesa/mtrr_fixme.c b/src/drivers/amd/agesa/mtrr_fixme.c index 1fbb55318d..fcb353c601 100644 --- a/src/drivers/amd/agesa/mtrr_fixme.c +++ b/src/drivers/amd/agesa/mtrr_fixme.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/src/drivers/intel/fsp1_1/car.c b/src/drivers/intel/fsp1_1/car.c index 67ed099695..bd3f4787a0 100644 --- a/src/drivers/intel/fsp1_1/car.c +++ b/src/drivers/intel/fsp1_1/car.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include diff --git a/src/drivers/intel/fsp1_1/fsp_util.c b/src/drivers/intel/fsp1_1/fsp_util.c index 2702b5a6eb..ab9f28f93f 100644 --- a/src/drivers/intel/fsp1_1/fsp_util.c +++ b/src/drivers/intel/fsp1_1/fsp_util.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include diff --git a/src/drivers/intel/fsp1_1/raminit.c b/src/drivers/intel/fsp1_1/raminit.c index a631fcae60..7c20b258e2 100644 --- a/src/drivers/intel/fsp1_1/raminit.c +++ b/src/drivers/intel/fsp1_1/raminit.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/src/drivers/smmstore/store.c b/src/drivers/smmstore/store.c index 6f2014b155..833407df4e 100644 --- a/src/drivers/smmstore/store.c +++ b/src/drivers/smmstore/store.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include From 361f6fff5fd301e69c1678cf20f107df7465aaf6 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 15 May 2019 22:05:54 +0200 Subject: [PATCH 163/221] src/cpu: Use 'include ' when appropriate Change-Id: I44346594bc106eed73a1268b82f026b69e5f4512 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32821 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/cpu/allwinner/a10/clock.c | 1 - src/cpu/amd/family_10h-family_15h/init_cpus.h | 1 - src/cpu/intel/haswell/finalize.c | 1 - src/cpu/intel/model_2065x/finalize.c | 1 - src/cpu/intel/model_206ax/finalize.c | 1 - src/cpu/ti/am335x/gpio.c | 1 - src/cpu/ti/am335x/uart.c | 1 - src/cpu/x86/mtrr/mtrr.c | 1 - 8 files changed, 8 deletions(-) diff --git a/src/cpu/allwinner/a10/clock.c b/src/cpu/allwinner/a10/clock.c index 76198b76ba..9e4e93dfe1 100644 --- a/src/cpu/allwinner/a10/clock.c +++ b/src/cpu/allwinner/a10/clock.c @@ -22,7 +22,6 @@ #include #include #include -#include static struct a10_ccm *const ccm = (void *)A1X_CCM_BASE; diff --git a/src/cpu/amd/family_10h-family_15h/init_cpus.h b/src/cpu/amd/family_10h-family_15h/init_cpus.h index 5d653d123b..cca00496ea 100644 --- a/src/cpu/amd/family_10h-family_15h/init_cpus.h +++ b/src/cpu/amd/family_10h-family_15h/init_cpus.h @@ -16,7 +16,6 @@ #ifndef INIT_CPUS_H #define INIT_CPUS_H -#include #include #include #include diff --git a/src/cpu/intel/haswell/finalize.c b/src/cpu/intel/haswell/finalize.c index cc2d1a4c36..16e54d746a 100644 --- a/src/cpu/intel/haswell/finalize.c +++ b/src/cpu/intel/haswell/finalize.c @@ -15,7 +15,6 @@ */ #include -#include #include #include #include "haswell.h" diff --git a/src/cpu/intel/model_2065x/finalize.c b/src/cpu/intel/model_2065x/finalize.c index 5b85601182..724e09ca20 100644 --- a/src/cpu/intel/model_2065x/finalize.c +++ b/src/cpu/intel/model_2065x/finalize.c @@ -15,7 +15,6 @@ */ #include -#include #include #include #include diff --git a/src/cpu/intel/model_206ax/finalize.c b/src/cpu/intel/model_206ax/finalize.c index 30b00bbaf1..98ce5552da 100644 --- a/src/cpu/intel/model_206ax/finalize.c +++ b/src/cpu/intel/model_206ax/finalize.c @@ -15,7 +15,6 @@ */ #include -#include #include #include #include diff --git a/src/cpu/ti/am335x/gpio.c b/src/cpu/ti/am335x/gpio.c index 2685839b23..8660f2ca91 100644 --- a/src/cpu/ti/am335x/gpio.c +++ b/src/cpu/ti/am335x/gpio.c @@ -16,7 +16,6 @@ #include #include #include -#include static struct am335x_gpio_regs *gpio_regs_and_bit(unsigned int gpio, uint32_t *bit) diff --git a/src/cpu/ti/am335x/uart.c b/src/cpu/ti/am335x/uart.c index c482a85d74..4e9d012037 100644 --- a/src/cpu/ti/am335x/uart.c +++ b/src/cpu/ti/am335x/uart.c @@ -12,7 +12,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c index e9efc8b1de..98449d5542 100644 --- a/src/cpu/x86/mtrr/mtrr.c +++ b/src/cpu/x86/mtrr/mtrr.c @@ -22,7 +22,6 @@ */ #include -#include #include #include #include From b874ef4925332f16aba1ce85696abfb1da72e0cb Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Wed, 15 May 2019 22:07:39 +0200 Subject: [PATCH 164/221] src/ec: Use 'include ' when appropriate Change-Id: Ifdb2dee08da45d698174583ee5ed44bf5a0243ff Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/32823 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/ec/compal/ene932/ec.c | 1 - src/ec/google/wilco/mailbox.c | 1 - src/ec/kontron/it8516e/ec.c | 1 - src/ec/lenovo/h8/h8.c | 1 - src/ec/lenovo/pmh7/pmh7.c | 1 - src/ec/quanta/ene_kb3940q/ec.c | 1 - src/ec/quanta/it8518/ec.c | 1 - src/ec/roda/it8518/ec.c | 1 - 8 files changed, 8 deletions(-) diff --git a/src/ec/compal/ene932/ec.c b/src/ec/compal/ene932/ec.c index 7d8880c185..cfabd8d12a 100644 --- a/src/ec/compal/ene932/ec.c +++ b/src/ec/compal/ene932/ec.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/src/ec/google/wilco/mailbox.c b/src/ec/google/wilco/mailbox.c index d47290ccaf..3414c4af14 100644 --- a/src/ec/google/wilco/mailbox.c +++ b/src/ec/google/wilco/mailbox.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/src/ec/kontron/it8516e/ec.c b/src/ec/kontron/it8516e/ec.c index 5565382109..c0042fc729 100644 --- a/src/ec/kontron/it8516e/ec.c +++ b/src/ec/kontron/it8516e/ec.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include #include diff --git a/src/ec/lenovo/h8/h8.c b/src/ec/lenovo/h8/h8.c index f707014c31..2b959ceea1 100644 --- a/src/ec/lenovo/h8/h8.c +++ b/src/ec/lenovo/h8/h8.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/src/ec/lenovo/pmh7/pmh7.c b/src/ec/lenovo/pmh7/pmh7.c index ef505cd164..30de6fe949 100644 --- a/src/ec/lenovo/pmh7/pmh7.c +++ b/src/ec/lenovo/pmh7/pmh7.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/src/ec/quanta/ene_kb3940q/ec.c b/src/ec/quanta/ene_kb3940q/ec.c index af2d3782a2..1f8e36c661 100644 --- a/src/ec/quanta/ene_kb3940q/ec.c +++ b/src/ec/quanta/ene_kb3940q/ec.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include "ec.h" diff --git a/src/ec/quanta/it8518/ec.c b/src/ec/quanta/it8518/ec.c index e293f7cb6a..5b9ba9f9bd 100644 --- a/src/ec/quanta/it8518/ec.c +++ b/src/ec/quanta/it8518/ec.c @@ -20,7 +20,6 @@ #include #include #include -#include #include "ec.h" #include "chip.h" diff --git a/src/ec/roda/it8518/ec.c b/src/ec/roda/it8518/ec.c index 4e69d116ab..09ff480a99 100644 --- a/src/ec/roda/it8518/ec.c +++ b/src/ec/roda/it8518/ec.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include "chip.h" From 3280aa7df266c964e1b354b18fcd3134f310b776 Mon Sep 17 00:00:00 2001 From: Xiang Wang Date: Wed, 20 Mar 2019 12:04:43 +0800 Subject: [PATCH 165/221] riscv: Fix MENTRY_FRAME_SIZE to fit different machine lengths Change-Id: Iabe390963bcbeb9ec6016faa8312d101431942da Signed-off-by: Xiang Wang Reviewed-on: https://review.coreboot.org/c/coreboot/+/31976 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Hug --- src/arch/riscv/include/mcall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/riscv/include/mcall.h b/src/arch/riscv/include/mcall.h index 192d2b4564..d7d67ce33b 100644 --- a/src/arch/riscv/include/mcall.h +++ b/src/arch/riscv/include/mcall.h @@ -27,7 +27,7 @@ #endif /* We save 37 registers, currently. */ -#define MENTRY_FRAME_SIZE (HLS_SIZE + 37 * 8) +#define MENTRY_FRAME_SIZE (HLS_SIZE + 37 * __SIZEOF_POINTER__) #ifndef __ASSEMBLER__ From b1e6654d86fff0016651ede345846f4437a2569c Mon Sep 17 00:00:00 2001 From: Xiang Wang Date: Fri, 14 Jun 2019 16:45:54 +0800 Subject: [PATCH 166/221] riscv: use mret to invoke M-mode payload and disable interrupts Fixes a logic error that sets MPIE, but didn't use mret to return to the payload. This left MIE set to an undefined value. Now all modes are handled the same way: - Trap vector base address point to the payload - Disable Interrupt - Return to payload using mret TEST=Run an M-mode payload Change-Id: Iaab595f916949c57104ec00f8b06ea047fe76bba Signed-off-by: Xiang Wang Reviewed-on: https://review.coreboot.org/c/coreboot/+/33462 Reviewed-by: Philipp Hug Reviewed-by: Patrick Rudolph Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/arch/riscv/payload.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/arch/riscv/payload.c b/src/arch/riscv/payload.c index f3ed5a44a6..903e8a6ab6 100644 --- a/src/arch/riscv/payload.c +++ b/src/arch/riscv/payload.c @@ -19,23 +19,38 @@ #include #include #include +#include void run_payload(struct prog *prog, void *fdt, int payload_mode) { void (*doit)(int hart_id, void *fdt) = prog_entry(prog); int hart_id = read_csr(mhartid); uintptr_t status = read_csr(mstatus); - status &= ~MSTATUS_MPIE; - status &= ~MSTATUS_MPP; + status = INSERT_FIELD(status, MSTATUS_MPIE, 0); switch (payload_mode) { case RISCV_PAYLOAD_MODE_U: + status = INSERT_FIELD(status, MSTATUS_MPP, PRV_U); + /* Trap vector base address point to the payload */ + write_csr(utvec, doit); + /* disable U-Mode interrupt */ + write_csr(uie, 0); break; case RISCV_PAYLOAD_MODE_S: - status |= MSTATUS_SPP; + status = INSERT_FIELD(status, MSTATUS_MPP, PRV_S); + /* Trap vector base address point to the payload */ + write_csr(stvec, doit); + /* disable S-Mode interrupt */ + write_csr(sie, 0); + /* disable MMU */ + write_csr(satp, 0); break; case RISCV_PAYLOAD_MODE_M: - doit(hart_id, fdt); - return; + status = INSERT_FIELD(status, MSTATUS_MPP, PRV_M); + /* Trap vector base address point to the payload */ + write_csr(mtvec, doit); + /* disable M-Mode interrupt */ + write_csr(mie, 0); + break; default: die("wrong privilege level for payload"); break; From e56fb89e7c04655ec0fed36484d9e509e08f662f Mon Sep 17 00:00:00 2001 From: Xiang Wang Date: Tue, 19 Feb 2019 15:59:48 +0800 Subject: [PATCH 167/221] riscv: workaround selfboot putting the coreboot table into prog_entry_arg On RISC-V the argument to a payload is always the hartid and a pointer to a FDT. selfboot sets the coreboot tables as an argument, work around this here. Change-Id: If6929897c7f12d8acb079eeebaef512ae506ca8b Signed-off-by: Xiang Wang Reviewed-on: https://review.coreboot.org/c/coreboot/+/31477 Reviewed-by: ron minnich Reviewed-by: Patrick Rudolph Reviewed-by: Philipp Hug Tested-by: build bot (Jenkins) --- src/arch/riscv/boot.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/arch/riscv/boot.c b/src/arch/riscv/boot.c index edf5295d79..8e4bb36af5 100644 --- a/src/arch/riscv/boot.c +++ b/src/arch/riscv/boot.c @@ -19,6 +19,7 @@ #include #include #include +#include /* * A pointer to the Flattened Device Tree passed to coreboot by the boot ROM. @@ -33,6 +34,12 @@ static void do_arch_prog_run(struct prog *prog) int hart_id; void *fdt = prog_entry_arg(prog); + /* + * Workaround selfboot putting the coreboot table into prog_entry_arg + */ + if (prog_cbfs_type(prog) == CBFS_TYPE_SELF) + fdt = HLS()->fdt; + /* * If prog_entry_arg is not set (e.g. by fit_payload), use fdt from HLS * instead. From 42c44c2f8391a3b56acf9215044d2b2787061738 Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Wed, 15 May 2019 20:27:04 +0530 Subject: [PATCH 168/221] Replace ENV_RAMSTAGE with ENV_PAYLOAD_LOADER This patch relying on new rule, ENV_PAYLOAD_LOADER which is set to ENV_RAMSTAGE. This approach will help to add future optimization (rampayload) in coreboot flow if required. Change-Id: Ib54ece7b9e5f281f8a092dc6f38c07406edfa5fa Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/c/coreboot/+/32725 Tested-by: build bot (Jenkins) Reviewed-by: ron minnich --- src/drivers/elog/elog.c | 2 +- src/include/memlayout.h | 8 ++++++-- src/include/rules.h | 2 +- src/include/stddef.h | 2 +- src/lib/imd_cbmem.c | 2 +- src/lib/memrange.c | 2 +- src/lib/prog_loaders.c | 2 +- src/lib/timestamp.c | 11 +++++++---- src/soc/intel/common/block/fast_spi/fast_spi.c | 2 +- src/soc/intel/common/block/i2c/i2c.c | 2 +- src/soc/intel/common/block/lpc/lpc_lib.c | 2 +- 11 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/drivers/elog/elog.c b/src/drivers/elog/elog.c index e41b55bba5..9ac2d3c095 100644 --- a/src/drivers/elog/elog.c +++ b/src/drivers/elog/elog.c @@ -859,7 +859,7 @@ int elog_init(void) " shrink size %d\n", region_device_sz(&es->nv_dev), es->full_threshold, es->shrink_size); - if (ENV_RAMSTAGE) + if (ENV_PAYLOAD_LOADER) elog_add_boot_count(); return 0; } diff --git a/src/include/memlayout.h b/src/include/memlayout.h index 273a80d240..1ed87b61c9 100644 --- a/src/include/memlayout.h +++ b/src/include/memlayout.h @@ -39,9 +39,13 @@ #define ARCH_STAGE_HAS_BSS_SECTION 1 #endif -/* Default is that currently ramstage, smm, and rmodules have a heap. */ +/* + * Default is that currently ENV_PAYLOAD_LOADER enable stage, smm, + * and rmodules have a heap. + */ #ifndef ARCH_STAGE_HAS_HEAP_SECTION -#define ARCH_STAGE_HAS_HEAP_SECTION (ENV_RAMSTAGE || ENV_SMM || ENV_RMODULE) +#define ARCH_STAGE_HAS_HEAP_SECTION (ENV_PAYLOAD_LOADER || ENV_SMM || \ + ENV_RMODULE) #endif #define STR(x) #x diff --git a/src/include/rules.h b/src/include/rules.h index fcb827df90..d8f6e7438b 100644 --- a/src/include/rules.h +++ b/src/include/rules.h @@ -277,7 +277,7 @@ * be built with simple device model. */ -#if (defined(__PRE_RAM__) || ENV_SMM || ENV_POSTCAR) +#if (defined(__PRE_RAM__) || ENV_SMM || !ENV_PAYLOAD_LOADER) #define __SIMPLE_DEVICE__ #endif diff --git a/src/include/stddef.h b/src/include/stddef.h index 993d5f09cc..7cae2e6dc8 100644 --- a/src/include/stddef.h +++ b/src/include/stddef.h @@ -23,7 +23,7 @@ typedef unsigned int wint_t; /* The devicetree data structures are only mutable in ramstage. All other stages have a constant devicetree. */ -#if !ENV_RAMSTAGE +#if !ENV_PAYLOAD_LOADER #define DEVTREE_EARLY 1 #else #define DEVTREE_EARLY 0 diff --git a/src/lib/imd_cbmem.c b/src/lib/imd_cbmem.c index 1a67ad5be1..b1b63f68b3 100644 --- a/src/lib/imd_cbmem.c +++ b/src/lib/imd_cbmem.c @@ -307,7 +307,7 @@ void cbmem_get_region(void **baseptr, size_t *size) imd_region_used(cbmem_get_imd(), baseptr, size); } -#if ENV_RAMSTAGE || (CONFIG(EARLY_CBMEM_LIST) \ +#if ENV_PAYLOAD_LOADER || (CONFIG(EARLY_CBMEM_LIST) \ && (ENV_POSTCAR || ENV_ROMSTAGE)) /* * -fdata-sections doesn't work so well on read only strings. They all diff --git a/src/lib/memrange.c b/src/lib/memrange.c index 96d7524218..79a1b0ee49 100644 --- a/src/lib/memrange.c +++ b/src/lib/memrange.c @@ -47,7 +47,7 @@ static struct range_entry *alloc_range(struct memranges *ranges) range_entry_unlink(&ranges->free_list, r); return r; } - if (ENV_RAMSTAGE) + if (ENV_PAYLOAD_LOADER) return malloc(sizeof(struct range_entry)); return NULL; } diff --git a/src/lib/prog_loaders.c b/src/lib/prog_loaders.c index 81ec2ec3c4..dfabd31910 100644 --- a/src/lib/prog_loaders.c +++ b/src/lib/prog_loaders.c @@ -160,7 +160,7 @@ fail: die_with_post_code(POST_INVALID_ROM, "Ramstage was not loaded!\n"); } -#ifdef __RAMSTAGE__ // gc-sections should take care of this +#if ENV_PAYLOAD_LOADER // gc-sections should take care of this static struct prog global_payload = PROG_INIT(PROG_PAYLOAD, CONFIG_CBFS_PREFIX "/payload"); diff --git a/src/lib/timestamp.c b/src/lib/timestamp.c index 38d0212845..adacf6b1b3 100644 --- a/src/lib/timestamp.c +++ b/src/lib/timestamp.c @@ -116,8 +116,11 @@ static struct timestamp_table *timestamp_alloc_cbmem_table(void) * based x86 platforms. */ static int timestamp_should_run(void) { - /* Only check boot_cpu() in other stages than ramstage on x86. */ - if ((!ENV_RAMSTAGE && CONFIG(ARCH_X86)) && !boot_cpu()) + /* + * Only check boot_cpu() in other stages than + * ENV_PAYLOAD_LOADER on x86. + */ + if ((!ENV_PAYLOAD_LOADER && CONFIG(ARCH_X86)) && !boot_cpu()) return 0; return 1; @@ -302,8 +305,8 @@ static void timestamp_sync_cache_to_cbmem(int is_recovery) if (ts_cbmem_table->base_time == 0) ts_cbmem_table->base_time = ts_cache_table->base_time; - /* Seed the timestamp tick frequency in ramstage. */ - if (ENV_RAMSTAGE) + /* Seed the timestamp tick frequency in ENV_PAYLOAD_LOADER. */ + if (ENV_PAYLOAD_LOADER) ts_cbmem_table->tick_freq_mhz = timestamp_tick_freq_mhz(); /* Cache no longer required. */ diff --git a/src/soc/intel/common/block/fast_spi/fast_spi.c b/src/soc/intel/common/block/fast_spi/fast_spi.c index 58e7db75a1..e40b84493e 100644 --- a/src/soc/intel/common/block/fast_spi/fast_spi.c +++ b/src/soc/intel/common/block/fast_spi/fast_spi.c @@ -249,7 +249,7 @@ void fast_spi_cache_bios_region(void) bios_size = ALIGN_UP(bios_size, alignment); base = 4ULL*GiB - bios_size; - if (ENV_RAMSTAGE) { + if (ENV_PAYLOAD_LOADER) { mtrr_use_temp_range(base, bios_size, type); } else { int mtrr = get_free_var_mtrr(); diff --git a/src/soc/intel/common/block/i2c/i2c.c b/src/soc/intel/common/block/i2c/i2c.c index a99dfea688..d551c51abf 100644 --- a/src/soc/intel/common/block/i2c/i2c.c +++ b/src/soc/intel/common/block/i2c/i2c.c @@ -47,7 +47,7 @@ uintptr_t dw_i2c_get_soc_early_base(unsigned int bus) return EARLY_I2C_BASE(bus); } -#if !ENV_RAMSTAGE +#if !ENV_PAYLOAD_LOADER static int lpss_i2c_early_init_bus(unsigned int bus) { const struct dw_i2c_bus_config *config; diff --git a/src/soc/intel/common/block/lpc/lpc_lib.c b/src/soc/intel/common/block/lpc/lpc_lib.c index c67c43532c..b31c799a6a 100644 --- a/src/soc/intel/common/block/lpc/lpc_lib.c +++ b/src/soc/intel/common/block/lpc/lpc_lib.c @@ -289,7 +289,7 @@ void pch_enable_lpc(void) soc_get_gen_io_dec_range(dev, gen_io_dec); lpc_set_gen_decode_range(gen_io_dec); soc_setup_dmi_pcr_io_dec(gen_io_dec); - if (ENV_RAMSTAGE) + if (ENV_PAYLOAD_LOADER) pch_lpc_interrupt_init(); } From 5ada0023d191eb6af1de6581f1b770b75b5554c4 Mon Sep 17 00:00:00 2001 From: Philipp Deppenwiese Date: Tue, 20 Nov 2018 13:54:49 +0100 Subject: [PATCH 169/221] cbfstool: Add ifittool Add the IntelFirmwareInterfaceTable-tool to modify the FIT. As cbfstool is overloaded with arguments, introduce a new tool to only modify FIT, which brings it's own command line syntax. Provide clean interface to: * Clear FIT * Add entry to CBFS file * Add entry to REGION * Delete entries * Add support for types other than 1 * Add support to dump current table * Add support for top-swap * Sort entries by type Most code is reused from existing cbfstool and functionality of cbfstool is kept. It will be removed once the make system uses only ifittool. Based on "Intel Trusted Execution Technology (Intel TXT) LAB Handout" and https://github.com/slimbootloader/slimbootloader . Change-Id: I0fe8cd70611d58823aca1147d5b830722ed72bd5 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/31493 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese --- util/cbfstool/Makefile | 8 +- util/cbfstool/Makefile.inc | 33 ++ util/cbfstool/fit.c | 729 ++++++++++++++++++++++++++++++------- util/cbfstool/fit.h | 60 ++- util/cbfstool/ifittool.c | 431 ++++++++++++++++++++++ 5 files changed, 1121 insertions(+), 140 deletions(-) create mode 100644 util/cbfstool/ifittool.c diff --git a/util/cbfstool/Makefile b/util/cbfstool/Makefile index d7137e907b..d5321f6959 100644 --- a/util/cbfstool/Makefile +++ b/util/cbfstool/Makefile @@ -12,7 +12,7 @@ OBJCOPY ?= objcopy VBOOT_SOURCE ?= $(top)/3rdparty/vboot .PHONY: all -all: cbfstool fmaptool rmodtool ifwitool cbfs-compression-tool +all: cbfstool ifittool fmaptool rmodtool ifwitool cbfs-compression-tool cbfstool: $(objutil)/cbfstool/cbfstool @@ -22,15 +22,18 @@ rmodtool: $(objutil)/cbfstool/rmodtool ifwitool: $(objutil)/cbfstool/ifwitool +ifittool: $(objutil)/cbfstool/ifittool + cbfs-compression-tool: $(objutil)/cbfstool/cbfs-compression-tool -.PHONY: clean cbfstool fmaptool rmodtool ifwitool cbfs-compression-tool +.PHONY: clean cbfstool ifittool fmaptool rmodtool ifwitool cbfs-compression-tool clean: $(RM) fmd_parser.c fmd_parser.h fmd_scanner.c fmd_scanner.h $(RM) $(objutil)/cbfstool/cbfstool $(cbfsobj) $(RM) $(objutil)/cbfstool/fmaptool $(fmapobj) $(RM) $(objutil)/cbfstool/rmodtool $(rmodobj) $(RM) $(objutil)/cbfstool/ifwitool $(ifwiobj) + $(RM) $(objutil)/cbfstool/ifittool $(ifitobj) $(RM) $(objutil)/cbfstool/cbfs-compression-tool $(cbfscompobj) linux_trampoline.c: linux_trampoline.S @@ -49,6 +52,7 @@ install: all $(INSTALL) fmaptool $(DESTDIR)$(BINDIR) $(INSTALL) rmodtool $(DESTDIR)$(BINDIR) $(INSTALL) ifwitool $(DESTDIR)$(BINDIR) + $(INSTALL) ifittool $(DESTDIR)$(BINDIR) $(INSTALL) cbfs-compression-tool $(DESTDIR)$(BINDIR) ifneq ($(V),1) diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc index 79285207b0..0340c3eecb 100644 --- a/util/cbfstool/Makefile.inc +++ b/util/cbfstool/Makefile.inc @@ -66,6 +66,35 @@ ifwiobj := ifwiobj += ifwitool.o ifwiobj += common.o +ifitobj := +ifitobj += ifittool.o +ifitobj += common.o +ifitobj += fit.o +ifitobj += cbfs_image.o +# Make it link .... +ifitobj += xdr.o +ifitobj += elfheaders.o +ifitobj += partitioned_file.o +ifitobj += cbfs-mkstage.o +ifitobj += cbfs-mkpayload.o +ifitobj += rmodule.o +# COMMONLIB +ifitobj += cbfs.o +ifitobj += mem_pool.o +ifitobj += region.o +# CRYPTOLIB +ifitobj += 2sha_utility.o +ifitobj += 2sha1.o +ifitobj += 2sha256.o +ifitobj += 2sha512.o +# FMAP +ifitobj += fmap.o +ifitobj += kv_pair.o +ifitobj += valstr.o +# compression algorithms +ifitobj += $(compressionobj) + + cbfscompobj := cbfscompobj += $(compressionobj) cbfscompobj += cbfscomptool.o @@ -149,6 +178,10 @@ $(objutil)/cbfstool/ifwitool: $(addprefix $(objutil)/cbfstool/,$(ifwiobj)) printf " HOSTCC $(subst $(objutil)/,,$(@)) (link)\n" $(HOSTCC) $(TOOLLDFLAGS) -o $@ $(addprefix $(objutil)/cbfstool/,$(ifwiobj)) +$(objutil)/cbfstool/ifittool: $(addprefix $(objutil)/cbfstool/,$(ifitobj)) + printf " HOSTCC $(subst $(objutil)/,,$(@)) (link)\n" + $(HOSTCC) $(TOOLLDFLAGS) -o $@ $(addprefix $(objutil)/cbfstool/,$(ifitobj)) + $(objutil)/cbfstool/cbfs-compression-tool: $(addprefix $(objutil)/cbfstool/,$(cbfscompobj)) printf " HOSTCC $(subst $(objutil)/,,$(@)) (link)\n" $(HOSTCC) $(TOOLLDFLAGS) -o $@ $(addprefix $(objutil)/cbfstool/,$(cbfscompobj)) diff --git a/util/cbfstool/fit.c b/util/cbfstool/fit.c index aeb1755032..86dde4d23d 100644 --- a/util/cbfstool/fit.c +++ b/util/cbfstool/fit.c @@ -2,6 +2,8 @@ * Firmware Interface Table support. * * Copyright (C) 2012 Google Inc. + * Copyright (C) 2019 9elements Agency GmbH + * Copyright (C) 2019 Facebook 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 @@ -25,17 +27,42 @@ #define FIT_POINTER_LOCATION 0xffffffc0 #define FIT_TABLE_LOWEST_ADDRESS ((uint32_t)(-(16 << 20))) #define FIT_ENTRY_CHECKSUM_VALID 0x80 -#define FIT_TYPE_HEADER 0x0 -#define FIT_HEADER_VERSION 0x0100 -#define FIT_HEADER_ADDRESS "_FIT_ " -#define FIT_TYPE_MICROCODE 0x1 -#define FIT_MICROCODE_VERSION 0x0100 +#define FIT_HEADER_VERSION 0x0100 +#define FIT_HEADER_ADDRESS "_FIT_ " +#define FIT_MICROCODE_VERSION 0x0100 +#define FIT_TXT_VERSION 0x0100 + +#define FIT_SIZE_ALIGNMENT 16 struct fit_entry { + /** + * Address is the base address of the firmware component + * must be aligned on 16 byte boundary + */ uint64_t address; + /** + * Size is the span of the component in multiple of 16 bytes + * Bits [24:31] are reserved and must be set to 0 + */ uint32_t size_reserved; + /** + * Component's version number in binary coded decimal (BCD) format. + * For the FIT header entry, the value in this field will indicate the + * revision number of the FIT data structure. The upper byte of the + * revision field indicates the major revision and the lower byte + * indicates the minor revision. + */ uint16_t version; + /** + * FIT types 0x00 to 0x7F + * Bit 7 (C_V) indicates whether component has valid checksum. + */ uint8_t type_checksum_valid; + /** + * Component's checksum. The modulo sum of all the bytes in the + * component and the value in this field (Chksum) must add up to zero. + * This field is only valid if the C_V flag is non-zero. + */ uint8_t checksum; } __packed; @@ -67,20 +94,20 @@ static inline void *rom_buffer_pointer(struct buffer *buffer, int offset) return &buffer->data[offset]; } -static inline int fit_entry_size_bytes(struct fit_entry *entry) +static inline size_t fit_entry_size_bytes(const struct fit_entry *entry) { return (entry->size_reserved & 0xffffff) << 4; } static inline void fit_entry_update_size(struct fit_entry *entry, - int size_bytes) + const int size_bytes) { /* Size is multiples of 16 bytes. */ entry->size_reserved = (size_bytes >> 4) & 0xffffff; } static inline void fit_entry_add_size(struct fit_entry *entry, - int size_bytes) + const int size_bytes) { int size = fit_entry_size_bytes(entry); size += size_bytes; @@ -114,8 +141,70 @@ static inline uint32_t offset_to_ptr(fit_offset_converter_t helper, return -helper(region, offset); } +/* + * Return the number of FIT entries. + */ +static inline size_t fit_table_entries(const struct fit_table *fit) +{ + if (!fit) + return 0; + + return (fit_entry_size_bytes(&fit->header) / FIT_SIZE_ALIGNMENT) - 1; +} + +/* + * Return the number of unused entries. + */ +static inline size_t fit_free_space(struct fit_table *fit, + const size_t max_entries) +{ + if (!fit) + return 0; + + return max_entries - fit_table_entries(fit); +} + +/* + * Sort entries by type and fill gaps (entries with type unused). + * To be called after adding or deleting entries. + * + * This one is critical, as mentioned in Chapter 1.2.1 "FIT Ordering Rules" + * "Firmware Interface Table BIOS Specification". + * + * We need to use a stable sorting algortihm, as the order of + * FIT_TYPE_BIOS_STARTUP matter for measurements. + */ +static void sort_fit_table(struct fit_table *fit) +{ + struct fit_entry tmp; + size_t i, j; + int swapped; + + /* Bubble sort entries */ + for (j = 0; j < fit_table_entries(fit) - 1; j++) { + swapped = 0; + for (i = 0; i < fit_table_entries(fit) - j - 1; i++) { + if (fit->entries[i].type_checksum_valid <= + fit->entries[i + 1].type_checksum_valid) + continue; + /* SWAP entries */ + memcpy(&tmp, &fit->entries[i], sizeof(tmp)); + memcpy(&fit->entries[i], &fit->entries[i + 1], + sizeof(fit->entries[i])); + memcpy(&fit->entries[i + 1], &tmp, + sizeof(fit->entries[i + 1])); + swapped = 1; + } + if (!swapped) + break; + } +} + static int fit_table_verified(struct fit_table *table) { + if (!table) + return 0; + /* Check that the address field has the proper signature. */ if (strncmp((const char *)&table->header.address, FIT_HEADER_ADDRESS, sizeof(table->header.address))) @@ -127,35 +216,17 @@ static int fit_table_verified(struct fit_table *table) if (fit_entry_type(&table->header) != FIT_TYPE_HEADER) return 0; - /* Assume that the FIT table only contains the header */ - if (fit_entry_size_bytes(&table->header) != sizeof(struct fit_entry)) + /* Assume that the FIT table contains at least the header */ + if (fit_entry_size_bytes(&table->header) < sizeof(struct fit_entry)) return 0; return 1; } -static struct fit_table *locate_fit_table(fit_offset_converter_t offset_helper, - struct buffer *buffer) -{ - struct fit_table *table; - uint32_t *fit_pointer; - - fit_pointer = rom_buffer_pointer(buffer, - ptr_to_offset(offset_helper, buffer, - FIT_POINTER_LOCATION)); - - /* Ensure pointer is below 4GiB and within 16MiB of 4GiB */ - if (fit_pointer[1] != 0 || fit_pointer[0] < FIT_TABLE_LOWEST_ADDRESS) - return NULL; - - table = rom_buffer_pointer(buffer, - ptr_to_offset(offset_helper, buffer, *fit_pointer)); - if (!fit_table_verified(table)) - return NULL; - else - return table; -} - +/* + * Update the FIT checksum. + * To be called after modifiying the table. + */ static void update_fit_checksum(struct fit_table *fit) { int size_bytes; @@ -163,6 +234,9 @@ static void update_fit_checksum(struct fit_table *fit) uint8_t result; int i; + if (!fit) + return; + fit->header.checksum = 0; size_bytes = fit_entry_size_bytes(&fit->header); result = 0; @@ -172,24 +246,504 @@ static void update_fit_checksum(struct fit_table *fit) fit->header.checksum = -result; } +/* + * Return a pointer to the next free entry. + * Caller must take care if enough space is available. + */ +static struct fit_entry *get_next_free_entry(struct fit_table *fit) +{ + return &fit->entries[fit_table_entries(fit)]; +} + +static void fit_location_from_cbfs_header(uint32_t *current_offset, + uint32_t *file_length, void *ptr) +{ + struct buffer buf; + struct cbfs_file header; + memset(&buf, 0, sizeof(buf)); + + buf.data = ptr; + buf.size = sizeof(header); + + bgets(&buf, header.magic, sizeof(header.magic)); + header.len = xdr_be.get32(&buf); + header.type = xdr_be.get32(&buf); + header.attributes_offset = xdr_be.get32(&buf); + header.offset = xdr_be.get32(&buf); + + *current_offset = header.offset; + *file_length = header.len; +} + +static int +parse_microcode_blob(struct cbfs_image *image, + const char *blob_name, + size_t *mcus_found, + struct microcode_entry *mcus, + const size_t max_fit_entries) +{ + size_t num_mcus; + uint32_t current_offset; + uint32_t file_length; + struct cbfs_file *mcode_file; + + mcode_file = cbfs_get_entry(image, blob_name); + if (!mcode_file) + return 1; + + fit_location_from_cbfs_header(¤t_offset, &file_length, + mcode_file); + current_offset += cbfs_get_entry_addr(image, mcode_file); + + num_mcus = 0; + while (file_length > sizeof(struct microcode_header)) { + const struct microcode_header *mcu_header; + + mcu_header = rom_buffer_pointer(&image->buffer, current_offset); + if (!mcu_header) { + ERROR("Couldn't parse microcode header.\n"); + return 1; + } + + /* Newer microcode updates include a size field, whereas older + * containers set it at 0 and are exactly 2048 bytes long */ + uint32_t total_size = mcu_header->total_size ?: 2048; + + /* Quickly sanity check a prospective microcode update. */ + if (total_size < sizeof(*mcu_header)) + break; + + /* FIXME: Should the checksum be validated? */ + mcus[num_mcus].offset = current_offset; + mcus[num_mcus].size = total_size; + + /* Proceed to next payload. */ + current_offset += mcus[num_mcus].size; + file_length -= mcus[num_mcus].size; + num_mcus++; + /* Reached limit of FIT entries. */ + if (num_mcus == max_fit_entries) + break; + if (file_length < sizeof(struct microcode_header)) + break; + } + + /* Update how many microcode updates we found. */ + *mcus_found = num_mcus; + + return 0; +} + +/* There can be zero or more FIT_TYPE_MICROCODE entries */ static void update_fit_ucode_entry(struct fit_table *fit, - struct fit_entry *entry, uint64_t mcu_addr) + struct fit_entry *entry, + const uint64_t mcu_addr) { entry->address = mcu_addr; /* * While loading MCU, its size is not referred from FIT and - * rather from the MCU header, hence we can assign zero here + * rather from the MCU header, hence we can assign zero here. */ - entry->size_reserved = 0x0000; + entry->size_reserved = 0; entry->type_checksum_valid = FIT_TYPE_MICROCODE; entry->version = FIT_MICROCODE_VERSION; entry->checksum = 0; fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); } +/* + * There can be zero or one FIT_TYPE_BIOS_ACM entry per table. + * In case there's a FIT_TYPE_BIOS_ACM entry, at least one + * FIT_TYPE_BIOS_STARTUP entry must exist. + * + * The caller has to provide valid arguments as those aren't verfied. + */ +static void update_fit_bios_acm_entry(struct fit_table *fit, + struct fit_entry *entry, + const uint64_t acm_addr) +{ + entry->address = acm_addr; + /* + * The Address field points to a BIOS ACM. The Address field points to + * the first byte of the AC module header. When BIOS ACM is loaded in + * Authenticated Code RAM, one MTRR base/limit pair is used to map it. + */ + entry->size_reserved = 0; + entry->type_checksum_valid = FIT_TYPE_BIOS_ACM; + entry->version = FIT_TXT_VERSION; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* + * In case there's a FIT_TYPE_BIOS_ACM entry, at least one + * FIT_TYPE_BIOS_STARTUP entry must exist. + * + * The caller has to provide valid arguments as those aren't verfied. + */ +static void update_fit_bios_startup_entry(struct fit_table *fit, + struct fit_entry *entry, + const uint64_t sm_addr, + const uint32_t sm_size) +{ + entry->address = sm_addr; + assert(sm_size % 16 == 0); + /* + * BIOS Startup code is defined as the code that gets control at the + * reset vector and continues the chain of trust in TCG-compliant + * fashion. In addition, this code may also configure memory and SMRAM. + */ + fit_entry_update_size(entry, sm_size); + entry->type_checksum_valid = FIT_TYPE_BIOS_STARTUP; + entry->version = FIT_TXT_VERSION; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* + * There can be zero or one FIT_TYPE_BIOS_POLICY Record in the FIT. + * If the platform uses the hash comparison method and employs a + * failsafe bootblock, one FIT_TYPE_BIOS_POLICY entry is needed to + * contain the failsafe hash. + * If the platform uses the Signature verification method, one + * FIT_TYPE_BIOS_POLICY entry is needed. In this case, the entry + * contains the OEM key, hash of the BIOS and signature over the hash + * using the OEM key. + * In all other cases, the FIT_TYPE_BIOS_POLICY record is not required. + * + * The caller has to provide valid arguments as those aren't verfied. + */ +static void update_fit_bios_policy_entry(struct fit_table *fit, + struct fit_entry *entry, + const uint64_t lcp_policy_addr, + const uint32_t lcp_policy_size) +{ + entry->address = lcp_policy_addr; + fit_entry_update_size(entry, lcp_policy_size); + entry->type_checksum_valid = FIT_TYPE_BIOS_POLICY; + entry->version = FIT_TXT_VERSION; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* + * There can be zero or one FIT_TYPE_TXT_POLICY entries + * + * The caller has to provide valid arguments as those aren't verfied. + */ +static void update_fit_txt_policy_entry(struct fit_table *fit, + struct fit_entry *entry, + uint64_t txt_policy_addr) +{ + entry->address = txt_policy_addr; + /* + * Points to the flag indicating if TXT is enabled on this platform. + * If not present, TXT is not disabled by FIT. + */ + entry->size_reserved = 0; + entry->type_checksum_valid = FIT_TYPE_TXT_POLICY; + entry->version = 0x1; + entry->checksum = 0; + fit_entry_add_size(&fit->header, sizeof(struct fit_entry)); +} + +/* Special case for ucode CBFS file, as it might contain more than one ucode */ +int fit_add_microcode_file(struct fit_table *fit, + struct cbfs_image *image, + const char *blob_name, + fit_offset_converter_t offset_helper, + const size_t max_fit_entries) +{ + struct microcode_entry *mcus; + + size_t i; + size_t mcus_found; + + mcus = malloc(sizeof(*mcus) * max_fit_entries); + if (!mcus) { + ERROR("Couldn't allocate memory for microcode entries.\n"); + return 1; + } + + if (parse_microcode_blob(image, blob_name, &mcus_found, mcus, + max_fit_entries)) { + ERROR("Couldn't parse microcode blob.\n"); + free(mcus); + return 1; + } + + if (mcus_found > fit_free_space(fit, max_fit_entries)) { + ERROR("Maximum of FIT entries reached.\n"); + free(mcus); + return 1; + } + + for (i = 0; i < mcus_found; i++) { + if (fit_add_entry(fit, + offset_to_ptr(offset_helper, &image->buffer, + mcus[i].offset), + 0, + FIT_TYPE_MICROCODE, + max_fit_entries)) { + + free(mcus); + return 1; + } + } + + free(mcus); + return 0; +} + +/* + * Return a pointer to the active FIT. + */ +struct fit_table *fit_get_table(struct buffer *bootblock, + fit_offset_converter_t offset_fn, + uint32_t topswap_size) +{ + struct fit_table *fit; + uint32_t *fit_pointer; + + fit_pointer = rom_buffer_pointer(bootblock, + ptr_to_offset(offset_fn, bootblock, + FIT_POINTER_LOCATION)); + + /* Ensure pointer is below 4GiB and within 16MiB of 4GiB */ + if (fit_pointer[1] != 0 || fit_pointer[0] < FIT_TABLE_LOWEST_ADDRESS) { + ERROR("FIT not found.\n"); + return NULL; + } + + fit = rom_buffer_pointer(bootblock, + ptr_to_offset(offset_fn, bootblock, *fit_pointer)); + if (!fit_table_verified(fit)) { + ERROR("FIT not found.\n"); + return NULL; + } + + if (topswap_size) { + struct fit_table *fit2 = (struct fit_table *)((uintptr_t)fit - + topswap_size); + if (!fit_table_verified(fit2)) { + ERROR("second FIT is invalid\n"); + return NULL; + } + fit = fit2; + } + + DEBUG("Operating on table (0x%x)\n", *fit_pointer - topswap_size); + + return fit; +} + +/* + * Dump the current FIT in human readable format to stdout. + */ +int fit_dump(struct fit_table *fit) +{ + size_t i; + + if (!fit) + return 1; + + printf("\n"); + printf(" FIT table:\n"); + + if (fit_table_entries(fit) < 1) { + printf(" empty\n\n"); + return 0; + } + + printf(" %-6s %-20s %-16s %-8s\n", "Index", "Type", "Addr", "Size"); + + for (i = 0; i < fit_table_entries(fit); i++) { + const char *name; + + switch (fit->entries[i].type_checksum_valid) { + case FIT_TYPE_MICROCODE: + name = "Microcode"; + break; + case FIT_TYPE_BIOS_ACM: + name = "BIOS ACM"; + break; + case FIT_TYPE_BIOS_STARTUP: + name = "BIOS Startup Module"; + break; + case FIT_TYPE_TPM_POLICY: + name = "TPM Policy"; + break; + case FIT_TYPE_BIOS_POLICY: + name = "BIOS Policy"; + break; + case FIT_TYPE_TXT_POLICY: + name = "TXT Policy"; + break; + case FIT_TYPE_KEY_MANIFEST: + name = "Key Manifest"; + break; + case FIT_TYPE_BOOT_POLICY: + name = "Boot Policy"; + break; + case FIT_TYPE_CSE_SECURE_BOOT: + name = "CSE SecureBoot"; + break; + case FIT_TYPE_TXTSX_POLICY: + name = "TXTSX policy"; + break; + case FIT_TYPE_JMP_DEBUG_POLICY: + name = "JMP debug policy"; + break; + case FIT_TYPE_UNUSED: + name = "unused"; + break; + default: + name = "unknown"; + } + + printf(" %6zd %-20s 0x%08"PRIx64" 0x%08zx\n", i, name, + fit->entries[i].address, + fit_entry_size_bytes(&fit->entries[i])); + } + printf("\n"); + return 0; +} + +/* + * Remove all entries from table. + */ +int fit_clear_table(struct fit_table *fit) +{ + if (!fit) + return 1; + + memset(fit->entries, 0, + sizeof(struct fit_entry) * fit_table_entries(fit)); + + /* Reset entry counter in header */ + fit_entry_update_size(&fit->header, sizeof(fit->header)); + + update_fit_checksum(fit); + + return 0; +} + +/* + * Returns true if the FIT type is know and can be added to the table. + */ +int fit_is_supported_type(const enum fit_type type) +{ + switch (type) { + case FIT_TYPE_MICROCODE: + case FIT_TYPE_BIOS_ACM: + case FIT_TYPE_BIOS_STARTUP: + case FIT_TYPE_BIOS_POLICY: + case FIT_TYPE_TXT_POLICY: + return 1; + case FIT_TYPE_TPM_POLICY: + case FIT_TYPE_KEY_MANIFEST: + case FIT_TYPE_BOOT_POLICY: + default: + return 0; + } +} + +/* + * Adds an known entry to the FIT. + * len is optional for same types and might be zero. + * offset is an absolute address in 32-bit protected mode address space. + */ +int fit_add_entry(struct fit_table *fit, + const uint32_t offset, + const uint32_t len, + const enum fit_type type, + const size_t max_fit_entries) +{ + struct fit_entry *entry; + + if (!fit) { + ERROR("Internal error."); + return 1; + } + + if (fit_free_space(fit, max_fit_entries) < 1) { + ERROR("No space left in FIT."); + return 1; + } + + if (!fit_is_supported_type(type)) { + ERROR("Unsupported FIT type %u\n", type); + return 1; + } + + DEBUG("Adding new entry type %u at offset %zd\n", type, + fit_table_entries(fit)); + + entry = get_next_free_entry(fit); + + switch (type) { + case FIT_TYPE_MICROCODE: + update_fit_ucode_entry(fit, entry, offset); + break; + case FIT_TYPE_BIOS_ACM: + update_fit_bios_acm_entry(fit, entry, offset); + break; + case FIT_TYPE_BIOS_STARTUP: + update_fit_bios_startup_entry(fit, entry, offset, len); + break; + case FIT_TYPE_BIOS_POLICY: + update_fit_bios_policy_entry(fit, entry, offset, len); + break; + case FIT_TYPE_TXT_POLICY: + update_fit_txt_policy_entry(fit, entry, offset); + break; + default: + return 1; + } + + sort_fit_table(fit); + + update_fit_checksum(fit); + + return 0; +} + +/* + * Delete one entry from table. + */ +int fit_delete_entry(struct fit_table *fit, + const size_t idx) +{ + if (!fit) { + ERROR("Internal error."); + return 1; + } + + if (idx >= fit_table_entries(fit)) { + ERROR("Index out of range."); + return 1; + } + + memset(&fit->entries[idx], 0, sizeof(struct fit_entry)); + + fit->entries[idx].type_checksum_valid = FIT_TYPE_UNUSED; + + sort_fit_table(fit); + + /* The unused entry is now the last one */ + fit_entry_add_size(&fit->header, -(int)sizeof(struct fit_entry)); + + update_fit_checksum(fit); + + return 0; +} + +/* Legacy code. TODO: Remove once ifittool is merged. */ + static void add_microcodde_entries(struct fit_table *fit, const struct cbfs_image *image, - int num_mcus, struct microcode_entry *mcus, + ssize_t num_mcus, + struct microcode_entry *mcus, fit_offset_converter_t offset_helper, uint32_t first_mcu_addr) { @@ -214,113 +768,32 @@ static void add_microcodde_entries(struct fit_table *fit, } } -static void cbfs_file_get_header(struct buffer *buf, struct cbfs_file *file) -{ - bgets(buf, &file->magic, sizeof(file->magic)); - file->len = xdr_be.get32(buf); - file->type = xdr_be.get32(buf); - file->attributes_offset = xdr_be.get32(buf); - file->offset = xdr_be.get32(buf); -} - -static int fit_header(void *ptr, uint32_t *current_offset, uint32_t *file_length) -{ - struct buffer buf; - struct cbfs_file header; - buf.data = ptr; - buf.size = sizeof(header); - cbfs_file_get_header(&buf, &header); - *current_offset = header.offset; - *file_length = header.len; - return 0; -} - -static int parse_microcode_blob(struct cbfs_image *image, - struct cbfs_file *mcode_file, - struct microcode_entry *mcus, - int total_entries, int *mcus_found) -{ - int num_mcus; - uint32_t current_offset; - uint32_t file_length; - - fit_header(mcode_file, ¤t_offset, &file_length); - current_offset += (int)((char *)mcode_file - image->buffer.data); - - num_mcus = 0; - while (file_length > sizeof(struct microcode_header)) - { - const struct microcode_header *mcu_header; - - mcu_header = rom_buffer_pointer(&image->buffer, current_offset); - - /* Newer microcode updates include a size field, whereas older - * containers set it at 0 and are exactly 2048 bytes long */ - uint32_t total_size = mcu_header->total_size - ? mcu_header->total_size : 2048; - - /* Quickly sanity check a prospective microcode update. */ - if (total_size < sizeof(*mcu_header)) - break; - - /* FIXME: Should the checksum be validated? */ - mcus[num_mcus].offset = current_offset; - mcus[num_mcus].size = total_size; - - /* Proceed to next payload. */ - current_offset += mcus[num_mcus].size; - file_length -= mcus[num_mcus].size; - num_mcus++; - - /* Reached limit of FIT entries. */ - if (num_mcus == total_entries) - break; - if (file_length < sizeof(struct microcode_header)) - break; - } - - /* Update how many microcode updates we found. */ - *mcus_found = num_mcus; - - return 0; -} - int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, - const char *microcode_blob_name, int empty_entries, + const char *microcode_blob_name, + unsigned int empty_entries, fit_offset_converter_t offset_fn, uint32_t topswap_size, - uint32_t first_mcu_addr) + uint32_t first_mcu_addr) { struct fit_table *fit, *fit2; - struct cbfs_file *mcode_file; struct microcode_entry *mcus; - int mcus_found; + size_t mcus_found; int ret = 0; - // struct rom_image image = { .rom = rom, .size = romsize, }; - - fit = locate_fit_table(offset_fn, bootblock); + fit = fit_get_table(bootblock, offset_fn, 0); if (!fit) { ERROR("FIT not found.\n"); return 1; } - mcode_file = cbfs_get_entry(image, microcode_blob_name); - if (!mcode_file) { - ERROR("File '%s' not found in CBFS.\n", - microcode_blob_name); - return 1; - } - mcus = malloc(sizeof(*mcus) * empty_entries); - if (!mcus) { - ERROR("Couldn't allocate memory for microcode update entries.\n"); + ERROR("Couldn't allocate memory for microcode entries.\n"); return 1; } - if (parse_microcode_blob(image, mcode_file, mcus, empty_entries, - &mcus_found)) { + if (parse_microcode_blob(image, microcode_blob_name, &mcus_found, + mcus, empty_entries)) { ERROR("Couldn't parse microcode blob.\n"); ret = 1; goto out; @@ -333,7 +806,7 @@ int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, /* A second fit is exactly topswap size away from the bottom one */ if (topswap_size) { - fit2 = (struct fit_table *)((uintptr_t)fit - topswap_size); + fit2 = fit_get_table(bootblock, offset_fn, topswap_size); if (!fit_table_verified(fit2)) { ERROR("second FIT is invalid\n"); @@ -343,8 +816,8 @@ int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, /* Check if we have room for first entry */ if (first_mcu_addr) { if (mcus_found >= empty_entries) { - ERROR("No room, blob mcus = %d, total entries = %d\n", - mcus_found, empty_entries); + ERROR("No room, blob mcus = %zd, total entries" + " = %d\n", mcus_found, empty_entries); ret = 1; goto out; } diff --git a/util/cbfstool/fit.h b/util/cbfstool/fit.h index 42b3b4722a..e5872ab599 100644 --- a/util/cbfstool/fit.h +++ b/util/cbfstool/fit.h @@ -2,6 +2,8 @@ * Firmware Interface Table support. * * Copyright (C) 2012 Google Inc. + * Copyright (C) 2019 9elements Agency GmbH + * Copyright (C) 2019 Facebook 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 @@ -19,6 +21,26 @@ #include "cbfs_image.h" #include "common.h" +/** + * Based on "Intel Trusted Execution Technology (Intel TXT) LAB Handout" and + * https://github.com/slimbootloader/slimbootloader/ + */ +enum fit_type { + FIT_TYPE_HEADER = 0, + FIT_TYPE_MICROCODE = 1, + FIT_TYPE_BIOS_ACM = 2, + FIT_TYPE_BIOS_STARTUP = 7, + FIT_TYPE_TPM_POLICY = 8, + FIT_TYPE_BIOS_POLICY = 9, + FIT_TYPE_TXT_POLICY = 0xa, + FIT_TYPE_KEY_MANIFEST = 0xb, + FIT_TYPE_BOOT_POLICY = 0xc, + FIT_TYPE_CSE_SECURE_BOOT = 0x10, + FIT_TYPE_TXTSX_POLICY = 0x2d, + FIT_TYPE_JMP_DEBUG_POLICY = 0x2f, + FIT_TYPE_UNUSED = 127, +}; + /* * Converts between offsets from the start of the specified image region and * "top-aligned" offsets from the top of the entire flash image. Should work in @@ -28,15 +50,33 @@ typedef unsigned (*fit_offset_converter_t)(const struct buffer *region, unsigned offset); -/* - * populate FIT with the MCUs prepsent in the blob provided. - * - * first_mcu_addr is an address (in ROM) that will point to a - * microcode patch. When provided, it will be forced as the first - * MCU entry into the FIT located in the topswap bootblock. - */ +struct fit_table; + +struct fit_table *fit_get_table(struct buffer *bootblock, + fit_offset_converter_t offset_fn, + uint32_t topswap_size); +int fit_dump(struct fit_table *fit); +int fit_clear_table(struct fit_table *fit); +int fit_is_supported_type(const enum fit_type type); +int fit_add_entry(struct fit_table *fit, + const uint32_t offset, + const uint32_t len, + const enum fit_type type, + const size_t max_fit_entries); +int fit_delete_entry(struct fit_table *fit, + const size_t idx); + +int fit_add_microcode_file(struct fit_table *fit, + struct cbfs_image *image, + const char *blob_name, + fit_offset_converter_t offset_helper, + const size_t max_fit_entries); + +/* Legacy code */ int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, - const char *microcode_blob_name, int empty_entries, - fit_offset_converter_t offset_fn, - uint32_t topswap_size, uint32_t first_mcu_addr); + const char *microcode_blob_name, + unsigned int empty_entries, + fit_offset_converter_t offset_fn, uint32_t topswap_size, + uint32_t first_mcu_addr); + #endif diff --git a/util/cbfstool/ifittool.c b/util/cbfstool/ifittool.c new file mode 100644 index 0000000000..a83fd96715 --- /dev/null +++ b/util/cbfstool/ifittool.c @@ -0,0 +1,431 @@ +/* + * cbfstool, CLI utility for creating rmodules + * + * Copyright (C) 2019 9elements Agency GmbH + * Copyright (C) 2019 Facebook 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 +#include +#include +#include +#include + +#include "common.h" +#include "cbfs_image.h" +#include "partitioned_file.h" +#include "fit.h" + +/* Global variables */ +partitioned_file_t *image_file; + +static const char *optstring = "H:j:f:r:d:t:n:s:caDvh?"; +static struct option long_options[] = { + {"file", required_argument, 0, 'f' }, + {"region", required_argument, 0, 'r' }, + {"add-cbfs-entry", no_argument, 0, 'a' }, + {"add-region", no_argument, 0, 'A' }, + {"del-entry", required_argument, 0, 'd' }, + {"clear-table", no_argument, 0, 'c' }, + {"fit-type", required_argument, 0, 't' }, + {"cbfs-filename", required_argument, 0, 'n' }, + {"max-table-size", required_argument, 0, 's' }, + {"topswap-size", required_argument, 0, 'j' }, + {"dump", no_argument, 0, 'D' }, + {"verbose", no_argument, 0, 'v' }, + {"help", no_argument, 0, 'h' }, + {"header-offset", required_argument, 0, 'H' }, + {NULL, 0, 0, 0 } +}; + +static void usage(const char *name) +{ + printf( + "ifittool: utility for modifying Intel Firmware Interface Table\n\n" + "USAGE: %s [-h] [-H] [-v] [-D] [-c] <-f|--file name> <-s|--max-table-size size> <-r|--region fmap region> OPERATION\n" + "\tOPERATION:\n" + "\t\t-a|--add-entry : Add a CBFS file as new entry to FIT\n" + "\t\t-A|--add-region : Add region as new entry to FIT (for microcodes)\n" + "\t\t-d|--del-entry number : Delete existing entry\n" + "\t\t-t|--fit-type : Type of new entry\n" + "\t\t-n|--name : The CBFS filename or region to add to table\n" + "\tOPTIONAL ARGUMENTS:\n" + "\t\t-h|--help : Display this text\n" + "\t\t-H|--header-offset : Do not search for header, use this offset\n" + "\t\t-v|--verbose : Be verbose\n" + "\t\t-D|--dump : Dump FIT table (at end of operation)\n" + "\t\t-c|--clear-table : Remove all existing entries (do not update)\n" + "\t\t-j|--topswap-size : Use second FIT table if non zero\n" + "\tREQUIRED ARGUMENTS:\n" + "\t\t-f|--file name : The file containing the CBFS\n" + "\t\t-s|--max-table-size : The number of possible FIT entries in table\n" + "\t\t-r|--region : The FMAP region to operate on\n" + , name); +} + +static int is_valid_topswap(size_t topswap_size) +{ + switch (topswap_size) { + case (64 * KiB): + case (128 * KiB): + case (256 * KiB): + case (512 * KiB): + case (1 * MiB): + break; + default: + ERROR("Invalid topswap_size %zd\n", topswap_size); + ERROR("topswap can be 64K|128K|256K|512K|1M\n"); + return 0; + } + return 1; +} + +/* + * Converts between offsets from the start of the specified image region and + * "top-aligned" offsets from the top of the entire boot media. See comment + * below for convert_to_from_top_aligned() about forming addresses. + */ +static unsigned int convert_to_from_absolute_top_aligned( + const struct buffer *region, unsigned int offset) +{ + assert(region); + + size_t image_size = partitioned_file_total_size(image_file); + + return image_size - region->offset - offset; +} + +/* + * Converts between offsets from the start of the specified image region and + * "top-aligned" offsets from the top of the image region. Works in either + * direction: pass in one type of offset and receive the other type. + * N.B. A top-aligned offset is always a positive number, and should not be + * confused with a top-aligned *address*, which is its arithmetic inverse. */ +static unsigned int convert_to_from_top_aligned(const struct buffer *region, + unsigned int offset) +{ + assert(region); + + /* Cover the situation where a negative base address is given by the + * user. Callers of this function negate it, so it'll be a positive + * number smaller than the region. + */ + if ((offset > 0) && (offset < region->size)) + return region->size - offset; + + return convert_to_from_absolute_top_aligned(region, offset); +} + +/* + * Get a pointer from an offset. This function assumes the ROM is located + * in the host address space at [4G - romsize -> 4G). It also assume all + * pointers have values within this address range. + */ +static inline uint32_t offset_to_ptr(fit_offset_converter_t helper, + const struct buffer *region, int offset) +{ + return -helper(region, offset); +} + +enum fit_operation { + NO_OP = 0, + ADD_CBFS_OP, + ADD_REGI_OP, + ADD_ADDR_OP, + DEL_OP +}; + +int main(int argc, char *argv[]) +{ + int c; + const char *input_file = NULL; + const char *name = NULL; + const char *region_name = NULL; + enum fit_operation op = NO_OP; + bool dump = false, clear_table = false; + size_t max_table_size = 0; + size_t table_entry = 0; + uint32_t addr = 0; + size_t topswap_size = 0; + enum fit_type fit_type = 0; + uint32_t headeroffset = ~0u; + + verbose = 0; + + if (argc < 4) { + usage(argv[0]); + return 1; + } + + while (1) { + int optindex = 0; + char *suffix = NULL; + + c = getopt_long(argc, argv, optstring, long_options, &optindex); + + if (c == -1) + break; + + switch (c) { + case 'h': + usage(argv[0]); + return 1; + case 'a': + if (op != NO_OP) { + ERROR("specified multiple actions at once\n"); + usage(argv[0]); + return 1; + } + op = ADD_CBFS_OP; + break; + case 'A': + if (op != NO_OP) { + ERROR("specified multiple actions at once\n"); + usage(argv[0]); + return 1; + } + op = ADD_REGI_OP; + break; + case 'x': + if (op != NO_OP) { + ERROR("specified multiple actions at once\n"); + usage(argv[0]); + return 1; + } + op = ADD_ADDR_OP; + addr = atoll(optarg); + break; + case 'c': + clear_table = true; + break; + case 'd': + if (op != NO_OP) { + ERROR("specified multiple actions at once\n"); + usage(argv[0]); + return 1; + } + op = DEL_OP; + table_entry = atoi(optarg); + break; + case 'D': + dump = true; + break; + case 'f': + input_file = optarg; + break; + case 'H': + headeroffset = strtoul(optarg, &suffix, 0); + if (!*optarg || (suffix && *suffix)) { + ERROR("Invalid header offset '%s'.\n", optarg); + return 1; + } + break; + case 'j': + topswap_size = atoi(optarg); + if (!is_valid_topswap(topswap_size)) + return 1; + break; + case 'n': + name = optarg; + break; + case 'r': + region_name = optarg; + break; + case 's': + max_table_size = atoi(optarg); + break; + case 't': + fit_type = atoi(optarg); + break; + case 'v': + verbose++; + break; + default: + break; + } + } + + if (input_file == NULL) { + ERROR("No input file given\n"); + usage(argv[0]); + return 1; + } + + if (op == ADD_CBFS_OP || op == ADD_REGI_OP) { + if (fit_type == 0) { + ERROR("Adding FIT entry, but no type given\n"); + usage(argv[0]); + return 1; + } else if (name == NULL) { + ERROR("Adding FIT entry, but no name set\n"); + usage(argv[0]); + return 1; + } else if (max_table_size == 0) { + ERROR("Maximum table size not given\n"); + usage(argv[0]); + return 1; + } + } + if (op == ADD_ADDR_OP) { + if (fit_type == 0) { + ERROR("Adding FIT entry, but no type given\n"); + usage(argv[0]); + return 1; + } else if (max_table_size == 0) { + ERROR("Maximum table size not given\n"); + usage(argv[0]); + return 1; + } + } + + if (!region_name) { + ERROR("Region not given\n"); + usage(argv[0]); + return 1; + } + + image_file = partitioned_file_reopen(input_file, + op != NO_OP || clear_table); + + struct buffer image_region; + + if (!partitioned_file_read_region(&image_region, image_file, + region_name)) { + partitioned_file_close(image_file); + ERROR("The image will be left unmodified.\n"); + return 1; + } + + struct buffer bootblock; + // The bootblock is part of the CBFS on x86 + buffer_clone(&bootblock, &image_region); + + struct cbfs_image image; + if (cbfs_image_from_buffer(&image, &image_region, headeroffset)) { + partitioned_file_close(image_file); + return 1; + } + + struct fit_table *fit = fit_get_table(&bootblock, + convert_to_from_top_aligned, + topswap_size); + if (!fit) { + partitioned_file_close(image_file); + ERROR("FIT not found.\n"); + return 1; + } + + if (clear_table) { + if (fit_clear_table(fit)) { + partitioned_file_close(image_file); + ERROR("Failed to clear table.\n"); + return 1; + } + } + + switch (op) { + case ADD_REGI_OP: + { + struct buffer region; + addr = 0; + + if (partitioned_file_read_region(®ion, image_file, name)) { + addr = -convert_to_from_top_aligned(®ion, 0); + } else { + partitioned_file_close(image_file); + return 1; + } + + if (fit_add_entry(fit, addr, 0, fit_type, max_table_size)) { + partitioned_file_close(image_file); + ERROR("Adding type %u FIT entry\n", fit_type); + return 1; + } + break; + } + case ADD_CBFS_OP: + { + if (fit_type == FIT_TYPE_MICROCODE) { + if (fit_add_microcode_file(fit, &image, name, + convert_to_from_top_aligned, + max_table_size)) { + return 1; + } + } else { + uint32_t offset, len; + struct cbfs_file *cbfs_file; + + cbfs_file = cbfs_get_entry(&image, name); + if (!cbfs_file) { + partitioned_file_close(image_file); + ERROR("%s not found in CBFS.\n", name); + return 1; + } + + len = ntohl(cbfs_file->len); + offset = offset_to_ptr(convert_to_from_top_aligned, + &image.buffer, + cbfs_get_entry_addr(&image, cbfs_file) + + ntohl(cbfs_file->offset)); + + + if (fit_add_entry(fit, offset, len, fit_type, + max_table_size)) { + partitioned_file_close(image_file); + ERROR("Adding type %u FIT entry\n", fit_type); + return 1; + } + } + break; + } + case ADD_ADDR_OP: + { + if (fit_add_entry(fit, addr, 0, fit_type, max_table_size)) { + partitioned_file_close(image_file); + ERROR("Adding type %u FIT entry\n", fit_type); + return 1; + } + } + break; + case DEL_OP: + { + if (fit_delete_entry(fit, table_entry)) { + partitioned_file_close(image_file); + ERROR("Deleting FIT entry %zu failed\n", table_entry); + return 1; + } + break; + } + case NO_OP: + default: + break; + } + + if (op != NO_OP || clear_table) { + if (!partitioned_file_write_region(image_file, &bootblock)) { + ERROR("Failed to write changes to disk.\n"); + partitioned_file_close(image_file); + return 1; + } + } + + if (dump) { + if (fit_dump(fit)) { + partitioned_file_close(image_file); + return 1; + } + } + + partitioned_file_close(image_file); + + return 0; +} From 5e3b92a92404c6d131682ddfd501bd88341e77a4 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Mon, 18 Feb 2019 13:33:16 +0100 Subject: [PATCH 170/221] Makefile: Use ifittool to update FIT Depend on ifittool and use it to update FIT instead cbfstool FIT code. Move the TOPSWAP / microcode handling out of cbfstool and implement it in the Makefile. The new FIT looks like the old one and has been tested on Broadwell-DE. The TOPSWAP / microcode code path needs test on real hardware. Change-Id: I687469d62557f81e9d88398cfc93182164fdac95 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/31495 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese Reviewed-by: Christian Walter --- Makefile.inc | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index 7ac0a829e2..362243eb6a 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -513,6 +513,7 @@ CBFSTOOL:=$(objutil)/cbfstool/cbfstool FMAPTOOL:=$(objutil)/cbfstool/fmaptool RMODTOOL:=$(objutil)/cbfstool/rmodtool IFWITOOL:=$(objutil)/cbfstool/ifwitool +IFITTOOL:=$(objutil)/cbfstool/ifittool $(obj)/cbfstool: $(CBFSTOOL) cp $< $@ @@ -526,6 +527,9 @@ $(obj)/rmodtool: $(RMODTOOL) $(obj)/ifwitool: $(IFWITOOL) cp $< $@ +$(obj)/ifittool: $(IFITTOOL) + cp $< $@ + _WINCHECK=$(shell uname -o 2> /dev/null) STACK= ifeq ($(_WINCHECK),Msys) @@ -638,7 +642,7 @@ install-git-commit-clangfmt: include util/crossgcc/Makefile.inc .PHONY: tools -tools: $(objutil)/kconfig/conf $(CBFSTOOL) $(objutil)/cbfstool/cbfs-compression-tool $(FMAPTOOL) $(RMODTOOL) $(IFWITOOL) $(objutil)/nvramtool/nvramtool $(ROMCC_BIN) $(objutil)/sconfig/sconfig $(IFDTOOL) $(CBOOTIMAGE) $(AMDFWTOOL) $(FUTILITY) $(BINCFG) +tools: $(objutil)/kconfig/conf $(CBFSTOOL) $(objutil)/cbfstool/cbfs-compression-tool $(FMAPTOOL) $(RMODTOOL) $(IFWITOOL) $(objutil)/nvramtool/nvramtool $(ROMCC_BIN) $(objutil)/sconfig/sconfig $(IFDTOOL) $(CBOOTIMAGE) $(AMDFWTOOL) $(FUTILITY) $(BINCFG) $(IFITTOOL) ########################################################################### # Common recipes for all stages @@ -1008,10 +1012,9 @@ $(obj)/fmap.fmap: $(obj)/fmap.fmd $(FMAPTOOL) ifeq ($(CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK),y) TS_OPTIONS := -j $(CONFIG_INTEL_TOP_SWAP_BOOTBLOCK_SIZE) -FIT_OPTIONS := $(TS_OPTIONS) endif ifneq ($(CONFIG_UPDATE_IMAGE),y) -$(obj)/coreboot.pre: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) $$(cpu_ucode_cbfs_file) $(obj)/fmap.fmap $(obj)/fmap.desc +$(obj)/coreboot.pre: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) $(IFITTOOL) $$(cpu_ucode_cbfs_file) $(obj)/fmap.fmap $(obj)/fmap.desc $(CBFSTOOL) $@.tmp create -M $(obj)/fmap.fmap -r $(shell cat $(obj)/fmap.desc) ifeq ($(CONFIG_ARCH_X86),y) $(CBFSTOOL) $@.tmp add \ @@ -1055,9 +1058,6 @@ $(REFCODE_BLOB): $(RMODTOOL) endif FIT_ENTRY=$(call strip_quotes, $(CONFIG_INTEL_TOP_SWAP_FIT_ENTRY_FMAP_REG)) -ifneq ($(FIT_ENTRY),) -FIT_OPTIONS += -q $(FIT_ENTRY) -endif ifeq ($(CONFIG_HAVE_RAMSTAGE),y) RAMSTAGE=$(objcbfs)/ramstage.elf @@ -1087,15 +1087,38 @@ endif ifeq ($(CONFIG_CPU_INTEL_FIRMWARE_INTERFACE_TABLE),y) ifeq ($(CONFIG_CPU_MICROCODE_CBFS_EXTERNAL_HEADER),y) @printf " UPDATE-FIT\n" - $(CBFSTOOL) $@.tmp update-fit -n cpu_microcode_blob.bin -x $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) \ - $(FIT_OPTIONS) + $(IFITTOOL) -f $@.tmp -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) \ + -r COREBOOT endif - ifeq ($(CONFIG_USE_CPU_MICROCODE_CBFS_BINS),y) @printf " UPDATE-FIT\n" - $(CBFSTOOL) $@.tmp update-fit -n cpu_microcode_blob.bin -x $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) \ - $(FIT_OPTIONS) + $(IFITTOOL) -f $@.tmp -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) \ + -r COREBOOT endif + $(IFITTOOL) -f $@.tmp -D -r COREBOOT + +# Second FIT in TOP_SWAP bootblock +ifeq ($(CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK),y) +# INTEL_TOP_SWAP_FIT_ENTRY_FMAP_REG adds a region as first ucode into the seconds bootblock +ifneq ($(FIT_ENTRY),) + @printf " UPDATE-FIT2\n" + $(IFITTOOL) -f $@.tmp -A -n $(FIT_ENTRY) -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) \ + $(TS_OPTIONS) -r COREBOOT +endif +ifeq ($(CONFIG_CPU_MICROCODE_CBFS_EXTERNAL_HEADER),y) + @printf " UPDATE-FIT2\n" + $(IFITTOOL) -f $@.tmp -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) \ + $(TS_OPTIONS) -r COREBOOT +endif +ifeq ($(CONFIG_USE_CPU_MICROCODE_CBFS_BINS),y) + @printf " UPDATE-FIT2\n" + $(IFITTOOL) -f $@.tmp -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) \ + $(TS_OPTIONS) -r COREBOOT +endif + $(IFITTOOL) -f $@.tmp -D $(TS_OPTIONS) -r COREBOOT + +endif + endif mv $@.tmp $@ @printf " CBFSLAYOUT $(subst $(obj)/,,$(@))\n\n" From 9ab80a33a53ec294d89d9d37deb5d48ada2e1935 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Mon, 18 Feb 2019 14:35:54 +0100 Subject: [PATCH 171/221] cbfstool: Drop update-fit option The ifittool is used instead. Drop old code. Change-Id: I70fec5fef9ffd1ba3049badb398783f31aefb02f Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/31496 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese --- src/soc/intel/Kconfig | 2 +- util/cbfstool/Makefile.inc | 1 - util/cbfstool/cbfstool.c | 69 --------------------------- util/cbfstool/fit.c | 96 -------------------------------------- util/cbfstool/fit.h | 7 --- 5 files changed, 1 insertion(+), 174 deletions(-) diff --git a/src/soc/intel/Kconfig b/src/soc/intel/Kconfig index c447046de6..b8befc0fd2 100644 --- a/src/soc/intel/Kconfig +++ b/src/soc/intel/Kconfig @@ -46,5 +46,5 @@ config INTEL_TOP_SWAP_FIT_ENTRY_FMAP_REG hold a microcode) whose address as the first entry in the topswap FIT. This is useful in creating a asymmetric FIT in top swap bootblock than the one in non-topswap bootblock. This string will be passed - onto cbfstool (-q option). cbfstool will not parse the region for MCU + onto ifittool (-A -n option). ifittool will not parse the region for MCU entries, and only locate the region and insert its address into FIT. diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc index 0340c3eecb..efc3dca6f5 100644 --- a/util/cbfstool/Makefile.inc +++ b/util/cbfstool/Makefile.inc @@ -21,7 +21,6 @@ cbfsobj += cbfs-mkpayload.o cbfsobj += elfheaders.o cbfsobj += rmodule.o cbfsobj += xdr.o -cbfsobj += fit.o cbfsobj += partitioned_file.o # COMMONLIB cbfsobj += cbfs.o diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index e8b1f6f9ee..cf89b473fa 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -28,7 +28,6 @@ #include "cbfs_image.h" #include "cbfs_sections.h" #include "elfparsing.h" -#include "fit.h" #include "partitioned_file.h" #include #include @@ -84,7 +83,6 @@ static struct param { bool autogen_attr; bool machine_parseable; bool unprocessed; - int fit_empty_entries; enum comp_algo compression; int precompression; enum vb2_hash_algorithm hash; @@ -1190,54 +1188,6 @@ static int cbfs_read(void) return buffer_write_file(param.image_region, param.filename); } -static int cbfs_update_fit(void) -{ - if (!param.name) { - ERROR("You need to specify -n/--name.\n"); - return 1; - } - - if (param.fit_empty_entries <= 0) { - ERROR("Invalid number of fit entries " - "(-x/--empty-fits): %d\n", param.fit_empty_entries); - return 1; - } - - struct buffer bootblock; - // The bootblock is part of the CBFS on x86 - buffer_clone(&bootblock, param.image_region); - - struct cbfs_image image; - if (cbfs_image_from_buffer(&image, param.image_region, - param.headeroffset)) - return 1; - - uint32_t addr = 0; - - /* - * Get the address of provided region for first row. - */ - if (param.ucode_region) { - struct buffer ucode; - - if (partitioned_file_read_region(&ucode, - param.image_file, param.ucode_region)) - addr = -convert_to_from_top_aligned(&ucode, 0); - else - return 1; - } - - - if (fit_update_table(&bootblock, &image, param.name, - param.fit_empty_entries, convert_to_from_top_aligned, - param.topswap_size, addr)) - return 1; - - // The region to be written depends on the type of image, so we write it - // here rather than having main() write the CBFS region back as usual. - return !partitioned_file_write_region(param.image_file, &bootblock); -} - static int cbfs_copy(void) { struct cbfs_image src_image; @@ -1320,7 +1270,6 @@ static const struct command commands[] = { {"print", "H:r:vkh?", cbfs_print, true, false}, {"read", "r:f:vh?", cbfs_read, true, false}, {"remove", "H:r:n:vh?", cbfs_remove, true, true}, - {"update-fit", "H:r:n:x:vh?j:q:", cbfs_update_fit, true, true}, {"write", "r:f:i:Fudvh?", cbfs_write, true, true}, {"expand", "r:h?", cbfs_expand, true, true}, {"truncate", "r:h?", cbfs_truncate, true, true}, @@ -1486,15 +1435,6 @@ static void usage(char *name) "Truncate CBFS and print new size on stdout\n" " expand [-r fmap-region] " "Expand CBFS to span entire region\n" - " update-fit [-r image,regions] -n MICROCODE_BLOB_NAME \\\n" - " -x EMTPY_FIT_ENTRIES \\ \n" - " [-j topswap-size [-q ucode-region](Intel CPUs only)] " - "Updates the FIT table with microcode entries.\n" - " " - " ucode-region is a region in the FMAP, its address is \n" - " " - " inserted as the first entry in the topswap FIT. \n" - "\n" "OFFSETs:\n" " Numbers accompanying -b, -H, and -o switches* may be provided\n" " in two possible formats: if their value is greater than\n" @@ -1732,15 +1672,6 @@ int main(int argc, char **argv) case 'w': param.show_immutable = true; break; - case 'x': - param.fit_empty_entries = strtol( - optarg, &suffix, 0); - if (!*optarg || (suffix && *suffix)) { - ERROR("Invalid number of fit entries " - "'%s'.\n", optarg); - return 1; - } - break; case 'j': param.topswap_size = strtol(optarg, NULL, 0); if (!is_valid_topswap()) diff --git a/util/cbfstool/fit.c b/util/cbfstool/fit.c index 86dde4d23d..4cd84f232d 100644 --- a/util/cbfstool/fit.c +++ b/util/cbfstool/fit.c @@ -737,99 +737,3 @@ int fit_delete_entry(struct fit_table *fit, return 0; } - -/* Legacy code. TODO: Remove once ifittool is merged. */ - -static void add_microcodde_entries(struct fit_table *fit, - const struct cbfs_image *image, - ssize_t num_mcus, - struct microcode_entry *mcus, - fit_offset_converter_t offset_helper, - uint32_t first_mcu_addr) -{ - int i = 0; - /* - * Check if an entry has to be forced into the FIT at index 0. - * first_mcu_addr is an address (in ROM) that will point to a - * microcode patch. - */ - if (first_mcu_addr) { - struct fit_entry *entry = &fit->entries[0]; - update_fit_ucode_entry(fit, entry, first_mcu_addr); - i = 1; - } - - struct microcode_entry *mcu = &mcus[0]; - for (; i < num_mcus; i++) { - struct fit_entry *entry = &fit->entries[i]; - update_fit_ucode_entry(fit, entry, offset_to_ptr(offset_helper, - &image->buffer, mcu->offset)); - mcu++; - } -} - -int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, - const char *microcode_blob_name, - unsigned int empty_entries, - fit_offset_converter_t offset_fn, uint32_t topswap_size, - uint32_t first_mcu_addr) -{ - struct fit_table *fit, *fit2; - struct microcode_entry *mcus; - size_t mcus_found; - - int ret = 0; - - fit = fit_get_table(bootblock, offset_fn, 0); - if (!fit) { - ERROR("FIT not found.\n"); - return 1; - } - - mcus = malloc(sizeof(*mcus) * empty_entries); - if (!mcus) { - ERROR("Couldn't allocate memory for microcode entries.\n"); - return 1; - } - - if (parse_microcode_blob(image, microcode_blob_name, &mcus_found, - mcus, empty_entries)) { - ERROR("Couldn't parse microcode blob.\n"); - ret = 1; - goto out; - } - - add_microcodde_entries(fit, image, mcus_found, mcus, offset_fn, 0); - - update_fit_checksum(fit); - - /* A second fit is exactly topswap size away from the bottom one */ - if (topswap_size) { - - fit2 = fit_get_table(bootblock, offset_fn, topswap_size); - - if (!fit_table_verified(fit2)) { - ERROR("second FIT is invalid\n"); - ret = 1; - goto out; - } - /* Check if we have room for first entry */ - if (first_mcu_addr) { - if (mcus_found >= empty_entries) { - ERROR("No room, blob mcus = %zd, total entries" - " = %d\n", mcus_found, empty_entries); - ret = 1; - goto out; - } - /* Add 1 for the first entry */ - mcus_found++; - } - /* Add entries in the second FIT */ - add_microcodde_entries(fit2, image, mcus_found, mcus, - offset_fn, first_mcu_addr); - update_fit_checksum(fit2); - } -out: - free(mcus); - return ret; -} diff --git a/util/cbfstool/fit.h b/util/cbfstool/fit.h index e5872ab599..c647ec506e 100644 --- a/util/cbfstool/fit.h +++ b/util/cbfstool/fit.h @@ -72,11 +72,4 @@ int fit_add_microcode_file(struct fit_table *fit, fit_offset_converter_t offset_helper, const size_t max_fit_entries); -/* Legacy code */ -int fit_update_table(struct buffer *bootblock, struct cbfs_image *image, - const char *microcode_blob_name, - unsigned int empty_entries, - fit_offset_converter_t offset_fn, uint32_t topswap_size, - uint32_t first_mcu_addr); - #endif From 741000d31b9870b529c6911b55981f24976ce7f4 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Sun, 23 Jun 2019 11:39:59 +0200 Subject: [PATCH 172/221] util/cbfstool/flashmap: Correct local includes Change-Id: I78ba7afd2085c7e9c93e892470111bfee154bb04 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33733 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber Reviewed-by: Paul Menzel --- util/cbfstool/flashmap/fmap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/util/cbfstool/flashmap/fmap.c b/util/cbfstool/flashmap/fmap.c index f1d2fb9e0c..06f179f1f9 100644 --- a/util/cbfstool/flashmap/fmap.c +++ b/util/cbfstool/flashmap/fmap.c @@ -48,10 +48,9 @@ #include #include -#include -#include - +#include "fmap.h" #include "kv_pair.h" +#include "valstr.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) From c6b44cd7ce93979b35b57eb95432cf598f46685a Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Sun, 10 Mar 2019 13:21:12 +0100 Subject: [PATCH 173/221] mb/gigabyte/ga-h61ma-d3v: Add new mainboard as variant Tested with SeaBIOS as a payload, booting Arch Linux with a Linux kernel. The new code is based on autoport and the existing GA-H61M-S2PV code. The GA-H61M-S2PV has been boot-tested too, it still boots. Working: - S3 suspend/resume - USB ports and headers (Intel USB2 and EtronTech USB3) - Gigabit Ethernet - Integrated DVI/VGA graphics (libgfxinit) - PCIe x16 graphics - PCIe x1 ports - PS/2 port with a keyboard - SATA controllers (Intel SATA2 and Marvell SATA3) - User-space fan control (fancontrol on Linux) - Native raminit (4+4GB DDR3-1333) - flashrom, using the internal programmer. Tested with coreboot, as well as with the vendor firmware. Backup chip is untested. Untested: - VGA BIOS for integrated graphics init - Audio: Only front/read outputs has been tested. - Non-Linux OSes - ACPI thermal zone and OS-independent fan control Not working: - Default IFD defines the BIOS region as the entire flash chip. Using 'flashrom --ifd -i bios' is asking for a failed flash! Change-Id: I37928de158bb8fbb47fbda5d1ccd4efba7edab26 Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/31832 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig | 21 +- .../gigabyte/ga-h61m-s2pv/Kconfig.name | 3 + .../gigabyte/ga-h61m-s2pv/Makefile.inc | 3 +- .../gigabyte/ga-h61m-s2pv/hda_verb.c | 71 ------ .../gigabyte/ga-h61m-s2pv/romstage.c | 17 +- .../{ => variants/ga-h61m-s2pv}/devicetree.cb | 0 .../{ => variants/ga-h61m-s2pv}/gpio.c | 0 .../variants/ga-h61m-s2pv/hda_verb.c | 42 ++++ .../variants/ga-h61ma-d3v/devicetree.cb | 101 +++++++++ .../ga-h61m-s2pv/variants/ga-h61ma-d3v/gpio.c | 205 ++++++++++++++++++ .../variants/ga-h61ma-d3v/hda_verb.c | 42 ++++ 11 files changed, 425 insertions(+), 80 deletions(-) rename src/mainboard/gigabyte/ga-h61m-s2pv/{ => variants/ga-h61m-s2pv}/devicetree.cb (100%) rename src/mainboard/gigabyte/ga-h61m-s2pv/{ => variants/ga-h61m-s2pv}/gpio.c (100%) create mode 100644 src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61m-s2pv/hda_verb.c create mode 100644 src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/devicetree.cb create mode 100644 src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/gpio.c create mode 100644 src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/hda_verb.c diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig b/src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig index 5e46365bba..62d7f40117 100644 --- a/src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig @@ -13,7 +13,7 @@ ## GNU General Public License for more details. ## -if BOARD_GIGABYTE_GA_H61M_S2PV +if BOARD_GIGABYTE_GA_H61M_S2PV || BOARD_GIGABYTE_GA_H61MA_D3V config BOARD_SPECIFIC_OPTIONS def_bool y @@ -31,21 +31,36 @@ config BOARD_SPECIFIC_OPTIONS select INTEL_GMA_HAVE_VBT select HAVE_OPTION_TABLE select HAVE_CMOS_DEFAULT + select NO_UART_ON_SUPERIO if BOARD_GIGABYTE_GA_H61MA_D3V config MAINBOARD_DIR string default "gigabyte/ga-h61m-s2pv" +config VARIANT_DIR + string + default "ga-h61m-s2pv" if BOARD_GIGABYTE_GA_H61M_S2PV + default "ga-h61ma-d3v" if BOARD_GIGABYTE_GA_H61MA_D3V + config MAINBOARD_PART_NUMBER string - default "GA-H61M-S2PV" + default "GA-H61M-S2PV" if BOARD_GIGABYTE_GA_H61M_S2PV + default "GA-H61MA-D3V" if BOARD_GIGABYTE_GA_H61MA_D3V + +config DEVICETREE + string + default "variants/$(CONFIG_VARIANT_DIR)/devicetree.cb" config MAX_CPUS int default 8 +# Override the default variant behavior, since the data.vbt is the same +config INTEL_GMA_VBT_FILE + default "src/mainboard/$(MAINBOARDDIR)/data.vbt" + config USBDEBUG_HCD_INDEX # Bottom left port seen from rear int default 2 -endif # BOARD_GIGABYTE_GA_H61M_S2PV +endif # BOARD_GIGABYTE_GA_H61M_S2PV || BOARD_GIGABYTE_GA_H61MA_D3V diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig.name b/src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig.name index 04da3f01cf..83b5803d5f 100644 --- a/src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig.name +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/Kconfig.name @@ -1,2 +1,5 @@ config BOARD_GIGABYTE_GA_H61M_S2PV bool "GA-H61M-S2PV" + +config BOARD_GIGABYTE_GA_H61MA_D3V + bool "GA-H61MA-D3V" diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/Makefile.inc b/src/mainboard/gigabyte/ga-h61m-s2pv/Makefile.inc index ea035d3876..fe7cc81bb9 100644 --- a/src/mainboard/gigabyte/ga-h61m-s2pv/Makefile.inc +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/Makefile.inc @@ -1,3 +1,4 @@ -romstage-y += gpio.c +romstage-y += variants/$(VARIANT_DIR)/gpio.c +ramstage-y += variants/$(VARIANT_DIR)/hda_verb.c ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/hda_verb.c b/src/mainboard/gigabyte/ga-h61m-s2pv/hda_verb.c index 15a2b0159c..e69de29bb2 100644 --- a/src/mainboard/gigabyte/ga-h61m-s2pv/hda_verb.c +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/hda_verb.c @@ -1,71 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2018 Angel Pons - * - * 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 - -const u32 cim_verb_data[] = { - 0x10ec0887, /* Codec Vendor / Device ID: Realtek */ - 0x1458a002, /* Subsystem ID */ - - 0x0000000f, /* Number of 4 dword sets */ - /* NID 0x01: Subsystem ID. */ - AZALIA_SUBVENDOR(0x2, 0x1458a002), - - /* NID 0x11. */ - AZALIA_PIN_CFG(0x2, 0x11, 0x411111f0), - - /* NID 0x12. */ - AZALIA_PIN_CFG(0x2, 0x12, 0x411111f0), - - /* NID 0x14. */ - AZALIA_PIN_CFG(0x2, 0x14, 0x01014410), - - /* NID 0x15. */ - AZALIA_PIN_CFG(0x2, 0x15, 0x411111f0), - - /* NID 0x16. */ - AZALIA_PIN_CFG(0x2, 0x16, 0x411111f0), - - /* NID 0x17. */ - AZALIA_PIN_CFG(0x2, 0x17, 0x411111f0), - - /* NID 0x18. */ - AZALIA_PIN_CFG(0x2, 0x18, 0x01a19c50), - - /* NID 0x19. */ - AZALIA_PIN_CFG(0x2, 0x19, 0x02a19c60), - - /* NID 0x1a. */ - AZALIA_PIN_CFG(0x2, 0x1a, 0x0181345f), - - /* NID 0x1b. */ - AZALIA_PIN_CFG(0x2, 0x1b, 0x02214c20), - - /* NID 0x1c. */ - AZALIA_PIN_CFG(0x2, 0x1c, 0x411111f0), - - /* NID 0x1d. */ - AZALIA_PIN_CFG(0x2, 0x1d, 0x4004c601), - - /* NID 0x1e. */ - AZALIA_PIN_CFG(0x2, 0x1e, 0x411111f0), - - /* NID 0x1f. */ - AZALIA_PIN_CFG(0x2, 0x1f, 0x411111f0), -}; - -const u32 pc_beep_verbs[0] = {}; - -AZALIA_ARRAY_SIZES; diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/romstage.c b/src/mainboard/gigabyte/ga-h61m-s2pv/romstage.c index 7154cc9d22..27fbb2ccc7 100644 --- a/src/mainboard/gigabyte/ga-h61m-s2pv/romstage.c +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/romstage.c @@ -25,10 +25,15 @@ void pch_enable_lpc(void) { - pci_write_config16(PCH_LPC_DEV, LPC_EN, KBC_LPC_EN | - CNF1_LPC_EN | CNF2_LPC_EN | COMA_LPC_EN); + if (CONFIG(BOARD_GIGABYTE_GA_H61M_S2PV)) { + pci_write_config16(PCH_LPC_DEV, LPC_EN, KBC_LPC_EN | + CNF1_LPC_EN | CNF2_LPC_EN | COMA_LPC_EN); + pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x10); - pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x10); + } else if (CONFIG(BOARD_GIGABYTE_GA_H61MA_D3V)) { + pci_write_config16(PCH_LPC_DEV, LPC_EN, KBC_LPC_EN | + CNF1_LPC_EN); + } } void mainboard_rcba_config(void) @@ -58,8 +63,10 @@ void mainboard_early_init(int s3resume) void mainboard_config_superio(void) { - /* Enable serial port */ - ite_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); + if (!CONFIG(NO_UART_ON_SUPERIO)) { + /* Enable serial port */ + ite_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); + } /* Disable SIO WDT which kicks in DualBIOS */ ite_reg_write(SUPERIO_GPIO, 0xEF, 0x7E); diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/devicetree.cb b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61m-s2pv/devicetree.cb similarity index 100% rename from src/mainboard/gigabyte/ga-h61m-s2pv/devicetree.cb rename to src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61m-s2pv/devicetree.cb diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/gpio.c b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61m-s2pv/gpio.c similarity index 100% rename from src/mainboard/gigabyte/ga-h61m-s2pv/gpio.c rename to src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61m-s2pv/gpio.c diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61m-s2pv/hda_verb.c b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61m-s2pv/hda_verb.c new file mode 100644 index 0000000000..93c7e11618 --- /dev/null +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61m-s2pv/hda_verb.c @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2018 Angel Pons + * + * 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 + +const u32 cim_verb_data[] = { + 0x10ec0887, /* Realtek ALC887 */ + 0x1458a002, /* Subsystem ID */ + 0x0000000f, /* Number of 4 dword sets */ + AZALIA_SUBVENDOR(0x2, 0x1458a002), + AZALIA_PIN_CFG(0x2, 0x11, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x12, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x14, 0x01014410), + AZALIA_PIN_CFG(0x2, 0x15, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x16, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x17, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x18, 0x01a19c50), + AZALIA_PIN_CFG(0x2, 0x19, 0x02a19c60), + AZALIA_PIN_CFG(0x2, 0x1a, 0x0181345f), + AZALIA_PIN_CFG(0x2, 0x1b, 0x02214c20), + AZALIA_PIN_CFG(0x2, 0x1c, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x1d, 0x4004c601), + AZALIA_PIN_CFG(0x2, 0x1e, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x1f, 0x411111f0), +}; + +const u32 pc_beep_verbs[0] = {}; + +AZALIA_ARRAY_SIZES; diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/devicetree.cb b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/devicetree.cb new file mode 100644 index 0000000000..22d483e12a --- /dev/null +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/devicetree.cb @@ -0,0 +1,101 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 Angel Pons +## +## 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 northbridge/intel/sandybridge + register "gfx.did" = "{ 0x80000100, 0x80000240, 0x80000410 }" + register "gfx.ndid" = "3" + device cpu_cluster 0x0 on + chip cpu/intel/model_206ax + register "c1_acpower" = "1" + register "c1_battery" = "1" + register "c2_acpower" = "3" + register "c2_battery" = "3" + register "c3_acpower" = "5" + register "c3_battery" = "5" + device lapic 0x0 on end + device lapic 0xacac off end + end + end + register "pci_mmio_size" = "2048" + device domain 0x0 on + subsystemid 0x1458 0x5001 inherit + device pci 00.0 on end # Host bridge + device pci 01.0 on end # PCIe Bridge for discrete graphics + device pci 02.0 on end # Internal graphics + chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH + register "c2_latency" = "0x0065" + register "gen1_dec" = "0x003c0a01" + register "pcie_port_coalesce" = "1" + register "sata_interface_speed_support" = "0x3" + register "sata_port_map" = "0x33" + register "spi_lvscc" = "0x2005" + register "spi_uvscc" = "0x2005" + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 1a.0 on end # USB2 EHCI #2 + device pci 1b.0 on end # High Definition Audio Audio controller + device pci 1c.0 on end # PCIe Port #1 + device pci 1c.1 on end # PCIe Port #2 + device pci 1c.2 on end # PCIe Port #3 + device pci 1c.3 on end # PCIe Port #4 + device pci 1c.4 on end # PCIe Port #5 + device pci 1c.5 on end # PCIe Port #6 + device pci 1d.0 on end # USB2 EHCI #1 + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on # LPC bridge + chip superio/ite/it8728f + device pnp 2e.0 off end # Floppy + device pnp 2e.1 off end # COM1 + device pnp 2e.2 off end # COM2 + device pnp 2e.3 off end # Parallel port + device pnp 2e.4 on # Environment Controller + io 0x60 = 0x0a30 + io 0x62 = 0x0a20 + irq 0x70 = 9 + irq 0xf2 = 0x40 + end + device pnp 2e.5 on # Keyboard + io 0x60 = 0x60 + io 0x62 = 0x64 + irq 0x70 = 1 + irq 0xf0 = 0x08 + end + device pnp 2e.6 on # Mouse + irq 0x70 = 12 + end + device pnp 2e.7 on # GPIO + irq 0x25 = 0x40 + irq 0x26 = 0xf7 + irq 0x27 = 0x10 + irq 0x2c = 0x80 + io 0x60 = 0x0000 + io 0x62 = 0x0a00 + io 0x64 = 0x0000 + irq 0x73 = 0x00 + irq 0xcb = 0x00 + irq 0xf0 = 0x10 + irq 0xf1 = 0x40 + irq 0xf6 = 0x1c + end + device pnp 2e.a off end # CIR + end + end + device pci 1f.2 on end # SATA Controller 1 + device pci 1f.3 on end # SMBus + device pci 1f.5 off end # SATA Controller 2 + device pci 1f.6 on end # Thermal + end + end +end diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/gpio.c b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/gpio.c new file mode 100644 index 0000000000..b7173749d1 --- /dev/null +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/gpio.c @@ -0,0 +1,205 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Vladimir Serbinenko + * + * 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 + +static const struct pch_gpio_set1 pch_gpio_set1_mode = { + .gpio0 = GPIO_MODE_GPIO, + .gpio1 = GPIO_MODE_GPIO, + .gpio2 = GPIO_MODE_GPIO, + .gpio3 = GPIO_MODE_GPIO, + .gpio4 = GPIO_MODE_GPIO, + .gpio5 = GPIO_MODE_GPIO, + .gpio6 = GPIO_MODE_GPIO, + .gpio7 = GPIO_MODE_GPIO, + .gpio8 = GPIO_MODE_GPIO, + .gpio9 = GPIO_MODE_NATIVE, + .gpio10 = GPIO_MODE_NATIVE, + .gpio11 = GPIO_MODE_NATIVE, + .gpio12 = GPIO_MODE_GPIO, + .gpio13 = GPIO_MODE_GPIO, + .gpio14 = GPIO_MODE_NATIVE, + .gpio15 = GPIO_MODE_GPIO, + .gpio16 = GPIO_MODE_GPIO, + .gpio17 = GPIO_MODE_GPIO, + .gpio18 = GPIO_MODE_NATIVE, + .gpio19 = GPIO_MODE_GPIO, + .gpio20 = GPIO_MODE_NATIVE, + .gpio21 = GPIO_MODE_GPIO, + .gpio22 = GPIO_MODE_GPIO, + .gpio23 = GPIO_MODE_NATIVE, + .gpio24 = GPIO_MODE_GPIO, + .gpio25 = GPIO_MODE_NATIVE, + .gpio26 = GPIO_MODE_NATIVE, + .gpio27 = GPIO_MODE_GPIO, + .gpio28 = GPIO_MODE_GPIO, + .gpio29 = GPIO_MODE_GPIO, + .gpio30 = GPIO_MODE_NATIVE, + .gpio31 = GPIO_MODE_GPIO, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_direction = { + .gpio0 = GPIO_DIR_INPUT, + .gpio1 = GPIO_DIR_INPUT, + .gpio2 = GPIO_DIR_INPUT, + .gpio3 = GPIO_DIR_INPUT, + .gpio4 = GPIO_DIR_INPUT, + .gpio5 = GPIO_DIR_INPUT, + .gpio6 = GPIO_DIR_INPUT, + .gpio7 = GPIO_DIR_INPUT, + .gpio8 = GPIO_DIR_OUTPUT, + .gpio12 = GPIO_DIR_OUTPUT, + .gpio13 = GPIO_DIR_INPUT, + .gpio15 = GPIO_DIR_OUTPUT, + .gpio16 = GPIO_DIR_INPUT, + .gpio17 = GPIO_DIR_INPUT, + .gpio19 = GPIO_DIR_INPUT, + .gpio21 = GPIO_DIR_INPUT, + .gpio22 = GPIO_DIR_INPUT, + .gpio24 = GPIO_DIR_OUTPUT, + .gpio27 = GPIO_DIR_INPUT, + .gpio28 = GPIO_DIR_OUTPUT, + .gpio29 = GPIO_DIR_INPUT, + .gpio31 = GPIO_DIR_INPUT, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_level = { + .gpio8 = GPIO_LEVEL_HIGH, + .gpio12 = GPIO_LEVEL_HIGH, + .gpio15 = GPIO_LEVEL_LOW, + .gpio24 = GPIO_LEVEL_LOW, + .gpio28 = GPIO_LEVEL_LOW, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_reset = { + .gpio24 = GPIO_RESET_RSMRST, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_invert = { + .gpio13 = GPIO_INVERT, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_blink = { +}; + +static const struct pch_gpio_set2 pch_gpio_set2_mode = { + .gpio32 = GPIO_MODE_GPIO, + .gpio33 = GPIO_MODE_GPIO, + .gpio34 = GPIO_MODE_GPIO, + .gpio35 = GPIO_MODE_GPIO, + .gpio36 = GPIO_MODE_GPIO, + .gpio37 = GPIO_MODE_GPIO, + .gpio38 = GPIO_MODE_GPIO, + .gpio39 = GPIO_MODE_GPIO, + .gpio40 = GPIO_MODE_NATIVE, + .gpio41 = GPIO_MODE_NATIVE, + .gpio42 = GPIO_MODE_NATIVE, + .gpio43 = GPIO_MODE_NATIVE, + .gpio44 = GPIO_MODE_NATIVE, + .gpio45 = GPIO_MODE_NATIVE, + .gpio46 = GPIO_MODE_NATIVE, + .gpio47 = GPIO_MODE_NATIVE, + .gpio48 = GPIO_MODE_GPIO, + .gpio49 = GPIO_MODE_GPIO, + .gpio50 = GPIO_MODE_NATIVE, + .gpio51 = GPIO_MODE_NATIVE, + .gpio52 = GPIO_MODE_NATIVE, + .gpio53 = GPIO_MODE_NATIVE, + .gpio54 = GPIO_MODE_NATIVE, + .gpio55 = GPIO_MODE_NATIVE, + .gpio56 = GPIO_MODE_NATIVE, + .gpio57 = GPIO_MODE_GPIO, + .gpio58 = GPIO_MODE_NATIVE, + .gpio59 = GPIO_MODE_NATIVE, + .gpio60 = GPIO_MODE_NATIVE, + .gpio61 = GPIO_MODE_NATIVE, + .gpio62 = GPIO_MODE_NATIVE, + .gpio63 = GPIO_MODE_NATIVE, +}; + +static const struct pch_gpio_set2 pch_gpio_set2_direction = { + .gpio32 = GPIO_DIR_OUTPUT, + .gpio33 = GPIO_DIR_OUTPUT, + .gpio34 = GPIO_DIR_INPUT, + .gpio35 = GPIO_DIR_OUTPUT, + .gpio36 = GPIO_DIR_INPUT, + .gpio37 = GPIO_DIR_INPUT, + .gpio38 = GPIO_DIR_INPUT, + .gpio39 = GPIO_DIR_INPUT, + .gpio48 = GPIO_DIR_INPUT, + .gpio49 = GPIO_DIR_INPUT, + .gpio57 = GPIO_DIR_INPUT, +}; + +static const struct pch_gpio_set2 pch_gpio_set2_level = { + .gpio32 = GPIO_LEVEL_HIGH, + .gpio33 = GPIO_LEVEL_HIGH, + .gpio35 = GPIO_LEVEL_LOW, +}; + +static const struct pch_gpio_set2 pch_gpio_set2_reset = { +}; + +static const struct pch_gpio_set3 pch_gpio_set3_mode = { + .gpio64 = GPIO_MODE_NATIVE, + .gpio65 = GPIO_MODE_NATIVE, + .gpio66 = GPIO_MODE_NATIVE, + .gpio67 = GPIO_MODE_NATIVE, + .gpio68 = GPIO_MODE_GPIO, + .gpio69 = GPIO_MODE_GPIO, + .gpio70 = GPIO_MODE_NATIVE, + .gpio71 = GPIO_MODE_NATIVE, + .gpio72 = GPIO_MODE_GPIO, + .gpio73 = GPIO_MODE_NATIVE, + .gpio74 = GPIO_MODE_NATIVE, + .gpio75 = GPIO_MODE_NATIVE, +}; + +static const struct pch_gpio_set3 pch_gpio_set3_direction = { + .gpio68 = GPIO_DIR_INPUT, + .gpio69 = GPIO_DIR_INPUT, + .gpio72 = GPIO_DIR_INPUT, +}; + +static const struct pch_gpio_set3 pch_gpio_set3_level = { +}; + +static const struct pch_gpio_set3 pch_gpio_set3_reset = { +}; + +const struct pch_gpio_map mainboard_gpio_map = { + .set1 = { + .mode = &pch_gpio_set1_mode, + .direction = &pch_gpio_set1_direction, + .level = &pch_gpio_set1_level, + .blink = &pch_gpio_set1_blink, + .invert = &pch_gpio_set1_invert, + .reset = &pch_gpio_set1_reset, + }, + .set2 = { + .mode = &pch_gpio_set2_mode, + .direction = &pch_gpio_set2_direction, + .level = &pch_gpio_set2_level, + .reset = &pch_gpio_set2_reset, + }, + .set3 = { + .mode = &pch_gpio_set3_mode, + .direction = &pch_gpio_set3_direction, + .level = &pch_gpio_set3_level, + .reset = &pch_gpio_set3_reset, + }, +}; diff --git a/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/hda_verb.c b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/hda_verb.c new file mode 100644 index 0000000000..e160538d9f --- /dev/null +++ b/src/mainboard/gigabyte/ga-h61m-s2pv/variants/ga-h61ma-d3v/hda_verb.c @@ -0,0 +1,42 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 Angel Pons + * + * 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 + +const u32 cim_verb_data[] = { + 0x10ec0887, /* Realtek ALC887 */ + 0x1458a002, /* Subsystem ID */ + 0x0000000f, /* Number of 4 dword sets */ + AZALIA_SUBVENDOR(0x2, 0x1458a002), + AZALIA_PIN_CFG(0x2, 0x11, 0x411110f0), + AZALIA_PIN_CFG(0x2, 0x12, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x14, 0x01014410), + AZALIA_PIN_CFG(0x2, 0x15, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x16, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x17, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x18, 0x01a19c50), + AZALIA_PIN_CFG(0x2, 0x19, 0x02a19c60), + AZALIA_PIN_CFG(0x2, 0x1a, 0x0181345f), + AZALIA_PIN_CFG(0x2, 0x1b, 0x02214c20), + AZALIA_PIN_CFG(0x2, 0x1c, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x1d, 0x4004c601), + AZALIA_PIN_CFG(0x2, 0x1e, 0x411111f0), + AZALIA_PIN_CFG(0x2, 0x1f, 0x41c46060), +}; + +const u32 pc_beep_verbs[0] = {}; + +AZALIA_ARRAY_SIZES; From fd666ed0b5f187aefcc1319b05f4f036396ba296 Mon Sep 17 00:00:00 2001 From: Piotr Kleinschmidt Date: Tue, 21 May 2019 12:14:36 +0200 Subject: [PATCH 174/221] Documentation: Add PC Engines apu1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Describe how to run coreboot on the PC Engines apu1 mainboard. Change-Id: If79693e893c4afe52bf1c9aa8017ac6f650a96e4 Signed-off-by: Piotr Kleinschmidt Reviewed-on: https://review.coreboot.org/c/coreboot/+/32907 Tested-by: build bot (Jenkins) Reviewed-by: Michał Żygowski Reviewed-by: Paul Menzel Reviewed-by: Kyösti Mälkki --- Documentation/mainboard/index.md | 4 + Documentation/mainboard/pcengines/apu1.md | 97 ++++++++++++++++++ .../mainboard/pcengines/apu1_spi.jpg | Bin 0 -> 25809 bytes Documentation/mainboard/pcengines/apu1c1.jpg | Bin 0 -> 48550 bytes 4 files changed, 101 insertions(+) create mode 100644 Documentation/mainboard/pcengines/apu1.md create mode 100644 Documentation/mainboard/pcengines/apu1_spi.jpg create mode 100644 Documentation/mainboard/pcengines/apu1c1.jpg diff --git a/Documentation/mainboard/index.md b/Documentation/mainboard/index.md index 03af2c338c..205964fb1e 100644 --- a/Documentation/mainboard/index.md +++ b/Documentation/mainboard/index.md @@ -90,6 +90,10 @@ The boards in this section are not real mainboards, but emulators. - [RK9 Flash Header](roda/rk9/flash_header.md) +## PC Engines + +- [APU1](pcengines/apu1.md) + ## SiFive - [SiFive HiFive Unleashed](sifive/hifive-unleashed.md) diff --git a/Documentation/mainboard/pcengines/apu1.md b/Documentation/mainboard/pcengines/apu1.md new file mode 100644 index 0000000000..ccadd63a61 --- /dev/null +++ b/Documentation/mainboard/pcengines/apu1.md @@ -0,0 +1,97 @@ +# PC Engines APU1 + +This page describes how to run coreboot on PC Engines APU1 platform. + +## Technology + +```eval_rst ++------------+--------------------------------------------------------+ +| CPU | AMD G series T40E APU | ++------------+--------------------------------------------------------+ +| CPU core | 1 GHz dual core (Bobcat core) with 64 bit support | +| | 32K data + 32K instruction + 512KB L2 cache per core | ++------------+--------------------------------------------------------+ +| DRAM | 2 or 4 GB DDR3-1066 DRAM | ++------------+--------------------------------------------------------+ +| Boot | From SD card, USB, mSATA, SATA | ++------------+--------------------------------------------------------+ +| Power | 6 to 12W of 12V power | ++------------+--------------------------------------------------------+ +| Firmware | coreboot with support for iPXE and USB boot | ++------------+--------------------------------------------------------+ +``` + +## Flashing coreboot + +```eval_rst ++---------------------+--------------------------+ +| Type | Value | ++=====================+==========================+ +| Socketed flash | no | ++---------------------+--------------------------+ +| Model | MX25L1606E | ++---------------------+--------------------------+ +| Size | 2 MiB | ++---------------------+--------------------------+ +| Package | SOP-8 | ++---------------------+--------------------------+ +| Write protection | jumper on WP# pin | ++---------------------+--------------------------+ +| Dual BIOS feature | no | ++---------------------+--------------------------+ +| Internal flashing | yes | ++---------------------+--------------------------+ +``` + +### Internal programming + +The SPI flash can be accessed using [flashrom]. It is important to execute +command with a `-c ` argument: + + flashrom -p internal -c "MX25L1606E" -w coreboot.rom + +### External programming + +**IMPORTANT**: When programming SPI flash, first you need to enter apu1 in S5 +(Soft-off) power state. S5 state can be forced by shorting power button pin on +J2 header. + +The external access to flash chip is available through standard SOP-8 clip or +SOP-8 header next to the flash chip on the board. Notice that not all boards +have a header soldered down originally. Hence, there could be an empty slot with +8 eyelets, so you can solder down a header on your own. The SPI flash chip and +SPI header are marked in the picture below. Also there is SPI header pin layout +included. Notice, that signatures at the schematic can be ambiguous: +- J12 SPIDI = U35 SO = MISO +- J12 SPIDO = U35 SI = MOSI + +There is no restrictions as to the programmer device. It is only recommended to +flash firmware without supplying power. External programming can be performed, +for example using OrangePi and Armbian. You can exploit linux_spi driver which +provide communication with SPI devices. Example command to program SPI flash +with OrangePi using linux_spi: + + flashrom -w coreboot.rom -p linux_spi:dev=/dev/spidev1.0,spispeed=16000 -c + "MX25L1606E" + + +**apu1 platform with marked in SPI header and SPI flash chip** + +![][apu1c1_flash] + +**SPI header pin layout** + +![][spi_header] + + +### Schematics + +PC Engines APU platform schematics are available for free on PC Engines official +site. Depending on the configuration: +[apu1c](https://www.pcengines.ch/schema/apu1c.pdf) and +[apu1d](https://www.pcengines.ch/schema/apu1d.pdf). + + +[apu1c1_flash]: apu1c1.jpg +[spi_header]: apu1_spi.jpg +[flashrom]: https://flashrom.org/Flashrom diff --git a/Documentation/mainboard/pcengines/apu1_spi.jpg b/Documentation/mainboard/pcengines/apu1_spi.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0746733c98d68dd5fd1ab20b96984da46d7447d9 GIT binary patch literal 25809 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 u~%WaMQ46chkJdAfkdCEyK!gN22Sg^7dx z3>yy@2ak}7h>(DQke-}^go=fMjg^^!iHU65DTRTRS$$h51lwlgIL`Jlirzx zCm=2t3nEq1O{y_@!oX|l68H@J#Y-}BidT$G%q*;Y`~rePP~kUkrDbI0DD7Lt|5O zOKZ=s-oAeLz~Io-^vv(sx%q{~jZMVX_Rj8~z5Ua(bL7S4)xYbT|KLIaK>rQv>G|Kl z{tsM)PqhW}g2+`2#xG{(%)iF(+iRpO)ut=oha%;MuL3lMzNKIWP zv0pIoZM-`D548V6_J0Q~@c#?h{{r^EaV-M4Ae5)g0}%o+;1H@FD}T55`DVu-OY{hI zAm5DNW~+?0(ad%|Sx*(6NUCIB=3`Cva0-qB_}=oyma0x=cz~A9bE=tg9SiX|JvS(6 z5aAe%hE*R5$S=_SD2z})CtZ?!cSr7?=SbbP6DA;`MZ{yMgE19?34s7iT|W63pxGq} zfmM-<-lTt&&2E25b2o*ldG{d+>Ou1@rU2kJQ_n2T4q>(vWN$7q$FGps&CBk^Hm22# zaV+3N#GLY7&Wm48|HF>V@|DG0OzP6;!nGnl809<+2pONSOeL=y04H%i0+*`0a%Qzc zD;Y5cMq8)jjkaRDotTJpqpW>A5&uJTBm`1Zh=hImNu|aev~*JNsxE7$5>SzG@?%w# zaZP}KR)%K;#avk<9BB#H0#w$YX8g+~o-t)5rc0kt=#+YAgP{r~LylRaytVBh!AJgu zL&Zk9L;JZs-i0t3zMK4o0tbV@tD!$u>{6!geR^gOK*a$rWV#Q=9sbleS-utyjK-=D@bhIFu8}&s5Wq?W=IVsVa&2jXDmZ4g#%H&eT z$HT~urnp!Y*w2fB;$QaAZP(?v^y#*l!{8uAqPJ}ctO^0MHCq`neGC@3u*FfOJX3@^ zkJ=h?CfhFNBu6d>x6N5QYUp#-J(4BF2^L9Eh8=hv=ju|6VE5U}!M#5}X02L;f;&K` zBpYrWXeHV1I}yQ?)>*>*bTsR`t7Xro+e-;*Mn#UWS1dHIHJV-NEdg)>YOK#HE3q&r zj`k7g4CWjAdNQynO=L_9rCht@fY}lWxop*e z5~iI)Cd@!ZD?@Ns&VqV5<{v4_92GarK;m`ka7NN*Vxsd98{uE6Snuqiph))|Gwdq+ zt{c}rO7G`b$GnnzGl)I;Kpw5?I~D-_*+3-07xkZDHxQD<0aC^<#M1=r19+Wjw*n5j zi!c!hkyi#%7@uRt(g|Bn!#!{a){fy>$TaFEg05-q3s_hVcNf{+AC#>v6o2P^SbwM8ZePk10n1_$^xpI*-!2gY z@`m4kcM(rw^gNOk+IrB!jrsvz(Ukgu?+-d;*(E=?o=lk7dLRMN!7KMHsFBD%AZ{`0 zmss6J4jL<_V-;#*Y21}oIB&FPK0EKy37@|J!7<_w8;yHg^9;k=#BQ5ssPaxKJWc?p z!_G<=%&A&qUT4&U;>ekW;^T=+qmL~+x$E{kT%Lw}mpX;UXeCJ4v zV*JimISJos$H)27(l7atH2RUEKUeH7p<|?mD=tu`Qi~Ro8q=5U=j2~UPB%rCBL7kL zeD-g&CVuU%>g28>q{2F3@a`&U23v!7QOhWO2Fjmje69m3WiI*ae><2*Li+HAfv8D; zhirwtqc8H8sUF=qdewh3aD6;4D>^bSp=Jh#0tS!3*N|RlbxsDN?mMfS`m6!G?Ma`E|I0%?l8Jb=OY#Wy9I)u449- z#aU{P;b){tkHEA0>pdG|@wn{M!ffh&T;Pno3yd6j1fr;F4{3g1-QmfcN~azBv8w)4 z;Nb4x_@`s&`BwvWHZ=Zl|MUr%%GN|et6r>TJL3@$hQ6AA|NDyn=LT~<(r+mC-;cQr z%)2t`cKb5mwQhA-dIXp0Uzubc#C$T7*!m ztlh_5ZAwR-`qC*~CYhN+hF>Ggm3f$&(+1<{6FgFJwp@=48lQPNqAymA_$v3BbF;hT zQ~48=FwDJWIk%1*9rzs5I^ur_-OH%bTq?OME%-gtc<8~cVP?vk{fpG+ zs}nQP@({e!TnOf0Y~f7~<|#IdwCH9coj-9{MaC0Ulzic~D=JWS{!-PsYc+g!ET)=M zv~+N_C_Vl5t)2ehs|i6!%$`n8T>~!7Jc2rL%U3&Xlaie2XZ-O3IV7oWy9CSvg-z9E z5xLC?91Nsu=d$Sk8NkmIsR=W;KxDhvcFk3qH$1NcYPg`F9ihR8hNSy6H&U|lY~jCZ z-0{t0eylDwDP+3lshGFb6k4_CU^KpG){)_oRVlL4zv|=K5MZv@ z&wkH)QR4KQF^XMetgvpfXST)P@XF4Cydjr1Jty9PgzFh)`UF)ORmLKxP^AcFHTbSt zGi{b|_{V+T!qJ{}hufUsU1ae)&Md*Nl8GEwNnS#tt{Szg1C!aWe!43HB*qDIFoPh0 zA7R9r%{+;{8$Vk~T_1s*nTXPXHvzlx!kHycD?>C8B)D6hjt zg$>Kc>lF_$RWdhstRlwBUZ?C>A}pQTY|S14$=nMYjFE`om9A^eoksv}`?_w`C$W1= zd=?U4ljF@{3`CXK%*vQK^+% z^_Mc*zi7Az3km|{A+En()U2&6Q_i+n=WMaRfr@|lSuZzz?RwrSY36|ftox6W`&IZChb1AlE^AzgFd&Q%C4&`Zweynlw z$j!R-W__{!O#xYFEnDS*1I6HjwKWkJunee4cxOl#U=FlOZ%RA)|eFlFGHmHv}nynkEHFp*f)eUH?{8QlPMgf9XRwuQD%!NsxAP*dRa$;SC9`{j$~tU`D}0|5_9A) z3Qq1fsH*=agq;H}NK%Ei4fmZDFjPnzev((Z>%P?0w}W*zXPI?z9hh8 z76KMbh7b)v7TJT>V8N8KC-Kq%A39BT7BkJviR_gtGJoL7k64}dQTVS4x<=ln7ZiDZ zmG@Tw^ zjIKPFn>u#f@G2LbOJNwu+a`OsP&<7YIxQt{7OtnCPFvj*v?H_2a0w#os>J_Y**W%g zpSX`0_Xxcj!};JyZMB<9p>CiqUv)~xf8!_Bxk0JUOy8WnwSLQVxk?oJjG&C+;4_|n z*_A7PKZThMxZWTQ$4d<^p94pU-#^Y@SpZ+t=C9c?FPq2-SqN9Inad2^Upv~tk+=o%#e%jT93s+8HcT09ZcwE4-MlD`(%b`3!z-}njYuDq@ z2+Rpi7$n`{7q255i!%^}<;IEi2?AZ?l`n60c#Jq`Q7;l2QM4G9g;>+3} zE5z&_OnQ6v(b4nWj7m}E`n}!mKT1T=S%l4vo!za#ZE1+9m~L|}@?#18dPIuqiE1q( zor#?3)+4unrjY9Vm9Gt}q!@aUl!K!Gr3V$9dc6Cmb9t6AN9u!7zGPq;{;z>+RTc5n zG8~&vR@gY9`H?NAg0EM}?rn^8(K}iM3%7gG;wi1kKpa`Dif!;VR(*B%jZmh zSnu83A}zx4@i9D0iIpi)iPr5x)>8VPsHgw0vq7YekEg?uIj=^z<4blGnpV~m2J${QRj15 zpPeOp3?+sPZS-b?{V~xEge2!BC~lvXH)l2EIuF2a7X57%sL1j{!b_(zlHY4GxsA+} zxu^ci4dH&=A@i9`6?H56QXmg^WP&=Yqz8I)^lRo6yH3}G2U6Gf?-sp0Z>W4_>JE=( z6Fy?7FAADPb9st4bh4%wX|60}%-gj5dN=vmkR)rBC6DnnC%+L1OoaGQj9^c{ZfOuL z7#t`jBXl&|;8x&OzJ0&3w!?{k$a<4-u=j7e5WlrNP+w`p*c2QTlZdD)aA_zQCD&1u zhXj&;M|nkV1XgHFo|TSCb1LQj^$Z1ODq$puI>5IR8v)F0)u|f6%)V-`BZbj0 z$&QGjH|A`_2Z~MGAZNsCF~=`DG+c_Q8m_Sly4dTu+8wTzadD(jwcFM=j{JDTj-I&f zehJa@1T|v}hGv@H*{?h-$})`X;TBJz;iC9#xXC=pi%vd!F3Tj8pI?%oV(E;ESPhAr zX`y$^>;>kxxcbjvc!tG2GV@V=4e;A4wKT8kRQLLn zl;e*WOSaVq*&}_0bcY?}!4P&&eYZSh$5dFmxR3?gMV3@$L2A{WI_T3Q;5L&WUyq{B zT>K|$LlDY1Ix1|sqU`W1zMa^pGLDNOX73$?27m${i<^3{KH)%qRU#EIXRo9GjFgso zeuBrO-h*U~TefIJX;C=3bH+)ygao)ufPHdRT3z@fyDI@qHsd3KDb?wdysW$McXuZ; zVkK=Y2XY|VPhLV|r5Y*~Lalraa*!YMAeW5AN|eF@!Mr93cL3cf2y2 zKBKm#fbj+7X@kTFw&mmx2@YgMx3GZ^sWf?D73{R|Hi`e)cFT7W^9oL5Gz>dm{S+RbGb6Ho!8~3g=VE9hgjhN-(EOdMEu<`iaMPLW zJA-fUMn3}FWx`oGqaQ_i3{^?yRt=#^57IajIdE#$sYap#aM+h%1rfP5tGs{T<_yzVuu3KTtg1}1Xh_X zqQ{^gt{k1-SVfDgc^w&;DNXf@o3D1A?u3kyf2+y?Z%xT1)8W${(l6)hoF$(p=?8|O83SUc@7y{u>U<53*JA-p)cmLH z)OHbi*O#RsP?}_+GeEOt?n^Rdwr%zNGJcUIUPfzau<3QkZX{x=@Z%SQ@&g7{a_0QJ zgzAh8@NDa!J18o%d{O)chEObM;szlmbg-JrhZkMmG|jneBE<+}_nsUO*JK>>sGnvE zg;Of%$P?<1N!6}5a*xwoFroO?ne13F10?IT*}_8 zi^}iYft=eXs*aH{UCL+hAz5em_2>&Q8}wjW_|2=Ch>r}KRAGTZ3GqS$V;ER>EGY&V z9_47Z;RZTMCw;Z^{jxci6;ZNscoy6r(+ok*>@OJt;6i)j3R?~pk3bzFaEE;IYD2+a z5-l=L4QVno7XOFREAJ^JdhssqTNfl6v%+~XBg)zHOkt$|O{|`4wx7as{Ou8nM?aad z(>d|n4K~Li^7hXw@8nDeTBGI=uHhzH{D*aIHm=C>u_C3esd8B<4#fEV8SCt(%*VLK zSb4O|(z7_6F9qYH)&3Yh!oCeD3<;1#9wAx;Wt5Eueg?@6&)%rk_vlgTWoGq)^Ow$+ zW5?~9OH}sjyOnH_w{NXUBZ$w=P%gov78W_yjaD3uSom4XLDRIC@N zpDr3DJ1PmI9E6Ms?KEJGUvlivmc^Ku+>LgxI$OTUuP?p!UrBL@Nc3lO`+xCbT_>VAQCawDL-9? zTQQ|>^-e_v)!rX-FV>k+&KuL9GbnkOV}D-)br?*)m#egrn-ghdK?ofz-Puw)Kg70N z9O=4w5s9hnjtXhy7)N(_-b@U8Q{u;QBq0C;N6~LSKfQPE$}%+sX^~9D6%i5gxq-(B z5jrpTatrsw>u>54I&!a8v@j^;cfMLtFX&Qk!%O<)iLP}u8C`?HW9dQnw0<3`V@rE6 zFpr-z>Ksw8>iFq9ZlyCP6MfIz$A`E&fQO`nHnepoZ=H^cfEO>>kG9)|#0_zYv-|7b zkwm)Lj_k}L)JN>d@P_}`4)jkr3FG(YHa5j?s-qc`Q~LuC{4ExF3RA%?8W8PnHYR8{ zu2%_QwX!6 zZh6n?IyRxUP?Lt7@xFUk^GZgD<|1wJgF!4l?--s`NOr;>Wk60IQNc)1lHX0A;z(VB zYvUYAd^7QRDpvB?hI__O0eJId@W&D`7gMN^_cknmJ-mP~yMU8-{5+3rpBI^fk(J5) zZ&H>j%a4K?RDCcX<0>DwW&>GF*nyuQR#Ry4BQ7eGf-%MR^6}Rv3~A4PhURcnr(EO! zU@7^l0yHF@A4r+O40dnpn96(Qe{YSdS_RHzT=pZpvnlA>m%LHmiL}DIroc407h@4P zpYUU~iS_$(e$a=ZB*^af`k?_}A^UqX*=%l>?JWP3`e!ENiK?a?X5I7rplH^R`fk3D zAUaCXBBtG?eoSYbwCb)p!Ytjin*S<+Gw?gG!fZ!Y#8oV6?? z;plCB%u)plPRr4 zReLJKvd6iLDYYdTZg;^$HFvK>jQ&KiN00Sy)HUzcA}=eX9g!_#!e|fmv;7CAva#_l ztQcr#_%Q6mjBJI_^XaPDVvMZRQ5jV}M7EKp9Qj}l#<^;f-d37vEI4}`&7GfIJn2>T zo!^^>3&nX$otjkSQolC;7gj>PxFK!sI_*n+Y@Oq)lqwbR3>}V^Ys?Qr<^PEyu0|E0=H+97 zBgCKXb0BY?*nZpo0Ql=Ih15rE{ksjN=@=wzFxy7=U)WdCFQO&zxkJFN4hab~N5m0i_ zUbgK>^C@uK_(wkm6b^4YuLS!nfzAIu0<&fBe_>a>9HmoS+@vl#?k(_fziQ&(eFRv&Jw#*J7pNeNg8A z1Voq54mkxt&1OEqq8O*yQr+fE?FE>BW3xL*Ec-2#GQJ(8MbK9)+d4XRNd*2@h#e;E za;Vo^iO|;?!VReV#gDCnRqJnoW{z0Rp9W=Wz}R+e0qk$l zBKJ1NGbHj9qa-Hks6koRW4;~5F3s1oePNaG`JF}}i0UcyGzJ)Ug~|&uWq9Y!A}QJ! zi!IF0ATLIQ7$H&j!Ve!xicQ?3we4zvpuo?FhF5Gv1tsc~A0r#r{1n{G?>ibB5iMTu z_Z_A8_t!1h#SvIk8>$B3A{!KMLr6bGQpNjTdOv_?zsFm&SX-}*=qTRmV~$br3UKi@ zyMbe>YzMrOj8Mh*#JF{Le)2F_VkIwhb$iz0oCrT?YrVuZ9Q~4Yohwfd;ZP6_YNkkn zw#A0LKJz*B4xeuSjn)|QDga^$+0}5>Cc1bS-XcYFT>e0n?O1>>pSWx8U@yY|n$J`s zE{ml2wliCy>wDQ}V?W_6k(L)sMt9}VYZ+Tm8o57QGCX9Yl3OpX8%oyae$MLkMieSJ zHW>hKa7p*c{5?8^!yGYG*^I=?IKTEynlKu&X!NAnu)+r{qa-wA6lT+XfCOFI1u7xO zRk~dVS*EGxrKc`r#^>4c$%pvNb2WB=9D6hTCp90O3-pTP1ldT727XYaI=hmB;+V?0>#MLy5gBcc0jL;b%iORW4DBr-H3Q0La(b$9T?b1VuE0w#K@$Nt zI%5XpE}Y*~!3((ws)mKKF$uJoF8)5wnubO;QM^=!_T#54prSn2Yh3~p?@RCebFN9N zBvU6p&W}aYyVE1scmQe(6;e9jFsQH|s9u zIUV`_)-4+OWa*o$F$_|A4epKG_D&yKhA-D0oUD)-Z^^R7%Q}Zsm1{&j6*kNYWb}Pt z20bD2=GER`Q=7FC7+N4=Z8K-{?>S11>Vt`NB5^w<(cJHBTw`LV*?+Fw+f0sc3v8)T zQV}oKX^d?U+HW%`(q!juqd;z9gg44afC*1YRqhsx!G8xeLX%Z_t<3; zdDc(WO!qZAO<6WZbu!|hF-$&4xn~L6OJszAU=p2GwW%+{_Z+q|MZ9bW_ZJVAN@eN-K6zPzDuGz0IZOF z@HUyb=+#kxrhf&N27G#&f2xc0b@@{{c!C8!8tVnBf*$B!O)u3~>?{kX(7)^WMVNss zn=kli>#8gKZcE_LFs+8fYYJwK3?fPRRPA<%w1$2yfx&)}W$g0L)Y>*y!F1JCjK~Sq~<8B|_)9WvH?SJP- zQCG4zwP*+#W>;<*So9AR+h^zenAUh!&k?Iapsu+hTg@I2&9Kj_E-Z(Qi7ABG)2YHB6#~Xso@)2p>~c)a`Q%E`X=Hq(MH!%g**KA8bK@Kg*b%N@wr!BZ zHL2E#3eRV3Z6_IUtT0$1eNNmcb$s>x!e0qofhl9WgMbWI^}qPdzF2>3M~)}^v8d&# zDzxLW^u>)qD3NYCHpz!3;hUR6yOw8ThqV`Er1@XOqi0ujv&z`B^c`ROUA3aj6O z%Q_bSVkp{Dil+?7p!lzKJc@01R4Bs-D5BY^N1Z~ zwHz7T;Jlr)dY%xF*)rx;zVrvL;4qer7p-f2olWuAp5P+2Ka)$O_c@Y}gAAwGi>*Lv z5W76ka(UgjdJukgQJ%nci0^Y?r53fMtOYo{#P|J!8NYIKS?-EE|Hn_*W%&*1oHJ)z ztBa@e_#e{wVJ zN5b|e5jn9aYdu2TGCGm!1rm-ys}CFZFK=J%L|b8O>gie4*1QS0nZ=5tm89UDXg8Z` zwKv#sFjc(OS)(e&vER?f)g>+7ml3cMeIQ*>Q2W+PN-7f{@ak}&#vdMk5Hq4feTqJ} zZ(HA#V6*~}@5kywmN=ZrRkFWLEb`1ugfREHzChNZwWseNxyOoie2kwaN%J55lpL3t zW7!ftEyKSz@jDpJeS9kCZP&i7Hg?AnOjGG?5N5F>oNwbOK#uIv@=lt0QAQpkwmUV( zuYfY<_Cqi^;y9)!0Yc3!fvty6a3JUMnF}0@7GvZ~l8TwxH37&%a>aLIS-_sr-fB+5 z1XC$gZaFB4uWeayh`59PsY^sx*}%NBuVi2qY!;u3L34ZXJc&a$c+J-u5>}O5)LGJ!I;;)Z*vYtX!jo!umSeb6BlQgk$76cnCvM?4nyGc-NMae2wZG$8I-*zhrJsaQ#t{1@-BK1 zxAAqjyVV>7T*vqBZ3Nh8G*3qX-4@f?so1q1*Jy9uuLrxrE8~9OZ*<#N{n>X!okH3P z^hFvXvad#M@FJ~F@!KgI^e}6&mA_;km1SS;okuMmwLSt3WDnZ-^&YlYZ=cv7Zw$n~ zHZjxuw!~cYz!%Z>nTLd@vuov8DdrgsLX@5y8#WB(eFbNQZ4(|nxEhia-0S7$sD7*)?Dph*_cDt@qH8c)2Z9kRhV@9Q2bv`GWuhqhag{TthmTyJ z5}*zuX3uRT~^{pDRx`cIc;I)YB?rIa6*vvZ?iyUK)@x zS&M$^G}W4??2!XS z)wBi!(~Osp(ebkb)l?6e%Qi3Y<*OMCDd0`;QO5dQ>ZpC)Af3Qg#woHg{YouHEoxPf zdq|;(h^DeTU~hhwwux23k|R0|TE1FdWgRcfAx_yQhn8F;^)}zdFm9;`VX*kMjIOD^ zBVp*AM^bMt)&(loQZ7c1lXg7o;NExDOl3~xY`e#~w%`aJj?m?!aKdkna@1yLLxtiZejk)XyA+(n*u2VpL36Dc-D|=sAsw@GdpFUQKhz&eXmcC7z7z{97Xeb_Apl z3ZIP-jN=%LQknfa9vEa>yG1Zgn)d2``}edcIT0z!*Edx7n5s{dHr?u!Y0uvKpxmUl6feBl zh2yLev*6MHg-}N0;Ag7NHPEhUrdt~U?>g1HcXLV{qV0`u{1j?@>}F3K*efe0Q-nmr zD_G8RB!2dAt0_@7=F@&N5=3+3Cr5W7AlcH14TT%+Wcb?U-EVa90rR1n9kD#oSd0}w zX*(J@wkKohkJ7;~Nwz<%%RCIVaGKqBeVPpT&>Z&n?*u5Lc*jMCzd^PjLF0~H+TSzr zdsa*cug`|M+t)I_dG7pUsx9|J$}l_1 zGNyzR!Fy%3<{ACNJgw}j&{_w20SzeG;J7Hh7^{ulalGQ7gbZ>2m_&*QhU-6MpDagz zPOFV&0DAqNzia$(JU)->Y((^>4meK{cKHbzC*SHad=;|8l%X|y&d~wSWbOZISYk}< z?}AB-o$HuqbgeYPz4jN;^axa@p%DJ!qD5E(RA=eLbb(o)*(Xuv)3;;fl4?}u7mol)zVMAwMZm+j z=KP#yAuOfHAhTFfgKL=pQGP_fXBO?5M)}1~KggY2&9|t+cHDy^Ucc9rYhh8hc;Jut zk4o0X#Jt?$eeSaNs*_H~o*zE@w*<)TcL)+{j7+br7%5Zn4idN7Gk*gyi3M{#RqFfa z^ZMvSetN^niuc)w2A!SF>_S+&dGY!r$Hp@KghyJ_cBO5Mpu3Pl){&}94i(){OlEx) zCRSM`M8Vr>qicm7Q%N!2H)E2#6JFR6ZTDaN2!V^lqJJa}EotFVtC8O%0 z#>U{;LY<}Gj{vVkgqM*SWKU+~k{`PT&Hyf8aq#x#!}XSZxY|%=%lpbHoPbN@&w`7@*L zBs~6e9CDyQ675k(Q1nj|hwYQjT@>>#KOA5BdR{8*GZ~b>eP9XI)^r<8s^{EC=_+|5 z5q@2MJ^tVfg67?e{H`$t@YMIUzfBXCnS<1FG-)~L*EO+1SB2}302bM?z)ox}lKrRB zbckwkj`mQTRO_gH}@ zvPusv@)-xpIypJ*M7Q%J%_LU>mEW_6Px-awT(WH*BSE=kvV059$H$wAgSex^#y=`iuF7;$ ze{<3jK`nGl)iUe{F36Cju|o{+ehIy5ZEB#eZ{(>M&AYbqCvIqg=JN6l2Pw&Ix6nhC ztWkC&Lzt*;oad?(zBtYIM~e3^m;`?L1wYW(n}%~{77vY|!&1(&a<*m|0)=NwAaCO| zM+irGmUs=X^(^U{SyjQIrFE(t%h|m0Eb3>+P+HA_m0}}v3-?0Fn<-h`7{9Hqp~#Wv zL{1n!swVow18E{6^ehbG8pQyPxr^U_6qX^=Q- zsm7QRB2}2vUuai~=b}Xy8DNE?5sX#n%gqftGcdl@)0V^6uk{+&xvUV>q2S12b0~xK zgl~r#q4MaWftm{O#FEd*6^0%GtEOmCG$T_f=WZYa6nEyD>}2|)EH6rR+C@q&n?#o&!b?!qb)Qkz`l2EGqymUhU(NyqHM`!d zea(q`CeJ<=PwwjhwpLMr-Q1VX|Bm%(wXC=KS~@l+^?JNRTc}Hn%T;p?6Lsp{EonTT z2VO%H@eJ{DbkV$4EHn^rU!8p2c!ZJ`CDOzj_x88`HdzRCg~5><$G9YYimWQ05-vw-(IDeHkL1<|KpjT-7enk3uP4&w*;KZdv6ijJJy{&Ek#*4g&fF zbz0&v!`}v21e?){);I||XVBckgf05|mPeY%Rq0tIu`H=BXg?$KlUZIHM{jP4wR6f# zN8wNL21I7t`I3Cd;Tz<@$R#PSHSF1?95ejqMDXO9q`ipY-okPa^0!~;dgQn6-*#pAY&+g%Sg2EQ=_Mct=C$FivLk-IcbR ziJCXdkF}HGH8I~$uOr=E2ztyAX^;hn6( zjYkNW2WFK*4<&wMr2NmhexGl4TCLUHk3fK5l(aZn9F6#&J|^X2#v#z0B2s z-#cx#mhqm&B+hY|WY^=v3=TLXai-5pteo?}v<~;ILjpp;3?X4aJWRN{+;>fpN<`b?=wbmYXTp{wJRo{><)f z$6;14ZHst^br1Ig>gw`ltcck*wf6;hEJF~Hgm#NolYpw#1+V|bswdD}dA{gB6(OYng?<_q?_Z}&C-rpQM6F&UWV z!cmjAps-+3jPd0=SH;FRiSPt+3DpViUiP#1Rr5{oko?k|7KKYm93^52HTeU5sn&K zI(sw4*v9dY>W>btIKvn-6~2<>XKWM!19 zHMlq+)!2WFMFQ>&A5K^Tt+rCm!ubpvj$JOR3o7JEcH#ovdE^@`F)LEVSn)(wrEtzTN(6A*q!L zYqakFC;vwkGCz}i<9hGEYAApHR^H*Wv1SNXTulH+=Ow7nb&e!ZE_#$qM2_Su>pX(r zZLr$Gt~9Vkgf*(JbZBq~FF=LISuTPBVLC9tI46DEZ{=$)ViZh590flK=|6 zN$=30USuBFKeI%CPEPsyd{;csuT@y|nKMi?w8!4hVFA>>?OHeS{3|_TrFosX1nm}!7}XQ;mVcOFJL{z zlfaA?%oO9W(Dy1&I6^%v&WoT4eb)a08wvJM`(;lygvo8yK2}gTIEf!3))#C+j1_HTUwI0vF zDOR;gE;#6R4`Q%P1rnMj3u;Nfi7gWvuH{Zls`RQ{L+MYJI<9AjmIuo;A~SV^BsJ~x z8{;>*bOQ|8C->6w8+UJZ43kY#4U?`QcQ&s|+P7cS^I1%Bq<5QyrHsVQeav!>NBR3t zN2kPea=HB@RV2MMwzek|D1E6VjaVw$sU=-#BG5&UF!KDV|5RS*boJ5$|3tJPFgs}g z=gjTlXRu+-*SMU+ZNB=(EdKacYI_U;vMS$xUh`{+RamhpMZO%;>(|SY5JGNc_-dQj zRir3}T+j(jr#V4ijgzg+721-eZzOFdpSj|`C85VHF_zoAfbTx>)%z9n>NO1&KbxIx zn_E#{FRD7v)*Cm3EHYpR2f-{=9^6gu`=8**-fW0b@&CBqQz6Mg}@+wXlip&2*H(P=F|sg zIKml!bD&xsVokGPvHA*++rf3tUqaN1U#ek{-86dVH9hloG)Zj8(-wM=jbGK=s9!G0 z{SZn%6K&CjZV~_em(@T~W`u?I-kgqsF4~DKx^twr8 z@|#?c$bF5XxK4SFE+Xbd-VcC7Y<@1(*<99%EypQ3g5_q8Q9=i3!9A7YnL9Z={e7|5 zSZG05GHYMV7^Y@KNAznLEL>;H482m{`zmE+x@xWtCD@A4o}^D|*8d@7Q=~qX>#!#Y$(aH`PJx49D**mi0V|h<#c4okEA}cD((y? zqqymGta03*nPN=rLK;t*4o)tNC*J3y6xQIgZno%|`#7O-Tv;cZ?L5d%4AZivNAYd3 zcn32|mO4bF8CjIUdOiRyfSSu*8&=iug~(|kJRpUx5?EyT@q|ZjUc!e5k>du=o-xJ* z9n7Amze*kwQ7BR%aSe6T&;s@?3vkx`-V(@XM@o!$HUmxZO6ne^pqMa*@4Wp%Yoi&T zxmSN#T*F5hBK2)Y-x+DkPmVWsiIszjThetC{yzW`LG8ZF*M#xv^O%{VGU7Pg0fKh) zIs7YV?T$zboc{Gje;R$=)5U+bJ83Q#q@Gy^%jt}a*3`S4)m7b&PE8k5`&FgFTZa%8 zVgn4Z01mnKs=B3x+}D=ZHx}1P4Y1_Me8PTW-G3ZcRWy)1gKK$G1CR&GPvKL5ZW`Vh zS19sx_;X!6tKvENbg{?jnr^htFDoMWd}MbV@luc57(u4?D zeQ}D>jbn-u6#nb@o4lvcds84n=wl~ld0+?L9-^kVwx3X#vk)tFNZYijXy}#g~Ej{7z`Zr z1RCPufut#wIBuP{eKTG+C0tG-q+Lf98(Q9nUoxjoKI(Tn7<5k!%@nf7bnP4~x<=pk zMsevyzL(*KmulR3j7Qxrd-Uz^SnZ_TM;(^g5f*>->R5j5bHVG#$2CGb8?7>Hsc$5g z%VlpSK=|K)NWuK8f9(1H0MF@u1NN)=5z_wvWcXyj)BUl$wKy%mfPX5M(?#&?v+agf znYwMsBcH;#8E-+gYdE7R8^)5cI3%$HJv(Q$YO{ z!OjPIr|}WqJyUvcL#_|}2B_$-9nPD0j=7b=cVfBQkGq50-n;O#l<@F!)wGDI1sOJu zrdud1Z3VoFvSQp46qC8wj5pMJRcl2{aX#y)KqRUS_$z~-bIwTTrBtxFn%=-Mc^Kkc ze(10OC?lNXsQfWnZ9G?6eVeL0kL3@vtZ1WXU@^(=a4V^7VznZ;F$t`L2}Q)V<;1wo zIowC%p0$~Is7W(2qO34CNY|hl$RD8ms`F1IyH{Z(Ku8{6`mnqndG)Khgf>>7M*=g3 z9%GRhIDBJh&u(c7Ny*rNi`Jfbp)CSzLxwpm!6O}eQyTVXlH@#S!)&~6+&DN>jlP-u zsh4t0FU`_O%W5J;VDe)FpkO^ZikkdKa{{DNZCk6M8EBVqAP&O={{XK?LcSGaCd*d6 zX;=Xz&jrkTum(9Kc;O;y_vv7m6)?$xBU6a_Y_OoF&9t7>t3qA8yp^d*N>c@omVNHlLdw zy?ExIsNTM%B1lM>H;5?+gGqpj!@!WWBi&yunH8&UhHEnkeDZ z>|^q!k8yvPq}Wz&o&J@|$&3OyIqhAxopEZmHeySd72-uWG6A&Xzck`fW;c>B)fY{xYIou9-_oUvo zcII2ADJ{W~NQ{D^iO0XG{Hl~pkF+AAI8r`{c=Z%)fXO`SaH`1WgTVQV>`&FdIeyJbt}urmr+feX>pE7A^P<)a3NdLoTrl)?P%A z$W=epvoQHjXJ`)=37fNVZg}UjGtf2AC+3Pj^^K0DX2MP7%0Kq9ApEI zwN`yTCAN-O%!Dj4vy-=mZ1&Ge+`CI?uP)kD0bNhZQal5N1B5(tkLO7;xqFqhbb?!1 zrj8UsyHq-mFf)#T_pFF)l1nc;er4WQ%2?Q(V>!qe>&0D~Ij%IKmZ;uZI(ecv&N5UE zxyMj@Rn0A>gF~4%B5jxN6*=fT(CppGwb_*VeXxn!`$8~O6SL?JJNKxyUSS#Z6s;+f zOFemvPM$0oiPR zNNjskO1EBAdeVs`E_ z2p>uSVUKn@f4XVFU=_h9-jq2!GUZQt1FHShIQBFF86dYKk7`ni56ZYc)c*iD6NW|y z)O4iV80CYXO!lA#mE1dkJ9ME`jBXV3B9YLM>xxC1Gse@Or63!(a}q$HA?O0)oZee< zLjyqwe)|$V0HiXz!cu#GpCHVX$ClE#KVgxWdk^uXo5hn%QZZpYyQl9J+XJW8 zxt1DTt-8l^eyclj!6V)Wr_2s27r4{FX(83goP&U4U|WpiIrgrr=yKj`baeOLB)$pe zB(lXWGVwAg0Q($Q7prSJj;|gkoJkNrDuOuts#{+_P~Njj5)@M4%mZ#Ci~xJmJ;*AW zd)%TztO-^?pl83o{{UW*tYrHfrQA}ifH>zJ2Wqus9wpnjg+F^8>r+*VCr za}Fg#^9(mmm4j<>HKcB^N2uVE+L1>xa})CDW|D@MB`EBiwfIKe|V5wbFQ2P5M@*{{Y3ek=yQ?=dbQ8 zpGk;JspdB)XU&7|F~xb9M|@R(Rrwure&jx84Zxn?5l-YgqLpGnJ9>;7c9VTHSGNK3 zQ_5rr;2)T&0RFX7c;Sg7+agM?yN=xar_lS;^p$tKoJOI}2Tqu;MYOjXjrKaFzqTsM zVgNUh9(=KosrSDVQg~8V)I3vrbsDIQN=aOWAQs~T@aQ30^f~xfozM&2|1U)6!jfS>;)z zhy}<~@`49WoEqjVt&6ylJi31oKu+JSXM_I$ccue6Vk;=!o0Kf$xf&uTwD-GgwkfSEjrvx4iY3VX8t<+LT7$P|&V<#A{%iQ5@ zrE^~EOo|IfxQ=N8qLb(jPx8q%Z(e!))mf$leV=Gpm-u}?wMzd0P`0_Vdw7F3_1X(B zBb7Z*(zGW<7B>X-DIgqYpPSaJLZcT zK&W7QT` z^Ffj(eX(0JoE9LAWMk`5YWJ^p{zd>;oR!=#+~clmW#L$+h(`$rX&<}07W`yzTLT~- z)y!VVBfpq&*ZbSQUjG1Eq;I2FAUeIpxqCDuCf%fng8~RWPvchMvxTg#rH&*jmdeG6 z-G({!9CqMV9l$SsjFgudiM4W;K0XgTVrxhJSRz+<(#dRis zEn`iX&hlz$bO~gVG`BIb6NZo;2jNg?`l9LHcbOS=a5)WvwW^*bj!4XFX(__;-giG- z-UNpTmmSz1OYgf=gGokpnK$ z=1iZj*0XF-*=jb<7_!dWW05-oah`{tYEHpq$v?2JBD)r?EJ9x>&7N?eejREPrB3&& zWUm-zPcRdl9y8A#m8ANLok1nqST(eVX$0d8eFr0sDXn`N>k`T_h^_wa#`(C$!J^uhI)Uec`x)9si`J(73+Qmo!ft>J9OnO!grJ~&=Ze?NS zOd=a%W49wYM`J1-8ZY73#bUwX( z=zHrEaSJWzINiCxJREiVz3Qf`a`!rEEH;S3Fxv|brG_$2G4E9Dba~~qH&aH-YT$t; z;09^j9n&Pfn%-HVFi0HvXLbie>Cjf+fNo;8)aQAmR0i3AW5CZ9jdi9+0YPfA`K(xc z?zq}J=8J7MSfp2;Fjr{<4hiT$B9~HC?rrK#=3Yw6f(v?kRXnld802=U^ELB37{Y*i z5quU2dVMja4nKVQ65A1q6hU2_A|yVsq`9 zu^XQFs_|?c>Tnm=^{KcL2i?$8=Zs>70CY5@alxPl@6Q`)a-biUi~)=qLYX`oE&v%i z6`<`M7L#YvlyZ7g0K$>nQgA(K#2-p-0qu$aHmEtx6ks<_XrM=C+k%yDGM3P(Sc3f$v>eQBE!Ps-l(=4^Y=1Hi{41y6kRqiE_j zkHk|!C2&aRr7B?OE;mpEwka6xO?ddtA>OQT6s;J>#(yJRFN~sQ*KVE_ zGp^#&Y+U(&TJG9BU)hpRGXDTWTsMkm5bL*%Y_Z72m`EkygP-B`Ury?_|zwr}5c?5zYuMo$}v1b(%Rc1fHu1RNd@YTjD}O|1u1 znkgP9X=L-%Mlj?7k~)s#+O#HydmF^OX!nL71jz#f)K@#FosGC05n4h_5JMk)(4K}; zZ9NMbo$=IUfyKOWc|?*I7;ZW&Uej!E|ET|9?NhQQn;_Kz+>3+4Sm zAFWk;m=;Nu9@qh#IEjXFjAIx*{{Tv(Hl)!mhYhFpYI*j{Bl(1qV-3OS&MFN*NQYLk zGdr@(B-ps%5sdT4Z(1a}ivHDw$&Y+&`0~e>(FQ*=#YLlBq*f$Nw=jglEh01r|A71($&UgJ*GeD9UyY%m=`Am{nk zdGMX&FTEgV7=MtJJvwLWUM?QBI(Vww@=H~}q18A^(}POq6DO6m39@EFxsJc8ovYKi;m(#Wt3bTwYHq0WwAkxtkd~ zc;ot24=YTML5QnI=9{uNH_d^L{Bkja^{sGA{hFVmGOc$x7%|>Tm!jynd4umI#&Uh@ zuhlOFo|q47##?%F69DT$`E{kjtJ?D)|RDu?PDBhRkG?Z7#xD2pZt2d zmWMo5%>Mv12F~Ws)Ybd#X5#KPNs5Jb+;)$z_?pf|F09*B0qxY*n}1|Ri?y0v?4xr6 zHuKL+aY+isYPj4m$3I$}P3j0e@ltKFborSB0Ov7-g4}H!_NY+B_D9H5F<=+2K=18H zP6_UA=vOvAUEFhsB%0`wZ-x1owxX1X> zEycv(iKH$G-N_w&Y2L<>e5%IN&18j^PlNb>bi}STj`5$5*?70Vh>FA=RFR8I;*T+ z+hJj|Sb#!C_|%QV@gL_D1BpWB*xRDWU0gX}6!Jz6IrpuVu}eK6ZrP-fM2dnT#tB{9 zhB?nT;<@-tUTU=aysY!Lt#n4`PJa%4jwwRSC*QVTp#b&t$9fP)a6!(sCDewC80)|N zuT1{{caN=2*?JbExk#hLFtlh0I1Hzp<2fpM{*@@aZ;=6Y+yMRnM~cw{Tge1Fix~b@J2~oc_eY`c z#dI^;%$^q!t->v$NJhmOJG1q!YfOeFk#G>U#!^FPCuz@rr%YE-4vua#BK};BGs?`H z-0dlz4_>&YlVh?l<$~+&F?kuDQj7-FIl=m8(AAlP!?7j-TrVRXIW?)I`8rOhttvD~ zB5lRb8N+lxm1OEyOLKbiD~AX8m!bEjjXD)(y7HeJ8G#^WMsb=WxGqR3x4&G}GZaQw zV&5|kgEZKkOoVR*w)6mw^l;JIc=EoBvFzJ0iUH`@c=($L(VsI zT>2lB`qocz+UV$Xt4n*Uf|8IFsAb%G@-jax)#+`tw77)U(;$5~rPNW9%@NeA1OTZRBY|7q z90hd7;Qs)wBoUL@PxLjBt`%=Fl04OHXexO)0+-|+PZb^jI4ll&3Q$P<%s!L= z^R$7={VF$!age-@;L*Q$#|nMv%eQIV!za>^0^l#tLq?1@Dd2ii{JqZ~T0p8g9zL`H zG-%6{jMAu5Fb7ITC}7zv&+~H-+aF(_U%vypl}vMIQ5z5!3u}N_COU~GTU=!C&~x=-rnQ#q&lsOVE+JSTJ3DA{_GyRvD@8$ zDx%PqkxAQ+UUNiNVFE5k-UN^-a-rP5`r%0Ci%*3t-Iy_Dj~rzFd|-YQvG|JlB}RAL zfbzKe!w3HWt@&1YiDGFOwp5=^X`zNNYo1s-6MWKwZ_uSyOJ;5l6wS3kjdPw)uTStl zoiJ5|-xphXIF>t<1cK|z9k zUUB~b0YCTAs`I%}xfmy!uFe1$9mRI4aEi26h8)f6%Y#;dQ*ZWlu>&1YbN7Gvlm7sH z8fW&!vaZ(C?LqC76`t*qeT`O`3o?})j`^X*4I2{ccBV20ooc;s*d6o!Bl4;@x6obQ z$1E_z0f-Uh#-jw}oS&vg;PFY zx9@-PU!bceS%)N@F4%L>uf0(%9BR7($nJUn06i)PV9o|`JDNEVu1kA)4bg!8mMFZU zN!Xxo;0}K;)YS{?()O1sQa_eJqvZgPrAY0$vy6IHE~La?P85)(x>QYBXk1m!x+H>q z2F;>HSvD1rg&8N-tJt^pYC8ETKJ0TU=NJd4=lTk*p-SJ_l5S#l%Yl>A<*6l+f`gt7 zTvFvF=*z9HkmZ)b)N|9z6vN^&ji2o6R_VcCO~3q4>T5g9gQeXAT}l>Y#C{6AAoJ}6S0SX$umkiUgwOBUu+k^O2vAO*ndoaU#LqSI`IKPf z)Y_Mcu0#(IxmRWcVHHp61#{N6ziZ^NPI1#U4t&~TD#BZ&mAvF{-l`Tk zwJV8~@vI6Pw+_NTcH%~_XV zf@su39ooh&)l{e_<^&UtoruL6Taj-otb++Mvy&q!2Mjw8TF#nl+iYRw*aG~+AY&LG zr8+5`+mit>$ruhqX94lt{{XemS_xKL8rmF#?6D&zB*}a zMx_m`Xp=V6=7;;4BLbk*U1YUs7w)lgKN4yx?2D(=#(-u;`qxurhic&T70Sc@uzhQ% zv2T@n*E2m7Y{Z1)Can2gIjWI4jph>&K=ka95^C zKD4atdMKusW9|4;xC`?sJn`*8EIB#FH*4}jZo?^>CX6;@5LY_E(mNM zrKv1Jg5CBL}#}jjUm9uVUMAp1uEcn1Kd*q z&&#<9^rr+?KPC_3no}7+cyakq19=A=QMlusnEKLzjseK`qic3?k4$u=F#%qn53Xt^ zlPo}R53v<5l!ueIKEjVJG4p-w|Rha^^WPx<_IN=NV&;mAxZ_5U+a~Qx7$_J`fR+?@$Pp*$Sor z#_nroZDUHc2HssI8d!cte>I3Cb?L=tT=;`dcuW@hdfUk=@hE`#q>sDT86W#8{Ofj0o4DkYcA8P5 z0Jt|lbT;5Sf3;K_#Rv?8>{#8L{{W;O3El1f(W98r$}4h^yp%TIDCBXSzTkgagle

}QG8aC0;18m>ICPmPq+Evr+sGXCJ4G**$j9y5%U7Rqt_p$E?`oL zg>|ZVT3pv03C;>3LyRBtYd+IcxiN3Kh;GJkp!C5%(EgRHtz9+G*_!IYSXMS5A3G(u zT#lZ?spU`r{nHY;2jx8DKm1SrJzC%JklkEF@(n#oVUG@d$^3)TokvnE<+S~* zcOHl3z$|-u5PtzmM|>AYMP0WqZR|qQmdYF z3BghM0r?8Xy;iun65Lw=WJTH%P5=N3e9TRvy|dm+2x${`eG}>F^{L9vxNk4FO}^Rw zpRHN6)Spj;!4yPmLYQpOmGX_<)N7)|c0A~Y%&*%RDj~bh?sYIYeh|V7a z3&ubk?j!nEE~bTMS8u-{%VM@Q8Q$YiZ?)TnmOREr?YKE4=kYaO?ghE>_*Ez|o%zV2 z%Id`PB**D2$)z?V2t3}09)s4MDV|Z7*UbZ*sL#J|r|VUd%WHE4k?tF}3^5h6rAKuR zn$p|B3PI;=-0X5#LT%MnhSQ6f)CA(fafIsKbiHYC)BTFhDVYJLLm8wAn@78L+?uEb0a(K)9_3!{{VdV z!2bXmPqWT5`={fl%h&wif8SN37NdW114VA94YTDP3CaHeKS4~3R==GjmMdu4W5)ff z_j$nmarp`^9LUO%)+=dF@7{xj#wlU8y=c{*H^Try+uPUm{VH9N9ILWi z+SNRyw<{P5G7fm!Kg0E*%H&3*Zets1)CTff+->R5{{V>mDWO7_-oaQ5VB>?*w&c0g zmm|o9fX+&RjuaE$o)7C(Y}(fCu4JCtGbjx<_T7d&e7GNvG)7isIVYkuJTKwJ)Glss zZi2}jtYc(tov$J28y$xg*vl_ITcQO6pcql?1!HL1tP$DX+CdumtOn7NySiZW_>an| zw}=`d5v_=28*p6b`Bn3%n^L0ctD_^u`W38l3%hn$k+K{PnXEl7AhC|;J*#(E)??H{ z+uZ>Q=W}50AXZ(BDi7|CdX^6pPz0HNXOQrl{N%$ zftzsZaZR>ml24IXji(MhCKvuiavK6kRID6Junu4dfpE4MIT! zJ8%z5S2@{W++5xM?c{lLfw!qR=~is)ZzYOtw$Jmf2Je((IPdR@gG_aYQGw*)ROg40(X*0HLrYfq__58qyU*H2)07|n9=0la-{r?DR(>MNc{ppBTi z09ve|01uc|Xbv%hpRHL_&MHPq0QRNFxcn)bMsvkGZ>B$;FbohopQ)r79-o~A5!Jsc zOpo#@01^jGesqM4ec#TFzwGhrO=TGMKJX-j@UE|Ok{oLL+^@m;B|1``2PS3QIpW%eJKtJIU^nTphC6? zKvVT|oRGh^#Q=NML2 z_2)DI>@Q$J^#X!Ij!QS;{uG6Z{{R5`j%mAOB#|c`jI@}?+7Q~st_MKpr?q+hu&EZU za6G>|67CWs068Zk2b0&grFXU>PwkjD5Pnz39@W5WOk>s^qEs-K=1B+4r##}fqH)#T zobA&*Q%sSpl18jX^*9ILn!vr@EX6|k_jJ9YYOlIaBx(% z-_y1()nlmrmFWcZspi*#Cs%OaDHL!Tg!i7*JX_GkXlj+E(Qr0 z`^UXtB+QWla!*Q+aL*yAPQ@u%8d~k$wavA-fJREQZVJae2fwvpl0UgtOAkh-mL82s zyOPG+Tz!^dD#jUrIL~a1RM(oH+aoI0(I!YaQH*0e4?)lAQ5N=ULc{y5O5?c_le>C_ z1a>{>ZPH_TKmhDTNw|M?sN6rg)P-VgKJDx$G9dsID8X2BpIVzy)PC7+uttj<9VyW)`0A;B+f3no>K8B8+4D(qS;t-GwgDn35-c6_S6*a}J%#i}iZEm^Uxh4Mq zWDUHZZ`PyJb#Y@0AxREfcL8zw{{WtqE~Bl*d1hf)<^+&_Y-5kcsanOUJ6L_5o4e)v zRlURS5)vG-`E%%cfAy-B<-{i1*%4TINwn@c$@ccBY;XRBa*?0`fw^sDbm(L&l1hJV+D^qgU{tryZsM53Tflz>fg$wo0Hy89m=lQ z5+($eVaaUcujTsHPcPh5;v9f{#2FdsN0HC^#QdnZ?nC8|TGZ3^MYOl_rb8-jEsTr~ z2R!{Mhm-#RO%u0jPbdAg@7jxvI~o&eR@WCzH1@^D&=q&%931oYIs7RaHM+34`zTmp zRUTpylGr5Y`F@p|B9tSL!>&N95M8V`(?Su*m;iC@PUGe;Xz+QEkWfGGLCKGI0Zx04 zIUks#NU~;<>fU(pSR;MhmHCH0+#0i?%>-7Gv*YEHKRaQ%4#K0BKR;GsXE21A7YrQj zJPtGK{uC8`tV+6kR{Djnl!ir-xK{%VJAX4*E-fHiNgY-_%7m&cL9z1w9XjXnr%!b= zUc&blZ3GtTk`Df83^GQ2MNy0G4Fp@QCv*0Bke#69zIGqNfheoobQTL1p*7^fIPKAJ zHy~ZDw0{rz>sN*Dn}&^U)fPZiu$aitBaXyYUF6%WXN)hF3@VNY=W+xG^(L^AHB*eM zsN*;_NgAsiG!kj;dvPX9?T8gBNISB5H4XLb6I!I-yegSl6fwy@)rqBCwXMYNxj!fb z1CBHQ0N1TEsv(6V`#314Bo_O})bUA@F2bp%*$#Biv?2J6RcbDGeycwx4TNg^S~ zMsfMov3YNCD@k&yuiGvM9mo0aOD%xbbxSKtV;dc%al0Vkll;G}C7}7&LMd)-Bv1{+ zV;+nRGT!3SCgSNBDNXW)Jfn5fw8Ld@ih{q^m8zcCE!2^??4K~Na_g9ura|*AQ82QQ1 zA6_b6;&QfzLh;_LN&ccQ@v9Q)vRiF3JY=>os!n;%I)UhDO(yKd?(r~0QpJW30FnI- zBPLw%{BTKiAh?K0`>&7?P7Z5uSXrvf@mu8X9Tm78i2BzfyX@z3NWp;Uc*v)$v${6v zTn0HmG3ivLV7X@fQ7^6*J|hHe#&M1+DS5TW`z`%yOG{?HX@GJ(xXhgMyB@U}A*}wO z{{ULbp{*{aWM6rD^{$r0Hr46*S2Y*j71G!bm3cLUk3no~L+(%08LLUt9Ez(J2Ol+B zOds!Npk#r4bNJJ^Bd0Xg$6#|$2Ln9^(tr~fKXlS${eGhqx!uUe;YY9a;(!`|&M7|< ze+qCMbo^)-{`WLk00Yot@}xgQ`BR7CNsxVi3IIX@>M`{cQsiffC=uCbJnSRf9DgcI zs`JqM=9e$dO8o~~P|VyAMmA*&76=< zf6uKLIL=SMKjBIX9;<`voYL%2*}(eZfEpN%nQx^h-TTB0`qRrW7%G0b6o8)1yVL_f z4cMo#&!`lqaO}q&F^W^c`;K$yD9Je$%R;*Bxr5ot%abGiFqG z2ChXGSPUL})T0^hPXq>OFb)tNrmW8zAyq}r2RNq5IE4gp01v3`S_yZj&1no520#%& zB_kO<&p%RsN~;;!8JWizBOR%C`x;-fsciYl$sPS^uNJ@=TsD0wNw|TsP66VZyV%gh z+4mJW_7vj=<=$jaNZd!`K&~@?v7|5TY39^t9%}U?^r&TwN4E~GpH9?=aofF(YS?MW z_Ah&SlSgbEMzXFkyBQ$XE_tnXmeF*5rsiXGU;Rn{09F@h=j%-u8#k#!S#9LHm2Dif zD%cFhm`*ZDs#f8Ze7P_J9yX4(ZCC--h@=wH=qYdjKEBkRV*1hM14o!B0XMI$4KK;G zAI6t>r1J#;MhHRj^2fiWNef1pVpurOPfAeWpYfm&PaM(~gZ%Wz-hQ5flkEwgy#0Lz zGdQN1R)O-8dFlP(5S|Y8dsI7B#k5ElC`137qFVAN%U1h`_d&ziGUfOa>xE z8Cg30?rNr=er;xPAug(3dEJi6-Vwk~Fy}dt5i%7B>hN7^zC2(1QI5-sgnm2N3Z%yPt$qY%( zM#aak_}1=?cWD-jbsYCk42%d>M#k=(HDuoDw()7kdv;=X4X1Iz8NuW0Stb%=-MEqN zDG{ob*>_TSo>=^ue8m7{mIRJZ0;U&MLK%U*y=E%dQpW`I{V`b~6t~KU9<;HjW5NIj zQcnVl*r_|Q(V=6x&Uo+GQoDn|=sD(^W!&Lc?&tHS4bpH1c;=BM-8OkrX@m-lS|$Xx zdSjZ5AM`}}AL~~1#M>;9s}uzr<|~|W%~e7Eihv$D=AwTIwLYeFe34xph#N;7S2mmx zT@`@=MPVb*j>gm{kClH~wwb`rK9x=e1b3@w2d6(;fs&5Ajy|;T6SwuK)s!E+ew85S z7|-&c1t%x1H#zIpj2c2f>Ph@404<)_6u(?j1_!2pDmH=m_n-jn2b>B60ysINfH?ki zg_oht06QRm2;z!n3FmhoN+=Q9jii5*Kb$6&@E=mi_sAI3hpH4_rJ1x7monhcAM zG7sxY;bLKqpqzdbn}=}UU8bY+6K^Wx@if6W7yvo^GeB6Md}n~eKkreD^VEBai_Ry2 zPvQ+Kmc~I)eNJcsOm07Me+I=H5ND~!sV1AXo2xMQ1Y(04jvFoY!K5-v2M1O|&k(n7 zab9bwGJnEBb0x_C088^mz{5QD)Rpb$2IxZ|~KNiNouEOPG2-GQEd zwU2$~eX-1;w-62(sJjwj3v@%5vqO4&Z zn+JHvAdjtI)6p3uc0`g;0YL45PT~DCNXmM#A&Yw{f8sn3U;ecc@WVLIa0URaeM%)a zOz?oAum>0*WBJiws^i{{VW1v>cMK{{WwV z{IvVSu=J?T{{S!kT7A!NT2r@w@O|&@nqdpGqGxBJ^{60u4ZQyVtoz5)(y93q24)M_ zo^jr-FkR<_`_0(;Qx4s|6QJy90;|U?QDMLe8}+4VWR=N5oCW?=`GnP?jdO$3Ez7V z2Ng)!Sio-y_+2G2uwdX4N1WXN2l|iBoBsd^zlD6UAkM7pRJ<1@Ck2%7SAYozKltxTsTP=#+K90@*j2evleB}6#}w=w zsEK?n;aOO!IVY2WIpZB^W$5 zb0d>1TjCMnm!}!c7C~fDlfj-BjF9p=kikxFIubGm<;@}RKZdfy%#;wNkMH^c)c%#P zb>Y;xd0XuazGSH{-Oe_q+<#hgXewS-^Uv=gXtB4Z?DPKsk5ORLxrRI$;jb*>>OiEC zpFDLO`c#ME&W=~*mgkYd-ao>x{{X@+zh+o|)OeAfJ3Umduf1<5+KRq_3U(#iq2l`9 zin>OtHJQt*724UxLFTE)rd(Vm`*^Y!B$C6mZTRt3{82e1f)xh?{gF~=w%F22xjtLw zP7$(4Be!lVD{3UQ8)>Q=TR5NWa`7JR!G<{7lh@k0%Sj#YBHB7IC+In@su;l2{FRp_ zAZU&wZVpc$m_L-zI6LB+A8OMI?YQQwOC(70tEH z@Va|fo+J($BH(TcoMRmNAHuW@kV?ikdvzXK9LjP5OR;1uBu0`JVQ>NR zdX)ni13fy@FPRxLTqJfI4V!u9P5y390v?Nxu6e4ecVll14n=G0msa;~j~huOilIX| zA9tVrwKCI2H<2uY<`~$4!!`-){vWLtCQUtw^!sCRX&!X*a7j3F_!%Vs0P!SM%^XV? zieW{KQbdrh&cJ|ptU2wjU}C4t8%Y6%Ks930)Qy)3sX-i=-I93(@Ij))TIRO4cIsEg zMcDg>@&Ll~+nVOBCo$bC35;JU`Nw~1v3M>pBo{twG6sA`csb}!G1CXqvj`^y@#(># zn#kL}HnT!L%`$T2vZ58pB%FN)2Ojmm;mGr%Ulg@Tf`iK*W8;D=ii$&(Kse2GNLmHF ziU|rL!M#GbJ-TNWZqDGF(1{n={$LJo|nX1Sfb{!EE4yF-f8g1w@Kj)g~|ifQ+)`y}c@&eA_3~)}6huTe)Hm zSO|gTK*{_?Wu`vNzwaJDDw*tSOLk|cQC$Ur8$r!;$PRcl(AWkjE1pNA9gUbyK<2J0 zjB|rj;Zu><^Q&qKjO{f8CQ!qm{b~5)EzLxv0iC!%N|SdT4rze7J(Pj#NKP@6){{9N z{{UJE_n-ybIs^JrU}KgT_oU7bwEzL00i*-5(**uh5>F#IsQzC{UzB$IXaU6T?tcm? zq=uq^J3l%WUa7}@rjIr?9BwDjP*t|@PvB@pbJe-@t!`#C%EV+U{veO(Qf^W($XnC^ zX$n3@9B0?kl*Hq#pFk)93jz0IBmM$uM7@k`PjUgIFt!E=!95KI7s37Fk6cgy)1dwq zKG-yiDQu9VA4A0+P7f|~>rN;?ibdnK01Q`xM&ap#aZ!^V?Clx<0CJomzgOA)Fyglp9E}7R@ zo(T4|a!LNNpJZp>KAmgREEQK#ladG7&Q3k+%cOj25=647wcc?nrduAnYoeaV6_@NK-$H4X+!gOV!RL=|z)4^dG-(_siDjANcVRE{Lu^8%wd>54}^O2?`&lq+y4NM@A{8Q zVcZk={^zLmq>9RYMoDCXJVzNDxdUi9$MQ8cpQKz|z|tX$YXObz&r|*stQKTvcJufC z^LHMV8xp8V-+-X?6(rI5Gszol%1Fv^xf}|DOnFWBe&GHZLLi=Xkv6G(?$6CpEA;0C zbZ<&I5S$T={xu>+HT0_;yanV7_hV8?0CmL!M9|7)8%c8D5_#gP#WTY$^d(px2sk3A zHdC%rRr1+;Ioe0m8jY>qEvf)^eDH)5igqf@>0$ByvWgYvM*v_qmNI^{KacgMVdcvj zkM^P!%`|TaWnff}#8hR-44v{IhB(?$|F@j5>9)ZO*qGcaC zvX0rvqU>(xRz4x?J;lHM`ak1K{{RaUS0BS}f9;w702<^ofI{`}lTO3B=V2iFQs!ZE zt{)L~Uh&)i0N=CzG^gS=se(M4eERHf@vcA1fBEKrI!%xN06fp7kSFK=eQx{~JM zi_0O)9kpvtYuk`vhVa6OIy0339Q*YD02-lhXLES0ZLOq~FW%Us;-!Pnv}b5$NZpX5 z4gBEs6cmeBpKGva)L-x33x4WCamnk?TFsI|?$09@W;rZJB+$`MJdKuVNb1YTACKWt zFasYpN3oe)CX=hxDJxhfD>YjTI2kKwMH!#Z*~ zX-X@|U1EnLATxLTE1AaAkUDi=>MM7{nxFQ4${9g0msjb)BZK-A`csbLTk2`*lUhk~ z>28T4q1w`(OP^n1?OgVuVG&a-XrYHJ0O~5~h6`Dx`#ONG+p-RGRP`Iwg4xOBk&IVl zse6|cYeCDE5?$X2W)VjK^1Qt5&hEI$&$y^yEg%&I6|O&-SBhM+JY?>^(yIh%l)X% z#$~fdDDy(37t3}ojy@5N7`Tf+9cwfW1LV_o|vR6XaFhdX*Ln)ezdth zhK=5!{!{?nt(@RdP7Uux76Y){?8F7g$6Ql`agC&r>L?y*>QE0raZCHb&;j*1tqjIH z9)xG`G~gT#5xMs1K;O|>Pvc5Nqk*&&>SzHO8w;F|prpnRE4jO5Qk0X8?1$T>1AnL^ z+JF-h6UaFBrj=rF5P?r%*&wL==mGlf0DWly1ON}dbK06!+xlXjS-UcWP1@UuEy?Z; z3;;!*c97p%O@|-q$@dti?P2No(h%c~$|wPB(EYY;-K~%FuRO5Rwmf{{TikKBm0rGOnE)F~W)1leayEbkecs*C&Tdw9JB41Ojl!Jg$0y znv457-3gP*3cHwWEKWzu*YMqsdZN?E<>Sm5*hk&>r29loE)~Hgi2x^TR@X;5b}C5| z+d05xR>oBI9@Jbok`3cHE>A7=skH#n%Nrmp3@BI;$K4g4!+^?ir}U|1GjcEZ^@si6 z=~=hm>r?%~S`o1OEIj`J5A>|-zJX$5o@`~EV+=sS z&po<-I*&&1Pbm6wn-;*43x>~Q4DP#MgIVnbq6@lB0T-h=lJT+hcB)4?OV^gBt#L{fu2afs83(S z{{RJ6mSK&FwXz0CUi2c9vo!TBM%HaYc_MOA+bVYRkIJ%cSX^De5N;u{jC$g>G_)te|cM2m}%6a&T)#^fpp^j%!;P9zi@8 z5?m$$5n~zu03g;ZmKP}4Fg{0YbJrix*5tPL(LyG-gj$4AnGw%8$S0HEnn%@Sw!Mm3 zpt@BGrT4i8L$vY^ILTsv8iF)z#&Y)Pi8NB96+e3;JkrZBj!mR7=R7@VPjM~IsEc_C zyI~Oh(zfCOT<4FjYCEL+Om3FCM6f(u$jYorj(Uu7+w!C?Q#qwqWZ;0OoSfGG0Ejhv zE7gSCI}oJg6~;683g-|;+lvyo9AliC(9#y)&Styv_F!O0GCGW(r3se_HK9W4Q6x-@ z&PIB3S{5+CEnxdqw33GflVbo*I_9))A5K`IyNxZwsXL-EF$XJ-dF_mktwCpNb3L0F zEn^_zgAC*h5rNNsO*gr2T54w8X}1dO>1`rJdTt-*(9~}Q&6oz_8BqZsWDql2(%fIe zWL8wUmDW~MKbXV}54-qvsyF(am*lH?n>Z>SQr!j*UsKI34BA#HdE?Q$cc;fHyJHx} zPc2%dnj(=tgZs$<3QCYq1Cht$_|`12N|UrN8wpeI0x)R`);0V+s#)pr&bL|l$SOi^ z$6Cvh>LVkSE%%8Wd(s#a{l4F=bTQm%{{X#-pkJ9>Z}Lei@|=I3->p(KjP$Y3*aLBR z-zY4~TOfDTk56L-+W8b$8n1-lXsILBI&I~$oI+?GtkY0G^$Ca?Xn z=tymv28Kyw3mZJn0ubL{!k|Ue?*7sC5jlz?cdRT~S0~ny4O?P>4I3Ec1zAo%-8Iwr zeo2{LGT|+eF(3*FU~_;EzD;w|S>8tjUED(`jff?jV<$c9cfz+3{{U#DGY}EpCOPf_ z!5^(S?j?KKn%b_D7`Ho$TDy|V8jQ9Nb6h5=qt65R(o5#W-M_o|S7E8ib3U_mEb;>z zHWe|*$E{JjD%SD_`=xmpuBk=J8~qG5;j0os72~O9{&JJ$bw^UJaS|1kl1YX6xf?FAX1CPS2KCchh;f+<9f!yGdG4p4GpXXFBE}CnZCPC$^ zHbV8s6g`N3Lth?SecprkY49AtzMGHqs2*ixEAw&y}gAKhDc&P z>w8WoV%8RZbM>x+O*uv4vS*T{I#Q}B z6zzbDVi}Q+f{s7Qr+I2S@k!-@z&uhIfB=8`^uJ6~e50NXF2Xq!0J+Z~;*8|=rm$`^ zN%Lo=ARn44Jh1vvOh;xHanCsQrx@7x2l2&5u8rL1(>*E9V^f{{_a%2o3PsTcel!eu-T>fz38wN+11@R%vNFG|Fuyp!KS}@!5C#B0 zQfR?FI{j%2FFz?XZ%{B79_D}@vAgs5(dD0P3TSRJKqJ_i0|q<{QUTj}$#6{}Qc2}V zpzX*k27N^#IP3xXPz07sw(9FY^Xz(kO?k$rEsedLaK|}(vo;T0@!Gu_#JAe6$_x>0 zkUdUKdAr?91=;f9k@YV%nfAw*-NrJ1J}ah^(Bi1B%qeHLF_(WgI5bI(0bIjtlSf;$-u656Br*_g!`*`6_uf2CA(F>WeT zY58zDs@BH}xN?7XowL|gxykanoNhg_NavcfG~>Xwi;v+S%A0p?F0JG86bTRj>Q8KS zALoj46ZUAo-2Rnb=0}Le=)^LxAdjV3J&UJ9wTX&cU#XM(z~|{ywJX(YSnaK&Fm{t7}OxMoPhDZ$;@^H2q3MPQ_}^f>8G znRd)wkd-`V7_A|$-J3LtS$F|J3(p6Sg2)S0@KP{^qqLp3d&r zPkD0qLLy%-HS3Jy*Sl1HbjzlFneFa_h*~qi3(JCgbmO0Tt9Pc!9fWEd%;_U2L-HO$ z$@U-4nW8l#xp+Z_SYeU(7?`xYZVR~npRHr+cb{vD8=om5Ne0vlDPnej4+QaAGHF*n zbGMlhB5dQ!JhLW0m1o`9q&hXb9ElQVj|5;S&pp1BoyVe9MxC-Xt?U;uI1;s!KH=By zkUI*Yt6WVTi)^};!vYu=$RiaVpMHkueW>k;Vsug$9F-swk9uYNhI=MiR7MZoe=WX# zJ!)CCCatNNYYei&r6YG8G8CR_{5Kai6SG9PY%W7Caf}hgJ4V%CO+y<3(cs_#(T^Fc z*BaatJ;ORn`|}>~8yO3?{0=^}%yhY8-&Hz{3vGEbt`(fBDyaEEJ^jC0h6{+`-6gR} zE!;asCT@19=Of=grBi|ik}2+y+8{|#rAro5obm^6>r&e3mlD_}97a^Uep@df5zq3Y zRzFd1?u5c!u=yE411ARq>snTN&HPS8^0aWaaztQqLH75l zo5U$Szm+n`11J&^j(TqV`TXjg&GPCG90?ocq}&TgTlhff_*ER~Bwx5N+)o3g%!cOS zyu@jU#xinG9dZZZNcybHXkFUYScGCj83&QO7|++QwLo;)#rz@(9nvP)vXmeyo}GPZ z(`fe#Xv5AfzFR3>xZzHHXw<7K-ISe#dX=zci8ARS@`)o1LFYb|vYRc_T80M1Ct={^ zpO|;gxvY(CL>G`WKPeF*$T`6t{{V$L&r*pj?~>zlTwJ0AlLL%4dHjdvNscbk)NSSk zr0T4|Y+QyU^SoB3ha7i>ZI<0x_GHRVHjiKP=~&u}O%z58lb3Y?af|>PJx91Tv*CG_ z1>%#3F(F@Y4jcK3aNMemH=(bo>CGpZb8hF$2L+#iPqlH{#MiMV1Xz!|gPQ9+O+C-{ ztTwO^EiKR?OyisaTk$5cWdYEG$Rijv*ykxjLnTHLo!Q07BQ#7n!6WmjEhL%?gjmyi zuOL(IBM~*ijks6n1wTy&O+{EUMh905oxg=}t9DCpfJks!Cga(YqUd z@!(Uw%N(zU3>p}e@}Y8b?bfzrmKdguMXF*{+l{|;?aoD2jGAreV(DoPo;}a?tn24cj}gMdzhmReOzIRz_9wqyuXMgN%9#gHf3-E*V4-#LCAk zqZu@G64P?FFb@QCS{4>*cqR@cK3pvz*|(@2@_Kzas!0rv2}Li1&e58XL2&U0NFA31 z?g&W0>r#yRm+UmiZse6D^8ihxZ6iF8Kdniq*hQy^k}oq1N%`^pD;%*<3LU>rDtK75 zBXK9@?tO(RzjW4?XImb`C{zv%WhU@UAd3nzn%PRNzyA zf<3C@hR1Khq-3KYQ-|ZtF?S9r!Jqr4n1=v!-xSl3DcL#3IQ~@MGmb|z00K`#)|?;I zWYTW#C@eT214sa{_vV7x9OsHmu70!!9Vh@SLFvU51I}`2pbo=w?c^x;qjHgvjC%n_ zBRz-bM%cP+UEcMfAPL+uRQ?oi3Qh<=N==cIfP?U*{n$MK`p^O^a(?pXwkb;mZht{b z`>b>yfu!1){t`ZvfI~K0fyFNJdENQbNJGZJN3{S#qZ?=e>ilqd`cq7xFDLY+0Wp#X z;YaTJ6d0rei2)f6noZ<&KaCiO1BGA8fq~EhK9m6^p69u}+H&7#z~{d;=5E(T{>vPD zrCB5fN02HO<0m=irFvDMR+jj1qwL*JLDsy+M7VOWMI4jIto<$+u5Tk*Q{@o@gY*?s)za>KjRQZ|DMHPpvPbc=I{{S{NoMN`TKVf;T z+p^l2ks=@v>_$(oN>{tEoGh+vO(oM@#$dOX%EG!h$PMz0lk41ml|HejnB$IRC{L6F z#;uK{btBYs_);GO>e7IG%W^=#{ptSz3bh}FHK_T zbo=L{=hBgW^Yi>E)v?%Ax`PJ}!3qN1F~)eP(>tFT`>D`pu&l`m97Z=0o=*Y!tM;}c z=Eu*3Oz(_sRV6_f<8@NEi_E@q2@Ink^dRP&d#zmQHy>q%*`t0~ZYLy+RVe9pX$bQX zUQKTt?GolhQ`EP7bNbatWnmyG)Etafb?naf@?o)-{*|?)!pfdwFa?1bQ^@U7mEDnU zowYWb?UPuUW4xM8z;41}anA3X9OAL3)h>g`pK5s`$sKrMntkTCab-8yqLH2gFh+CN ztzbzji>Ux^GI*+%gZ6EmLimzG<-DVk;kbU_V0Nlg>JwZkOaO(;fq|Y$@A%YqT4a-9 zmUzd^qoa54(w19Bf=Oc}nGwqHF`s&d*$(Jzd*t1Q18C1RJGI1-tZ#4%Dd1O5;l9=-_zl(8YBpk}^O}oO)TFXV;7Lq~ z$;$5O&0)LlyOVFqy>``0Lv;sZakWWqr(M$dah2NSWw`uv>xz8(cb5;G45A>6cd*7z zK3sA1sO+I=E#})VBqL=`JDw@JwxczS^f=Mr-)xMaaen1b6)^$hB)L zYq-pT$k@T7Bo6gcR=P1;MT>@$aL&?mgVL!-t0_X{6ZrxdV-g0Di7ffZ1F#hxt>m^- ztdTiV4+s496`V`SF$sV&1_{Mm+m#6UETE1E#%dnpaplzCms%IhvQ9!xv?(K_V}M8D zii7RRB&!f|a(TyLSlB3bIQOd%?}_7`S8&b%Bo4fPI_Ox2qswCzPV(ltJ>9A@OgzjX zJNZs_^&gKFQqJCK7|Cd@5@cnah7YH1wRtXcQp|5Rv&`9$ec5gWFKm;D$!Kg1JS#Bhg?y+p_#xYi{WGw}v2qbSQ z_YyJ4=cPq?Z=0ubtr&7jsmDrBV<`@>)LOh$>YA!O!=xM-_&Tr=957ri?{6! z9f&e*WM7<*bMIc8YqT9mu=z!|IP~Vc#&|8vLgMaM`xfaoTltvBr#<^uT`i6|?qL`} zwk74vU>*_hKNH@tWI33fpnD43WPvTW$sl}>m05p~tT{919P)mctC3MUeJCb|@NU+PZAj#>V)6`ekLqd?cezen%R=3^jdfov5YYZH)rIkPt#-=* zFpoFnBt^~-<5~7z6x0$`+_7zLKh_Uie?wQTG&_q+i+QG0+qiUW=Z|W%kwkm|>5~{IeZNy`x z6VxK?Zs|>S(fM)Pmt!PjB0<3;Aby{PH_mD0l1Jg1LU3E9XWL#h7a~Q49D)c8x#%%d zL*{wm#BMTjKwgywRW&YWj-#ReFM4q!cW=G@>WW7(E?h{X9a%BnoXI|O<;jiM`<>`9 zR@Y%!Lhc(uB!3Qj zQ#7lDLn)9&$Cd)S0gyAAwRNjUByvQtLJKJYgxSIMr+ovd&Nf=&O{z<9af-7Wxw&BD z1aLt;Fe#FJmkhyDW5>;$=M=CPmUALTKy2`Xf&Oz@j#{GP5s%^MJJV)tF9ZX)^rZRG zS8!pK1a#z59n+sJGFv3`f!dMJV}DM#WYf?(zR01G_#>b=Jx{ppRCH+_WtgfK{n6lh z4o`7VN9UVXgUh#M3PCwc@`Q$jHv=Yl~^}W zNaIG`ACxa%EE!mOHt@1D>4IZT3iH^FI3!S845&pXphb zEm30Km0ca%1TZy!Qo38Hhm>Kdm+^`7Eq${Ez^4 zE?EBn5gUi{IHt5BD^bOk=KYWsP~fQqV32$MRjF?%`xvoXg}G4M*J7RzrDNOOHSVPX z%IKy%!eVjC|+=b6z1yU(q=PfW1gV8|8TIC<+f0v&1 z*Xl;n^hy4Xsz*!%!TQ%Aen-eB9+eU|z0tF0eSH)#h-6g|urcSVpZ@?|I_`O;yv*bi zw;-=hwVMQso@J1I2mb(Gv>}?_Dbi^gNp_x9lpOxFT*7am(VMtWgIWm?B#RrAEVwR9 zjNtd;xQ7eL1pal^SX{&+k_k$*Q%AZnD-~4h)2UzV3r5NE z{{XA$oK#QYE)6+oW;goA`kLC)e&E2*<5;XmnBQ92(^zaAisxr!HaDQ@fO-1WwOsc# zP6CJ1@T+LUu1Fr0nMCTi?@t5QnvDlv>S{m^GED@5T=BskhLDax7#`GMlh+?ZPUASi zKT%8u6=Hf1#)H8bIQ(hkVDZP{Msw9o05pJjJc>Y=>GF@IIFbF|(trRxC;_`vAHB)< zqMebRLB$kU4!{Nj<~=>JMpT}FnvJHLgYvK8L6$-~lk_9}Yf=feU|J&hnIG9sLLi=Rx=ZceQ2k4)1$eAz!hXbYZ-e<}t^=CAOaeMK*u$5Kz_ zQINyMmz*U8qWS1v3q++Z%J1q-Q>ep%9 zjCB3u@y>mHdHiagt*_limirqUWCRVxhZ*dCwJDW$@W=A2dS`^2Uu2r)+ABDilEd#g z^dI9*uEleAIr}-MzFUiikYje|UD(~9YO^iMMzL;VH#>fJKPVk=0seL9w%SgYrbH6T z$`u2R?7Nu$CaODWm-3r=EaH)m2QY#9){(=_qX#%AspZq^vNL6)h^L`IKT*vnxQ69$ ziLt=@q~||FT|bHZ6XZnqnpkE<<>4nJ4^{sF3dZntoHshtEyPPAq%PrDWMmF2o^f$@ zX6iAL(8rj8Ce`5Qk}2sEMnfQOhmpm4GwFJ3BPp=A83be?2A~>cnkLnZf!G66YZ@q= zR9--`Wq4f3dh&2>%FNs8JYaf*oN0#KO<1`ZBW2~%k2g$Ly$vk#7 zqb{>EHpx7e!-pk$6NHIc3SAhbhHIyF`Qol>@KVt;0LnqIptA*e8r<8Rz;6*Vj@ZX_(@UGtVfX zX1UcJ2+vx9GU1obAeB|Zfq|aYX2LZ$!z2*O;E(tTs!(m?doUgGS2WzVqY|9qi5&Zi zE@f>=A+V3^hE|ogm2Z$Qp%~_&w2gf4oRBbj9{A$A3#Uk~r$tl>9f0{qty2Bia>F2> zLyD`K`zBGjwpkJOWZ(>Q?agP*pD0lmKDDtUuc1GQs7rzTBag<5l^RVL%MdMx3_g?{ z(2~)T7;*I#vmC}f#X!pp9y3WS%_L5oe8U_lskwg5nF{jG?(W%Qc`e6p{&N>y`Eh$Y~>|hHx57ATmk(tSPQC5fG83E1pfeyMlZ3rAdWJlhF#hIb!e4z&6iz( z?mLee!1~uL_%DOd9)CK~Yxa^oftx4!RTPJLl~jy@+~d7NcQ?M59fA?dZ3B(C>T1j^ z(wLJdB0RZZDze&0PCj4z?0=12i%xz4*`NC8Ds0Tq%@TjyUau#~fP=JHAST&N4@?Dvj)qDs7M>B9H^1<2dPB zUdDG;xSEx$P+XOba6GVZ4teL?)E3|B-;dAeYf{ELFDVSDhXd!&{0pytN~8O+adsgf z$GGh)(;U=P+T~LCjOPCUTHjMz`fvpXaak-sc;8ys(+9{nu6B0EV`>!vdK^`>QI0sO z@B@xW`cDd?Sn{0It=|N5aB2TkZBr4Cz8~G0q1DVDcYm%iU3g}e|Y{>QwRs5 zkH(4s?3OW;kiV5YXSW!n!vn@o)Y1UmN`QW~sRDqqyc@ zq=tN-O!TA!f+$`A1M5Igy%e0&e8}<3;CfQ|i-CY~Ko0~Fl0f`vIR5YBieZ-{0Y4Db zfRp?=`kFvURRPYypIQqy0AukPrgBdxznP^4lx0W#@+k~+4c$h5qL**?Kp#qvGLh5| zs?%5!FiCI1fF!q9DXEyZd7=Tc9dm<>SDVdqe(#G&SX>2lc|gF=JFrJnj;6f>%}8wZ zfb0~TZZdJ$*9#DqODkoHIV3B;I~&%zsqAo6m6^^JmS}b>1;FLlbNC9S{g{cDcO{A7 z0bNMae9gXMNf~dK1CyUq?Nwh$xVMqK=nJUI{D(aM0EKC5nR`hUuGwR_L=luRq6Nnv z!av5X$d*fPS{dbeb`O&TbH;zIS%qLv5Gl8oNl?UXIM`H-UD>3U?BXf>yAHMR>+e?Zc534oRYtnf30KLM(<^J2m!WFC6f_NB}lbA@b!^sFfI5Mw=i zR6WeIeNk=RKuw=T#ZH z)tyM=P`dvBuC4s)n{}$W)}l1EM#hxWTBM~A&lH#~kiBq7`~@d!k`MKxzX$mm2G)j4 z+_lpxxC5ML(xdWD3hgC{$m8>?aNDf2DB2gEF0FPgtPz6!6fCo>MQ%5_E*}|fu zD8V7qocf9i0C$Yw@r+kQxKYMEdQrTC!K%1>Hgo7UBJy&_jyhAE7+=p-Wm0g<=xcXz z%AE2!s#>$NS+-7aMHdGPBRU(`SyhWMUg`-Ivm~B$0Kp@xo__h_xx`=y&2-vEw3>aJ z29JEB9#ir1^O`p@XsK_mT-zB+XL}$+*N{DV_oWigsG~{4D)MkK(x8_3O+1n?P*@T2 zih|ngTKTG~jk~jo1S=SwnxK4V4KN`6n z2OOWEs&Em3lloP(BePaxER41}9-j2&9jl_2@EiZDpzW9vW$2;^fPfKV4bKOE2oItnxB!-@bx0P96A zJr5_;(Lfz`WE_{l^u;tr%y&C2I0Od(Q)26wZ(Ca!~p0{ZbTV%TP7%!h2C}_ty zZ1=~ddF0Ta4^4Aza{|io$+26eK^f2KU2lSo*|NUaFq!?=nVqGv{{ZT)d&XDVg}$k8 zc+f)&AP61#Ssii<0qwhrx-)Ew)RWlAl)Z>++nqjm;+4Y&l;L-0BOfhAKZssPRXm~~ z-MK(v*Yc|x_4N9^pmm?jv{?pAl1n}hLFv}HNtX`TazNvn>P}YF!`Y;4X?NCeY4@(q z>iAHRXC?hl0|OrQZ0fe=&Rd5JCTWle17v_ZlZ*=HVo<8%cU)A?>RHGnZeVfrs#hN> zI-5@r$EQUV%o#FGDcu6LcCSuOG0rnx#g*;8uVjiK>GGW$9u7S!0@U_ug^fYhkTK??Ak*E2M8pb1u-4$8O2yZP>vaDBdbU{R zvNhfRf^$13Dmj0B+&%bJulc}rWulWAB>Hh#8(scS( zi8-v_4U_ikj=%BkC-STL=7e?9*s~TvADvB-at&2hJabZRIqO!6XmfHiRnIx8nT9*n zW{_?^w1FbE@DFP^AbhAu_N*{AjAR@d+q!S`S-sHKAtych)U%$d_lV9h+NH5jbqIaj zR7a|J_lXZ-1w*dLy{j@$ZZ+cPJnr|7P+QRm#TAwy=_Ds;-aInH=>h~CO~Q$ zF#PxJPWcJOa!+b;06sI2D+8hX$)S)}(cTiPx$fUym0C)1D;5;xr z4HX^~^ceclMZoRK=K%mdxyYeVkGvHJxujsksxuh}NDdp53 zdJ3`RHa>!y1e^jB@HC({K3%^~X#l@4>3~m6ifhI|`Ivv-CYKU(!1@-TmqXB>r63!Q zapoxY$26ukBPL9bVMqfp;4k7SaLdjy^%$TGsdagDeN?e6_IZ z*9Jv7O6uujF1ITyw)|$LnSdgzbGwRrlGrEGq-C3PykMU7EZ_?%F;wD^$D9n*%`s@o zXfGTFNd=sYL{b6q=yJFTPubC7uStgWlmB8qsOA9 zGR(YV0Dp~H(o)ht5Z#LcOe+J9PI=pd&(^Um^(hwC;wJ_}Due{L-NOU^MQG?2PYlfN zys|OD?ZrcOb}dHwo4bxNQRa=*)AzAdY>=#Sd8QI*X5>>`^XWkBCV3{Zd_j|Dxc>hD z^sPd9;;8BoiOgt5MoGuvQ72>#U0CMWlW!7^yPNt`LBZO6de>2FrAF}`(PsvvI#g;o zhOzdj=k_u(JUB?dxg(&qllfKkY}KT&js%iLk823qx3yJ>a1Ch*a~so(iqx5TCZx&D zMyCe`l(qq_M#PoyDxPx2q?Sz7N=8mwaI>Q*c^4TSdCf}Wa$XYY^NW~|iJLq#=4O?Ci8cVBxCQ_%@ifAOL z9jc=4j&`gmmvp<28L1(6$s0*r^%WM?^sOBz;zv+ETxORCf0b0@ zJ!?~?DC^R>u60eyO4l0{Kt`aBK&=}=f!I}59;=V7T!BdR0;P#7D;JX^s|?7nr;xz=5^GZ-#5l+AMtzo-ap}9CKru)%SmA?b zwkQSHgBp*cAMmCDzA!*+kETec}2ybIl+S%^q=vVn5k52MjpK z_B>P9aUO&9q-Dv;UVZ5dXpviln;(ZX?2s~C5$b6OAdSIkPbWJ?AQO79{{UDAxHN!+ z&T>6XIDz~_^rp89!sL36XaRQx^{6hQHx}<2@>pXT;MC!P>EE%Y720}oXim=H)z3e> z(Pmq@cU!0%&o~%AjZm9U5xXlSO3Ty|qZQw3<<{Id#ud8`dK&Ysei<%2OL!qxa%8{& zXFp2qRc@|esV3}7x;4bPDFU_z*`3`+HXe z&$k}0*4^$8Kjqc0z=G};cOBFFp7U5AXU6F|0wEY>k4#9zEz zXCF$h{{RT;w}YhApJ15}Z{i>0Rn8?%bvbclH)j!l-%Ct;K)=HuuijeT@J4|axqRz( z0YDFKMm;MN#Fp_|Y7G=F9Tf0Dr0N!^#k*XK>~8!dL64xtTK@oqb5N4ird>W`9@2M+ z&Oba=y&ebqWHNLHA&T{w#ylF~`2PS!eEvqG+TDrMNbxNfOD!tB#{>9Ru70)DC9sUU z4ls@Us}Dw5rM!*8HpS}L;8#k(gpi&_#{NdR2HTXEhrhI@F9o zIH;L(*EO(_UQC_`YLB3)nFu^)qQURdq|q|YpZ@?KNuGE-eig34djVNmcpqy|q5f5@ z(dVNdz}Gch#6of03Tah6zbcby^fc0^(Ee4D+-Ey+{{SBnf4pilQe1I!C;P|w(+IA# zXto=kX$>!WX`JOz{@nV_v5EJIjv_m7F zb`B~m5P0I3%wZnU(46M7gw%9rJ5Ki#P?4_m-98oN-~pueA#quI7`6Z;`eLsLl^<{f zAE~86(YSOZGMs`%U$qFwly{hA@Z@@U{{UOOWOl%OkH)AC(K%*DBRJ_+$|;k1UznWa zQ?Z{~9YoNh3l%ObqPhdj9FF6PgZm~A?=bvpOBB07IK^em(OjvSU)eC8j@3Q2id(T@ zNhgkK{{WYoO`P&5=WjseL_iM0oD}vIFP26yI@5w{s04 zl*Dm^hV;!a!o=aWk?BAR(gVg@@T6A9LJ0RGnnMoHyT>@%1t>yK8RxND147NE#BfYq z*Mg)SwZzAzUD{un;)pl|l_v(e({F*07xKkKV%T|Lzd>3?qeA6O=k>9u>l382TY|`; zKmz~|&Y2|Ir}jtof7x*mImSBvwb2-f$yZK$0Z_CI21Ja0wEeReA~~%lO;<^fy{)lU zBN;gV02;^CG+jqgyAEIq3Hga&KT7Tz*!2zhcc|J2KA)W@RkGA6Ip;}r7N&2`DzU{kwN1bt0f8Jr7?gXcwmYEu0cJigneq(INA)|?3GfGNeW0X==F0x*r=6rw&m52Yz1 zu%mal7^VXGV2&F!6&*21TL;pNk=4Hn1TN5f4AD&|9q~mL1HNt~0CdGW*XczSv4I+s zmE_d!2GPLiXrhrrItakyG_FW)4k)6420V|g2ktc#QW&Umtx=~dMHB#J;PX*jk|I(G z2iA%y3`iM@l1V4)Q@8rO`_V-L8=sttMdz;3pqL>KZd{m#rD58)9 zed Date: Fri, 31 May 2019 14:07:05 +0200 Subject: [PATCH 175/221] Documentation: Add PC Engines apu2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Describe how to run coreboot on the PC Engines apu2 mainboard. Change-Id: Id1d553c7f7485358960d92e714d50ba0f75b3581 Signed-off-by: Piotr Kleinschmidt Reviewed-on: https://review.coreboot.org/c/coreboot/+/33146 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- Documentation/mainboard/index.md | 4 + Documentation/mainboard/pcengines/apu2.jpg | Bin 0 -> 45462 bytes Documentation/mainboard/pcengines/apu2.md | 116 ++++++++++++++++++ .../mainboard/pcengines/apu2_spi.jpg | Bin 0 -> 22774 bytes 4 files changed, 120 insertions(+) create mode 100644 Documentation/mainboard/pcengines/apu2.jpg create mode 100644 Documentation/mainboard/pcengines/apu2.md create mode 100644 Documentation/mainboard/pcengines/apu2_spi.jpg diff --git a/Documentation/mainboard/index.md b/Documentation/mainboard/index.md index 205964fb1e..77e84efb51 100644 --- a/Documentation/mainboard/index.md +++ b/Documentation/mainboard/index.md @@ -86,6 +86,10 @@ The boards in this section are not real mainboards, but emulators. - [MS-7707](msi/ms7707/ms7707.md) +## PC Engines + +- [APU2](pcengines/apu2.md) + ## Roda - [RK9 Flash Header](roda/rk9/flash_header.md) diff --git a/Documentation/mainboard/pcengines/apu2.jpg b/Documentation/mainboard/pcengines/apu2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ae83b9ce9389ce83e081393714accd5098e6ae2c GIT binary patch literal 45462 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 literal 0 HcmV?d00001 diff --git a/Documentation/mainboard/pcengines/apu2.md b/Documentation/mainboard/pcengines/apu2.md new file mode 100644 index 0000000000..4a02e12f77 --- /dev/null +++ b/Documentation/mainboard/pcengines/apu2.md @@ -0,0 +1,116 @@ +# PC Engines APU2 + +This page describes how to run coreboot on PC Engines APU2 platform. + +## Technology + +```eval_rst ++------------+---------------------------------------------------------------+ +| CPU | AMD G series GX-412TC | ++------------+---------------------------------------------------------------+ +| CPU core | 1 GHz quad Puma core with 64 bit support | +| | 32K data + 32K instruction cache per core, shared 2MB L2 cache| ++------------+---------------------------------------------------------------+ +| DRAM | 2 or 4 GB DDR3-1333 DRAM | ++------------+---------------------------------------------------------------+ +| Boot | From SD card, USB, mSATA SSD, SATA | ++------------+---------------------------------------------------------------+ +| Power | 6 to 12W of 12V power | ++------------+---------------------------------------------------------------+ +| Firmware | coreboot with support for iPXE and USB boot | ++------------+---------------------------------------------------------------+ +``` + +## Required proprietary blobs + +To build working coreboot image some blobs are needed. + +```eval_rst ++-----------------+---------------------------------+---------------------+ +| Binary file | Apply | Required / Optional | ++=================+=================================+=====================+ +| amdfw.rom* | AMD Platform Security Processor | Required | ++-----------------+---------------------------------+---------------------+ +| AGESA.bin | AGESA Platform Initialization | Required | ++-----------------+---------------------------------+---------------------+ +| xhci.bin | AMD XHCI controller | Optional | ++-----------------+---------------------------------+---------------------+ +``` +(\*) - package containing all required blobs for PSP. Directory, in which all +blobs are listed and available is: *3rdparty/southbridge/amd/avalon/PSP* + +## Flashing coreboot + +```eval_rst ++---------------------+--------------------------+ +| Type | Value | ++=====================+==========================+ +| Socketed flash | no | ++---------------------+--------------------------+ +| Model | W25Q64 | ++---------------------+--------------------------+ +| Size | 8 MiB | ++---------------------+--------------------------+ +| Package | SOIC-8 | ++---------------------+--------------------------+ +| Write protection | jumper on WP# pin* | ++---------------------+--------------------------+ +| Dual BIOS feature | no | ++---------------------+--------------------------+ +| Internal flashing | yes | ++---------------------+--------------------------+ +``` +(\*) - It is used in normal SPI mode, but can be dangerous when using Quad SPI +Flash. Then, pull-down resistors should be considered rather than jumper. + +### Internal programming + +The SPI flash can be accessed using [flashrom]. + + flashrom -p internal -w coreboot.rom + +### External programming + +**IMPORTANT**: When programming SPI flash, first you need to enter apu2 in S5 +(Soft-off) power state. S5 state can be forced by shorting power button pin on +J2 header. + +The external access to flash chip is available through standard SOP-8 clip or +SOP-8 header next to the flash chip on the board. Notice that not all boards +have a header soldered down originally. Hence, there could be an empty slot with +8 eyelets, so you can solder down a header on your own. The SPI flash chip and +SPI header are marked in the picture below. Also there is SPI header and SPI +flash pin layout included. Depend on using header or clip there are important +rules: +- using header J6 - don't connect 1,7,8 pins +- using clip U23 - don't connect 3,7,8 pins + +Also signatures at the schematic can be ambiguous: +- J6 SPIDI = U23 SO = MISO +- J6 SPIDO = U23 SI = MOSI + +There is no restrictions as to the programmer device. It is only recommended to +flash firmware without supplying power. External programming can be performed, +for example using OrangePi and Armbian. You can exploit linux_spi driver which +provides communication with SPI devices. Example command to program SPI flash +with OrangePi using linux_spi: + + flashrom -f -w coreboot.rom -p linux_spi:dev=/dev/spidev1.0,spispeed=16000 + +**apu2 platform with marked in SPI header and SPI flash chip** + +![][apu2_flash] + +**SPI header pin layout** + +![][spi_header] + +## Schematics + +PC Engines APU2 [platform schematics](https://pcengines.ch/schema/apu2d.pdf) +are available for free on PC Engines official site. Both configurations +(2GB/4GB) have the same PCB and schematic. + +[apu2_flash]: apu2.jpg +[spi_header]: apu2_spi.jpg +[flashrom]: https://flashrom.org/Flashrom diff --git a/Documentation/mainboard/pcengines/apu2_spi.jpg b/Documentation/mainboard/pcengines/apu2_spi.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f8a5b5861e98f1e656c1c805363ae2e43fc17bf8 GIT binary patch literal 22774 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 literal 0 HcmV?d00001 From 393c71c21300a088ff5c46ea263b3b2e28084ce6 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Sun, 16 Jun 2019 16:09:42 +0800 Subject: [PATCH 176/221] add ctype.h header Sometimes coreboot needs to compile external code (e.g. vboot_reference) using its own set of system header files. When these headers don't line up with C Standard Library, it causes problems. Create ctype.h header file. Relocate ctype.h functions from string.h into ctype.h. Update source files which call ctype.h functions accordingly. Note that ctype.h still lacks five functions which are not used in coreboot source: isalnum, isalpha, iscntrl, isgraph, ispunct BUG=b:124141368 TEST=make clean && make test-abuild BRANCH=none Change-Id: I31b5e8af49956ec024a392a73c3c9024b9a9c194 Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/33525 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/console/vtxprintf.c | 1 + src/include/ctype.h | 56 ++++++++++++++++++++ src/include/string.h | 52 ------------------ src/lib/device_tree.c | 1 + src/lib/edid.c | 1 + src/lib/fit.c | 1 + src/lib/hexdump.c | 1 + src/lib/hexstrtobin.c | 1 + src/lib/string.c | 1 + src/vendorcode/cavium/bdk/lame_string.c | 1 + src/vendorcode/cavium/bdk/libdram/dram-spd.c | 1 + src/vendorcode/google/chromeos/vpd_mac.c | 1 + 12 files changed, 66 insertions(+), 52 deletions(-) create mode 100644 src/include/ctype.h diff --git a/src/console/vtxprintf.c b/src/console/vtxprintf.c index c429ac79e2..01091c82e8 100644 --- a/src/console/vtxprintf.c +++ b/src/console/vtxprintf.c @@ -16,6 +16,7 @@ */ #include +#include #include #define call_tx(x) tx_byte(x, data) diff --git a/src/include/ctype.h b/src/include/ctype.h new file mode 100644 index 0000000000..b4684af768 --- /dev/null +++ b/src/include/ctype.h @@ -0,0 +1,56 @@ +#ifndef CTYPE_H +#define CTYPE_H + +static inline int isspace(int c) +{ + switch (c) { + case ' ': case '\f': case '\n': + case '\r': case '\t': case '\v': + return 1; + default: + return 0; + } +} + +static inline int isprint(int c) +{ + return c >= ' ' && c <= '~'; +} + +static inline int isdigit(int c) +{ + return (c >= '0' && c <= '9'); +} + +static inline int isxdigit(int c) +{ + return ((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F')); +} + +static inline int isupper(int c) +{ + return (c >= 'A' && c <= 'Z'); +} + +static inline int islower(int c) +{ + return (c >= 'a' && c <= 'z'); +} + +static inline int toupper(int c) +{ + if (islower(c)) + c -= 'a'-'A'; + return c; +} + +static inline int tolower(int c) +{ + if (isupper(c)) + c -= 'A'-'a'; + return c; +} + +#endif /* CTYPE_H */ diff --git a/src/include/string.h b/src/include/string.h index d164f32b83..30241303eb 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -50,56 +50,4 @@ char *strrchr(const char *s, int c); */ unsigned int skip_atoi(char **s); -static inline int isspace(int c) -{ - switch (c) { - case ' ': case '\f': case '\n': - case '\r': case '\t': case '\v': - return 1; - default: - return 0; - } -} - -static inline int isprint(int c) -{ - return c >= ' ' && c <= '~'; -} - -static inline int isdigit(int c) -{ - return (c >= '0' && c <= '9'); -} - -static inline int isxdigit(int c) -{ - return ((c >= '0' && c <= '9') || - (c >= 'a' && c <= 'f') || - (c >= 'A' && c <= 'F')); -} - -static inline int isupper(int c) -{ - return (c >= 'A' && c <= 'Z'); -} - -static inline int islower(int c) -{ - return (c >= 'a' && c <= 'z'); -} - -static inline int toupper(int c) -{ - if (islower(c)) - c -= 'a'-'A'; - return c; -} - -static inline int tolower(int c) -{ - if (isupper(c)) - c -= 'A'-'a'; - return c; -} - #endif /* STRING_H */ diff --git a/src/lib/device_tree.c b/src/lib/device_tree.c index 2e81a08779..b8faab53b8 100644 --- a/src/lib/device_tree.c +++ b/src/lib/device_tree.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/src/lib/edid.c b/src/lib/edid.c index 3087172952..e2f213c5b0 100644 --- a/src/lib/edid.c +++ b/src/lib/edid.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/src/lib/fit.c b/src/lib/fit.c index 045f52f408..f1052e8f23 100644 --- a/src/lib/fit.c +++ b/src/lib/fit.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/src/lib/hexdump.c b/src/lib/hexdump.c index ca36ddee0e..1e689e3e53 100644 --- a/src/lib/hexdump.c +++ b/src/lib/hexdump.c @@ -13,6 +13,7 @@ */ #include +#include #include #include diff --git a/src/lib/hexstrtobin.c b/src/lib/hexstrtobin.c index ed2abc4e8b..61290b86d3 100644 --- a/src/lib/hexstrtobin.c +++ b/src/lib/hexstrtobin.c @@ -11,6 +11,7 @@ * GNU General Public License for more details. */ +#include #include #include diff --git a/src/lib/string.c b/src/lib/string.c index a19f017852..eb6adb67c7 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/src/vendorcode/cavium/bdk/lame_string.c b/src/vendorcode/cavium/bdk/lame_string.c index 11c5add209..3906ca5904 100644 --- a/src/vendorcode/cavium/bdk/lame_string.c +++ b/src/vendorcode/cavium/bdk/lame_string.c @@ -11,6 +11,7 @@ */ #include +#include #include #include diff --git a/src/vendorcode/cavium/bdk/libdram/dram-spd.c b/src/vendorcode/cavium/bdk/libdram/dram-spd.c index 1296119b65..84df69a923 100644 --- a/src/vendorcode/cavium/bdk/libdram/dram-spd.c +++ b/src/vendorcode/cavium/bdk/libdram/dram-spd.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include diff --git a/src/vendorcode/google/chromeos/vpd_mac.c b/src/vendorcode/google/chromeos/vpd_mac.c index e3ef04b669..fcd3efec9e 100644 --- a/src/vendorcode/google/chromeos/vpd_mac.c +++ b/src/vendorcode/google/chromeos/vpd_mac.c @@ -15,6 +15,7 @@ #include #include +#include #include #include From bc15cc3e86a7b2a1b5dd8b46443b9a859beeba93 Mon Sep 17 00:00:00 2001 From: Peter Lemenkov Date: Wed, 10 May 2017 16:21:03 +0200 Subject: [PATCH 177/221] mb/lenovo/z61t: Remove `fn_ctrl_swap` option It seems that the EC on t60/x60/z61t doesn't support it. This wasn't even introduced in z61t so let's remove the remaining bits. This commit follows up on commit a5fcc2e4 with Change-Id Id2964002406a5fcf992f0ffc3627e3f66a2bb13f ("mb/lenovo/x60/t60: Remove `fn_ctrl_swap` option"). Tested on a real hardware. Change-Id: Ifd5e7823af305cc4a0194ee2097a749e43680c55 Signed-off-by: Nico Huber Signed-off-by: Peter Lemenkov Reviewed-on: https://review.coreboot.org/c/coreboot/+/33364 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber Reviewed-by: Andrey Korolyov --- src/mainboard/lenovo/z61t/cmos.layout | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/z61t/cmos.layout b/src/mainboard/lenovo/z61t/cmos.layout index b9e2b4494a..75ad42760c 100644 --- a/src/mainboard/lenovo/z61t/cmos.layout +++ b/src/mainboard/lenovo/z61t/cmos.layout @@ -78,7 +78,7 @@ entries 952 8 h 0 volume 960 1 e 9 first_battery 961 1 e 1 trackpoint -962 1 e 1 fn_ctrl_swap +#962 1 r 0 unused 963 1 e 1 sticky_fn 964 1 e 1 power_management_beeps 965 1 e 1 low_battery_beep From 8b040c07309fbffe64b2695e111f724a4e979882 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Mon, 24 Jun 2019 08:57:56 +0200 Subject: [PATCH 178/221] mainboard/facebook/fbg1701: Use LCD Panel type for name of tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tc348860_table contains the eDP to MIPI Bridge controller type. b101uan08_table used the LCD Panel type. Use LCD Panel type for name of tables. Remove the incomplete resolution comments and specify the resolution at the start of the table to 1200x1920. BUG=N/A TEST=Config eDP and verify LCD panels are working on Facebook FBG-1701 Change-Id: Ic152ea1f95f155ab76638b57a259d37ce6f43037 Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33736 Reviewed-by: Kyösti Mälkki Tested-by: build bot (Jenkins) --- src/mainboard/facebook/fbg1701/ramstage.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/mainboard/facebook/fbg1701/ramstage.c b/src/mainboard/facebook/fbg1701/ramstage.c index 3903a6474e..5c78bccac5 100644 --- a/src/mainboard/facebook/fbg1701/ramstage.c +++ b/src/mainboard/facebook/fbg1701/ramstage.c @@ -28,8 +28,8 @@ struct edp_data { u8 data[6]; } __packed; -static const struct edp_data tc348860_table[] = { - /* set eDP bridge to eDP 1920 */ +static const struct edp_data b101uan01_table[] = { + /* set eDP bridge to 1200x1920 */ /* IO */ { 6, 0x68, { 0x08, 0x00, 0x01, 0x00, 0x00, 0x00 } }, /* Boot */ @@ -173,7 +173,7 @@ static const struct edp_data tc348860_table[] = { }; static const struct edp_data b101uan08_table[] = { - /* set eDP bridge to eDP 1920 */ + /* set eDP bridge to 1200x1920 */ /* IO Voltage Setting */ { 6, 0x68, { 0x08, 0x00, 0x01, 0x00, 0x00, 0x00 } }, /* Boot Settings */ @@ -333,7 +333,7 @@ static void mainboard_configure_edp_bridge(void) CPLD_PCB_VERSION_BIT; printk(BIOS_DEBUG, "CPLD version: %x\n", cpld_version); if (cpld_version < 7) - edptable = tc348860_table; + edptable = b101uan01_table; else edptable = b101uan08_table; @@ -341,7 +341,6 @@ static void mainboard_configure_edp_bridge(void) outb(CPLD_CMD_RESET_DSI_BRIDGE_ACTIVE, CPLD_RESET_PORT); outb(CPLD_CMD_RESET_DSI_BRIDGE_INACTIVE, CPLD_RESET_PORT); - /* set eDP bridge to eDP 1920 */ while (edptable->payload_length) { loops = 5; do { @@ -360,7 +359,6 @@ static void mainboard_configure_edp_bridge(void) void mainboard_silicon_init_params(SILICON_INIT_UPD *params) { - /* Configure the eDP bridge to eDP 1920 */ mainboard_configure_edp_bridge(); if (CONFIG(FSP1_1_DISPLAY_LOGO)) { From 3b4268379001f7f74989461183660a90a875f683 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Mon, 24 Jun 2019 11:30:39 +0200 Subject: [PATCH 179/221] mainboard/facebook/fbg1701: Set CBFS_SIZE to 0x600000 CBFS_SIZE equals size of whole SPI device. The descriptor and ME need to be placed in bottom part. Reduce the CBFS_SIZE to maximum avalaible size. BUG=N/A TEST=Boot Embedded Linux 4.20 on Facebook FBG-1701 Change-Id: Iecfae4573100c6787b6e8b1c4f2583a7fb3d95a3 Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33484 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans Reviewed-by: Paul Menzel --- src/mainboard/facebook/fbg1701/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/facebook/fbg1701/Kconfig b/src/mainboard/facebook/fbg1701/Kconfig index b3c589dc2f..95d8f6caae 100644 --- a/src/mainboard/facebook/fbg1701/Kconfig +++ b/src/mainboard/facebook/fbg1701/Kconfig @@ -54,7 +54,7 @@ config MAINBOARD_PART_NUMBER config CBFS_SIZE hex - default 0x00800000 + default 0x00600000 config CPU_MICROCODE_CBFS_LEN hex From 88164787ee7e7d9e13d5a9b95093fd70394ddc46 Mon Sep 17 00:00:00 2001 From: Patrick Havelange Date: Tue, 18 Jun 2019 12:15:07 +0200 Subject: [PATCH 180/221] soc/intel/dnv: Fix value of B_PCH_GPIO_RX_SCI_ROUTE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The value for that macro should be 1<<19. This is confirmed by the Intel doc and also by N_PCH_GPIO_RX_SCI_ROUTE. See Intel Atom® Processor C3000 Product Family Datasheet (February 2018) : https://www.intel.com/content/www/us/en/products/docs/processors/atom/c-series/c3000-family-datasheet.html Signed-off-by: Patrick Havelange Change-Id: I808d9131032a9796d837e00ad6fb3369b792e597 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33573 Reviewed-by: Paul Menzel Reviewed-by: HAOUAS Elyes Reviewed-by: Angel Pons Reviewed-by: David Guckian Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/soc/intel/denverton_ns/include/soc/gpio_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/soc/intel/denverton_ns/include/soc/gpio_defs.h b/src/soc/intel/denverton_ns/include/soc/gpio_defs.h index 43e0647bd0..ae61e6d7c4 100644 --- a/src/soc/intel/denverton_ns/include/soc/gpio_defs.h +++ b/src/soc/intel/denverton_ns/include/soc/gpio_defs.h @@ -182,7 +182,7 @@ #define V_PCH_GPIO_RX_APIC_ROUTE_EN 0x01 // GPIO Input Route SCI -#define B_PCH_GPIO_RX_SCI_ROUTE (1 << 10) +#define B_PCH_GPIO_RX_SCI_ROUTE (1 << 19) #define N_PCH_GPIO_RX_SCI_ROUTE 19 #define V_PCH_GPIO_RX_SCI_ROUTE_DIS 0x00 #define V_PCH_GPIO_RX_SCI_ROUTE_EN 0x01 From c32a92e5a00d19a031ad12e0133d1f1cf71dba96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=C3=B6sti=20M=C3=A4lkki?= Date: Fri, 4 Jan 2019 06:02:22 +0200 Subject: [PATCH 181/221] intel/945 boards: Use smp_write_pci_intsrc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Radically reduces line lengths and splits '(bus<<2) | INT' to separate parameters. Change-Id: I0cfd714da3d2773affdb34d1dab2ac32879e2cfd Signed-off-by: Kyösti Mälkki Reviewed-on: https://review.coreboot.org/c/coreboot/+/30740 Reviewed-by: HAOUAS Elyes Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/mainboard/apple/macbook21/mptable.c | 30 +++++++++++----------- src/mainboard/lenovo/t60/mptable.c | 30 +++++++++++----------- src/mainboard/lenovo/x60/mptable.c | 34 ++++++++++++------------- src/mainboard/lenovo/z61t/mptable.c | 30 +++++++++++----------- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/mainboard/apple/macbook21/mptable.c b/src/mainboard/apple/macbook21/mptable.c index cbd30c726e..61296134a8 100644 --- a/src/mainboard/apple/macbook21/mptable.c +++ b/src/mainboard/apple/macbook21/mptable.c @@ -41,21 +41,21 @@ static void *smp_write_config_table(void *v) smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, isa_bus, 0x00, MP_APIC_ALL, 0x00); smp_write_intsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x00, MP_APIC_ALL, 0x01); - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x01 << 2), 0x02, 0x10); /* PCIe root 0.02.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x02 << 2), 0x02, 0x10); /* VGA 0.02.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1b << 2), 0x02, 0x16); /* HD Audio 0:1b.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2), 0x02, 0x11); /* PCIe 0:1c.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x01, 0x02, 0x10); /* PCIe 0:1c.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x02, 0x02, 0x12); /* PCIe 0:1c.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x03, 0x02, 0x13); /* PCIe 0:1c.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) , 0x02, 0x15); /* USB 0:1d.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x01, 0x02, 0x13); /* USB 0:1d.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x02, 0x02, 0x12); /* USB 0:1d.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x03, 0x02, 0x10); /* USB 0:1d.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) , 0x02, 0x12); /* LPC 0:1f.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x01, 0x02, 0x13); /* IDE 0:1f.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x03, 0x02, 0x10); /* SATA 0:1f.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x03, (0x03 << 2) , 0x02, 0x13); /* Firewire 3:03.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x01, 0x00, 0x02, 0x10); /* PCIe root 0.01.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x02, 0x00, 0x02, 0x10); /* VGA 0.02.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1b, 0x00, 0x02, 0x16); /* HD Audio 0:1b.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x00, 0x02, 0x11); /* PCIe 0:1c.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x01, 0x02, 0x10); /* PCIe 0:1c.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x02, 0x02, 0x12); /* PCIe 0:1c.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x03, 0x02, 0x13); /* PCIe 0:1c.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x00, 0x02, 0x15); /* USB 0:1d.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x01, 0x02, 0x13); /* USB 0:1d.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x02, 0x02, 0x12); /* USB 0:1d.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x03, 0x02, 0x10); /* USB 0:1d.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x00, 0x02, 0x12); /* LPC 0:1f.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x01, 0x02, 0x13); /* IDE 0:1f.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x03, 0x02, 0x10); /* SATA 0:1f.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x03, 0x03, 0x00, 0x02, 0x13); /* Firewire 3:03.0 */ mptable_lintsrc(mc, isa_bus); return mptable_finalize(mc); diff --git a/src/mainboard/lenovo/t60/mptable.c b/src/mainboard/lenovo/t60/mptable.c index 838757e0c6..165b725ac6 100644 --- a/src/mainboard/lenovo/t60/mptable.c +++ b/src/mainboard/lenovo/t60/mptable.c @@ -41,21 +41,21 @@ static void *smp_write_config_table(void *v) smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, isa_bus, 0x00, MP_APIC_ALL, 0x00); smp_write_intsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x00, MP_APIC_ALL, 0x01); - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x01 << 2), 0x02, 0x10); /* PCIe root 0.02.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x02 << 2), 0x02, 0x10); /* VGA 0.02.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1b << 2), 0x02, 0x11); /* HD Audio 0:1b.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2), 0x02, 0x14); /* PCIe 0:1c.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x01, 0x02, 0x15); /* PCIe 0:1c.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x02, 0x02, 0x16); /* PCIe 0:1c.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x03, 0x02, 0x17); /* PCIe 0:1c.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) , 0x02, 0x10); /* USB 0:1d.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x01, 0x02, 0x11); /* USB 0:1d.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x02, 0x02, 0x12); /* USB 0:1d.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x03, 0x02, 0x13); /* USB 0:1d.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) , 0x02, 0x17); /* LPC 0:1f.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x01, 0x02, 0x10); /* IDE 0:1f.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x02, 0x02, 0x10); /* SATA 0:1f.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x06, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus 6:00.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x01, 0x00, 0x02, 0x10); /* PCIe root 0.01.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x02, 0x00, 0x02, 0x10); /* VGA 0.02.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1b, 0x00, 0x02, 0x11); /* HD Audio 0:1b.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x00, 0x02, 0x14); /* PCIe 0:1c.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x01, 0x02, 0x15); /* PCIe 0:1c.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x02, 0x02, 0x16); /* PCIe 0:1c.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x03, 0x02, 0x17); /* PCIe 0:1c.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x00, 0x02, 0x10); /* USB 0:1d.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x01, 0x02, 0x11); /* USB 0:1d.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x02, 0x02, 0x12); /* USB 0:1d.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x03, 0x02, 0x13); /* USB 0:1d.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x00, 0x02, 0x17); /* LPC 0:1f.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x01, 0x02, 0x10); /* IDE 0:1f.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x02, 0x02, 0x10); /* SATA 0:1f.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x06, 0x00, 0x00, 0x02, 0x10); /* Cardbus 6:00.0 */ mptable_lintsrc(mc, isa_bus); return mptable_finalize(mc); diff --git a/src/mainboard/lenovo/x60/mptable.c b/src/mainboard/lenovo/x60/mptable.c index 0118ba002f..886f72da37 100644 --- a/src/mainboard/lenovo/x60/mptable.c +++ b/src/mainboard/lenovo/x60/mptable.c @@ -41,23 +41,23 @@ static void *smp_write_config_table(void *v) smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, isa_bus, 0x00, MP_APIC_ALL, 0x00); smp_write_intsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x00, MP_APIC_ALL, 0x01); - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x01 << 2), 0x02, 0x10); /* PCIe root 0.02.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x02 << 2), 0x02, 0x10); /* VGA 0.02.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1b << 2), 0x02, 0x11); /* HD Audio 0:1b.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2), 0x02, 0x14); /* PCIe 0:1c.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x01, 0x02, 0x15); /* PCIe 0:1c.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x02, 0x02, 0x16); /* PCIe 0:1c.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x03, 0x02, 0x17); /* PCIe 0:1c.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) , 0x02, 0x10); /* USB 0:1d.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x01, 0x02, 0x11); /* USB 0:1d.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x02, 0x02, 0x12); /* USB 0:1d.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x03, 0x02, 0x13); /* USB 0:1d.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) , 0x02, 0x17); /* LPC 0:1f.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x01, 0x02, 0x10); /* IDE 0:1f.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x02, 0x02, 0x10); /* SATA 0:1f.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus 5:00.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x01, 0x02, 0x11); /* Firewire 5:00.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x05, (0x00 << 2) | 0x02, 0x02, 0x12); /* SDHC 5:00.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x01, 0x00, 0x02, 0x10); /* PCIe root 0.01.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x02, 0x00, 0x02, 0x10); /* VGA 0.02.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1b, 0x00, 0x02, 0x11); /* HD Audio 0:1b.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x00, 0x02, 0x14); /* PCIe 0:1c.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x01, 0x02, 0x15); /* PCIe 0:1c.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x02, 0x02, 0x16); /* PCIe 0:1c.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x03, 0x02, 0x17); /* PCIe 0:1c.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x00, 0x02, 0x10); /* USB 0:1d.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x01, 0x02, 0x11); /* USB 0:1d.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x02, 0x02, 0x12); /* USB 0:1d.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x03, 0x02, 0x13); /* USB 0:1d.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x00, 0x02, 0x17); /* LPC 0:1f.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x01, 0x02, 0x10); /* IDE 0:1f.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x02, 0x02, 0x10); /* SATA 0:1f.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x05, 0x00, 0x00, 0x02, 0x10); /* Cardbus 5:00.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x05, 0x00, 0x01, 0x02, 0x11); /* Firewire 5:00.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x05, 0x00, 0x02, 0x02, 0x12); /* SDHC 5:00.2 */ mptable_lintsrc(mc, isa_bus); return mptable_finalize(mc); diff --git a/src/mainboard/lenovo/z61t/mptable.c b/src/mainboard/lenovo/z61t/mptable.c index 838757e0c6..165b725ac6 100644 --- a/src/mainboard/lenovo/z61t/mptable.c +++ b/src/mainboard/lenovo/z61t/mptable.c @@ -41,21 +41,21 @@ static void *smp_write_config_table(void *v) smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, isa_bus, 0x00, MP_APIC_ALL, 0x00); smp_write_intsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x00, MP_APIC_ALL, 0x01); - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x01 << 2), 0x02, 0x10); /* PCIe root 0.02.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x02 << 2), 0x02, 0x10); /* VGA 0.02.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1b << 2), 0x02, 0x11); /* HD Audio 0:1b.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2), 0x02, 0x14); /* PCIe 0:1c.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x01, 0x02, 0x15); /* PCIe 0:1c.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x02, 0x02, 0x16); /* PCIe 0:1c.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1c << 2) | 0x03, 0x02, 0x17); /* PCIe 0:1c.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) , 0x02, 0x10); /* USB 0:1d.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x01, 0x02, 0x11); /* USB 0:1d.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x02, 0x02, 0x12); /* USB 0:1d.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1d << 2) | 0x03, 0x02, 0x13); /* USB 0:1d.3 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) , 0x02, 0x17); /* LPC 0:1f.0 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x01, 0x02, 0x10); /* IDE 0:1f.1 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x00, (0x1f << 2) | 0x02, 0x02, 0x10); /* SATA 0:1f.2 */ - smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x06, (0x00 << 2) | 0x00, 0x02, 0x10); /* Cardbus 6:00.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x01, 0x00, 0x02, 0x10); /* PCIe root 0.01.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x02, 0x00, 0x02, 0x10); /* VGA 0.02.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1b, 0x00, 0x02, 0x11); /* HD Audio 0:1b.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x00, 0x02, 0x14); /* PCIe 0:1c.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x01, 0x02, 0x15); /* PCIe 0:1c.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x02, 0x02, 0x16); /* PCIe 0:1c.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1c, 0x03, 0x02, 0x17); /* PCIe 0:1c.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x00, 0x02, 0x10); /* USB 0:1d.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x01, 0x02, 0x11); /* USB 0:1d.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x02, 0x02, 0x12); /* USB 0:1d.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1d, 0x03, 0x02, 0x13); /* USB 0:1d.3 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x00, 0x02, 0x17); /* LPC 0:1f.0 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x01, 0x02, 0x10); /* IDE 0:1f.1 */ + smp_write_pci_intsrc(mc, mp_INT, 0x00, 0x1f, 0x02, 0x02, 0x10); /* SATA 0:1f.2 */ + smp_write_pci_intsrc(mc, mp_INT, 0x06, 0x00, 0x00, 0x02, 0x10); /* Cardbus 6:00.0 */ mptable_lintsrc(mc, isa_bus); return mptable_finalize(mc); From 23e1202e353082c21e0b2cf4012226090b20a803 Mon Sep 17 00:00:00 2001 From: Caveh Jalali Date: Tue, 25 Jun 2019 15:46:50 -0700 Subject: [PATCH 182/221] atlas: enable GEO_SAR BUG=b:131634035 BRANCH=none TEST=verified SAR data shows up in ACPI SSDT table. Change-Id: I65ef59c9616b1cae3fa4c4b18bbfe4ed098d2891 Signed-off-by: Caveh Jalali Reviewed-on: https://review.coreboot.org/c/coreboot/+/33791 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/mainboard/google/poppy/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mainboard/google/poppy/Kconfig b/src/mainboard/google/poppy/Kconfig index e2ffe714c5..fda8c9e8b8 100644 --- a/src/mainboard/google/poppy/Kconfig +++ b/src/mainboard/google/poppy/Kconfig @@ -155,6 +155,7 @@ config VARIANT_SPECIFIC_OPTIONS_ATLAS select EXCLUDE_NATIVE_SD_INTERFACE select MAINBOARD_HAS_SPI_TPM_CR50 select VARIANT_HAS_CAMERA_ACPI + select GEO_SAR_ENABLE if CHROMEOS_WIFI_SAR config VARIANT_SPECIFIC_OPTIONS_POPPY def_bool n From 2ae3f51fa0ab9b1ec787297e9b237085e5fb3855 Mon Sep 17 00:00:00 2001 From: Felix Singer Date: Fri, 31 May 2019 02:06:22 +0200 Subject: [PATCH 183/221] mb/up/squared: Remove unnecessary code This patch removes unnecessary code which configures default FSP values. Change-Id: If7dae4f24a9fcb01d2d47063dd3a0f4ce6c120d2 Signed-off-by: Felix Singer Reviewed-on: https://review.coreboot.org/c/coreboot/+/33136 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/mainboard/up/squared/ramstage.c | 414 +++------------------------- 1 file changed, 38 insertions(+), 376 deletions(-) diff --git a/src/mainboard/up/squared/ramstage.c b/src/mainboard/up/squared/ramstage.c index e9fcfb2da3..be70ea995a 100644 --- a/src/mainboard/up/squared/ramstage.c +++ b/src/mainboard/up/squared/ramstage.c @@ -29,7 +29,6 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *silconfig) silconfig->CStateUnDemotion = 0x3; // 0x0 silconfig->PkgCStateDemotion = 0x1; // 0x0 silconfig->PkgCStateUnDemotion = 0x1; // 0x0 - silconfig->IpuEn = 0x0; // 0x1 silconfig->Pme = 0x1; // 0x0 silconfig->HdAudioIoBufferOwnership = 0x3; // 0x0 silconfig->DspEndpointDmic = 0x0; // 0x1 @@ -43,390 +42,53 @@ void mainboard_silicon_init_params(FSP_S_CONFIG *silconfig) silconfig->HpetDeviceNumber = 0xF; // 0x1f silconfig->IoApicBdfValid = 0x1; // 0x0 silconfig->IoApicDeviceNumber = 0x1F; // 0xf - silconfig->IshEnable = 0x0; // 0x1 - silconfig->SpiEiss = 0x0; // 0x1 silconfig->LPSS_S0ixEnable = 0x1; // 0x0 - silconfig->SdcardEnabled = 0x0; // 0x1 silconfig->eMMCHostMaxSpeed = 0x2; // 0x0 silconfig->Usb30Mode = 0x1; // 0x0 - silconfig->VtdEnable = 0x1; // 0x0 - silconfig->MonitorMwaitEnable = 0x0; // 0x1 - silconfig->HdAudioDspUaaCompliance = 0x1; // 0x0 - silconfig->InitS3Cpu = 0x1; // 0x0 + silconfig->HdAudioDspUaaCompliance = 0x1; // 0x0 + silconfig->InitS3Cpu = 0x1; // 0x0 - silconfig->PortUsb20PerPortTxPeHalf[0] = 0x0; - silconfig->PortUsb20PerPortPeTxiSet[0] = 0x7; - silconfig->PortUsb20PerPortTxiSet[0] = 0x0; - silconfig->PortUsb20HsSkewSel[0] = 0x0; - silconfig->PortUsb20IUsbTxEmphasisEn[0] = 0x3; - silconfig->PortUsb20PerPortRXISet[0] = 0x0; - silconfig->PortUsb20HsNpreDrvSel[0] = 0x0; + silconfig->PcieRpLtrMaxNonSnoopLatency[0] = 0x1003; // 0x0 + silconfig->PcieRpLtrMaxSnoopLatency[0] = 0x1003; // 0x0 - silconfig->PortUsb20PerPortTxPeHalf[1] = 0x0; - silconfig->PortUsb20PerPortPeTxiSet[1] = 0x6; - silconfig->PortUsb20PerPortTxiSet[1] = 0x0; - silconfig->PortUsb20HsSkewSel[1] = 0x0; - silconfig->PortUsb20IUsbTxEmphasisEn[1] = 0x3; - silconfig->PortUsb20PerPortRXISet[1] = 0x0; - silconfig->PortUsb20HsNpreDrvSel[1] = 0x0; + silconfig->PcieRpHotPlug[1] = 0x0; // 0x1 + silconfig->PcieRpPmSci[1] = 0x1; // 0x0 + silconfig->PcieRpTransmitterHalfSwing[1] = 0x0; // 0x1 + silconfig->PcieRpClkReqNumber[1] = 0x3; // 0x5 + silconfig->PcieRpLtrMaxNonSnoopLatency[1] = 0x1003; // 0x0 + silconfig->PcieRpLtrMaxSnoopLatency[1] = 0x1003; // 0x0 - silconfig->PortUsb20PerPortTxPeHalf[2] = 0x0; - silconfig->PortUsb20PerPortPeTxiSet[2] = 0x6; - silconfig->PortUsb20PerPortTxiSet[2] = 0x0; - silconfig->PortUsb20HsSkewSel[2] = 0x0; - silconfig->PortUsb20IUsbTxEmphasisEn[2] = 0x3; - silconfig->PortUsb20PerPortRXISet[2] = 0x0; - silconfig->PortUsb20HsNpreDrvSel[2] = 0x0; + silconfig->PcieRpHotPlug[2] = 0x0; // 0x1 + silconfig->PcieRpPmSci[2] = 0x1; // 0x0 + silconfig->PcieRpTransmitterHalfSwing[2] = 0x0; // 0x1 + silconfig->PcieRpLtrMaxNonSnoopLatency[2] = 0x1003; // 0x0 + silconfig->PcieRpLtrMaxSnoopLatency[2] = 0x1003; // 0x0 - silconfig->PortUsb20PerPortTxPeHalf[3] = 0x0; - silconfig->PortUsb20PerPortPeTxiSet[3] = 0x6; - silconfig->PortUsb20PerPortTxiSet[3] = 0x0; - silconfig->PortUsb20HsSkewSel[3] = 0x0; - silconfig->PortUsb20IUsbTxEmphasisEn[3] = 0x3; - silconfig->PortUsb20PerPortRXISet[3] = 0x0; - silconfig->PortUsb20HsNpreDrvSel[3] = 0x0; + silconfig->PcieRpHotPlug[3] = 0x0; // 0x1 + silconfig->PcieRpPmSci[3] = 0x1; // 0x0 + silconfig->PcieRpTransmitterHalfSwing[3] = 0x0; // 0x1 + silconfig->PcieRpLtrMaxNonSnoopLatency[3] = 0x1003; // 0x0 + silconfig->PcieRpLtrMaxSnoopLatency[3] = 0x1003; // 0x0 - silconfig->PortUsb20PerPortTxPeHalf[4] = 0x0; - silconfig->PortUsb20PerPortPeTxiSet[4] = 0x7; - silconfig->PortUsb20PerPortTxiSet[4] = 0x0; - silconfig->PortUsb20HsSkewSel[4] = 0x0; - silconfig->PortUsb20IUsbTxEmphasisEn[4] = 0x3; - silconfig->PortUsb20PerPortRXISet[4] = 0x0; - silconfig->PortUsb20HsNpreDrvSel[4] = 0x0; + silconfig->PcieRpHotPlug[4] = 0x0; // 0x1 + silconfig->PcieRpPmSci[4] = 0x1; // 0x0 + silconfig->PcieRpTransmitterHalfSwing[4] = 0x0; // 0x1 + silconfig->PcieRpLtrMaxNonSnoopLatency[4] = 0x1003; // 0x0 + silconfig->PcieRpLtrMaxSnoopLatency[4] = 0x1003; // 0x0 - silconfig->PortUsb20PerPortTxPeHalf[5] = 0x0; - silconfig->PortUsb20PerPortPeTxiSet[5] = 0x7; - silconfig->PortUsb20PerPortTxiSet[5] = 0x0; - silconfig->PortUsb20HsSkewSel[5] = 0x0; - silconfig->PortUsb20IUsbTxEmphasisEn[5] = 0x3; - silconfig->PortUsb20PerPortRXISet[5] = 0x0; - silconfig->PortUsb20HsNpreDrvSel[5] = 0x0; + silconfig->PcieRpHotPlug[5] = 0x0; // 0x1 + silconfig->PcieRpPmSci[5] = 0x1; // 0x0 + silconfig->PcieRpTransmitterHalfSwing[5] = 0x0; // 0x1 + silconfig->PcieRpLtrMaxNonSnoopLatency[5] = 0x1003; // 0x0 + silconfig->PcieRpLtrMaxSnoopLatency[5] = 0x1003; // 0x0 - silconfig->PortUsb20PerPortTxPeHalf[6] = 0x0; - silconfig->PortUsb20PerPortPeTxiSet[6] = 0x7; - silconfig->PortUsb20PerPortTxiSet[6] = 0x0; - silconfig->PortUsb20HsSkewSel[6] = 0x0; - silconfig->PortUsb20IUsbTxEmphasisEn[6] = 0x3; - silconfig->PortUsb20PerPortRXISet[6] = 0x0; - silconfig->PortUsb20HsNpreDrvSel[6] = 0x0; + silconfig->PortUs30bOverCurrentPin[0] = 0x0; // 0x1 - silconfig->PortUsb20PerPortTxPeHalf[7] = 0x0; - silconfig->PortUsb20PerPortPeTxiSet[7] = 0x1; - silconfig->PortUsb20PerPortTxiSet[7] = 0x3; - silconfig->PortUsb20HsSkewSel[7] = 0x1; - silconfig->PortUsb20IUsbTxEmphasisEn[7] = 0x1; - silconfig->PortUsb20PerPortRXISet[7] = 0x0; - silconfig->PortUsb20HsNpreDrvSel[7] = 0x3; - - - silconfig->WriteProtectionEnable[0] = 0x1; - silconfig->ReadProtectionEnable[0] = 0x1; - silconfig->ProtectedRangeLimit[0] = 0xFFF; - silconfig->ProtectedRangeBase[0] = 0x0; - - silconfig->IPC[0] = 0xFFFFEEF8; - silconfig->IPC[1] = 0xFFFFFFFF; - silconfig->IPC[2] = 0xFFFFFFFF; - silconfig->IPC[3] = 0xFFFFFFFF; - - silconfig->SataPortsDisableDynamicPg[0] = 0x0; - silconfig->SataPortsEnable[0] = 0x1; - silconfig->SataPortsDevSlp[0] = 0x0; - silconfig->SataPortsHotPlug[0] = 0x0; - silconfig->SataPortsInterlockSw[0] = 0x1; - silconfig->SataPortsExternal[0] = 0x0; - silconfig->SataPortsSpinUp[0] = 0x0; - silconfig->SataPortsSolidStateDrive[0] = 0x0; - silconfig->SataPortsEnableDitoConfig[0] = 0x0; - silconfig->SataPortsDmVal[0] = 0xF; - silconfig->SataPortsDitoVal[0] = 0x271; - - silconfig->SataPortsDisableDynamicPg[1] = 0x0; - silconfig->SataPortsEnable[1] = 0x1; - silconfig->SataPortsDevSlp[1] = 0x0; - silconfig->SataPortsHotPlug[1] = 0x0; - silconfig->SataPortsInterlockSw[1] = 0x1; - silconfig->SataPortsExternal[1] = 0x0; - silconfig->SataPortsSpinUp[1] = 0x0; - silconfig->SataPortsSolidStateDrive[1] = 0x0; - silconfig->SataPortsEnableDitoConfig[1] = 0x0; - silconfig->SataPortsDmVal[1] = 0xF; - silconfig->SataPortsDitoVal[1] = 0x271; - - - silconfig->PcieRootPortEn[0] = 0x1; - silconfig->PcieRpHide[0] = 0x0; - silconfig->PcieRpSlotImplemented[0] = 0x1; - silconfig->PcieRpHotPlug[0] = 0x0; - silconfig->PcieRpPmSci[0] = 0x1; - silconfig->PcieRpExtSync[0] = 0x1; - silconfig->PcieRpTransmitterHalfSwing[0] = 0x0; - silconfig->PcieRpAcsEnabled[0] = 0x1; - silconfig->PcieRpClkReqSupported[0] = 0x1; - silconfig->PcieRpClkReqNumber[0] = 0x2; - silconfig->PcieRpClkReqDetect[0] = 0x0; - silconfig->AdvancedErrorReporting[0] = 0x0; - silconfig->PmeInterrupt[0] = 0x0; - silconfig->UnsupportedRequestReport[0] = 0x0; - silconfig->FatalErrorReport[0] = 0x0; - silconfig->NoFatalErrorReport[0] = 0x0; - silconfig->CorrectableErrorReport[0] = 0x0; - silconfig->SystemErrorOnFatalError[0] = 0x0; - silconfig->SystemErrorOnNonFatalError[0] = 0x0; - silconfig->SystemErrorOnCorrectableError[0] = 0x0; - silconfig->PcieRpSpeed[0] = 0x0; - silconfig->PhysicalSlotNumber[0] = 0x0; - silconfig->PcieRpCompletionTimeout[0] = 0x0; - silconfig->PtmEnable[0] = 0x0; - silconfig->PcieRpAspm[0] = 0x4; - silconfig->PcieRpL1Substates[0] = 0x3; - silconfig->PcieRpLtrEnable[0] = 0x1; - silconfig->PcieRpLtrConfigLock[0] = 0x0; - silconfig->PcieRpSelectableDeemphasis[0] = 0x1; - silconfig->PcieRpNonSnoopLatencyOverrideValue[0] = 0x3C; - silconfig->PcieRpNonSnoopLatencyOverrideMultiplier[0] = 0x2; - silconfig->PcieRpSlotPowerLimitScale[0] = 0x0; - silconfig->PcieRpSlotPowerLimitValue[0] = 0x0; - silconfig->PcieRpLtrMaxNonSnoopLatency[0] = 0x1003; - silconfig->PcieRpNonSnoopLatencyOverrideMode[0] = 0x2; - silconfig->PcieRpLtrMaxSnoopLatency[0] = 0x1003; - silconfig->PcieRpSnoopLatencyOverrideMode[0] = 0x2; - silconfig->PcieRpSnoopLatencyOverrideValue[0] = 0x3C; - silconfig->PcieRpSnoopLatencyOverrideMultiplier[0] = 0x2; - - silconfig->PcieRootPortEn[1] = 0x1; - silconfig->PcieRpHide[1] = 0x0; - silconfig->PcieRpSlotImplemented[1] = 0x1; - silconfig->PcieRpHotPlug[1] = 0x0; - silconfig->PcieRpPmSci[1] = 0x1; - silconfig->PcieRpExtSync[1] = 0x1; - silconfig->PcieRpTransmitterHalfSwing[1] = 0x0; - silconfig->PcieRpAcsEnabled[1] = 0x1; - silconfig->PcieRpClkReqSupported[1] = 0x1; - silconfig->PcieRpClkReqNumber[1] = 0x3; - silconfig->PcieRpClkReqDetect[1] = 0x0; - silconfig->AdvancedErrorReporting[1] = 0x0; - silconfig->PmeInterrupt[1] = 0x0; - silconfig->UnsupportedRequestReport[1] = 0x0; - silconfig->FatalErrorReport[1] = 0x0; - silconfig->NoFatalErrorReport[1] = 0x0; - silconfig->CorrectableErrorReport[1] = 0x0; - silconfig->SystemErrorOnFatalError[1] = 0x0; - silconfig->SystemErrorOnNonFatalError[1] = 0x0; - silconfig->SystemErrorOnCorrectableError[1] = 0x0; - silconfig->PcieRpSpeed[1] = 0x0; - silconfig->PhysicalSlotNumber[1] = 0x1; - silconfig->PcieRpCompletionTimeout[1] = 0x0; - silconfig->PtmEnable[1] = 0x0; - silconfig->PcieRpAspm[1] = 0x4; - silconfig->PcieRpL1Substates[1] = 0x3; - silconfig->PcieRpLtrEnable[1] = 0x1; - silconfig->PcieRpLtrConfigLock[1] = 0x0; - silconfig->PcieRpSelectableDeemphasis[1] = 0x1; - silconfig->PcieRpNonSnoopLatencyOverrideValue[1] = 0x3C; - silconfig->PcieRpNonSnoopLatencyOverrideMultiplier[1] = 0x2; - silconfig->PcieRpSlotPowerLimitScale[1] = 0x0; - silconfig->PcieRpSlotPowerLimitValue[1] = 0x0; - silconfig->PcieRpLtrMaxNonSnoopLatency[1] = 0x1003; - silconfig->PcieRpNonSnoopLatencyOverrideMode[1] = 0x2; - silconfig->PcieRpLtrMaxSnoopLatency[1] = 0x1003; - silconfig->PcieRpSnoopLatencyOverrideMode[1] = 0x2; - silconfig->PcieRpSnoopLatencyOverrideValue[1] = 0x3C; - silconfig->PcieRpSnoopLatencyOverrideMultiplier[1] = 0x2; - - silconfig->PcieRootPortEn[2] = 0x1; - silconfig->PcieRpHide[2] = 0x0; - silconfig->PcieRpSlotImplemented[2] = 0x1; - silconfig->PcieRpHotPlug[2] = 0x0; - silconfig->PcieRpPmSci[2] = 0x1; - silconfig->PcieRpExtSync[2] = 0x1; - silconfig->PcieRpTransmitterHalfSwing[2] = 0x0; - silconfig->PcieRpAcsEnabled[2] = 0x1; - silconfig->PcieRpClkReqSupported[2] = 0x1; - silconfig->PcieRpClkReqNumber[2] = 0x0; - silconfig->PcieRpClkReqDetect[2] = 0x0; - silconfig->AdvancedErrorReporting[2] = 0x0; - silconfig->PmeInterrupt[2] = 0x0; - silconfig->UnsupportedRequestReport[2] = 0x0; - silconfig->FatalErrorReport[2] = 0x0; - silconfig->NoFatalErrorReport[2] = 0x0; - silconfig->CorrectableErrorReport[2] = 0x0; - silconfig->SystemErrorOnFatalError[2] = 0x0; - silconfig->SystemErrorOnNonFatalError[2] = 0x0; - silconfig->SystemErrorOnCorrectableError[2] = 0x0; - silconfig->PcieRpSpeed[2] = 0x0; - silconfig->PhysicalSlotNumber[2] = 0x2; - silconfig->PcieRpCompletionTimeout[2] = 0x0; - silconfig->PtmEnable[2] = 0x0; - silconfig->PcieRpAspm[2] = 0x4; - silconfig->PcieRpL1Substates[2] = 0x3; - silconfig->PcieRpLtrEnable[2] = 0x1; - silconfig->PcieRpLtrConfigLock[2] = 0x0; - silconfig->PcieRpSelectableDeemphasis[2] = 0x1; - silconfig->PcieRpNonSnoopLatencyOverrideValue[2] = 0x3C; - silconfig->PcieRpNonSnoopLatencyOverrideMultiplier[2] = 0x2; - silconfig->PcieRpSlotPowerLimitScale[2] = 0x0; - silconfig->PcieRpSlotPowerLimitValue[2] = 0x0; - silconfig->PcieRpLtrMaxNonSnoopLatency[2] = 0x1003; - silconfig->PcieRpNonSnoopLatencyOverrideMode[2] = 0x2; - silconfig->PcieRpLtrMaxSnoopLatency[2] = 0x1003; - silconfig->PcieRpSnoopLatencyOverrideMode[2] = 0x2; - silconfig->PcieRpSnoopLatencyOverrideValue[2] = 0x0; - silconfig->PcieRpSnoopLatencyOverrideMultiplier[2] = 0x2; - - silconfig->PcieRootPortEn[3] = 0x1; - silconfig->PcieRpHide[3] = 0x0; - silconfig->PcieRpSlotImplemented[3] = 0x1; - silconfig->PcieRpHotPlug[3] = 0x0; - silconfig->PcieRpPmSci[3] = 0x1; - silconfig->PcieRpExtSync[3] = 0x1; - silconfig->PcieRpTransmitterHalfSwing[3] = 0x0; - silconfig->PcieRpAcsEnabled[3] = 0x1; - silconfig->PcieRpClkReqSupported[3] = 0x1; - silconfig->PcieRpClkReqNumber[3] = 0x1; - silconfig->PcieRpClkReqDetect[3] = 0x0; - silconfig->AdvancedErrorReporting[3] = 0x0; - silconfig->PmeInterrupt[3] = 0x0; - silconfig->UnsupportedRequestReport[3] = 0x0; - silconfig->FatalErrorReport[3] = 0x0; - silconfig->NoFatalErrorReport[3] = 0x0; - silconfig->CorrectableErrorReport[3] = 0x0; - silconfig->SystemErrorOnFatalError[3] = 0x0; - silconfig->SystemErrorOnNonFatalError[3] = 0x0; - silconfig->SystemErrorOnCorrectableError[3] = 0x0; - silconfig->PcieRpSpeed[3] = 0x0; - silconfig->PhysicalSlotNumber[3] = 0x3; - silconfig->PcieRpCompletionTimeout[3] = 0x0; - silconfig->PtmEnable[3] = 0x0; - silconfig->PcieRpAspm[3] = 0x4; - silconfig->PcieRpL1Substates[3] = 0x3; - silconfig->PcieRpLtrEnable[3] = 0x1; - silconfig->PcieRpLtrConfigLock[3] = 0x0; - silconfig->PcieRpSelectableDeemphasis[3] = 0x1; - silconfig->PcieRpNonSnoopLatencyOverrideValue[3] = 0x3C; - silconfig->PcieRpNonSnoopLatencyOverrideMultiplier[3] = 0x2; - silconfig->PcieRpSlotPowerLimitScale[3] = 0x0; - silconfig->PcieRpSlotPowerLimitValue[3] = 0x0; - silconfig->PcieRpLtrMaxNonSnoopLatency[3] = 0x1003; - silconfig->PcieRpNonSnoopLatencyOverrideMode[3] = 0x2; - silconfig->PcieRpLtrMaxSnoopLatency[3] = 0x1003; - silconfig->PcieRpSnoopLatencyOverrideMode[3] = 0x2; - silconfig->PcieRpSnoopLatencyOverrideValue[3] = 0x3C; - silconfig->PcieRpSnoopLatencyOverrideMultiplier[3] = 0x2; - - silconfig->PcieRootPortEn[4] = 0x1; - silconfig->PcieRpHide[4] = 0x0; - silconfig->PcieRpSlotImplemented[4] = 0x1; - silconfig->PcieRpHotPlug[4] = 0x0; - silconfig->PcieRpPmSci[4] = 0x1; - silconfig->PcieRpExtSync[4] = 0x1; - silconfig->PcieRpTransmitterHalfSwing[4] = 0x0; - silconfig->PcieRpAcsEnabled[4] = 0x1; - silconfig->PcieRpClkReqSupported[4] = 0x1; - silconfig->PcieRpClkReqNumber[4] = 0x2; - silconfig->PcieRpClkReqDetect[4] = 0x0; - silconfig->AdvancedErrorReporting[4] = 0x0; - silconfig->PmeInterrupt[4] = 0x0; - silconfig->UnsupportedRequestReport[4] = 0x0; - silconfig->FatalErrorReport[4] = 0x0; - silconfig->NoFatalErrorReport[4] = 0x0; - silconfig->CorrectableErrorReport[4] = 0x0; - silconfig->SystemErrorOnFatalError[4] = 0x0; - silconfig->SystemErrorOnNonFatalError[4] = 0x0; - silconfig->SystemErrorOnCorrectableError[4] = 0x0; - silconfig->PcieRpSpeed[4] = 0x0; - silconfig->PhysicalSlotNumber[4] = 0x4; - silconfig->PcieRpCompletionTimeout[4] = 0x0; - silconfig->PtmEnable[4] = 0x0; - silconfig->PcieRpAspm[4] = 0x4; - silconfig->PcieRpL1Substates[4] = 0x3; - silconfig->PcieRpLtrEnable[4] = 0x1; - silconfig->PcieRpLtrConfigLock[4] = 0x0; - silconfig->PcieRpSelectableDeemphasis[4] = 0x1; - silconfig->PcieRpNonSnoopLatencyOverrideValue[4] = 0x3C; - silconfig->PcieRpNonSnoopLatencyOverrideMultiplier[4] = 0x2; - silconfig->PcieRpSlotPowerLimitScale[4] = 0x0; - silconfig->PcieRpSlotPowerLimitValue[4] = 0x0; - silconfig->PcieRpLtrMaxNonSnoopLatency[4] = 0x1003; - silconfig->PcieRpNonSnoopLatencyOverrideMode[4] = 0x2; - silconfig->PcieRpLtrMaxSnoopLatency[4] = 0x1003; - silconfig->PcieRpSnoopLatencyOverrideMode[4] = 0x2; - silconfig->PcieRpSnoopLatencyOverrideValue[4] = 0x3C; - silconfig->PcieRpSnoopLatencyOverrideMultiplier[4] = 0x2; - - silconfig->PcieRootPortEn[5] = 0x1; - silconfig->PcieRpHide[5] = 0x0; - silconfig->PcieRpSlotImplemented[5] = 0x1; - silconfig->PcieRpHotPlug[5] = 0x0; - silconfig->PcieRpPmSci[5] = 0x1; - silconfig->PcieRpExtSync[5] = 0x1; - silconfig->PcieRpTransmitterHalfSwing[5] = 0x0; - silconfig->PcieRpAcsEnabled[5] = 0x1; - silconfig->PcieRpClkReqSupported[5] = 0x1; - silconfig->PcieRpClkReqNumber[5] = 0x3; - silconfig->PcieRpClkReqDetect[5] = 0x0; - silconfig->AdvancedErrorReporting[5] = 0x0; - silconfig->PmeInterrupt[5] = 0x0; - silconfig->UnsupportedRequestReport[5] = 0x0; - silconfig->FatalErrorReport[5] = 0x0; - silconfig->NoFatalErrorReport[5] = 0x0; - silconfig->CorrectableErrorReport[5] = 0x0; - silconfig->SystemErrorOnFatalError[5] = 0x0; - silconfig->SystemErrorOnNonFatalError[5] = 0x0; - silconfig->SystemErrorOnCorrectableError[5] = 0x0; - silconfig->PcieRpSpeed[5] = 0x0; - silconfig->PhysicalSlotNumber[5] = 0x5; - silconfig->PcieRpCompletionTimeout[5] = 0x0; - silconfig->PtmEnable[5] = 0x0; - silconfig->PcieRpAspm[5] = 0x4; - silconfig->PcieRpL1Substates[5] = 0x3; - silconfig->PcieRpLtrEnable[5] = 0x1; - silconfig->PcieRpLtrConfigLock[5] = 0x0; - silconfig->PcieRpSelectableDeemphasis[5] = 0x1; - silconfig->PcieRpNonSnoopLatencyOverrideValue[5] = 0x3C; - silconfig->PcieRpNonSnoopLatencyOverrideMultiplier[5] = 0x2; - silconfig->PcieRpSlotPowerLimitScale[5] = 0x0; - silconfig->PcieRpSlotPowerLimitValue[5] = 0x0; - silconfig->PcieRpLtrMaxNonSnoopLatency[5] = 0x1003; - silconfig->PcieRpNonSnoopLatencyOverrideMode[5] = 0x2; - silconfig->PcieRpLtrMaxSnoopLatency[5] = 0x1003; - silconfig->PcieRpSnoopLatencyOverrideMode[5] = 0x2; - silconfig->PcieRpSnoopLatencyOverrideValue[5] = 0x3C; - silconfig->PcieRpSnoopLatencyOverrideMultiplier[5] = 0x2; - - - silconfig->SsicRate[0] = 0x1; - silconfig->SsicPortEnable[0] = 0x0; - silconfig->SsicRate[1] = 0x1; - silconfig->SsicPortEnable[1] = 0x0; - - silconfig->PortUsb30Enable[0] = 0x1; - silconfig->PortUs30bOverCurrentPin[0] = 0x0; - silconfig->PortUsb30Enable[1] = 0x1; - silconfig->PortUs30bOverCurrentPin[1] = 0x1; - silconfig->PortUsb30Enable[2] = 0x1; - silconfig->PortUs30bOverCurrentPin[2] = 0x1; - silconfig->PortUsb30Enable[3] = 0x1; - silconfig->PortUs30bOverCurrentPin[3] = 0x1; - silconfig->PortUsb30Enable[4] = 0x1; - silconfig->PortUs30bOverCurrentPin[4] = 0x1; - silconfig->PortUsb30Enable[5] = 0x1; - silconfig->PortUs30bOverCurrentPin[5] = 0x1; - - silconfig->PortUsb20Enable[0] = 0x1; - silconfig->PortUs20bOverCurrentPin[0] = 0x0; - silconfig->PortUsb20Enable[1] = 0x1; - silconfig->PortUs20bOverCurrentPin[1] = 0x1; - silconfig->PortUsb20Enable[2] = 0x1; - silconfig->PortUs20bOverCurrentPin[2] = 0x1; - silconfig->PortUsb20Enable[3] = 0x1; - silconfig->PortUs20bOverCurrentPin[3] = 0x1; - silconfig->PortUsb20Enable[4] = 0x1; - silconfig->PortUs20bOverCurrentPin[4] = 0x1; - silconfig->PortUsb20Enable[5] = 0x1; - silconfig->PortUs20bOverCurrentPin[5] = 0x1; - silconfig->PortUsb20Enable[6] = 0x1; - silconfig->PortUs20bOverCurrentPin[6] = 0x2; - silconfig->PortUsb20Enable[7] = 0x1; - silconfig->PortUs20bOverCurrentPin[7] = 0x2; + silconfig->PortUs20bOverCurrentPin[1] = 0x1; // 0x0 + silconfig->PortUs20bOverCurrentPin[2] = 0x1; // 0x0 + silconfig->PortUs20bOverCurrentPin[3] = 0x1; // 0x0 + silconfig->PortUs20bOverCurrentPin[4] = 0x1; // 0x0 + silconfig->PortUs20bOverCurrentPin[5] = 0x1; // 0x0 + silconfig->PortUs20bOverCurrentPin[6] = 0x2; // 0x0 + silconfig->PortUs20bOverCurrentPin[7] = 0x2; // 0x0 } From b4a1981289d785dc62be3cde9b87ba2a64946ec5 Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Tue, 25 Jun 2019 17:28:30 +0800 Subject: [PATCH 184/221] cbfstool/fit: need inttypes.h for PRIx64 This is causing coreboot build in Chromium OS to fail. BUG=None TEST=emerge-eve coreboot BRANCH=none Change-Id: I4faa140b3046651b4ed0a9aeefe437048c6ef0da Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/33780 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- util/cbfstool/fit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/util/cbfstool/fit.c b/util/cbfstool/fit.c index 4cd84f232d..ee12c96610 100644 --- a/util/cbfstool/fit.c +++ b/util/cbfstool/fit.c @@ -15,6 +15,7 @@ * GNU General Public License for more details. */ +#include #include #include #include From c8db633852229462c2d7e89ef1ac6ab34b47e5a3 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 17 Jun 2019 13:32:13 +0200 Subject: [PATCH 185/221] soc/intel/cannonlake/Kconfig: Don't have all variants select SOC_INTEL_CANNONLAKE This allows to use Kconfig options to differentiate between SOC variants. Change-Id: Ica11c68377e3d0dc8a8f48198e01a74d7bebe642 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33559 Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/soc/intel/cannonlake/Kconfig | 27 +++++++++++++-------------- src/soc/intel/cannonlake/Makefile.inc | 2 +- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index 7b4282c934..2279df2247 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -1,12 +1,9 @@ -config SOC_INTEL_CANNONLAKE +config SOC_INTEL_CANNONLAKE_BASE bool - help - Intel Cannonlake support config SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS bool - default n - select SOC_INTEL_CANNONLAKE + default y if SOC_INTEL_CANNONLAKE_BASE && !SOC_INTEL_CANNONLAKE help Single Kconfig option to select common base Cannonlake support. This Kconfig will help to select majority of CNL SoC features. @@ -16,34 +13,36 @@ config SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS required SoC support FSP headers. Any future Intel SoC would like to make use of CNL support might just select this Kconfig. +config SOC_INTEL_CANNONLAKE + bool + select SOC_INTEL_CANNONLAKE_BASE + help + Intel Cannonlake support + config SOC_INTEL_COFFEELAKE bool - default n - select SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS + select SOC_INTEL_CANNONLAKE_BASE help Intel Coffeelake support config SOC_INTEL_WHISKEYLAKE bool - default n - select SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS + select SOC_INTEL_CANNONLAKE_BASE help Intel Whiskeylake support config SOC_INTEL_COMETLAKE bool - default n - select SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS + select SOC_INTEL_CANNONLAKE_BASE help Intel Cometlake support config SOC_INTEL_CANNONLAKE_PCH_H bool - default n help Choose this option if you have a PCH-H chipset. -if SOC_INTEL_CANNONLAKE +if SOC_INTEL_CANNONLAKE_BASE config CPU_SPECIFIC_OPTIONS def_bool y @@ -297,7 +296,7 @@ config FSP_HEADER_PATH string "Location of FSP headers" default "3rdparty/fsp/CoffeeLakeFspBinPkg/Include/" if SOC_INTEL_COFFEELAKE || SOC_INTEL_WHISKEYLAKE default "src/vendorcode/intel/fsp/fsp2_0/cometlake/" if SOC_INTEL_COMETLAKE - default "src/vendorcode/intel/fsp/fsp2_0/cannonlake/" + default "src/vendorcode/intel/fsp/fsp2_0/cannonlake/" if SOC_INTEL_CANNONLAKE config FSP_FD_PATH string diff --git a/src/soc/intel/cannonlake/Makefile.inc b/src/soc/intel/cannonlake/Makefile.inc index 13289448b6..5017410234 100644 --- a/src/soc/intel/cannonlake/Makefile.inc +++ b/src/soc/intel/cannonlake/Makefile.inc @@ -1,4 +1,4 @@ -ifeq ($(CONFIG_SOC_INTEL_CANNONLAKE),y) +ifeq ($(CONFIG_SOC_INTEL_CANNONLAKE_BASE),y) subdirs-y += romstage subdirs-y += ../../../cpu/intel/microcode From 755a0131bec580f39097b2b4475e7bcd673a407e Mon Sep 17 00:00:00 2001 From: Sumeet Pawnikar Date: Fri, 21 Jun 2019 18:05:37 +0530 Subject: [PATCH 186/221] mb/google/hatch/variants/baseboard: Update PL2 power limit value Update PL2 power limit value from 44W to 64W. BUG=None BRANCH=None TEST=Build and Boot hatch EVT Change-Id: I3f4b5ab8bf0ce9464c322c148843f5a3e8d706d9 Signed-off-by: Sumeet Pawnikar Reviewed-on: https://review.coreboot.org/c/coreboot/+/33662 Tested-by: build bot (Jenkins) Reviewed-by: Tim Wawrzynczak Reviewed-by: Shelley Chen --- src/mainboard/google/hatch/variants/baseboard/devicetree.cb | 2 +- .../hatch/variants/baseboard/include/baseboard/acpi/dptf.asl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/hatch/variants/baseboard/devicetree.cb b/src/mainboard/google/hatch/variants/baseboard/devicetree.cb index a66c74328e..9a9125396c 100644 --- a/src/mainboard/google/hatch/variants/baseboard/devicetree.cb +++ b/src/mainboard/google/hatch/variants/baseboard/devicetree.cb @@ -36,7 +36,7 @@ chip soc/intel/cannonlake # Enable DPTF register "dptf_enable" = "1" register "tdp_pl1_override" = "15" - register "tdp_pl2_override" = "44" + register "tdp_pl2_override" = "64" register "Device4Enable" = "1" # Enable eDP device register "DdiPortEdp" = "1" diff --git a/src/mainboard/google/hatch/variants/baseboard/include/baseboard/acpi/dptf.asl b/src/mainboard/google/hatch/variants/baseboard/include/baseboard/acpi/dptf.asl index ff7db49334..b18932ec6c 100644 --- a/src/mainboard/google/hatch/variants/baseboard/include/baseboard/acpi/dptf.asl +++ b/src/mainboard/google/hatch/variants/baseboard/include/baseboard/acpi/dptf.asl @@ -118,7 +118,7 @@ Name (MPPC, Package () Package () { /* Power Limit 2 */ 1, /* PowerLimitIndex, 1 for Power Limit 2 */ 15000, /* PowerLimitMinimum */ - 44000, /* PowerLimitMaximum */ + 64000, /* PowerLimitMaximum */ 28000, /* TimeWindowMinimum */ 32000, /* TimeWindowMaximum */ 1000 /* StepSize */ From 6f7f39e96b3ead69e054218adedc3350ee46d775 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Mon, 17 Jun 2019 19:54:49 -0700 Subject: [PATCH 187/221] mb/google/hatch: Remove pulls on NC pads There is no need to add internal termination (PU/PD) on the not-connected pads. This change gets rid of the terminations on the NC pads. Change-Id: I3df538d7127e5ef75e6e6ff9db3524e26f0450ed Signed-off-by: Furquan Shaikh Reviewed-on: https://review.coreboot.org/c/coreboot/+/33570 Tested-by: build bot (Jenkins) Reviewed-by: Paul Fagerburg Reviewed-by: Aamir Bohra Reviewed-by: Tim Wawrzynczak --- src/mainboard/google/hatch/variants/baseboard/gpio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mainboard/google/hatch/variants/baseboard/gpio.c b/src/mainboard/google/hatch/variants/baseboard/gpio.c index e309175d03..5d0b8614dd 100644 --- a/src/mainboard/google/hatch/variants/baseboard/gpio.c +++ b/src/mainboard/google/hatch/variants/baseboard/gpio.c @@ -138,9 +138,9 @@ static const struct pad_config gpio_table[] = { /* C9 : UART_PCH_TX_DEBUG_RX */ PAD_CFG_NF(GPP_C9, NONE, DEEP, NF1), /* C10 : GPP_10 ==> GPP_C10_TP */ - PAD_NC(GPP_C10, DN_20K), + PAD_NC(GPP_C10, NONE), /* C11 : GPP_11 ==> GPP_C11_TP */ - PAD_NC(GPP_C11, DN_20K), + PAD_NC(GPP_C11, NONE), /* C12 : GPP_C12 ==> NC */ PAD_NC(GPP_C12, NONE), /* C13 : EC_PCH_INT_L @@ -343,7 +343,7 @@ static const struct pad_config gpio_table[] = { /* G6 : SD_CLK */ PAD_CFG_NF(GPP_G6, NONE, DEEP, NF1), /* G7 : SD_WP => NC */ - PAD_NC(GPP_G7, DN_20K), + PAD_NC(GPP_G7, NONE), /* * H0 : HP_INT_L */ From 80604cdf0337dcbd9baf7f7464845b3cddf91f8a Mon Sep 17 00:00:00 2001 From: Philip Chen Date: Thu, 20 Jun 2019 18:05:28 -0700 Subject: [PATCH 188/221] mb/google/hatch: Add a GPIO to enable/disable FPMCU power A FPMCU power-control pin (GPP_C11) is added to the latest hatch reference schematic. Even though this is not implemented in hatch rev1 board, the future hatch family boards with FPMCU should all have this control pin. On the old boards without this control pin, GPP_C11 is a floating TP, and thus this patch should be backward-compatible. BUG=b:130307667, b:135216932 TEST=build Signed-off-by: Philip Chen Change-Id: I6a84eeb6aab562258e749a8a5d09dadfa0e43587 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33655 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/mainboard/google/hatch/variants/baseboard/gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mainboard/google/hatch/variants/baseboard/gpio.c b/src/mainboard/google/hatch/variants/baseboard/gpio.c index 5d0b8614dd..9529cc750a 100644 --- a/src/mainboard/google/hatch/variants/baseboard/gpio.c +++ b/src/mainboard/google/hatch/variants/baseboard/gpio.c @@ -139,8 +139,8 @@ static const struct pad_config gpio_table[] = { PAD_CFG_NF(GPP_C9, NONE, DEEP, NF1), /* C10 : GPP_10 ==> GPP_C10_TP */ PAD_NC(GPP_C10, NONE), - /* C11 : GPP_11 ==> GPP_C11_TP */ - PAD_NC(GPP_C11, NONE), + /* C11 : GPP_11 ==> EN_FP_RAILS */ + PAD_CFG_GPO(GPP_C11, 1, DEEP), /* C12 : GPP_C12 ==> NC */ PAD_NC(GPP_C12, NONE), /* C13 : EC_PCH_INT_L From eb20320d7bf4b0e5c6e60040656c19323486f9ea Mon Sep 17 00:00:00 2001 From: Joel Kitching Date: Sun, 16 Jun 2019 17:26:53 +0800 Subject: [PATCH 189/221] vboot: remove vboot_handoff step Depthcharge no longer reads this data structure, and uses the vboot workbuf in vboot_working_data instead. Since vboot2 downstream migration is not yet completed, the vboot2 -> vboot1 migration code is still required, but has been relocated to depthcharge. BUG=b:124141368, b:124192753 TEST=make clean && make runtests BRANCH=none Change-Id: I769abbff79695b38d11fb6a93c2b42f64d4bafde Signed-off-by: Joel Kitching Reviewed-on: https://review.coreboot.org/c/coreboot/+/33535 Reviewed-by: Julius Werner Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/security/vboot/Makefile.inc | 2 +- src/security/vboot/vboot_handoff.c | 139 ----------------------------- src/security/vboot/vboot_loader.c | 11 --- 3 files changed, 1 insertion(+), 151 deletions(-) delete mode 100644 src/security/vboot/vboot_handoff.c diff --git a/src/security/vboot/Makefile.inc b/src/security/vboot/Makefile.inc index 3306f41a0b..6d195292e2 100644 --- a/src/security/vboot/Makefile.inc +++ b/src/security/vboot/Makefile.inc @@ -89,7 +89,7 @@ verstage-y += secdata_tpm.c romstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += secdata_tpm.c endif romstage-y += vboot_logic.c -romstage-y += vboot_handoff.c common.c +romstage-y += common.c ramstage-y += common.c postcar-y += common.c diff --git a/src/security/vboot/vboot_handoff.c b/src/security/vboot/vboot_handoff.c deleted file mode 100644 index 19773c5438..0000000000 --- a/src/security/vboot/vboot_handoff.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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. - */ - -#define NEED_VB20_INTERNALS /* Peeking into vb2_shared_data */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * Sets vboot_handoff based on the information in vb2_shared_data - */ -static void fill_vboot_handoff(struct vboot_handoff *vboot_handoff, - struct vb2_shared_data *vb2_sd) -{ - VbSharedDataHeader *vb_sd = - (VbSharedDataHeader *)vboot_handoff->shared_data; - uint32_t *oflags = &vboot_handoff->out_flags; - - vb_sd->flags |= VBSD_BOOT_FIRMWARE_VBOOT2; - - vboot_handoff->selected_firmware = vb2_sd->fw_slot; - - vb_sd->firmware_index = vb2_sd->fw_slot; - - vb_sd->magic = VB_SHARED_DATA_MAGIC; - vb_sd->struct_version = VB_SHARED_DATA_VERSION; - vb_sd->struct_size = sizeof(VbSharedDataHeader); - vb_sd->data_size = VB_SHARED_DATA_MIN_SIZE; - vb_sd->data_used = sizeof(VbSharedDataHeader); - vb_sd->fw_version_tpm = vb2_sd->fw_version_secdata; - - if (vb2_sd->recovery_reason) { - vb_sd->firmware_index = 0xFF; - if (vb2_sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY) - vb_sd->flags |= VBSD_BOOT_REC_SWITCH_ON; - *oflags |= VB_INIT_OUT_ENABLE_RECOVERY; - *oflags |= VB_INIT_OUT_CLEAR_RAM; - } - if (vb2_sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) { - *oflags |= VB_INIT_OUT_ENABLE_DEVELOPER; - *oflags |= VB_INIT_OUT_CLEAR_RAM; - vb_sd->flags |= VBSD_BOOT_DEV_SWITCH_ON; - vb_sd->flags |= VBSD_LF_DEV_SWITCH_ON; - } - - /* In vboot1, VBSD_FWB_TRIED is - * set only if B is booted as explicitly requested. Therefore, if B is - * booted because A was found bad, the flag should not be set. It's - * better not to touch it if we can only ambiguously control it. */ - /* if (vb2_sd->fw_slot) - vb_sd->flags |= VBSD_FWB_TRIED; */ - - /* copy kernel subkey if it's found */ - if (vb2_sd->workbuf_preamble_size) { - struct vb2_fw_preamble *fp; - uintptr_t dst, src; - printk(BIOS_INFO, "Copying FW preamble\n"); - fp = (struct vb2_fw_preamble *)((uintptr_t)vb2_sd + - vb2_sd->workbuf_preamble_offset); - src = (uintptr_t)&fp->kernel_subkey + - fp->kernel_subkey.key_offset; - dst = (uintptr_t)vb_sd + sizeof(VbSharedDataHeader); - assert(dst + fp->kernel_subkey.key_size <= - (uintptr_t)vboot_handoff + sizeof(*vboot_handoff)); - memcpy((void *)dst, (void *)src, - fp->kernel_subkey.key_size); - vb_sd->data_used += fp->kernel_subkey.key_size; - vb_sd->kernel_subkey.key_offset = - dst - (uintptr_t)&vb_sd->kernel_subkey; - vb_sd->kernel_subkey.key_size = fp->kernel_subkey.key_size; - vb_sd->kernel_subkey.algorithm = fp->kernel_subkey.algorithm; - vb_sd->kernel_subkey.key_version = - fp->kernel_subkey.key_version; - } - - vb_sd->recovery_reason = vb2_sd->recovery_reason; -} - -void vboot_fill_handoff(void) -{ - struct vboot_handoff *vh; - struct vb2_shared_data *sd; - - sd = vboot_get_shared_data(); - sd->workbuf_hash_offset = 0; - sd->workbuf_hash_size = 0; - - printk(BIOS_INFO, "creating vboot_handoff structure\n"); - vh = cbmem_add(CBMEM_ID_VBOOT_HANDOFF, sizeof(*vh)); - if (vh == NULL) - /* we don't need to failover gracefully here because this - * shouldn't happen with the image that has passed QA. */ - die("failed to allocate vboot_handoff structure\n"); - - memset(vh, 0, sizeof(*vh)); - - /* needed until we finish transtion to vboot2 for kernel verification */ - fill_vboot_handoff(vh, sd); -} - -/* - * For platforms that employ VBOOT_STARTS_IN_ROMSTAGE, the vboot - * verification doesn't happen until after cbmem is brought online. - * Therefore, the vboot results would not be initialized so don't - * automatically add results when cbmem comes online. - */ -#if !CONFIG(VBOOT_STARTS_IN_ROMSTAGE) -static void vb2_fill_handoff_cbmem(int unused) -{ - vboot_fill_handoff(); -} -ROMSTAGE_CBMEM_INIT_HOOK(vb2_fill_handoff_cbmem) -#endif diff --git a/src/security/vboot/vboot_loader.c b/src/security/vboot/vboot_loader.c index 1350307425..9e2cd00404 100644 --- a/src/security/vboot/vboot_loader.c +++ b/src/security/vboot/vboot_loader.c @@ -73,17 +73,6 @@ static void vboot_prepare(void) car_set_var(vboot_executed, 1); } - - /* - * Fill in vboot cbmem objects before moving to ramstage so all - * downstream users have access to vboot results. This path only - * applies to platforms employing VBOOT_STARTS_IN_ROMSTAGE because - * cbmem comes online prior to vboot verification taking place. For - * other platforms the vboot cbmem objects are initialized when - * cbmem comes online. - */ - if (ENV_ROMSTAGE && CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) - vboot_fill_handoff(); } static int vboot_locate(struct cbfs_props *props) From 1b35295ec2fe6c30c862baf79b08526cd8b4f1c4 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Thu, 21 Feb 2019 12:04:21 +0100 Subject: [PATCH 190/221] security: Add memory subfolder Add files to introduce a memory clearing framework. Introduce Kconfig PLATFORM_HAS_DRAM_CLEAR that is to be selected by platforms, that are able to clear all DRAM. Introduce Kconfig SECURITY_CLEAR_DRAM_ON_REGULAR_BOOT that is user selectable to always clear DRAM on non S3 boot. The function security_clear_dram_request tells the calling platform when to wipe all DRAM. Will be extended by TEE frameworks. Add Documentation for the new security API. Change-Id: Ifba25bfdd1057049f5cbae8968501bd9be487110 Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/31548 Tested-by: build bot (Jenkins) Reviewed-by: Philipp Deppenwiese Reviewed-by: Christian Walter --- Documentation/security/index.md | 1 + Documentation/security/memory_clearing.md | 44 +++++++++++++++++++++++ src/security/Kconfig | 1 + src/security/Makefile.inc | 1 + src/security/memory/Kconfig | 34 ++++++++++++++++++ src/security/memory/Makefile.inc | 3 ++ src/security/memory/memory.c | 33 +++++++++++++++++ src/security/memory/memory.h | 19 ++++++++++ 8 files changed, 136 insertions(+) create mode 100644 Documentation/security/memory_clearing.md create mode 100644 src/security/memory/Kconfig create mode 100644 src/security/memory/Makefile.inc create mode 100644 src/security/memory/memory.c create mode 100644 src/security/memory/memory.h diff --git a/Documentation/security/index.md b/Documentation/security/index.md index 9ad54866c2..379375b616 100644 --- a/Documentation/security/index.md +++ b/Documentation/security/index.md @@ -6,3 +6,4 @@ This section describes documentation about the security architecture of coreboot - [Verified Boot](vboot/index.md) - [Measured Boot](vboot/measured_boot.md) +- [Memory clearing](memory_clearing.md) diff --git a/Documentation/security/memory_clearing.md b/Documentation/security/memory_clearing.md new file mode 100644 index 0000000000..3d985925d9 --- /dev/null +++ b/Documentation/security/memory_clearing.md @@ -0,0 +1,44 @@ +# Memory clearing + +The main memory on computer platforms in high security environments contains +sensible data. On unexpected reboot the data might persist and could be +read by a malicious application in the bootflow or userspace. + +In order to prevent leaking information from pre-reset, the boot firmware can +clear the main system memory on boot, wiping all information. + +A common API indicates if the main memory has to be cleared. That could be +on user request or by a Trusted Execution Environment indicating that secrets +are in memory. + +As every platform has different bring-up mechanisms and memory-layouts, every +The device must indicate support for memory clearing as part of the boot +process. + +## Requirements + +1. The platform must clear all platform memory (DRAM) if requested +2. Code that is placed in DRAM might be skipped (as workaround) +3. Stack that is placed in DRAM might be skipped (as workaround) +4. All DRAM is cleared with zeros + +## Implementation + +A platform that supports memory clearing selects Kconfig +``PLATFORM_HAS_DRAM_CLEAR`` and calls + +```C +bool security_clear_dram_request(void); +``` + +to detect if memory should be cleared. + +The memory is cleared in ramstage as part of `DEV_INIT` stage. It's possible to +clear it earlier on some platforms, but on x86 MTRRs needs to be programmed +first, which happens in `DEV_INIT`. + +Without MTRRs (and caches enabled) clearing memory takes multiple seconds. +## Exceptions + +As some platforms place code and stack in DRAM (FSP1.0), the regions can be +skipped. diff --git a/src/security/Kconfig b/src/security/Kconfig index 6a334ac09c..8a1531a08d 100644 --- a/src/security/Kconfig +++ b/src/security/Kconfig @@ -14,3 +14,4 @@ source "src/security/vboot/Kconfig" source "src/security/tpm/Kconfig" +source "src/security/memory/Kconfig" diff --git a/src/security/Makefile.inc b/src/security/Makefile.inc index a940b82613..f62413e059 100644 --- a/src/security/Makefile.inc +++ b/src/security/Makefile.inc @@ -1,2 +1,3 @@ subdirs-y += vboot subdirs-y += tpm +subdirs-y += memory diff --git a/src/security/memory/Kconfig b/src/security/memory/Kconfig new file mode 100644 index 0000000000..5436119ba5 --- /dev/null +++ b/src/security/memory/Kconfig @@ -0,0 +1,34 @@ +## This file is part of the coreboot project. +## +## Copyright (C) 2019 Facebook Inc. +## Copyright (C) 2019 9elements Agency 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. +## + +menu "Memory initialization" + +config PLATFORM_HAS_DRAM_CLEAR + bool + default n + help + Selected by platforms that support clearing all DRAM + after DRAM initialization. + +config SECURITY_CLEAR_DRAM_ON_REGULAR_BOOT + depends on PLATFORM_HAS_DRAM_CLEAR + bool "Always clear all DRAM on regular boot" + help + Always clear the DRAM after DRAM initialization regardless + of additional security implementations in use. + This increases boot time depending on the amount of DRAM + installed. + +endmenu #Memory initialization diff --git a/src/security/memory/Makefile.inc b/src/security/memory/Makefile.inc new file mode 100644 index 0000000000..525c4dbb4d --- /dev/null +++ b/src/security/memory/Makefile.inc @@ -0,0 +1,3 @@ +romstage-$(CONFIG_PLATFORM_HAS_DRAM_CLEAR) += memory.c +postcar-$(CONFIG_PLATFORM_HAS_DRAM_CLEAR) += memory.c +ramstage-$(CONFIG_PLATFORM_HAS_DRAM_CLEAR) += memory.c diff --git a/src/security/memory/memory.c b/src/security/memory/memory.c new file mode 100644 index 0000000000..14f28578b5 --- /dev/null +++ b/src/security/memory/memory.c @@ -0,0 +1,33 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 9elements Agency GmbH + * Copyright (C) 2019 Facebook 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 +#include "memory.h" + +/** + * To be called after DRAM init. + * Tells the caller if DRAM must be cleared as requested by the user, + * firmware or security framework. + */ +bool security_clear_dram_request(void) +{ + if (CONFIG(SECURITY_CLEAR_DRAM_ON_REGULAR_BOOT)) + return true; + + /* TODO: Add TEE environments here */ + + return false; +} diff --git a/src/security/memory/memory.h b/src/security/memory/memory.h new file mode 100644 index 0000000000..ccb07d76ad --- /dev/null +++ b/src/security/memory/memory.h @@ -0,0 +1,19 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 9elements Agency GmbH + * Copyright (C) 2019 Facebook 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 + +bool security_clear_dram_request(void); From 804a0433e0a793876b954ad162f6efeef8f9a5d6 Mon Sep 17 00:00:00 2001 From: Tsung Ho Wu Date: Fri, 7 Jun 2019 15:03:49 -0700 Subject: [PATCH 191/221] drivers/pc80/tpm: add support for TPM emulator SwTPM 2.0 module Add software TPM 2.0 emulator to tpm device probe list. SwTPM: https://github.com/stefanberger/swtpm Tested on qemu q35 with MAINBOARD_HAS_LPC_TPM and MAINBOARD_HAS_TPM2 set in qemu-q35 Kconfig. Qemu: see qemu flags at https://s3hh.wordpress.com/2018/06/03/tpm-2-0-in-qemu/ How to see it work. Ubuntu 18.04: 1. Install SwTPM from https://github.com/stefanberger/swtpm 2. Add MAINBOARD_HAS_LPC_TPM and MAINBOARD_HAS_TPM2 to src/mainboard/emulation/qemu-q35/Kconfig and rebuild coreboot.rom 3. mkdir -p swtpm0 4. swtpm socket --tpmstate dir=swtpm0 --tpm2 --ctrl \ type=unixio,path=swtpm0/swtpm-sock --log level=20 & 5. qemu-system-x86_64 -machine q35 -m 2G \ -chardev socket,id=chrtpm,path=swtpm0/swtpm-sock \ -tpmdev emulator,id=tpm0,chardev=chrtpm -device \ tpm-tis,tpmdev=tpm0 -pflash build/coreboot.rom \ -serial $(tty) -display none 6. Check boot log and search 'Found TPM'. Change-Id: I5f58d2c117afbd057bb91697912db826db1d67a1 Signed-off-by: Tsung Ho Wu Reviewed-on: https://review.coreboot.org/c/coreboot/+/33302 Reviewed-by: Philipp Deppenwiese Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/drivers/pc80/tpm/tis.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/drivers/pc80/tpm/tis.c b/src/drivers/pc80/tpm/tis.c index e10332ba0a..23de003b47 100644 --- a/src/drivers/pc80/tpm/tis.c +++ b/src/drivers/pc80/tpm/tis.c @@ -146,10 +146,18 @@ static const struct device_name stmicro_devices[] = { {0xffff} }; +static const struct device_name swtpm_devices[] = { +#if CONFIG(TPM2) + {0x0001, "SwTPM 2.0" }, +#endif + {0xffff} +}; + static const struct vendor_name vendor_names[] = { {0x1114, "Atmel", atmel_devices}, {0x15d1, "Infineon", infineon_devices}, {0x1050, "Nuvoton", nuvoton_devices}, + {0x1014, "TPM Emulator", swtpm_devices}, {0x104a, "ST Microelectronics", stmicro_devices}, }; From e6a491e782a2abdddd035b370ab9cc3165f5230c Mon Sep 17 00:00:00 2001 From: Maxim Polyakov Date: Wed, 26 Jun 2019 11:17:37 +0300 Subject: [PATCH 192/221] mb/asrock/h110m: set serirq_mode to continuous mode By default, the LPC SIRQ mode is set to Quiet mode. Therefore, COM-port from the SurerIO chip don't work correctly after the LPC controller (PCI 0:1f.0) initialization. Console output is broken. The patch fixes this bug by overriding the serirq_mode option in the devicetree.cb to set Continuous SIRQ mode Change-Id: I37e26b271fb61f6c0343d6bf65c029924df82caf Signed-off-by: Maxim Polyakov Reviewed-on: https://review.coreboot.org/c/coreboot/+/33801 Reviewed-by: Nico Huber Tested-by: build bot (Jenkins) --- src/mainboard/asrock/h110m/devicetree.cb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mainboard/asrock/h110m/devicetree.cb b/src/mainboard/asrock/h110m/devicetree.cb index 158801f118..3067ffe53c 100644 --- a/src/mainboard/asrock/h110m/devicetree.cb +++ b/src/mainboard/asrock/h110m/devicetree.cb @@ -62,6 +62,9 @@ chip soc/intel/skylake register "pirqg_routing" = "PCH_IRQ11" register "pirqh_routing" = "PCH_IRQ11" + # Set LPC Serial IRQ mode + register "serirq_mode" = "SERIRQ_CONTINUOUS" + # Enabling SLP_S3#, SLP_S4#, SLP_SUS and SLP_A Stretch # SLP_S3 Minimum Assertion Width. Values 0: 60us, 1: 1ms, 2: 50ms, 3: 2s register "PmConfigSlpS3MinAssert" = "0x02" From b91b173f3dbd38aecf50f86cb27df352c64bd4e3 Mon Sep 17 00:00:00 2001 From: Felix Singer Date: Tue, 25 Jun 2019 13:42:03 +0200 Subject: [PATCH 193/221] mb/upsquared: Align partitions to 4KiB This fixes warnings while booting coreboot. Change-Id: If1e99b74ded5f743a3ad4fc829ae9747276c483a Signed-off-by: Felix Singer Reviewed-on: https://review.coreboot.org/c/coreboot/+/33784 Reviewed-by: Philipp Deppenwiese Reviewed-by: Arthur Heymans Tested-by: build bot (Jenkins) --- src/mainboard/up/squared/upsquared.fmd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mainboard/up/squared/upsquared.fmd b/src/mainboard/up/squared/upsquared.fmd index 4ea1375e10..891138ee63 100644 --- a/src/mainboard/up/squared/upsquared.fmd +++ b/src/mainboard/up/squared/upsquared.fmd @@ -3,14 +3,14 @@ FLASH 16M { SI_BIOS@0x1000 0xefe000 { IFWI@0x0 0x2ff000 OBB@0x2ff000 0xbff000 { - FMAP@0x0 0x800 - UNIFIED_MRC_CACHE@0x800 0x21000 { + FMAP@0x0 0x1000 + UNIFIED_MRC_CACHE@0x1000 0x21000 { RECOVERY_MRC_CACHE@0x0 0x10000 RW_MRC_CACHE@0x10000 0x10000 RW_VAR_MRC_CACHE@0x20000 0x1000 } - CONSOLE@0x21800 0x20000 - COREBOOT(CBFS)@0x41800 0xb7d800 + CONSOLE@0x22000 0x20000 + COREBOOT(CBFS)@0x42000 0xb7d000 BIOS_UNUSABLE@0xbbf000 0x40000 } } From 2bf6a301d39fcb49edf6eb5a18e6b384ed95205a Mon Sep 17 00:00:00 2001 From: Vlado Cibic Date: Sun, 9 Jun 2019 06:53:50 +0000 Subject: [PATCH 194/221] mainboard: Add support for ASUS P8Z77-M PRO desktop mainboard Add support for ASUS P8Z77-M PRO desktop mainboard Working: - Tianocore and SeaBIOS boot - PS/2 keyboard and mouse - Audio - S3 Suspend, shutdown and reboot - USB2 / USB3 - Gigabit Ethernet - SATA3, SATA2 and eSATA - NVME - CPU Temp sensors - TPM - Native raminit and also MRC - PCIe GPU in all PCIe slots (16x/8x/4x) (linux) - Integrated graphics with both libgfxinit and Intel Video OpROM (all connectors VGA/DVI-D/HDMI) Signed-off-by: Vlado Cibic Change-Id: I47d24ac8b236f929c3160f9a769b971d83710f9d Reviewed-on: https://review.coreboot.org/c/coreboot/+/33328 Reviewed-by: Angel Pons Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- Documentation/mainboard/asus/p8z77-m_pro.jpg | Bin 0 -> 97747 bytes Documentation/mainboard/asus/p8z77-m_pro.md | 168 +++++++++++++++ Documentation/mainboard/index.md | 1 + MAINTAINERS | 5 + src/mainboard/asus/p8z77-m_pro/Kconfig | 48 +++++ src/mainboard/asus/p8z77-m_pro/Kconfig.name | 17 ++ src/mainboard/asus/p8z77-m_pro/Makefile.inc | 19 ++ src/mainboard/asus/p8z77-m_pro/acpi/ec.asl | 1 + .../asus/p8z77-m_pro/acpi/platform.asl | 24 +++ .../asus/p8z77-m_pro/acpi/superio.asl | 17 ++ src/mainboard/asus/p8z77-m_pro/acpi_tables.c | 35 ++++ src/mainboard/asus/p8z77-m_pro/board_info.txt | 7 + src/mainboard/asus/p8z77-m_pro/cmos.default | 24 +++ src/mainboard/asus/p8z77-m_pro/cmos.layout | 185 ++++++++++++++++ src/mainboard/asus/p8z77-m_pro/data.vbt | Bin 0 -> 3902 bytes src/mainboard/asus/p8z77-m_pro/devicetree.cb | 109 ++++++++++ src/mainboard/asus/p8z77-m_pro/dsdt.asl | 43 ++++ .../asus/p8z77-m_pro/gma-mainboard.ads | 31 +++ src/mainboard/asus/p8z77-m_pro/gpio.c | 198 ++++++++++++++++++ src/mainboard/asus/p8z77-m_pro/hda_verb.c | 57 +++++ src/mainboard/asus/p8z77-m_pro/mainboard.c | 30 +++ src/mainboard/asus/p8z77-m_pro/romstage.c | 193 +++++++++++++++++ 22 files changed, 1212 insertions(+) create mode 100644 Documentation/mainboard/asus/p8z77-m_pro.jpg create mode 100644 Documentation/mainboard/asus/p8z77-m_pro.md create mode 100644 src/mainboard/asus/p8z77-m_pro/Kconfig create mode 100644 src/mainboard/asus/p8z77-m_pro/Kconfig.name create mode 100644 src/mainboard/asus/p8z77-m_pro/Makefile.inc create mode 100644 src/mainboard/asus/p8z77-m_pro/acpi/ec.asl create mode 100644 src/mainboard/asus/p8z77-m_pro/acpi/platform.asl create mode 100644 src/mainboard/asus/p8z77-m_pro/acpi/superio.asl create mode 100644 src/mainboard/asus/p8z77-m_pro/acpi_tables.c create mode 100644 src/mainboard/asus/p8z77-m_pro/board_info.txt create mode 100644 src/mainboard/asus/p8z77-m_pro/cmos.default create mode 100644 src/mainboard/asus/p8z77-m_pro/cmos.layout create mode 100644 src/mainboard/asus/p8z77-m_pro/data.vbt create mode 100644 src/mainboard/asus/p8z77-m_pro/devicetree.cb create mode 100644 src/mainboard/asus/p8z77-m_pro/dsdt.asl create mode 100644 src/mainboard/asus/p8z77-m_pro/gma-mainboard.ads create mode 100644 src/mainboard/asus/p8z77-m_pro/gpio.c create mode 100644 src/mainboard/asus/p8z77-m_pro/hda_verb.c create mode 100644 src/mainboard/asus/p8z77-m_pro/mainboard.c create mode 100644 src/mainboard/asus/p8z77-m_pro/romstage.c diff --git a/Documentation/mainboard/asus/p8z77-m_pro.jpg b/Documentation/mainboard/asus/p8z77-m_pro.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bc6ef2894b9bddef175b0136036e8c401f41efe9 GIT binary patch literal 97747 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 literal 0 HcmV?d00001 diff --git a/Documentation/mainboard/asus/p8z77-m_pro.md b/Documentation/mainboard/asus/p8z77-m_pro.md new file mode 100644 index 0000000000..7c841499fc --- /dev/null +++ b/Documentation/mainboard/asus/p8z77-m_pro.md @@ -0,0 +1,168 @@ +# ASUS P8Z77-M Pro + +This page describes how to run coreboot on the [ASUS P8Z77-M Pro] + +## Flashing coreboot + +```eval_rst ++---------------------+----------------+ +| Type | Value | ++=====================+================+ +| Socketed flash | yes | ++---------------------+----------------+ +| Model | W25Q64FVA1Q | ++---------------------+----------------+ +| Size | 8 MiB | ++---------------------+----------------+ +| Package | DIP-8 | ++---------------------+----------------+ +| Write protection | yes | ++---------------------+----------------+ +| Dual BIOS feature | no | ++---------------------+----------------+ +| Internal flashing | yes | ++---------------------+----------------+ +``` + +The flash IC is located right next to one of the SATA ports: +![](p8z77-m_pro.jpg) + +### Internal programming + +The main SPI flash cannot be written because Asus disables BIOSWE and +enables BLE/SMM_BWP flags in BIOS_CNTL for their latest bioses. +An external programmer is required. You must flash standalone, +flashing in-circuit doesn't work. The flash chip is socketed, so it's +easy to remove and reflash. + +## Working + +- PS/2 keyboard with SeaBIOS & Tianocore (in Mint 18.3/19.1) + +- Rear/front headphones connector audio & mic + +- S3 Suspend to RAM (tested with OS installed in a HDD/SSD and also with a + Mint 18.3/19.1 LiveUSB pendrive connected to USB3/USB2), but please + see [Known issues] + +- USB2 on rear (tested mouse/keyboard plugged there. Also, booting with + a Mint 18./19.1 LiveUSB works ok) + +- USB3 (Z77's and Asmedia's works, but please see [Known issues]) + +- Gigabit Ethernet (RTL8111F) + +- SATA3, SATA2 and eSATA (tested on all ports, hot-swap and TCG OPAL working) + (Blue SATA2) (Blue SATA2) (White SATA3) (Red eSATA SATA3 rear) + port 3 port 5 port 1 port 8 + port 4 port 6 port 2 port 7 + +- NVME SSD boot on PCIe-x16/x8/4x slot using Tianocore + (tested with M.2-to-PCIe adapter and a M.2 Samsung EVO 970 SSD) + +- CPU Temp sensors (tested PSensor on linux + HWINFO64 on Win10) + +- TPM on TPM-header (tested tpm-tools with Asus TPM 1.2 Infineon SLB9635TT12) + +- Native raminit and also MRC.bin(systemagent-r6.bin) memory initialization + (please see [Native raminit compatibility] and [MRC memory compatibility]) + +- Integrated graphics with both libgfxinit and the Intel Video BIOS OpROM + (VGA/DVI-D/HDMI tested and working) + +- 1x PCIe GPU in PCIe-16x/8x/4x slots (tested using Zotac GeForce GTX + 750Ti and FirePro W5100 under Mint 18.3/19.1) + +## Known issues + +- The rear's USB3s on bottom (closest to the PCB) have problems booting or + being used before the OS loads. For better compatibility, please use + the Z77's ones above the Ethernet connector or the Asmedia's top one + +- After S3 suspend, some USB3 connectors on rear seem not to work + +- At the moment, the power led does not blink when entering S3 state + +- Currently, we have not setup the SuperIO's Hardware Monitor (HWM), + so only the CPU sensors are reported + +- If you use the MRC.bin, the NVRAM variable gfx_uma_size may be ignored + as IGP's UMA could be reconfigured by the blob + +- Using TianoCore + a PCIe GPU under Windows crashes with an + ACPI_BIOS_ERROR fatal code, not sure why. Using just the IGP + works perfectly + +- Under Windows 10, if you experiment problems with PS/2 devices, change + HKLM\SYSTEM\CurrentControlSet\Services\i8042prt->Start from '3' to '1' + +## Untested + +- EHCI debugging +- S/PDIF audio +- Wake-on-LAN +- Serial port + +## Not working + +- PS/2 keyboard in Win10 using Tianocore (please see [Known issues]) +- PS/2 mouse using Tianocore +- PCIe graphics card on Windows and Tianocore (throws critical ACPI_BIOS_ERROR) + +## Native raminit compatibility + +- GSkill F3-2133C10D-16GAB(XMP,1.60v) 2x8GB kit works at 1333Mhz instead + of XMP 2133Mhz + +- Team Xtreem TXD38G2133HC9NDC01(XMP,1.50v) 2x4GB kit works at 1600Mhz + instead of XMP 2133Mhz + +- Kingston KVR1066D3N7K2/4G(JEDEC,1.50v) 2x4GB kit works at 1066Mhz + but the board only detects half its RAM, because those DIMMs have + Double Sided(DS) chips and seems only Single Sided(SS) ones are + fully detected + +- GSkill F3-10666CL9T2-24GBRL(JEDEC,1.50v) 6x4GB kit (4 DIMMs used) + works perfectly at full speed (1333Mhz) + +## MRC memory compatibility + +- GSkill F3-2133C10D-16GAB(XMP,1.60v) 2x8GB kit works at 1333Mhz + instead of XMP 2133Mhz + +- Team Xtreem TXD38G2133HC9NDC01(XMP,1.50v) 2x4GB kit works at + 1600Mhz instead of XMP 2133Mhz + +- Kingston KVR1066D3N7K2/4G(JEDEC,1.50v) 2x4GB kit works at 1066Mhz + but the board only detects half its RAM, as those DIMMs have + Double Sided(DS) chips and seems only Single Sided(SS) ones are + fully detected + +- GSkill F3-10666CL9T2-24GBRL(JEDEC,1.50v) 6x4GB kit (4 DIMMs used) + works perfectly at full speed (1333Mhz) + +## Technology + +```eval_rst ++------------------+--------------------------------------------------+ +| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` | ++------------------+--------------------------------------------------+ +| Southbridge | bd82x6x | ++------------------+--------------------------------------------------+ +| CPU | model_206ax | ++------------------+--------------------------------------------------+ +| Super I/O | Nuvoton NCT6779D | ++------------------+--------------------------------------------------+ +| EC | None | ++------------------+--------------------------------------------------+ +| Coprocessor | Intel Management Engine | ++------------------+--------------------------------------------------+ +``` + +## Extra resources + +- [Flash chip datasheet][W25Q64FVA1Q] + +[ASUS P8Z88-M Pro]: https://www.asus.com/Motherboards/P8Z77M_PRO/ +[W25Q64FVA1Q]: https://www.winbond.com/resource-files/w25q64fv%20revs%2007182017.pdf +[flashrom]: https://flashrom.org/Flashrom diff --git a/Documentation/mainboard/index.md b/Documentation/mainboard/index.md index 77e84efb51..14c62edeb9 100644 --- a/Documentation/mainboard/index.md +++ b/Documentation/mainboard/index.md @@ -7,6 +7,7 @@ This section contains documentation about coreboot on specific mainboards. - [F2A85-M](asus/f2a85-m.md) - [P8H61-M LX](asus/p8h61-m_lx.md) - [P8H61-M Pro](asus/p8h61-m_pro.md) +- [P8Z77-M Pro](asus/p8z77-m_pro.md) ## ASRock diff --git a/MAINTAINERS b/MAINTAINERS index e7780a8d72..83ba5232b3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -364,6 +364,11 @@ M: Angel Pons S: Maintained F: src/mainboard/asus/p8h61-m_pro/ +ASUS P8Z77-M PRO MAINBOARD +M: Vlado Cibic +S: Maintained +F: src/mainboard/asus/p8z77-m_pro/ + PC ENGINES ALL MAINBOARDS M: Piotr Król M: Michał Żygowski diff --git a/src/mainboard/asus/p8z77-m_pro/Kconfig b/src/mainboard/asus/p8z77-m_pro/Kconfig new file mode 100644 index 0000000000..8d29a9bc21 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/Kconfig @@ -0,0 +1,48 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 Vlado Cibic +## +## 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_ASUS_P8Z77_M_PRO + +config BOARD_SPECIFIC_OPTIONS + def_bool y + select BOARD_ROMSIZE_KB_8192 + select HAVE_ACPI_RESUME + select HAVE_ACPI_TABLES + select INTEL_INT15 + select NORTHBRIDGE_INTEL_SANDYBRIDGE + select SERIRQ_CONTINUOUS_MODE + select SOUTHBRIDGE_INTEL_C216 + select MAINBOARD_HAS_LPC_TPM + select MAINBOARD_HAS_TPM1 + select HAVE_OPTION_TABLE + select HAVE_CMOS_DEFAULT + select MAINBOARD_HAS_LIBGFXINIT + select INTEL_GMA_HAVE_VBT + select SUPERIO_NUVOTON_NCT6779D + select DRIVERS_ASMEDIA_ASPM_BLACKLIST # for ASM1061 eSATA + +config MAINBOARD_DIR + string + default "asus/p8z77-m_pro" + +config MAINBOARD_PART_NUMBER + string + default "P8Z77-M PRO" + +config MAX_CPUS + int + default 8 + +endif # BOARD_ASUS_P8Z77_M_PRO diff --git a/src/mainboard/asus/p8z77-m_pro/Kconfig.name b/src/mainboard/asus/p8z77-m_pro/Kconfig.name new file mode 100644 index 0000000000..c492094508 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/Kconfig.name @@ -0,0 +1,17 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 Vlado Cibic +## +## 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. +## + +config BOARD_ASUS_P8Z77_M_PRO + bool "P8Z77-M PRO" diff --git a/src/mainboard/asus/p8z77-m_pro/Makefile.inc b/src/mainboard/asus/p8z77-m_pro/Makefile.inc new file mode 100644 index 0000000000..0cc398a5e7 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/Makefile.inc @@ -0,0 +1,19 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 Vlado Cibic +## +## 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, either version 2 of the License, or +## (at your option) any later version. +## +## 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. +## + +romstage-y += gpio.c + +ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads diff --git a/src/mainboard/asus/p8z77-m_pro/acpi/ec.asl b/src/mainboard/asus/p8z77-m_pro/acpi/ec.asl new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/acpi/ec.asl @@ -0,0 +1 @@ + diff --git a/src/mainboard/asus/p8z77-m_pro/acpi/platform.asl b/src/mainboard/asus/p8z77-m_pro/acpi/platform.asl new file mode 100644 index 0000000000..3a696211c1 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/acpi/platform.asl @@ -0,0 +1,24 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 Vlado Cibic + * + * 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +Method(_WAK,1) +{ + Return(Package(){0,0}) +} + +Method(_PTS,1) +{ +} diff --git a/src/mainboard/asus/p8z77-m_pro/acpi/superio.asl b/src/mainboard/asus/p8z77-m_pro/acpi/superio.asl new file mode 100644 index 0000000000..7f1d04c9ba --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/acpi/superio.asl @@ -0,0 +1,17 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 Vlado Cibic + * + * 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, either version 2 of the License, or + * (at your option) any later version. + * + * 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 diff --git a/src/mainboard/asus/p8z77-m_pro/acpi_tables.c b/src/mainboard/asus/p8z77-m_pro/acpi_tables.c new file mode 100644 index 0000000000..2592c19a9e --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/acpi_tables.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 Vlado Cibic + * + * 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 +#include + +void acpi_create_gnvs(global_nvs_t *gnvs) +{ + /* Turn off power for USB ports in S3 by default */ + gnvs->s3u0 = 0; + gnvs->s3u1 = 0; + + /* Turn off power for USB ports in S5 by default */ + gnvs->s5u0 = 0; + gnvs->s5u1 = 0; + + /* critical temp that will shutdown the pc == 95C degrees */ + gnvs->tcrt = 95; + + /* temp to start throttling the cpu == 85C */ + gnvs->tpsv = 85; +} diff --git a/src/mainboard/asus/p8z77-m_pro/board_info.txt b/src/mainboard/asus/p8z77-m_pro/board_info.txt new file mode 100644 index 0000000000..66e6f0d6f9 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/board_info.txt @@ -0,0 +1,7 @@ +Category: desktop +Board URL: https://www.asus.com/Motherboards/P8Z77M_PRO/ +ROM package: DIP-8 +ROM protocol: SPI +ROM socketed: y +Flashrom support: y +Release year: 2013 diff --git a/src/mainboard/asus/p8z77-m_pro/cmos.default b/src/mainboard/asus/p8z77-m_pro/cmos.default new file mode 100644 index 0000000000..725ab9851d --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/cmos.default @@ -0,0 +1,24 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 Vlado Cibic +## +## 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. +## + +boot_option=Fallback +debug_level=Debug +gfx_uma_size=224M +nmi=Enable +sata_mode=AHCI +#usb3_xxxx options are only used with MRC blob, ignored else +usb3_mode=Enable +usb3_drv=Enable +usb3_streams=Enable diff --git a/src/mainboard/asus/p8z77-m_pro/cmos.layout b/src/mainboard/asus/p8z77-m_pro/cmos.layout new file mode 100644 index 0000000000..da29d1c10e --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/cmos.layout @@ -0,0 +1,185 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 Vlado Cibic +## +## 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 3 boot_option +388 4 h 0 reboot_counter + +# ----------------------------------------------------------------- +# coreboot config options: console +#392 3 r 0 unused +395 4 e 4 debug_level +#399 1 r 0 unused +#400 8 r 0 reserved for century byte + +# ----------------------------------------------------------------- +# coreboot config options: southbridge + +# Non Maskable Interrupt(NMI) support, which is an interrupt that may +# occur on a RAM or unrecoverable error. +408 1 e 1 nmi + +409 2 e 5 power_on_after_fail +411 1 e 6 sata_mode + +# ----------------------------------------------------------------- +# coreboot config options: northbridge + +# gfx_uma_size +# Quantity of shared video memory the IGP can use +# +416 5 e 7 gfx_uma_size + +# ----------------------------------------------------------------- +# coreboot config options: usb3 + +# usb3_mode +# Controls how the motherboard's USB3 ports act at boot time +421 2 e 8 usb3_mode + +# usb3_drv +# Load (or not) pre-OS xHCI USB3 bios driver +# +423 1 e 1 usb3_drv + +# usb3_streams +# Streams can provide more speed (as they can use 64Kb packets), +# but they might cause incompatibilities with some devices. +# +424 1 e 1 usb3_streams + +# ----------------------------------------------------------------- +# Sandy/Ivy Bridge MRC Scrambler Seed values +# note: MUST NOT be covered by checksum! +464 32 r 0 mrc_scrambler_seed +496 32 r 0 mrc_scrambler_seed_s3 +528 16 r 0 mrc_scrambler_seed_chk + +# ----------------------------------------------------------------- +# coreboot config options: check sums +544 16 h 0 check_sum + +# ----------------------------------------------------------------- + +enumerations +#ID value text + +# Generic on/off enum +1 0 Disable +1 1 Enable + +# boot_option +3 0 Fallback +3 1 Normal + +# debug_level +4 0 Emergency +4 1 Alert +4 2 Critical +4 3 Error +4 4 Warning +4 5 Notice +4 6 Info +4 7 Debug +4 8 Spew + +# power_on_after_fail +5 0 Disable +5 1 Enable +5 2 Keep + +# sata_mode +6 0 AHCI +6 1 Compatible + +# gfx_uma_size (Intel IGP Video RAM size) +7 0 32M +7 1 64M +7 2 96M +7 3 128M +7 4 160M +7 5 192M +7 6 224M +7 7 256M +7 8 288M +7 9 320M +7 10 352M +7 11 384M +7 12 416M +7 13 448M +7 14 480M +7 15 512M +7 16 544M +7 17 576M +7 18 608M +7 19 640M +7 20 672M +7 21 704M +7 22 736M +7 23 768M +7 24 800M +7 25 832M +7 26 864M +7 27 896M +7 28 928M +7 29 960M +7 30 992M + +# usb3_mode +# Disable = Use the port always as USB 2.0 for compatibility +# Enable = Use the port always as USB 3.0 for speed +# Auto = Initialize the port as USB 2.0, until the OS loads +# xHCI USB 3.0 driver +# SmartAuto = Same as Auto but, if the OS loads the xHCI USB 3.0 driver +# and the computer is reset, keep the USB 3.0 mode. +# +8 0 Disable +8 1 Enable +8 2 Auto +8 3 SmartAuto + +# ----------------------------------------------------------------- +# +# +checksums + +checksum 392 431 544 diff --git a/src/mainboard/asus/p8z77-m_pro/data.vbt b/src/mainboard/asus/p8z77-m_pro/data.vbt new file mode 100644 index 0000000000000000000000000000000000000000..34679b36a9fa8b9662bbb54e2ee6911d43347e1b GIT binary patch literal 3902 zcmdT{U1%It6h5;v`*&w1*-T=)S<`S+OS?()GrO%z2&>L+HZhxSlTCKJtVQgm-R%#g zX}bNP1#71oY(%%<#kx(F&f+qe_^r7fNu&umM?vaxOP z)cD{g`YEh{hQ_~y8r!j> zG+ioB9V``TCii@dGFq9$5AB&Q(y>E(x0lKTlyRXq4Q=e*u#r+V)EA2Mh1F0P_3*&c z>Oe@9Nn&Vld~-UPie;1IV|09yCX$(0CNs1-o_c|%C&x#U@nm)=AroUOgZpNWmiO%1 zeUJtRJ84)|)gB}aQDez;a9?@0m&T^2=_K3L!F!uX*YX-vsf7od{a1?a_jdkeox#hryX5*-XDb!;4(sDq4SKXoh zTjrSgF4G>BgU|+Qcw?l0AgaX^!y}`q^kg=d-}<6{;?>vY0&u4SxLJkU7TFvc-yS4B9P^)>KVJpy(0mA|bi)qA?DMRvn+8Sq3GQYevuGPE+9ES0EbUpb5 zJV^hTH}Ny*&~c4cHBh!(&N;h^$;GClcE5weS$?>~;>^18AVb~0D3^7Rnqd@g1l|*! zYcXbR0jQm9@B;Utb1VGe?19EN!E4@ei>&{q;rQdUci0Q&?@zYPVwv`Z1^n{`O}&-v$01Fa5%+eB&kGd+BYjA`!BJ&?r&H2+0%r z3Q;PAoF()!QLYg3GocPqX%R`gNE4!x6G=g&uZzkVk$f!Dc~SXEB)^E1NJ^VT)=D%b zDKAN6w?yBPl&VB7NOVC`u1VyEL={d4W@TlkOlD9CQ>b{2)70H|b`gx~)!BkLk!5{$WlU46@1Kq&9YOJpk1-U8zdyAe&{xfv;da z;u>^!zmX3QuT95*?%&_vqvd<J&f{0@Bk5}owC*S1jbRLC5(sR8H2$yK&7Fo{`M&`FihXhb literal 0 HcmV?d00001 diff --git a/src/mainboard/asus/p8z77-m_pro/devicetree.cb b/src/mainboard/asus/p8z77-m_pro/devicetree.cb new file mode 100644 index 0000000000..4f5e5bf9bb --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/devicetree.cb @@ -0,0 +1,109 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2019 Vlado Cibic +## +## 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 northbridge/intel/sandybridge + register "gfx.did" = "{ 0x80000100, 0x80000240, 0x80000410 }" + register "gfx.ndid" = "3" + device cpu_cluster 0x0 on + chip cpu/intel/model_206ax + register "c1_acpower" = "1" + register "c1_battery" = "1" + register "c2_acpower" = "3" + register "c2_battery" = "3" + register "c3_acpower" = "5" + register "c3_battery" = "5" + device lapic 0x0 on end + device lapic 0xacac off end + end + end + device domain 0x0 on + subsystemid 0x1043 0x84ca inherit + device pci 00.0 on end # Host bridge + device pci 01.0 on end # PCIe Bridge for discrete graphics + device pci 02.0 on end # Internal graphics VGA controller + chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH + register "c2_latency" = "0x0065" + register "gen1_dec" = "0x000c0291" + register "gen4_dec" = "0x0000ff29" + register "pcie_port_coalesce" = "1" + register "sata_interface_speed_support" = "0x3" # 0x3=SATAIII + register "sata_port_map" = "0x3f" # Enable the six SATA ports + register "spi_lvscc" = "0x2005" + register "spi_uvscc" = "0x2005" + register "superspeed_capable_ports" = "0x0000000f" + register "xhci_overcurrent_mapping" = "0x00000c03" + register "xhci_switchable_ports" = "0x0000000f" # the 4 ports + device pci 14.0 on end # USB 3.0 Controller + device pci 16.0 on end # Management Engine Interface 1 + device pci 16.1 off end # Management Engine Interface 2 + device pci 16.2 off end # Management Engine IDE-R + device pci 16.3 off end # Management Engine KT + device pci 19.0 off end # Intel Gigabit Ethernet + device pci 1a.0 on end # USB2 EHCI 2 + device pci 1b.0 on end # High Definition Audio controller + device pci 1c.0 on end # PCIe Root Port 1 PCIEX_16_3 + device pci 1c.1 on end # PCIe Root Port 6 RTL8111F + device pci 1c.2 off end # PCIe Port 3 unused + device pci 1c.3 off end # PCIe Port 4 unused + device pci 1c.4 off end # PCIe Port 5 unused + device pci 1c.5 on end # PCIe Root Port 7 ASM1042 USB3 + device pci 1c.6 on end # PCIe Root Port 8 ASM1061 eSATA + device pci 1c.7 off end # PCIe Port 8 unused + device pci 1d.0 on end # USB2 EHCI 1 + device pci 1e.0 off end # PCI bridge + device pci 1f.0 on # LPC bridge + chip superio/nuvoton/nct6779d + device pnp 2e.1 off end # Parallel + device pnp 2e.2 off end # UART A + device pnp 2e.3 on # UART B, IR + io 0x60 = 0x2f8 # COM2 address + end + device pnp 2e.5 on # PS2 KBC + io 0x60 = 0x0060 # KBC1 base + io 0x62 = 0x0064 # KBC2 base + irq 0x70 = 1 # Keyboard IRQ + irq 0x72 = 12 # Mouse IRQ + + # KBC 12Mhz/A20 speed/sw KBRST + drq 0xf0 = 0x82 + end + device pnp 2e.6 off end # CIR + device pnp 2e.7 on end # GPIOs 6-8 + device pnp 2e.8 off end # WDT1 GPIO 0-1 + device pnp 2e.9 off end # GPIO 1-8 + device pnp 2e.a on # ACPI + drq 0xe4 = 0x10 # Enable 3VSBS to power RAM on S3 + drq 0xe7 = 0x10 # 0.5s S3 delay for compatibility + end + device pnp 2e.b off end # HWM, LED + device pnp 2e.d off end # WDT1 + device pnp 2e.e off end # CIR wake-up + device pnp 2e.f on # GPIO PP/OD + drq 0xe6 = 0x7f # GP7 PP + end + device pnp 2e.14 on end # Port 80 UART + device pnp 2e.16 off end # Deep sleep + end + chip drivers/pc80/tpm + device pnp 4e.0 on end # TPM module + end + end + device pci 1f.2 on end # SATA Controller 1 + device pci 1f.3 on end # SMBus + device pci 1f.5 off end # SATA Controller 2 + device pci 1f.6 off end # Thermal + end + end +end diff --git a/src/mainboard/asus/p8z77-m_pro/dsdt.asl b/src/mainboard/asus/p8z77-m_pro/dsdt.asl new file mode 100644 index 0000000000..89ad30c997 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/dsdt.asl @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 Vlado Cibic + * + * 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 ACPI_VIDEO_DEVICE \_SB.PCI0.GFX0 + +#include +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, /* DSDT revision: ACPI 2.0 and up */ + OEM_ID, + ACPI_TABLE_CREATOR, + 0x20141018 /* OEM revision */ +) +{ + #include "acpi/platform.asl" + #include "acpi/superio.asl" + #include + #include + + #include + #include + + Device (\_SB.PCI0) + { + #include + #include + #include + } +} diff --git a/src/mainboard/asus/p8z77-m_pro/gma-mainboard.ads b/src/mainboard/asus/p8z77-m_pro/gma-mainboard.ads new file mode 100644 index 0000000000..f9dd430d24 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/gma-mainboard.ads @@ -0,0 +1,31 @@ +-- +-- This file is part of the coreboot project. +-- +-- Copyright (C) 2019 Vlado Cibic +-- +-- 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, either version 2 of the License, or +-- (at your option) any later version. +-- +-- 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. +-- + +with HW.GFX.GMA; +with HW.GFX.GMA.Display_Probing; + +use HW.GFX.GMA; +use HW.GFX.GMA.Display_Probing; + +private package GMA.Mainboard is + + ports : constant Port_List := + (HDMI1, -- DVI-D port on rear + HDMI3, -- real HDMI port on rear + Analog, -- VGA port on rear + others => Disabled); + +end GMA.Mainboard; diff --git a/src/mainboard/asus/p8z77-m_pro/gpio.c b/src/mainboard/asus/p8z77-m_pro/gpio.c new file mode 100644 index 0000000000..c8842159d3 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/gpio.c @@ -0,0 +1,198 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Vladimir Serbinenko + * Copyright (C) 2019 Vlado Cibic + * + * 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 + +static const struct pch_gpio_set1 pch_gpio_set1_mode = { + .gpio0 = GPIO_MODE_GPIO, + .gpio1 = GPIO_MODE_GPIO, + .gpio2 = GPIO_MODE_NATIVE, + .gpio3 = GPIO_MODE_NATIVE, + .gpio4 = GPIO_MODE_NATIVE, + .gpio5 = GPIO_MODE_NATIVE, + .gpio6 = GPIO_MODE_GPIO, + .gpio7 = GPIO_MODE_GPIO, + .gpio8 = GPIO_MODE_GPIO, + .gpio9 = GPIO_MODE_NATIVE, + .gpio10 = GPIO_MODE_NATIVE, + .gpio11 = GPIO_MODE_NATIVE, + .gpio12 = GPIO_MODE_GPIO, + .gpio13 = GPIO_MODE_GPIO, + .gpio14 = GPIO_MODE_NATIVE, + .gpio15 = GPIO_MODE_GPIO, + .gpio16 = GPIO_MODE_GPIO, + .gpio17 = GPIO_MODE_GPIO, + .gpio18 = GPIO_MODE_NATIVE, + .gpio19 = GPIO_MODE_NATIVE, + .gpio20 = GPIO_MODE_NATIVE, + .gpio21 = GPIO_MODE_GPIO, + .gpio22 = GPIO_MODE_NATIVE, + .gpio23 = GPIO_MODE_NATIVE, + .gpio24 = GPIO_MODE_GPIO, + .gpio25 = GPIO_MODE_NATIVE, + .gpio26 = GPIO_MODE_NATIVE, + .gpio27 = GPIO_MODE_GPIO, + .gpio28 = GPIO_MODE_GPIO, + .gpio29 = GPIO_MODE_GPIO, + .gpio30 = GPIO_MODE_NATIVE, + .gpio31 = GPIO_MODE_GPIO, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_direction = { + .gpio0 = GPIO_DIR_INPUT, + .gpio1 = GPIO_DIR_INPUT, + .gpio6 = GPIO_DIR_INPUT, + .gpio7 = GPIO_DIR_INPUT, + .gpio8 = GPIO_DIR_OUTPUT, + .gpio12 = GPIO_DIR_OUTPUT, + .gpio13 = GPIO_DIR_INPUT, + .gpio15 = GPIO_DIR_OUTPUT, + .gpio16 = GPIO_DIR_INPUT, + .gpio17 = GPIO_DIR_INPUT, + .gpio21 = GPIO_DIR_INPUT, + .gpio24 = GPIO_DIR_OUTPUT, + .gpio27 = GPIO_DIR_INPUT, + .gpio28 = GPIO_DIR_OUTPUT, + .gpio29 = GPIO_DIR_OUTPUT, + .gpio31 = GPIO_DIR_OUTPUT, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_level = { + .gpio8 = GPIO_LEVEL_HIGH, + .gpio12 = GPIO_LEVEL_LOW, + .gpio15 = GPIO_LEVEL_LOW, + .gpio24 = GPIO_LEVEL_LOW, + .gpio28 = GPIO_LEVEL_LOW, + .gpio29 = GPIO_LEVEL_HIGH, + .gpio31 = GPIO_LEVEL_HIGH, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_reset = { +}; + +static const struct pch_gpio_set1 pch_gpio_set1_invert = { + .gpio1 = GPIO_INVERT, + .gpio13 = GPIO_INVERT, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_blink = { +}; + +static const struct pch_gpio_set2 pch_gpio_set2_mode = { + .gpio32 = GPIO_MODE_GPIO, + .gpio33 = GPIO_MODE_GPIO, + .gpio34 = GPIO_MODE_GPIO, + .gpio35 = GPIO_MODE_NATIVE, + .gpio36 = GPIO_MODE_NATIVE, + .gpio37 = GPIO_MODE_NATIVE, + .gpio38 = GPIO_MODE_NATIVE, + .gpio39 = GPIO_MODE_NATIVE, + .gpio40 = GPIO_MODE_NATIVE, + .gpio41 = GPIO_MODE_NATIVE, + .gpio42 = GPIO_MODE_NATIVE, + .gpio43 = GPIO_MODE_NATIVE, + .gpio44 = GPIO_MODE_NATIVE, + .gpio45 = GPIO_MODE_GPIO, + .gpio46 = GPIO_MODE_GPIO, + .gpio47 = GPIO_MODE_NATIVE, + .gpio48 = GPIO_MODE_NATIVE, + .gpio49 = GPIO_MODE_GPIO, + .gpio50 = GPIO_MODE_NATIVE, + .gpio51 = GPIO_MODE_NATIVE, + .gpio52 = GPIO_MODE_NATIVE, + .gpio53 = GPIO_MODE_NATIVE, + .gpio54 = GPIO_MODE_NATIVE, + .gpio55 = GPIO_MODE_NATIVE, + .gpio56 = GPIO_MODE_NATIVE, + .gpio57 = GPIO_MODE_GPIO, + .gpio58 = GPIO_MODE_NATIVE, + .gpio59 = GPIO_MODE_NATIVE, + .gpio60 = GPIO_MODE_NATIVE, + .gpio61 = GPIO_MODE_NATIVE, + .gpio62 = GPIO_MODE_NATIVE, + .gpio63 = GPIO_MODE_NATIVE, +}; + +static const struct pch_gpio_set2 pch_gpio_set2_direction = { + .gpio32 = GPIO_DIR_OUTPUT, + .gpio33 = GPIO_DIR_OUTPUT, + .gpio34 = GPIO_DIR_INPUT, + .gpio45 = GPIO_DIR_INPUT, + .gpio46 = GPIO_DIR_INPUT, + .gpio49 = GPIO_DIR_INPUT, + .gpio57 = GPIO_DIR_OUTPUT, +}; + +static const struct pch_gpio_set2 pch_gpio_set2_level = { + .gpio32 = GPIO_LEVEL_HIGH, + .gpio33 = GPIO_LEVEL_HIGH, + .gpio57 = GPIO_LEVEL_LOW, +}; + +static const struct pch_gpio_set2 pch_gpio_set2_reset = { +}; + +static const struct pch_gpio_set3 pch_gpio_set3_mode = { + .gpio64 = GPIO_MODE_NATIVE, + .gpio65 = GPIO_MODE_NATIVE, + .gpio66 = GPIO_MODE_NATIVE, + .gpio67 = GPIO_MODE_NATIVE, + .gpio68 = GPIO_MODE_GPIO, + .gpio69 = GPIO_MODE_GPIO, + .gpio70 = GPIO_MODE_NATIVE, + .gpio71 = GPIO_MODE_NATIVE, + .gpio72 = GPIO_MODE_GPIO, + .gpio73 = GPIO_MODE_NATIVE, + .gpio74 = GPIO_MODE_NATIVE, + .gpio75 = GPIO_MODE_NATIVE, +}; + +static const struct pch_gpio_set3 pch_gpio_set3_direction = { + .gpio68 = GPIO_DIR_INPUT, + .gpio69 = GPIO_DIR_INPUT, + .gpio72 = GPIO_DIR_INPUT, +}; + +static const struct pch_gpio_set3 pch_gpio_set3_level = { +}; + +static const struct pch_gpio_set3 pch_gpio_set3_reset = { +}; + +const struct pch_gpio_map mainboard_gpio_map = { + .set1 = { + .mode = &pch_gpio_set1_mode, + .direction = &pch_gpio_set1_direction, + .level = &pch_gpio_set1_level, + .blink = &pch_gpio_set1_blink, + .invert = &pch_gpio_set1_invert, + .reset = &pch_gpio_set1_reset, + }, + .set2 = { + .mode = &pch_gpio_set2_mode, + .direction = &pch_gpio_set2_direction, + .level = &pch_gpio_set2_level, + .reset = &pch_gpio_set2_reset, + }, + .set3 = { + .mode = &pch_gpio_set3_mode, + .direction = &pch_gpio_set3_direction, + .level = &pch_gpio_set3_level, + .reset = &pch_gpio_set3_reset, + }, +}; diff --git a/src/mainboard/asus/p8z77-m_pro/hda_verb.c b/src/mainboard/asus/p8z77-m_pro/hda_verb.c new file mode 100644 index 0000000000..4fd3fcc5e3 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/hda_verb.c @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Vladimir Serbinenko + * Copyright (C) 2019 Vlado Cibic + * + * 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 + +const u32 cim_verb_data[] = { + 0x10ec0892, /* Codec Vendor / Device ID: Realtek */ + 0x10438436, /* Subsystem ID */ + + 0x0000000f, /* Number of 4 dword sets */ + /* Subsystem ID */ + AZALIA_SUBVENDOR(0x0, 0x10438436), + + AZALIA_PIN_CFG(0x0, 0x11, 0x99430140), + AZALIA_PIN_CFG(0x0, 0x12, 0x411111f0), + AZALIA_PIN_CFG(0x0, 0x14, 0x01014010), + AZALIA_PIN_CFG(0x0, 0x15, 0x01011012), + AZALIA_PIN_CFG(0x0, 0x16, 0x01016011), + AZALIA_PIN_CFG(0x0, 0x17, 0x01012014), + AZALIA_PIN_CFG(0x0, 0x18, 0x01a19850), + AZALIA_PIN_CFG(0x0, 0x19, 0x02a19c60), + AZALIA_PIN_CFG(0x0, 0x1a, 0x0181305f), + AZALIA_PIN_CFG(0x0, 0x1b, 0x02214c20), + AZALIA_PIN_CFG(0x0, 0x1c, 0x411111f0), + AZALIA_PIN_CFG(0x0, 0x1d, 0x4005e601), + AZALIA_PIN_CFG(0x0, 0x1e, 0x01456130), + AZALIA_PIN_CFG(0x0, 0x1f, 0x411111f0), + 0x80862806, /* Codec Vendor / Device ID: Intel */ + 0x80860101, /* Subsystem ID */ + + 0x00000004, /* Number of 4 dword sets */ + /* Subsystem ID */ + AZALIA_SUBVENDOR(0x3, 0x80860101), + + AZALIA_PIN_CFG(0x3, 0x05, 0x58560010), + AZALIA_PIN_CFG(0x3, 0x06, 0x58560020), + AZALIA_PIN_CFG(0x3, 0x07, 0x18560030), +}; + +const u32 pc_beep_verbs[0] = {}; + +AZALIA_ARRAY_SIZES; diff --git a/src/mainboard/asus/p8z77-m_pro/mainboard.c b/src/mainboard/asus/p8z77-m_pro/mainboard.c new file mode 100644 index 0000000000..6cb41cc738 --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/mainboard.c @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 Vlado Cibic + * + * 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 +#include + +static void mainboard_enable(struct device *dev) +{ + install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_NONE, + GMA_INT15_PANEL_FIT_DEFAULT, + GMA_INT15_BOOT_DISPLAY_DEFAULT, + 0); +} + +struct chip_operations mainboard_ops = { + .enable_dev = mainboard_enable +}; diff --git a/src/mainboard/asus/p8z77-m_pro/romstage.c b/src/mainboard/asus/p8z77-m_pro/romstage.c new file mode 100644 index 0000000000..b5593ec23c --- /dev/null +++ b/src/mainboard/asus/p8z77-m_pro/romstage.c @@ -0,0 +1,193 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2019 Vlado Cibic + * + * 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 +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#define GLOBAL_DEV PNP_DEV(0x2e, 0) +#define SERIAL_DEV PNP_DEV(0x2e, NCT6779D_SP2) + +void pch_enable_lpc(void) +{ + pci_write_config16(PCH_LPC_DEV, LPC_EN, + CNF1_LPC_EN | CNF2_LPC_EN | + KBC_LPC_EN | COMB_LPC_EN); + + /* Set COMB/COM2 IO range to 2F8h-2FFh */ + pci_write_config16(PCH_LPC_DEV, LPC_IO_DEC, 0x10); +} + +void mainboard_rcba_config(void) +{ +} + +const struct southbridge_usb_port mainboard_usb_ports[] = { + /* {enable, current, oc_pin} */ + { 1, 2, 0 }, /* Port 0: USB3 front internal header, top */ + { 1, 2, 0 }, /* Port 1: USB3 front internal header, bottom */ + { 1, 2, 1 }, /* Port 2: USB3 rear, ETH top */ + { 1, 2, 1 }, /* Port 3: USB3 rear, ETH bottom */ + { 1, 2, 2 }, /* Port 4: USB2 rear, PS2 top */ + { 1, 2, 2 }, /* Port 5: USB2 rear, PS2 bottom */ + { 1, 2, 3 }, /* Port 6: USB2 internal header USB78, top */ + { 1, 2, 3 }, /* Port 7: USB2 internal header USB78, bottom */ + { 1, 2, 4 }, /* Port 8: USB2 internal header USB910, top */ + { 1, 2, 4 }, /* Port 9: USB2 internal header USB910, bottom */ + { 1, 2, 6 }, /* Port 10: USB2 internal header USB1112, top */ + { 1, 2, 5 }, /* Port 11: USB2 internal header USB1112, bottom */ + { 0, 2, 5 }, /* Port 12: Unused. Asus propietary DEBUG_PORT ??? */ + { 0, 2, 6 } /* Port 13: Unused. Asus propietary DEBUG_PORT ??? */ +}; + +void mainboard_early_init(int s3resume) +{ +} + +void mainboard_config_superio(void) +{ + /* Setup COM/UART */ + nuvoton_pnp_enter_conf_state(GLOBAL_DEV); + + /* TODO / FIXME: Setup Multifuncion/SIO pins for COM */ + + pnp_set_logical_device(SERIAL_DEV); + nuvoton_pnp_exit_conf_state(GLOBAL_DEV); + nuvoton_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); +} + +void mainboard_get_spd(spd_raw_data *spd, bool id_only) +{ + read_spd(&spd[0], 0x50, id_only); + read_spd(&spd[1], 0x51, id_only); + read_spd(&spd[2], 0x52, id_only); + read_spd(&spd[3], 0x53, id_only); +} + +int mainboard_should_reset_usb(int s3resume) +{ + return !s3resume; +} + +void mainboard_fill_pei_data(struct pei_data *pei_data) +{ + /* + * USB3 mode: + * 0 = Disable: work always as USB 2.0(ehci) + * 1 = Enable: work always as USB 3.0(xhci) + * 2 = Auto: work as USB2.0(ehci) until OS loads USB3 xhci driver + * 3 = Smart Auto : same than Auto, but if OS loads USB3 driver + * and reboots, it will keep the USB3.0 speed + */ + int usb3_mode = 1; + get_option(&usb3_mode, "usb3_mode"); + usb3_mode &= 0x3; /* ensure it's 0/1/2/3 only */ + + /* Load USB3 pre-OS xHCI driver */ + int usb3_drv = 1; + get_option(&usb3_drv, "usb3_drv"); + usb3_drv &= 0x1; /* ensure it's 0/1 only */ + + /* Use USB3 xHCI streams */ + int usb3_streams = 1; + get_option(&usb3_streams, "usb3_streams"); + usb3_streams &= 0x1; /* ensure it's 0/1 only */ + + struct pei_data pd = { + .pei_version = PEI_VERSION, + .mchbar = (uintptr_t)DEFAULT_MCHBAR, + .dmibar = (uintptr_t)DEFAULT_DMIBAR, + .epbar = DEFAULT_EPBAR, + .pciexbar = CONFIG_MMCONF_BASE_ADDRESS, + .smbusbar = SMBUS_IO_BASE, + .wdbbar = 0x4000000, + .wdbsize = 0x1000, + .hpet_address = CONFIG_HPET_ADDRESS, + .rcba = (uintptr_t)DEFAULT_RCBABASE, + .pmbase = DEFAULT_PMBASE, + .gpiobase = DEFAULT_GPIOBASE, + .thermalbase = 0xfed08000, + .system_type = 1, /* 0=Mobile, 1=Desktop/Server */ + .tseg_size = CONFIG_SMM_TSEG_SIZE, + .spd_addresses = { 0xa0, 0xa2, 0xa4, 0xa6 }, /* SMBus mul 2 */ + .ts_addresses = { 0x00, 0x00, 0x00, 0x00 }, + .ec_present = 0, /* Asus 2203 bios shows XUECA016, but no EC */ + .gbe_enable = 0, /* Board uses no Intel GbE but a RTL8111F */ + .dimm_channel0_disabled = 0, /* Both DIMM enabled */ + .dimm_channel1_disabled = 0, /* Both DIMM enabled */ + .max_ddr3_freq = 1600, /* 1333=Sandy; 1600=Ivy */ + .usb_port_config = { + /* {enabled, oc_pin, cable len 0x0080=<8inches/20cm} */ + { 1, 0, 0x0080 }, /* USB3 front internal header */ + { 1, 0, 0x0080 }, /* USB3 front internal header */ + { 1, 1, 0x0080 }, /* USB3 ETH top connector */ + { 1, 1, 0x0080 }, /* USB3 ETH botton connector */ + { 1, 2, 0x0080 }, /* USB2 PS2 top connector */ + { 1, 2, 0x0080 }, /* USB2 PS2 botton connector */ + { 1, 3, 0x0080 }, /* USB2 internal header (USB78) */ + { 1, 3, 0x0080 }, /* USB2 internal header (USB78) */ + { 1, 4, 0x0080 }, /* USB2 internal header (USB910) */ + { 1, 4, 0x0080 }, /* USB2 internal header (USB910) */ + { 1, 6, 0x0080 }, /* USB2 internal header (USB1112) */ + { 1, 5, 0x0080 }, /* USB2 internal header (USB1112) */ + { 0, 5, 0x0080 }, /* Unused. Asus DEBUG_PORT ??? */ + { 0, 6, 0x0080 } /* Unused. Asus DEBUG_PORT ??? */ + }, + .usb3 = { + /* 0=Disable; 1=Enable (start at USB3 speed) + * 2=Auto (start as USB2 speed until OS loads) + * 3=Smart Auto (like Auto but keep speed on reboot) + */ + usb3_mode, + /* 4 bit switch mask. 0=not switchable, 1=switchable + * Means once it's loaded the OS, it can swap ports + * from/to EHCI/xHCI. Z77 has four USB3 ports, so 0xf + */ + 0xf, + usb3_drv, /* 1=Load xHCI pre-OS drv */ + /* 0=Don't use xHCI streams for better compatibility + * 1=use xHCI streams for better speed + */ + usb3_streams + }, + /* ASUS P8Z77-M Pro manual says 1.35v DIMMs are supported */ + .ddr3lv_support = 1, + /* PCIe 3.0 support. As we use Ivy Bridge, let's enable it, + * but might cause some system inestability ! + */ + .pcie_init = 1, + /* Command Rate. 0=Auto; 1=1N; 2=2N. + * Leave it always at Auto for compatibility & stability + */ + .nmode = 0, + /* DDR refresh rate. 0=Auto based on DRAM's temperature; + * 1=Normal rate for speed; 2=Double rate for stability + */ + .ddr_refresh_rate_config = 0 + }; + + /* copy the data to output PEI */ + *pei_data = pd; +} From 5399f8084845225d666c1fcddc8b1f2d775b59eb Mon Sep 17 00:00:00 2001 From: Prudhvi Yarlagadda Date: Tue, 11 Jun 2019 16:05:02 +0530 Subject: [PATCH 195/221] libpayload: Re-initialize UART RX UART RX needs to be re-initialized in libpayload as it is getting reset at the end of coreboot. Change-Id: I7820bd7afd2e5f81e21a43f330ed42d3a732d577 Signed-off-by: Prudhvi Yarlagadda Reviewed-on: https://review.coreboot.org/c/coreboot/+/33424 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- payloads/libpayload/drivers/serial/qcs405.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/payloads/libpayload/drivers/serial/qcs405.c b/payloads/libpayload/drivers/serial/qcs405.c index 9f02e17263..7a80aae9c3 100644 --- a/payloads/libpayload/drivers/serial/qcs405.c +++ b/payloads/libpayload/drivers/serial/qcs405.c @@ -547,8 +547,10 @@ void serial_console_init(void) uart_board_param.uart_dm_base = (void *)(uintptr_t)sc_ptr->baseaddr; - /* TODO: We should rely on coreboot init. */ - msm_boot_uart_dm_init(uart_board_param.uart_dm_base); + /* We should re-initialise uart rx as it gets reset in coreboot. */ + write32(MSM_BOOT_UART_DM_IMR(uart_board_param.uart_dm_base), + MSM_BOOT_UART_DM_IMR_ENABLED); + msm_boot_uart_dm_init_rx_transfer(uart_board_param.uart_dm_base); console_add_output_driver(&consout); console_add_input_driver(&consin); From 096fd0a64b03fa3ecbdf14e3f27434a4d79ae26c Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Mon, 10 Jun 2019 13:18:59 -0700 Subject: [PATCH 196/221] qualcomm: qclib: Ensure interface table entry name is terminated This string is printed in dump_te_table() so we should make sure it's properly null-terminated. This fixes Coverity issue 1401305. Change-Id: I45827f552c2d8a4e01b50a699ac88ee457043282 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/33375 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Patrick Georgi --- src/soc/qualcomm/common/qclib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/soc/qualcomm/common/qclib.c b/src/soc/qualcomm/common/qclib.c index 73c525001e..25512a938f 100644 --- a/src/soc/qualcomm/common/qclib.c +++ b/src/soc/qualcomm/common/qclib.c @@ -41,7 +41,7 @@ void qclib_add_if_table_entry(const char *name, void *base, struct qclib_cb_if_table_entry *te = &qclib_cb_if_table.te[qclib_cb_if_table.num_entries++]; assert(qclib_cb_if_table.num_entries <= qclib_cb_if_table.max_entries); - strncpy(te->name, name, sizeof(te->name)); + strncpy(te->name, name, sizeof(te->name) - 1); te->blob_address = (uintptr_t)base; te->size = size; te->blob_attributes = attrs; From 7be4f30c5a0ae2177423c38235fd6b4c11c83f82 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Tue, 25 Jun 2019 19:36:27 +0200 Subject: [PATCH 197/221] arch/riscv/mcall: Drop debug code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The printk has no effect as console_init() hasn't been called. Also drop unused variables and headers. Change-Id: I5bf5a8822c69bbcc3de1de460d19585b8330649f Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33786 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki Reviewed-by: Philipp Hug --- src/arch/riscv/mcall.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/arch/riscv/mcall.c b/src/arch/riscv/mcall.c index eaef6442c5..afb17c1043 100644 --- a/src/arch/riscv/mcall.c +++ b/src/arch/riscv/mcall.c @@ -25,24 +25,15 @@ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#include -#include -#include #include #include #include -int mcalldebug; // set this interactively for copious debug. - void hls_init(uint32_t hart_id, void *fdt) { - printk(BIOS_SPEW, "hart %d: HLS is %p\n", hart_id, HLS()); memset(HLS(), 0, sizeof(*HLS())); HLS()->fdt = fdt; HLS()->hart_id = hart_id; mtime_init(); - - printk(BIOS_SPEW, "Time is %p and timecmp is %p\n", - HLS()->time, HLS()->timecmp); } From efc39cbec787b9447669c29e664e9ac74c476783 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Sun, 23 Jun 2019 19:23:30 +0200 Subject: [PATCH 198/221] mb/emulation/qemu-riscv: Use generic 8250 uart driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop hacked uart code and use the generic 8250 uart driver for ns16550a. Tested on qemu-system-riscv64: * The UART is still working. Change-Id: I6efda913fa39e0cfa466b52c570572aca90dacdf Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33735 Reviewed-by: Kyösti Mälkki Reviewed-by: Philipp Hug Tested-by: build bot (Jenkins) --- src/mainboard/emulation/qemu-riscv/Kconfig | 2 +- src/mainboard/emulation/qemu-riscv/uart.c | 35 +--------------------- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/src/mainboard/emulation/qemu-riscv/Kconfig b/src/mainboard/emulation/qemu-riscv/Kconfig index d15c99e966..f0f658d0d9 100644 --- a/src/mainboard/emulation/qemu-riscv/Kconfig +++ b/src/mainboard/emulation/qemu-riscv/Kconfig @@ -37,9 +37,9 @@ config BOARD_SPECIFIC_OPTIONS def_bool y select SOC_UCB_RISCV select BOARD_ROMSIZE_KB_4096 - select HAVE_UART_SPECIAL select BOOT_DEVICE_NOT_SPI_FLASH select MISSING_BOARD_RESET + select DRIVERS_UART_8250MEM config MAINBOARD_DIR string diff --git a/src/mainboard/emulation/qemu-riscv/uart.c b/src/mainboard/emulation/qemu-riscv/uart.c index 021713a40a..271e994493 100644 --- a/src/mainboard/emulation/qemu-riscv/uart.c +++ b/src/mainboard/emulation/qemu-riscv/uart.c @@ -15,42 +15,9 @@ #include #include -#include #include -static uint8_t *buf = (void *)QEMU_VIRT_UART0; uintptr_t uart_platform_base(int idx) { - return (uintptr_t) buf; + return (uintptr_t) QEMU_VIRT_UART0; } - -void uart_init(int idx) -{ -} - -unsigned char uart_rx_byte(int idx) -{ - return *buf; -} - -void uart_tx_byte(int idx, unsigned char data) -{ - *buf = data; -} - -void uart_tx_flush(int idx) -{ -} - -#ifndef __PRE_RAM__ -void uart_fill_lb(void *data) -{ - struct lb_serial serial; - serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED; - serial.baseaddr = QEMU_VIRT_UART0; - serial.baud = 115200; - serial.regwidth = 1; - lb_add_serial(&serial, data); - lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data); -} -#endif From e06e9197b8c5811694cac2ee370bb0cb9288be73 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Thu, 27 Jun 2019 22:53:47 +0200 Subject: [PATCH 199/221] lib/gnat: Use ADAFLAGS instead of CFLAGS Commit 6d7564cdfe (Move -Wlogical-op into xcompile) introduced GCC_ADAFLAGS_ but forgot to use them for libgnat. Fix that. Change-Id: Ia9079f01bb3c2a08296a3d3cc32fdf4ae5bb60c7 Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/33847 Reviewed-by: Patrick Georgi Reviewed-by: Angel Pons Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- src/lib/gnat/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/gnat/Makefile.inc b/src/lib/gnat/Makefile.inc index 3f22c0e8e1..c8886ec0aa 100644 --- a/src/lib/gnat/Makefile.inc +++ b/src/lib/gnat/Makefile.inc @@ -24,7 +24,7 @@ ADAFLAGS_libgnat-$(1) := \ -gnatg \ -gnatpg \ -I$$(src)/lib/gnat/ \ - $$(GCC_CFLAGS_$(1)) \ + $$(GCC_ADAFLAGS_$(1)) \ libgnat-$(1)-y += a-unccon.ads libgnat-$(1)-y += ada.ads From 7eb009a2ef4f7e0772948320a94fba126516d2d9 Mon Sep 17 00:00:00 2001 From: Nico Huber Date: Thu, 27 Jun 2019 22:58:18 +0200 Subject: [PATCH 200/221] lib/gnat: Enable -Werror We want to catch warnings as early as possible. Change-Id: Ifdb2ff8f7973d557a437ac127e073306f76ca6f6 Signed-off-by: Nico Huber Reviewed-on: https://review.coreboot.org/c/coreboot/+/33848 Reviewed-by: Patrick Georgi Reviewed-by: Angel Pons Reviewed-by: HAOUAS Elyes Tested-by: build bot (Jenkins) --- src/lib/gnat/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/gnat/Makefile.inc b/src/lib/gnat/Makefile.inc index c8886ec0aa..ebd04862bf 100644 --- a/src/lib/gnat/Makefile.inc +++ b/src/lib/gnat/Makefile.inc @@ -25,6 +25,7 @@ ADAFLAGS_libgnat-$(1) := \ -gnatpg \ -I$$(src)/lib/gnat/ \ $$(GCC_ADAFLAGS_$(1)) \ + -Werror \ libgnat-$(1)-y += a-unccon.ads libgnat-$(1)-y += ada.ads From 6033bdca8da89d3d78e58bc18fa8f1ddc4566635 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Tue, 18 Jun 2019 15:41:42 +0200 Subject: [PATCH 201/221] payloads/external/LinuxBoot: Update x86_64 defconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add support for Linux 5.x ** Select PCI, which isn't the default anymore with 5.x ** Select google firmware driver, which wasn't build any more * Add support for Intel LPSS uart ** Select MFD and MFD_INTEL_LPSS_PCI ** Increase console count to 32 * Add support for coreboot framebuffer ** Select FB_SIMPLE * Add support for eMMC/SDHCI ** Select MMC_SDHCI_* * Add support for u-root's localboot ** Select KEXEC_FILE_LOAD ** Select FIRMWARE_MEMMAP Stats: * Kernel size 1.9MiB * U-root (core + systemboot) 4.6MiB Tested on Intel APL Up² board: * Fixes non working console on APL Up2 board and eMMC bootmedia shows up. * Allows to boot GNU/Linux from eMMC using 'localboot' Change-Id: Ib5bd33531741e588ac7d5ff6a02b0482f6655ddf Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/33581 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Philipp Deppenwiese --- payloads/external/LinuxBoot/x86_64/defconfig | 92 ++++++++++---------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/payloads/external/LinuxBoot/x86_64/defconfig b/payloads/external/LinuxBoot/x86_64/defconfig index 39ae162f5f..b28a80f39a 100644 --- a/payloads/external/LinuxBoot/x86_64/defconfig +++ b/payloads/external/LinuxBoot/x86_64/defconfig @@ -4,6 +4,7 @@ CONFIG_KERNEL_XZ=y CONFIG_SYSVIPC=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y CONFIG_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_CGROUPS=y CONFIG_MEMCG=y @@ -36,36 +37,20 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_SLOB=y # CONFIG_SLAB_MERGE_DEFAULT is not set -CONFIG_GCC_PLUGINS=y -CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y -CONFIG_GCC_PLUGIN_STRUCTLEAK=y -CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y -CONFIG_GCC_PLUGIN_RANDSTRUCT=y -# CONFIG_VMAP_STACK is not set -CONFIG_REFCOUNT_FULL=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_PARTITION_ADVANCED=y -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -# CONFIG_MQ_IOSCHED_DEADLINE is not set -# CONFIG_MQ_IOSCHED_KYBER is not set # CONFIG_ZONE_DMA is not set # CONFIG_X86_MPPARSE is not set # CONFIG_X86_EXTENDED_PLATFORM is not set -CONFIG_IOSF_MBI=y # CONFIG_SCHED_OMIT_FRAME_POINTER is not set # CONFIG_DMI is not set -CONFIG_PREEMPT=y # CONFIG_X86_MCE is not set # CONFIG_MICROCODE is not set CONFIG_X86_MSR=y CONFIG_X86_CPUID=y -# CONFIG_SPARSEMEM_VMEMMAP is not set -# CONFIG_COMPACTION is not set # CONFIG_MTRR is not set # CONFIG_X86_INTEL_UMIP is not set # CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS is not set CONFIG_KEXEC=y +CONFIG_KEXEC_FILE=y # CONFIG_RELOCATABLE is not set # CONFIG_MODIFY_LDT_SYSCALL is not set # CONFIG_SUSPEND is not set @@ -78,12 +63,30 @@ CONFIG_ACPI_VIDEO=y # CONFIG_ACPI_TABLE_UPGRADE is not set # CONFIG_X86_PM_TIMER is not set # CONFIG_CPU_IDLE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCIEASPM_POWER_SUPERSAVE=y -CONFIG_PCI_MSI=y # CONFIG_ISA_DMA_API is not set +CONFIG_GOOGLE_FIRMWARE=y +CONFIG_GOOGLE_COREBOOT_TABLE=y +CONFIG_GOOGLE_FRAMEBUFFER_COREBOOT=y +CONFIG_GOOGLE_MEMCONSOLE_COREBOOT=y +CONFIG_GOOGLE_VPD=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_VMAP_STACK is not set +CONFIG_REFCOUNT_FULL=y +CONFIG_GCC_PLUGINS=y +CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y +CONFIG_GCC_PLUGIN_STRUCTLEAK=y +CONFIG_GCC_PLUGIN_RANDSTRUCT=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set # CONFIG_BINFMT_SCRIPT is not set # CONFIG_COREDUMP is not set +# CONFIG_SPARSEMEM_VMEMMAP is not set +# CONFIG_COMPACTION is not set +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCI_MSI=y # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -92,35 +95,38 @@ CONFIG_DEVTMPFS_MOUNT=y # CONFIG_ALLOW_DEV_COREDUMP is not set # CONFIG_PNP_DEBUG_MESSAGES is not set CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NVME=y +CONFIG_NVME_MULTIPATH=y CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_LOWLEVEL is not set CONFIG_ATA=y -CONFIG_SATA_AHCI=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -# CONFIG_SERIAL_8250_EXAR is not set -# CONFIG_SERIAL_8250_LPSS is not set -# CONFIG_SERIAL_8250_MID is not set -# CONFIG_SERIAL_8250_PNP is not set CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +# CONFIG_SERIAL_8250_PNP is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=32 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_DEV_BUS=y CONFIG_HW_RANDOM_TIMERIOMEM=y -# CONFIG_HW_RANDOM_AMD is not set # CONFIG_HW_RANDOM_VIA is not set CONFIG_TCG_TPM=y CONFIG_TCG_TIS=y -# CONFIG_DEVPORT is not set CONFIG_I2C=y CONFIG_POWER_SUPPLY=y # CONFIG_HWMON is not set -# CONFIG_VGA_ARB is not set +CONFIG_MFD_INTEL_LPSS_PCI=y CONFIG_FB=y CONFIG_FIRMWARE_EDID=y CONFIG_FB_FOREIGN_ENDIAN=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_TILEBLITTING=y +CONFIG_FB_SIMPLE=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_VGACON_SOFT_SCROLLBACK=y CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y @@ -128,14 +134,14 @@ CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y # CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PCI=y +CONFIG_MMC_SDHCI_ACPI=y +CONFIG_MMC_SDHCI_PLTFM=y CONFIG_SYNC_FILE=y # CONFIG_VIRTIO_MENU is not set # CONFIG_X86_PLATFORM_DEVICES is not set -# CONFIG_FIRMWARE_MEMMAP is not set -CONFIG_GOOGLE_FIRMWARE=y -CONFIG_GOOGLE_COREBOOT_TABLE_ACPI=y -CONFIG_GOOGLE_MEMCONSOLE_COREBOOT=y -CONFIG_GOOGLE_VPD=y CONFIG_EXT4_FS=y # CONFIG_FILE_LOCKING is not set # CONFIG_DNOTIFY is not set @@ -149,7 +155,13 @@ CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_UTF8=y CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set -# CONFIG_ENABLE_WARN_DEPRECATED is not set +CONFIG_SECURITY_DMESG_RESTRICT=y +CONFIG_FORTIFY_SOURCE=y +# CONFIG_CRYPTO_ECHAINIV is not set +CONFIG_CRYPTO_SHA256_SSSE3=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_JITTERENTROPY=y +# CONFIG_CRYPTO_HW is not set # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=1024 # CONFIG_UNUSED_SYMBOLS is not set @@ -163,11 +175,3 @@ CONFIG_FRAME_WARN=1024 CONFIG_OPTIMIZE_INLINING=y # CONFIG_X86_DEBUG_FPU is not set CONFIG_UNWINDER_GUESS=y -CONFIG_SECURITY_DMESG_RESTRICT=y -CONFIG_FORTIFY_SOURCE=y -# CONFIG_CRYPTO_ECHAINIV is not set -CONFIG_CRYPTO_SHA256_SSSE3=y -CONFIG_CRYPTO_ANSI_CPRNG=y -CONFIG_CRYPTO_JITTERENTROPY=y -# CONFIG_CRYPTO_HW is not set -# CONFIG_VIRTUALIZATION is not set From 479637d8a26344d60fa0172ba4c5a1e9eea2be25 Mon Sep 17 00:00:00 2001 From: Seunghwan Kim Date: Tue, 25 Jun 2019 17:37:11 +0900 Subject: [PATCH 202/221] mb/google/kohaku: Correct trackpad i2c address Correct i2c address of trackpad. It should be 0x20. BUG=None BRANCH=None TEST=Verified trackpad works on pre-evt system Change-Id: I7ded21ce8ff9e907e436777a27edb4273512011d Signed-off-by: Seunghwan Kim Reviewed-on: https://review.coreboot.org/c/coreboot/+/33798 Tested-by: build bot (Jenkins) Reviewed-by: Tim Wawrzynczak Reviewed-by: Shelley Chen --- src/mainboard/google/hatch/variants/kohaku/overridetree.cb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/google/hatch/variants/kohaku/overridetree.cb b/src/mainboard/google/hatch/variants/kohaku/overridetree.cb index 69875bdde2..cf422ed01d 100644 --- a/src/mainboard/google/hatch/variants/kohaku/overridetree.cb +++ b/src/mainboard/google/hatch/variants/kohaku/overridetree.cb @@ -70,7 +70,7 @@ chip soc/intel/cannonlake register "generic.irq" = "ACPI_IRQ_EDGE_LOW(GPP_D21_IRQ)" register "generic.probed" = "1" register "hid_desc_reg_offset" = "0x20" - device i2c 0x2c on end + device i2c 0x20 on end end end # I2C 0 From 16a70c3d40db0d31d8b6c6c13603d27ad6bf5be3 Mon Sep 17 00:00:00 2001 From: Mike Banon Date: Wed, 26 Jun 2019 09:38:03 +0300 Subject: [PATCH 203/221] asus/am1i-a: Enable UART according to CONFIG_UART_FOR_CONSOLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It has been observed by me and Elisenda Cuadros / Gergely Kiss [1] that the boot process of this board is super slow when UART 0 is being used - even if nothing is connected to it. Enable UART according to CONFIG_UART_FOR_CONSOLE - and, if UART 0 is selected, it will be initialized at romstage and this problem will not happen. [1] https://mail.coreboot.org/pipermail/coreboot/2018-February/086132.html Signed-off-by: Mike Banon Change-Id: I6579aa8fd092da84f8afdcc33496db45c582919f Reviewed-on: https://review.coreboot.org/c/coreboot/+/33796 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki Reviewed-by: Paul Menzel --- src/mainboard/asus/am1i-a/romstage.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mainboard/asus/am1i-a/romstage.c b/src/mainboard/asus/am1i-a/romstage.c index 4b172eaad8..5e1218abd3 100644 --- a/src/mainboard/asus/am1i-a/romstage.c +++ b/src/mainboard/asus/am1i-a/romstage.c @@ -25,7 +25,15 @@ #include #define ITE_CONFIG_REG_CC 0x02 + +#if CONFIG_UART_FOR_CONSOLE == 0 +#define SERIAL_DEV PNP_DEV(0x2e, IT8623E_SP1) +#elif CONFIG_UART_FOR_CONSOLE == 1 #define SERIAL_DEV PNP_DEV(0x2e, IT8623E_SP2) +#else +#error "Invalid value for CONFIG_UART_FOR_CONSOLE" +#endif + #define GPIO_DEV PNP_DEV(0x2e, IT8623E_GPIO) #define CLKIN_DEV PNP_DEV(0x2e, IT8623E_GPIO) #define ENVC_DEV PNP_DEV(0x2e, IT8623E_EC) From 85d3b40a19358c4014eceaea3204feece8b15edd Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Sat, 15 Jun 2019 16:42:00 -0500 Subject: [PATCH 204/221] soc/intel/cannonlake: fix use of legacy 8254 timer FSP sets the use of the 8254 timer via the Enable8254ClockGating UPD, which defaults to enabled, overriding what is set by coreboot. Per the FSP integration guide, this UPD needs to be disabled when a legacy OS is booted (ie, when SeaBIOS is used as the payload). Add a Kconfig option to set the UPD properly based on payload selection, and remove the existing coreboot code in lpc.c since it is either ineffective or being overridden by FSP. Test: build/boot out-of-tree WHL board with both SeaBIOS and Tianocore, ensure 8254 timer usage set correctly for each. Signed-off-by: Matt DeVillier Change-Id: I0e888bf754cb72093f14fc02f39bddcd6d288203 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33512 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/soc/intel/cannonlake/Kconfig | 8 ++++++++ src/soc/intel/cannonlake/chip.h | 2 -- src/soc/intel/cannonlake/fsp_params.c | 4 ++++ src/soc/intel/cannonlake/lpc.c | 11 ----------- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index 2279df2247..679efce396 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -314,4 +314,12 @@ config SOC_INTEL_CANNONLAKE_DEBUG_CONSENT Setting non-zero value will allow to use DBC or DCI to debug SOC. PlatformDebugConsent in FspmUpd.h has the details. +config USE_LEGACY_8254_TIMER + bool "Use Legacy 8254 Timer" + default y if PAYLOAD_SEABIOS + default n + help + This sets the Enable8254ClockGating UPD, which according to the FSP Integration + guide needs to be disabled in order to boot SeaBIOS, but should otherwise be enabled. + endif diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index 3b4c980e2d..71aa2086d5 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -246,8 +246,6 @@ struct soc_intel_cannonlake_config { /* Enable/Disable EIST. 1b:Enabled, 0b:Disabled */ uint8_t eist_enable; - /* Statically clock gate 8254 PIT. */ - uint8_t clock_gate_8254; /* Enable C6 DRAM */ uint8_t enable_c6dram; /* diff --git a/src/soc/intel/cannonlake/fsp_params.c b/src/soc/intel/cannonlake/fsp_params.c index dd9388296d..783ebb7ab3 100644 --- a/src/soc/intel/cannonlake/fsp_params.c +++ b/src/soc/intel/cannonlake/fsp_params.c @@ -244,6 +244,10 @@ void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd) /* disable Legacy PME */ memset(params->PcieRpPmSci, 0, sizeof(params->PcieRpPmSci)); + /* Legacy 8254 timer support */ + params->Enable8254ClockGating = !CONFIG_USE_LEGACY_8254_TIMER; + params->Enable8254ClockGatingOnS3 = 1; + /* USB */ for (i = 0; i < ARRAY_SIZE(config->usb2_ports); i++) { params->PortUsb20Enable[i] = config->usb2_ports[i].enable; diff --git a/src/soc/intel/cannonlake/lpc.c b/src/soc/intel/cannonlake/lpc.c index 56fefa5c05..6cc34515d7 100644 --- a/src/soc/intel/cannonlake/lpc.c +++ b/src/soc/intel/cannonlake/lpc.c @@ -207,16 +207,6 @@ static void pch_misc_init(void) outb(0x70, (1 << 7)); }; -static void clock_gate_8254(const struct device *dev) -{ - const config_t *config = dev->chip_info; - - if (!config->clock_gate_8254) - return; - - itss_clock_gate_8254(); -} - void lpc_soc_init(struct device *dev) { /* Legacy initialization */ @@ -237,7 +227,6 @@ void lpc_soc_init(struct device *dev) soc_pch_pirq_init(dev); setup_i8259(); i8259_configure_irq_trigger(9, 1); - clock_gate_8254(dev); soc_mirror_dmi_pcr_io_dec(); } From e5845bfb2d676b358fdaa1bc754de6101c8dceb7 Mon Sep 17 00:00:00 2001 From: Elyes HAOUAS Date: Mon, 24 Jun 2019 19:22:58 +0200 Subject: [PATCH 205/221] {soc,northbridge}/Kconfig: Remove unused CACHE_MRC_SIZE_KB Change-Id: Ie922832bc7641a44a53c0cda8d808579c66420b5 Signed-off-by: Elyes HAOUAS Reviewed-on: https://review.coreboot.org/c/coreboot/+/33743 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/northbridge/intel/haswell/Kconfig | 4 ---- src/northbridge/intel/sandybridge/Kconfig | 4 ---- src/soc/intel/broadwell/Kconfig | 4 ---- 3 files changed, 12 deletions(-) diff --git a/src/northbridge/intel/haswell/Kconfig b/src/northbridge/intel/haswell/Kconfig index e1067c5949..3678cb803d 100644 --- a/src/northbridge/intel/haswell/Kconfig +++ b/src/northbridge/intel/haswell/Kconfig @@ -55,10 +55,6 @@ config MMCONF_BASE_ADDRESS hex default 0xf0000000 -config CACHE_MRC_SIZE_KB - int - default 512 - config DCACHE_RAM_BASE hex default 0xff7c0000 diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig index 59cf92c0ee..53725cafb4 100644 --- a/src/northbridge/intel/sandybridge/Kconfig +++ b/src/northbridge/intel/sandybridge/Kconfig @@ -64,10 +64,6 @@ config VGA_BIOS_ID string default "8086,0106" -config CACHE_MRC_SIZE_KB - int - default 512 - config BOOTBLOCK_NORTHBRIDGE_INIT string default "northbridge/intel/sandybridge/bootblock.c" diff --git a/src/soc/intel/broadwell/Kconfig b/src/soc/intel/broadwell/Kconfig index d81ab8ac95..801800c5f4 100644 --- a/src/soc/intel/broadwell/Kconfig +++ b/src/soc/intel/broadwell/Kconfig @@ -106,10 +106,6 @@ config VGA_BIOS_ID string default "8086,0406" -config CACHE_MRC_SIZE_KB - int - default 512 - config DCACHE_RAM_BASE hex default 0xff7c0000 From 09bf63eacf5ae3cf3d8d1937bff1e69bf10f73d7 Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Fri, 31 May 2019 16:03:27 +0300 Subject: [PATCH 206/221] MAINTAINERS: Add myself as a maintainer for apple boards Change-Id: I33bf45c81cc4be157ea71806900a545ee68ecee8 Signed-off-by: Evgeny Zinoviev Reviewed-on: https://review.coreboot.org/c/coreboot/+/33148 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 83ba5232b3..73ca6dfed9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -164,6 +164,11 @@ M: Patrick Rudolph S: Maintained F: src/mainboard/lenovo/ +APPLE MAINBOARDS +M: Evgeny Zinoviev +S: Maintained +F: src/mainboard/apple/ + GETAC P470 MAINBOARD M: Patrick Georgi S: Maintained From 8a443b9aded5a2e78871484b80c09a94bf54708d Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Mon, 24 Jun 2019 16:37:45 -0600 Subject: [PATCH 207/221] sb/amd/rs780: Remove dead assignment We return immediately after, so this assignment can be removed. Change-Id: I2a317ada0132a40b623402055b3b995bde80ddf5 Signed-off-by: Jacob Garber Found-by: scan-build 8.0.0 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33773 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Angel Pons --- src/southbridge/amd/rs780/cmn.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/southbridge/amd/rs780/cmn.c b/src/southbridge/amd/rs780/cmn.c index 17ca98079a..1520748796 100644 --- a/src/southbridge/amd/rs780/cmn.c +++ b/src/southbridge/amd/rs780/cmn.c @@ -263,7 +263,6 @@ u8 PcieTrainPort(struct device *nb_dev, struct device *dev, u32 port) gfx_gpp_sb_sel = PCIE_CORE_INDEX_GPP; break; default: - gfx_gpp_sb_sel = -1; return 0; } From 70f6d8261427104d246847e4289d6bae07db851e Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Mon, 24 Jun 2019 13:24:16 -0600 Subject: [PATCH 208/221] cpu/amd/family_10h-family_15h: Remove dead assignment Pstate_num is initialized later when it is used as a loop index, so this duplicate assignment can be removed. Change-Id: I71429bd3306139a823ed39e751d779e4d874f657 Signed-off-by: Jacob Garber Found-by: scan-build 8.0.0 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33745 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/cpu/amd/family_10h-family_15h/powernow_acpi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cpu/amd/family_10h-family_15h/powernow_acpi.c b/src/cpu/amd/family_10h-family_15h/powernow_acpi.c index e648b71750..be936f66e3 100644 --- a/src/cpu/amd/family_10h-family_15h/powernow_acpi.c +++ b/src/cpu/amd/family_10h-family_15h/powernow_acpi.c @@ -259,8 +259,6 @@ void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP) else if (mctGetLogicalCPUID(0) & AMD_FAM15_ALL) boost_count = (dtemp >> 2) & 0x7; - Pstate_num = 0; - /* See if the CPUID(0x80000007) returned EDX[7]==1b */ cpuid1 = cpuid(0x80000007); if ((cpuid1.edx & 0x80) != 0x80) { From 93064ff7cd348f143b9c890a15b65680d3265525 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Mon, 24 Jun 2019 13:02:27 -0600 Subject: [PATCH 209/221] device/dram: Inline value into print statement By default printram() expands to nothing in normal builds, and so scan-build thinks that the assignment to reg8 is unused. Inline the value of reg8 into the print statement to silence the warning. Change-Id: I921fe08949c4135367bee9646b3b365097fab19e Signed-off-by: Jacob Garber Found-by: scan-build 8.0.0 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33744 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons --- src/device/dram/ddr3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/device/dram/ddr3.c b/src/device/dram/ddr3.c index 3272dac6d7..834dc83db6 100644 --- a/src/device/dram/ddr3.c +++ b/src/device/dram/ddr3.c @@ -382,8 +382,7 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd) dimm->flags.therm_sensor ? "yes" : "no"); /* SDRAM Device Type */ - reg8 = spd[33]; - printram(" Standard SDRAM : %s\n", (reg8 & 0x80) ? "no" : "yes"); + printram(" Standard SDRAM : %s\n", (spd[33] & 0x80) ? "no" : "yes"); if (spd[63] & 0x01) { dimm->flags.pins_mirrored = 1; From d10680bbbfc045627625ca0ce79e04491978cedf Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Tue, 11 Jun 2019 14:13:04 -0600 Subject: [PATCH 210/221] nb/intel/pineview: Remove unused code All the clocks are switched on anyway, so this series of if statements isn't needed. Change-Id: I654043fd6736caa6890fd697015c577ddaa7cd41 Signed-off-by: Jacob Garber Found-by: Coverity CID 13473{27-30} Reviewed-on: https://review.coreboot.org/c/coreboot/+/33408 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Angel Pons --- src/northbridge/intel/pineview/raminit.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/northbridge/intel/pineview/raminit.c b/src/northbridge/intel/pineview/raminit.c index 72063cbdad..1d24ea2217 100644 --- a/src/northbridge/intel/pineview/raminit.c +++ b/src/northbridge/intel/pineview/raminit.c @@ -1141,16 +1141,7 @@ static void sdram_dlltiming(struct sysinfo *s) MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1; MCHBAR32(0x1a0) = 0x551803; - if (ONLY_DIMMA_IS_POPULATED(s->dimms, 0)) { - reg8 = 0x3c; - } else if (ONLY_DIMMB_IS_POPULATED(s->dimms, 0)) { - reg8 = 0x27; - } else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, 0)) { - reg8 = 0x24; - } else { - // None - reg8 = 0x3f; - } + reg8 = 0x00; //switch all clocks on anyway MCHBAR32(0x5a0) = (MCHBAR32(0x5a0) & ~0x3f000000) | (reg8 << 24); From f77f7cdf891a3ab47f71eb392e4229ece33f27ac Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Wed, 5 Jun 2019 16:32:28 -0600 Subject: [PATCH 211/221] device,nb/amd: Deduplicate add_more_links() This function is duplicated in many AMD northbridge files, and all the definitions have started to diverge somewhat. This moves a single copy into device utils and deletes the rest. The function definition from nb/amd/amdfam10 was chosen to be kept, since it contains several fixes from commit 59d609217b (AMD fam10: Fix add_more_links) that the others don't have. For the ease of diffing, the checkpatch lints and other small cleanups will be done in a follow-up patch. Change-Id: I5ea73126092449db3f18e19ac0660439313072de Signed-off-by: Jacob Garber Reviewed-on: https://review.coreboot.org/c/coreboot/+/33237 Reviewed-by: Angel Pons Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/device/device_util.c | 36 +++++++++++++++++++ src/include/device/device.h | 1 + .../amd/agesa/family15tn/northbridge.c | 36 ------------------- .../amd/agesa/family16kb/northbridge.c | 36 ------------------- src/northbridge/amd/amdfam10/northbridge.c | 36 ------------------- src/northbridge/amd/pi/00630F01/northbridge.c | 36 ------------------- src/northbridge/amd/pi/00660F01/northbridge.c | 36 ------------------- src/northbridge/amd/pi/00730F01/northbridge.c | 36 ------------------- 8 files changed, 37 insertions(+), 216 deletions(-) diff --git a/src/device/device_util.c b/src/device/device_util.c index 47df3052e2..e2370a1cce 100644 --- a/src/device/device_util.c +++ b/src/device/device_util.c @@ -654,6 +654,42 @@ bool dev_is_active_bridge(struct device *dev) return 0; } +void add_more_links(struct device *dev, unsigned total_links) +{ + struct bus *link, *last = NULL; + int link_num = -1; + + for (link = dev->link_list; link; link = link->next) { + if (link_num < link->link_num) + link_num = link->link_num; + last = link; + } + + if (last) { + int links = total_links - (link_num + 1); + if (links > 0) { + link = malloc(links*sizeof(*link)); + if (!link) + die("Couldn't allocate more links!\n"); + memset(link, 0, links*sizeof(*link)); + last->next = link; + } + } else { + link = malloc(total_links*sizeof(*link)); + memset(link, 0, total_links*sizeof(*link)); + dev->link_list = link; + } + + for (link_num = link_num + 1; link_num < total_links; link_num++) { + link->link_num = link_num; + link->dev = dev; + link->next = link + 1; + last = link; + link = link->next; + } + last->next = NULL; +} + static void resource_tree(const struct device *root, int debug_level, int depth) { int i = 0; diff --git a/src/include/device/device.h b/src/include/device/device.h index 32cf07282b..52635e1bd2 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -191,6 +191,7 @@ const char *bus_path(struct bus *bus); void dev_set_enabled(struct device *dev, int enable); void disable_children(struct bus *bus); bool dev_is_active_bridge(struct device *dev); +void add_more_links(struct device *dev, unsigned total_links); /* Option ROM helper functions */ void run_bios(struct device *dev, unsigned long addr); diff --git a/src/northbridge/amd/agesa/family15tn/northbridge.c b/src/northbridge/amd/agesa/family15tn/northbridge.c index d73ad72de0..c6457a3998 100644 --- a/src/northbridge/amd/agesa/family15tn/northbridge.c +++ b/src/northbridge/amd/agesa/family15tn/northbridge.c @@ -772,42 +772,6 @@ static void sysconf_init(struct device *dev) // first node node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; //NodeCnt[2:0] } -static void add_more_links(struct device *dev, unsigned int total_links) -{ - struct bus *link, *last = NULL; - int link_num; - - for (link = dev->link_list; link; link = link->next) - last = link; - - if (last) { - int links = total_links - last->link_num; - link_num = last->link_num; - if (links > 0) { - link = malloc(links*sizeof(*link)); - if (!link) - die("Couldn't allocate more links!\n"); - memset(link, 0, links*sizeof(*link)); - last->next = link; - } - } - else { - link_num = -1; - link = malloc(total_links*sizeof(*link)); - memset(link, 0, total_links*sizeof(*link)); - dev->link_list = link; - } - - for (link_num = link_num + 1; link_num < total_links; link_num++) { - link->link_num = link_num; - link->dev = dev; - link->next = link + 1; - last = link; - link = link->next; - } - last->next = NULL; -} - static void cpu_bus_scan(struct device *dev) { struct bus *cpu_bus; diff --git a/src/northbridge/amd/agesa/family16kb/northbridge.c b/src/northbridge/amd/agesa/family16kb/northbridge.c index 7ca5a6ed53..928d9d2e8a 100644 --- a/src/northbridge/amd/agesa/family16kb/northbridge.c +++ b/src/northbridge/amd/agesa/family16kb/northbridge.c @@ -798,42 +798,6 @@ static void sysconf_init(struct device *dev) // first node node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; //NodeCnt[2:0] } -static void add_more_links(struct device *dev, unsigned int total_links) -{ - struct bus *link, *last = NULL; - int link_num; - - for (link = dev->link_list; link; link = link->next) - last = link; - - if (last) { - int links = total_links - last->link_num; - link_num = last->link_num; - if (links > 0) { - link = malloc(links*sizeof(*link)); - if (!link) - die("Couldn't allocate more links!\n"); - memset(link, 0, links*sizeof(*link)); - last->next = link; - } - } - else { - link_num = -1; - link = malloc(total_links*sizeof(*link)); - memset(link, 0, total_links*sizeof(*link)); - dev->link_list = link; - } - - for (link_num = link_num + 1; link_num < total_links; link_num++) { - link->link_num = link_num; - link->dev = dev; - link->next = link + 1; - last = link; - link = link->next; - } - last->next = NULL; -} - static void cpu_bus_scan(struct device *dev) { struct bus *cpu_bus; diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c index e28b89b8e4..79f43db387 100644 --- a/src/northbridge/amd/amdfam10/northbridge.c +++ b/src/northbridge/amd/amdfam10/northbridge.c @@ -1361,42 +1361,6 @@ static void sysconf_init(struct device *dev) // first node #endif } -static void add_more_links(struct device *dev, unsigned total_links) -{ - struct bus *link, *last = NULL; - int link_num = -1; - - for (link = dev->link_list; link; link = link->next) { - if (link_num < link->link_num) - link_num = link->link_num; - last = link; - } - - if (last) { - int links = total_links - (link_num + 1); - if (links > 0) { - link = malloc(links*sizeof(*link)); - if (!link) - die("Couldn't allocate more links!\n"); - memset(link, 0, links*sizeof(*link)); - last->next = link; - } - } else { - link = malloc(total_links*sizeof(*link)); - memset(link, 0, total_links*sizeof(*link)); - dev->link_list = link; - } - - for (link_num = link_num + 1; link_num < total_links; link_num++) { - link->link_num = link_num; - link->dev = dev; - link->next = link + 1; - last = link; - link = link->next; - } - last->next = NULL; -} - static void remap_bsp_lapic(struct bus *cpu_bus) { struct device_path cpu_path; diff --git a/src/northbridge/amd/pi/00630F01/northbridge.c b/src/northbridge/amd/pi/00630F01/northbridge.c index 309a762840..518c6e2ab9 100644 --- a/src/northbridge/amd/pi/00630F01/northbridge.c +++ b/src/northbridge/amd/pi/00630F01/northbridge.c @@ -786,42 +786,6 @@ static void sysconf_init(struct device *dev) // first node node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; //NodeCnt[2:0] } -static void add_more_links(struct device *dev, unsigned total_links) -{ - struct bus *link, *last = NULL; - int link_num; - - for (link = dev->link_list; link; link = link->next) - last = link; - - if (last) { - int links = total_links - last->link_num; - link_num = last->link_num; - if (links > 0) { - link = malloc(links*sizeof(*link)); - if (!link) - die("Couldn't allocate more links!\n"); - memset(link, 0, links*sizeof(*link)); - last->next = link; - } - } - else { - link_num = -1; - link = malloc(total_links*sizeof(*link)); - memset(link, 0, total_links*sizeof(*link)); - dev->link_list = link; - } - - for (link_num = link_num + 1; link_num < total_links; link_num++) { - link->link_num = link_num; - link->dev = dev; - link->next = link + 1; - last = link; - link = link->next; - } - last->next = NULL; -} - static void cpu_bus_scan(struct device *dev) { struct bus *cpu_bus; diff --git a/src/northbridge/amd/pi/00660F01/northbridge.c b/src/northbridge/amd/pi/00660F01/northbridge.c index 41641ee65f..c67e5ff2ee 100644 --- a/src/northbridge/amd/pi/00660F01/northbridge.c +++ b/src/northbridge/amd/pi/00660F01/northbridge.c @@ -784,42 +784,6 @@ static void sysconf_init(struct device *dev) // first node node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; // NodeCnt[2:0] } -static void add_more_links(struct device *dev, unsigned total_links) -{ - struct bus *link, *last = NULL; - int link_num; - - for (link = dev->link_list; link; link = link->next) - last = link; - - if (last) { - int links = total_links - last->link_num; - link_num = last->link_num; - if (links > 0) { - link = malloc(links*sizeof(*link)); - if (!link) - die("Couldn't allocate more links!\n"); - memset(link, 0, links*sizeof(*link)); - last->next = link; - } - } - else { - link_num = -1; - link = malloc(total_links*sizeof(*link)); - memset(link, 0, total_links*sizeof(*link)); - dev->link_list = link; - } - - for (link_num = link_num + 1; link_num < total_links; link_num++) { - link->link_num = link_num; - link->dev = dev; - link->next = link + 1; - last = link; - link = link->next; - } - last->next = NULL; -} - static void cpu_bus_scan(struct device *dev) { struct bus *cpu_bus; diff --git a/src/northbridge/amd/pi/00730F01/northbridge.c b/src/northbridge/amd/pi/00730F01/northbridge.c index 2ca9d4efbd..377d91eeae 100644 --- a/src/northbridge/amd/pi/00730F01/northbridge.c +++ b/src/northbridge/amd/pi/00730F01/northbridge.c @@ -1025,42 +1025,6 @@ static void sysconf_init(struct device *dev) // first node node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; //NodeCnt[2:0] } -static void add_more_links(struct device *dev, unsigned int total_links) -{ - struct bus *link, *last = NULL; - int link_num; - - for (link = dev->link_list; link; link = link->next) - last = link; - - if (last) { - int links = total_links - last->link_num; - link_num = last->link_num; - if (links > 0) { - link = malloc(links*sizeof(*link)); - if (!link) - die("Couldn't allocate more links!\n"); - memset(link, 0, links*sizeof(*link)); - last->next = link; - } - } - else { - link_num = -1; - link = malloc(total_links*sizeof(*link)); - memset(link, 0, total_links*sizeof(*link)); - dev->link_list = link; - } - - for (link_num = link_num + 1; link_num < total_links; link_num++) { - link->link_num = link_num; - link->dev = dev; - link->next = link + 1; - last = link; - link = link->next; - } - last->next = NULL; -} - static void cpu_bus_scan(struct device *dev) { struct bus *cpu_bus; From 464f4d6ee240e5afd44317d9b7bc4a1228c04899 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Wed, 5 Jun 2019 17:03:30 -0600 Subject: [PATCH 212/221] device: Tidy up add_more_links() - Add documentation comment - Use 'unsigned int' to make checkpatch happy - Return early if no more links need to be added - Add error handling if malloc fails - Clean up whitespace Change-Id: I70976ee2539b058721d0ae3c15edf279253cd9b7 Signed-off-by: Jacob Garber Found-by: Coverity CID 1229634 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33238 Reviewed-by: Angel Pons Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/device/device_util.c | 21 ++++++++++++++++----- src/include/device/device.h | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/device/device_util.c b/src/device/device_util.c index e2370a1cce..11954a1982 100644 --- a/src/device/device_util.c +++ b/src/device/device_util.c @@ -654,7 +654,13 @@ bool dev_is_active_bridge(struct device *dev) return 0; } -void add_more_links(struct device *dev, unsigned total_links) +/** + * Ensure the device has a minimum number of bus links. + * + * @param dev The device to add links to. + * @param total_links The minimum number of links to have. + */ +void add_more_links(struct device *dev, unsigned int total_links) { struct bus *link, *last = NULL; int link_num = -1; @@ -668,15 +674,20 @@ void add_more_links(struct device *dev, unsigned total_links) if (last) { int links = total_links - (link_num + 1); if (links > 0) { - link = malloc(links*sizeof(*link)); + link = malloc(links * sizeof(*link)); if (!link) die("Couldn't allocate more links!\n"); - memset(link, 0, links*sizeof(*link)); + memset(link, 0, links * sizeof(*link)); last->next = link; + } else { + /* No more links to add */ + return; } } else { - link = malloc(total_links*sizeof(*link)); - memset(link, 0, total_links*sizeof(*link)); + link = malloc(total_links * sizeof(*link)); + if (!link) + die("Couldn't allocate more links!\n"); + memset(link, 0, total_links * sizeof(*link)); dev->link_list = link; } diff --git a/src/include/device/device.h b/src/include/device/device.h index 52635e1bd2..8e9454c4e1 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -191,7 +191,7 @@ const char *bus_path(struct bus *bus); void dev_set_enabled(struct device *dev, int enable); void disable_children(struct bus *bus); bool dev_is_active_bridge(struct device *dev); -void add_more_links(struct device *dev, unsigned total_links); +void add_more_links(struct device *dev, unsigned int total_links); /* Option ROM helper functions */ void run_bios(struct device *dev, unsigned long addr); From c22ebc9339bf75ab55bbb885ede0c63314f46014 Mon Sep 17 00:00:00 2001 From: Jacob Garber Date: Mon, 24 Jun 2019 18:32:03 -0600 Subject: [PATCH 213/221] sb/amd/sb{700,800}: Clean up index manipulations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It looks like in days gone by that these switches were once parts of loops that incremented 'index' as they went along. However, we don't have any loops anymore, so remove the needless increments and streamline the rest of the assignments. Change-Id: Iaabee984333c273af7810f9c11ed26bbb2a995d1 Signed-off-by: Jacob Garber Found-by: scan-build 8.0.0 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33774 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/southbridge/amd/sb700/sb700.c | 11 +---------- src/southbridge/amd/sb800/sb800.c | 19 +++++++------------ 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/southbridge/amd/sb700/sb700.c b/src/southbridge/amd/sb700/sb700.c index e3594fd583..1836f34eb0 100644 --- a/src/southbridge/amd/sb700/sb700.c +++ b/src/southbridge/amd/sb700/sb700.c @@ -104,7 +104,7 @@ void sb7xx_51xx_enable(struct device *dev) { struct device *sm_dev = NULL; struct device *bus_dev = NULL; - int index = -1; + int index; u32 deviceid; u32 vendorid; @@ -171,7 +171,6 @@ void sb7xx_51xx_enable(struct device *dev) index = 8; set_sm_enable_bits(sm_dev, 0xac, 1 << index, (dev->enabled ? 1 : 0) << index); - index += 32 * 3; break; case PCI_DEVFN(0x12, 0): case PCI_DEVFN(0x12, 1): @@ -179,7 +178,6 @@ void sb7xx_51xx_enable(struct device *dev) index = dev->path.pci.devfn & 3; set_sm_enable_bits(sm_dev, 0x68, 1 << index, (dev->enabled ? 1 : 0) << index); - index += 32 * 2; break; case PCI_DEVFN(0x13, 0): case PCI_DEVFN(0x13, 1): @@ -187,34 +185,27 @@ void sb7xx_51xx_enable(struct device *dev) index = (dev->path.pci.devfn & 3) + 4; set_sm_enable_bits(sm_dev, 0x68, 1 << index, (dev->enabled ? 1 : 0) << index); - index += 32 * 2; break; case PCI_DEVFN(0x14, 5): index = 7; set_sm_enable_bits(sm_dev, 0x68, 1 << index, (dev->enabled ? 1 : 0) << index); - index += 32 * 2; break; case PCI_DEVFN(0x14, 0): - index = 0; break; case PCI_DEVFN(0x14, 1): - index = 1; break; case PCI_DEVFN(0x14, 2): index = 3; set_pmio_enable_bits(sm_dev, 0x59, 1 << index, (dev->enabled ? 1 : 0) << index); - index += 32 * 4; break; case PCI_DEVFN(0x14, 3): index = 20; set_sm_enable_bits(sm_dev, 0x64, 1 << index, (dev->enabled ? 1 : 0) << index); - index += 32 * 1; break; case PCI_DEVFN(0x14, 4): - index = 4; break; default: printk(BIOS_DEBUG, "unknown dev: %s deviceid=%4x\n", dev_path(dev), diff --git a/src/southbridge/amd/sb800/sb800.c b/src/southbridge/amd/sb800/sb800.c index eda4d304d3..801cc65e4a 100644 --- a/src/southbridge/amd/sb800/sb800.c +++ b/src/southbridge/amd/sb800/sb800.c @@ -228,7 +228,7 @@ void sb800_enable(struct device *dev) { struct device *sm_dev = NULL; struct device *bus_dev = NULL; - int index = -1; + int index; u32 deviceid; u32 vendorid; @@ -295,9 +295,9 @@ void sb800_enable(struct device *dev) switch (dev->path.pci.devfn - (devfn - (0x14 << 3))) { case PCI_DEVFN(0x11, 0): - index = 8; - set_pmio_enable_bits(0xDA, 1 << 0, - (dev->enabled ? 1 : 0) << 0); + index = 0; + set_pmio_enable_bits(0xDA, 1 << index, + (dev->enabled ? 1 : 0) << index); /* Set the device ID of SATA as 0x4390 to reduce the confusing. */ dword = pci_read_config32(dev, 0x40); dword |= 1 << 0; @@ -305,7 +305,6 @@ void sb800_enable(struct device *dev) pci_write_config16(dev, 0x2, 0x4390); dword &= ~1; pci_write_config32(dev, 0x40, dword);//for (;;); - index += 32 * 3; break; case PCI_DEVFN(0x12, 0): case PCI_DEVFN(0x12, 2): @@ -318,15 +317,13 @@ void sb800_enable(struct device *dev) index = (dev->path.pci.devfn & 0x3) / 2 + 2; set_pmio_enable_bits(0xEF, 1 << index, (dev->enabled ? 1 : 0) << index); - index += 32 * 2; break; case PCI_DEVFN(0x14, 0): - index = 0; break; case PCI_DEVFN(0x14, 1): - index = 1; - set_pmio_enable_bits(0xDA, 1 << 3, - (dev->enabled ? 0 : 1) << 3); + index = 3; + set_pmio_enable_bits(0xDA, 1 << index, + (dev->enabled ? 0 : 1) << index); break; case PCI_DEVFN(0x14, 2): index = 0; @@ -337,7 +334,6 @@ void sb800_enable(struct device *dev) index = 0; set_pmio_enable_bits(0xEC, 1 << index, (dev->enabled ? 1 : 0) << index); - index += 32 * 1; break; case PCI_DEVFN(0x14, 4): index = 0; @@ -356,7 +352,6 @@ void sb800_enable(struct device *dev) break; case PCI_DEVFN(0x15, 0): set_sb800_gpp(dev); - index = 4; break; case PCI_DEVFN(0x15, 1): case PCI_DEVFN(0x15, 2): From ce4d39d2d74817e88c8804c1a55ad417301466f7 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Thu, 27 Jun 2019 16:52:37 -0700 Subject: [PATCH 214/221] libpayload: cbgfx: Run cbgfx_init() before we need it for draw_box() calculate_color() uses the 'fbinfo' global that is initialized by cbgfx_init(), so we need to run the latter before we can run the former or we get a null pointer access. Change-Id: I73ca8e20ca36f64d699379d504fd41dc2084f157 Signed-off-by: Julius Werner Reviewed-on: https://review.coreboot.org/c/coreboot/+/33855 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph Reviewed-by: Paul Menzel Reviewed-by: Daisuke Nojiri --- payloads/libpayload/drivers/video/graphics.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/payloads/libpayload/drivers/video/graphics.c b/payloads/libpayload/drivers/video/graphics.c index 49563267a9..85a8642c72 100644 --- a/payloads/libpayload/drivers/video/graphics.c +++ b/payloads/libpayload/drivers/video/graphics.c @@ -183,6 +183,10 @@ int draw_box(const struct rect *box, const struct rgb_color *rgb) struct vector top_left; struct vector size; struct vector p, t; + + if (cbgfx_init()) + return CBGFX_ERROR_INIT; + const uint32_t color = calculate_color(rgb, 0); const struct scale top_left_s = { .x = { .n = box->offset.x, .d = CANVAS_SCALE, }, @@ -193,9 +197,6 @@ int draw_box(const struct rect *box, const struct rgb_color *rgb) .y = { .n = box->size.y, .d = CANVAS_SCALE, } }; - if (cbgfx_init()) - return CBGFX_ERROR_INIT; - transform_vector(&top_left, &canvas.size, &top_left_s, &canvas.offset); transform_vector(&size, &canvas.size, &size_s, &vzero); add_vectors(&t, &top_left, &size); From ab0ab966f5a7613c091136b081c36fa77b589d84 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Tue, 9 Apr 2019 18:32:11 -0600 Subject: [PATCH 215/221] pci_ids.h: Add AMD Picasso IDs Change-Id: I4ac67d1577229e63424dd7fd0ff84d1acfe826c3 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/c/coreboot/+/33748 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes Reviewed-by: Martin Roth Reviewed-by: Edward O'Callaghan --- src/include/device/pci_ids.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h index 2c8fadcc6f..35c457a636 100644 --- a/src/include/device/pci_ids.h +++ b/src/include/device/pci_ids.h @@ -304,6 +304,7 @@ #define PCI_DEVICE_ID_AMD_15H_MODEL_303F_NB_IOMMU 0x1423 #define PCI_DEVICE_ID_AMD_16H_MODEL_303F_NB_IOMMU 0x1567 #define PCI_DEVICE_ID_AMD_15H_MODEL_707F_NB_IOMMU 0x1577 +#define PCI_DEVICE_ID_AMD_17H_MODEL_101F_NB_IOMMU 0x15d1 #define PCI_DEVICE_ID_ATI_SB600_LPC 0x438D #define PCI_DEVICE_ID_ATI_SB600_SATA 0x4380 @@ -451,6 +452,12 @@ #define PCI_DEVICE_ID_AMD_CZ_USB3_0 0x7914 #define PCI_DEVICE_ID_AMD_CZ_SMBUS 0x790B +#define PCI_DEVICE_ID_AMD_PCO_LPC 0x790e +#define PCI_DEVICE_ID_AMD_PCO_HDA0 0x15de +#define PCI_DEVICE_ID_AMD_PCO_HDA1 0x15e3 +#define PCI_DEVICE_ID_AMD_PCO_XHCI0 0x15e0 +#define PCI_DEVICE_ID_AMD_PCO_XHCI1 0x15e1 + #define PCI_VENDOR_ID_VLSI 0x1004 #define PCI_DEVICE_ID_VLSI_82C592 0x0005 #define PCI_DEVICE_ID_VLSI_82C593 0x0006 From 86dbe0f3072d87830b073bd4f372961f924e6df0 Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Fri, 28 Jun 2019 18:18:37 +0530 Subject: [PATCH 216/221] Kconfig: Enable RAMPAYLOAD for x86 This patch makes CONFIG_RAMPAYLOAD default enable upon selection of HAVE_RAMPAYLOAD kconfig from mainboard for x86 platform. Without this CL, CONFIG_RAMPAYLOAD is still disabled although mainboard has selected CONFIG_HAVE_RAMPAYLOAD. Change-Id: I40308bbf970a0dbe5f7e2086ed8a7a70c2a3a32c Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/c/coreboot/+/33859 Reviewed-by: ron minnich Tested-by: build bot (Jenkins) --- src/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kconfig b/src/Kconfig index 72d826f43f..919d257c62 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -290,7 +290,7 @@ config HAVE_RAMPAYLOAD config RAMPAYLOAD bool "Enable coreboot flow without executing ramstage" - default n + default y if ARCH_X86 depends on HAVE_RAMPAYLOAD help If this option is enabled, coreboot flow will skip ramstage From 6bdaaefb3077938b86a65725a7732c992a0b2328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=C3=B6sti=20M=C3=A4lkki?= Date: Thu, 27 Jun 2019 06:10:38 +0300 Subject: [PATCH 217/221] intel/fsp_rangeley: Use fixed FSB/BCLK value 100 MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to commit d731a24 src/cpu/intel: Set get_ia32_fsb function common value of 200 was silently used as a default for fsp_rangeley (model_406dx) in cpu/x86/lapic/apic_timer:set_timer_fsb(). After the commit, get_ia32_fsb() returns -2, eventually resulting with divide-by-zero in timer_monotonic_get(), as get_timer_fsb() returns 0. Add Rangeley CPUID model 0x4d to get_ia32_fsb() as a fix, using BCLK = 100 MHz based on the comments in northbridge/intel/fsp_rangeley/udelay.c Change-Id: I306f85dba9b1e91539fc0ecc9b2ae9d54f82be6c Signed-off-by: Kyösti Mälkki Reviewed-on: https://review.coreboot.org/c/coreboot/+/33822 Tested-by: build bot (Jenkins) Reviewed-by: HAOUAS Elyes --- src/cpu/intel/common/fsb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/intel/common/fsb.c b/src/cpu/intel/common/fsb.c index 83220de3bc..d66e87a396 100644 --- a/src/cpu/intel/common/fsb.c +++ b/src/cpu/intel/common/fsb.c @@ -46,6 +46,7 @@ static int get_fsb(void) case 0x3a: /* IvyBridge BCLK fixed at 100MHz */ case 0x3c: /* Haswell BCLK fixed at 100MHz */ case 0x45: /* Haswell-ULT BCLK fixed at 100MHz */ + case 0x4d: /* Rangeley BCLK fixed at 100MHz */ ret = 100; break; } From 40dc75efcbab64634e7b2e007f87affb2cee3b01 Mon Sep 17 00:00:00 2001 From: Pavel Sayekat Date: Sun, 30 Jun 2019 11:38:07 +0600 Subject: [PATCH 218/221] util/superiotool/nuvoton.c: Minor tag update/removal Signed-off-by: Pavel Sayekat Change-Id: Ic193f31b9776683849578bf9009c51bf22d1dae6 Reviewed-on: https://review.coreboot.org/c/coreboot/+/33910 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- util/superiotool/nuvoton.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/superiotool/nuvoton.c b/util/superiotool/nuvoton.c index 75522441e6..81bff96eab 100644 --- a/util/superiotool/nuvoton.c +++ b/util/superiotool/nuvoton.c @@ -594,7 +594,7 @@ static const struct superio_registers reg_table[] = { {0x05, "Keyboard Controller", {0x30,0x60,0x61,0x62,0x63,0x70,0x72,0xf0,EOT}, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83,EOT}}, - {0x06, "CIR", + {0x06, "Consumer IR", {0x30,0x60,0x61,0x70,EOT}, {0x00,0x00,0x00,0x00,EOT}}, {0x07, "GPIO 7, GPIO 8", @@ -622,7 +622,7 @@ static const struct superio_registers reg_table[] = { {0x00,0x00,0x00,0x00,0x7f,0x7f,0x7f,0x7f,0x7f,0xa8, 0x08,0x7f,0x00,0x81,0x00,0x00,0x00,0x00,0x87,0x47, 0x00,0x00,0x00,0x02,EOT}}, - {0x0d, "BCLK, WDT2", + {0x0d, "WDT2", {0xe7,0xe8,0xeb,0xed,0xf0,0xf3,EOT}, {0x10,0x32,0x14,0x00,0x00,0x00,EOT}}, {0x0e, "CIR Wake-Up", From 3891d272a0d5831c78464d2cd2bf89ef29d2cca1 Mon Sep 17 00:00:00 2001 From: Frans Hendriks Date: Wed, 12 Jun 2019 11:14:55 +0200 Subject: [PATCH 219/221] security/tpm/tss/tcg-2.0/tss.c: Add debug message to tlcl_lib_init() No message is reported in tlcl_lib_init() when tis_init() or tis_open() returned an error value. Add debug string. BUG=N/A TEST=Build binary and verified logging on Facebook FBG-1701 Change-Id: I522e488ddd3a1bd94a1a8c8470c757bd79c6d5c5 Signed-off-by: Frans Hendriks Reviewed-on: https://review.coreboot.org/c/coreboot/+/33415 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/security/tpm/tss/tcg-2.0/tss.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/security/tpm/tss/tcg-2.0/tss.c b/src/security/tpm/tss/tcg-2.0/tss.c index e579bff78e..c4b553840f 100644 --- a/src/security/tpm/tss/tcg-2.0/tss.c +++ b/src/security/tpm/tss/tcg-2.0/tss.c @@ -181,10 +181,15 @@ uint32_t tlcl_lib_init(void) if (done) return VB2_SUCCESS; - if (tis_init()) + if (tis_init()) { + printk(BIOS_ERR, "%s: tis_init returned error\n", __func__); return VB2_ERROR_UNKNOWN; - if (tis_open()) + } + + if (tis_open()) { + printk(BIOS_ERR, "%s: tis_open returned error\n", __func__); return VB2_ERROR_UNKNOWN; + } car_set_var(tlcl_init_done, 1); From a449290ca2d587d6eb9efca99d34c8a8658e3178 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Mon, 17 Jun 2019 10:50:47 +0200 Subject: [PATCH 220/221] Use 3rdparty/intel-microcode Instead of maintaining this in 3rdparty/blobs use the 3rdparty/intel-microcode which is maintained by Intel. This allows for some finegrained control where family+model span multiple targets. Microcode updates present in 3rdparty/blobs/soc/intel/{baytrail,broadwell} are left out since those contain updates not present in the Intel repo. Those are presumably early CPU samples that did not end up in products. The following MCU are get a new revision: old: sig 0x000306c3, pf_mask 0x32, 2018-04-02, rev 0x0025, size 23552 sig 0x00040651, pf_mask 0x72, 2018-04-02, rev 0x0024, size 22528 sig 0x000206a7, pf_mask 0x12, 2018-04-10, rev 0x002e, size 12288 sig 0x000306a9, pf_mask 0x12, 2018-04-10, rev 0x0020, size 13312 sig 0x000706a1, pf_mask 0x01, 2018-05-22, rev 0x0028, size 73728 sig 0x000506c9, pf_mask 0x03, 2018-05-11, rev 0x0032, size 16384 sig 0x000506ca, pf_mask 0x03, 2018-05-11, rev 0x000c, size 14336 sig 0x000806e9, pf_mask 0xc0, 2018-03-24, rev 0x008e, size 98304 sig 0x000906e9, pf_mask 0x2a, 2018-03-24, rev 0x008e, size 98304 sig 0x000906ea, pf_mask 0x22, 2018-05-02, rev 0x0096, size 97280 sig 0x000906eb, pf_mask 0x02, 2018-03-24, rev 0x008e, size 98304 sig 0x00050665, pf_mask 0x10, 2018-04-20, rev 0xe00000a, size 18432 sig 0x000506e3, pf_mask 0x36, 2018-04-17, rev 0x00c6, size 99328 sig 0x000906e9, pf_mask 0x2a, 2018-03-24, rev 0x008e, size 98304 sig 0x000406e3, pf_mask 0xc0, 2018-04-17, rev 0x00c6, size 99328 new: sig 0x000306c3, pf_mask 0x32, 2019-02-26, rev 0x0027, size 23552 sig 0x00040651, pf_mask 0x72, 2019-02-26, rev 0x0025, size 21504 sig 0x000206a7, pf_mask 0x12, 2019-02-17, rev 0x002f, size 12288 sig 0x000306a9, pf_mask 0x12, 2019-02-13, rev 0x0021, size 14336 sig 0x000706a1, pf_mask 0x01, 2019-01-02, rev 0x002e, size 73728 sig 0x000506c9, pf_mask 0x03, 2019-01-15, rev 0x0038, size 17408 sig 0x000506ca, pf_mask 0x03, 2019-03-01, rev 0x0016, size 15360 sig 0x000806e9, pf_mask 0xc0, 2019-04-01, rev 0x00b4, size 99328 sig 0x000906e9, pf_mask 0x2a, 2019-04-01, rev 0x00b4, size 99328 sig 0x000906ea, pf_mask 0x22, 2019-04-01, rev 0x00b4, size 98304 sig 0x000906eb, pf_mask 0x02, 2019-04-01, rev 0x00b4, size 99328 sig 0x00050665, pf_mask 0x10, 2019-03-23, rev 0xe00000d, size 19456 sig 0x000506e3, pf_mask 0x36, 2019-04-01, rev 0x00cc, size 100352 sig 0x000906e9, pf_mask 0x2a, 2019-04-01, rev 0x00b4, size 99328 sig 0x000406e3, pf_mask 0xc0, 2019-04-01, rev 0x00cc, size 100352 Change-Id: Idcfb3c3c774e0b47637e1b5308c28002aa044f1c Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/33554 Tested-by: build bot (Jenkins) Reviewed-by: Nico Huber --- src/cpu/intel/haswell/Makefile.inc | 4 ++-- src/cpu/intel/model_1067x/Makefile.inc | 2 +- src/cpu/intel/model_106cx/Makefile.inc | 2 +- src/cpu/intel/model_2065x/Makefile.inc | 2 +- src/cpu/intel/model_206ax/Makefile.inc | 4 ++-- src/cpu/intel/model_65x/Makefile.inc | 2 +- src/cpu/intel/model_67x/Makefile.inc | 2 +- src/cpu/intel/model_68x/Makefile.inc | 2 +- src/cpu/intel/model_6bx/Makefile.inc | 2 +- src/cpu/intel/model_6ex/Makefile.inc | 2 +- src/cpu/intel/model_6fx/Makefile.inc | 2 +- src/cpu/intel/model_6xx/Makefile.inc | 2 +- src/cpu/intel/model_f2x/Makefile.inc | 2 +- src/cpu/intel/model_f3x/Makefile.inc | 2 +- src/cpu/intel/model_f4x/Makefile.inc | 2 +- src/soc/intel/apollolake/Makefile.inc | 4 ++-- src/soc/intel/cannonlake/Kconfig | 2 ++ src/soc/intel/cannonlake/Makefile.inc | 22 +++++++++++++++++---- src/soc/intel/fsp_broadwell_de/Makefile.inc | 2 +- src/soc/intel/skylake/Makefile.inc | 8 ++++---- 20 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/cpu/intel/haswell/Makefile.inc b/src/cpu/intel/haswell/Makefile.inc index fa467e5a8b..72f66ef7b8 100644 --- a/src/cpu/intel/haswell/Makefile.inc +++ b/src/cpu/intel/haswell/Makefile.inc @@ -43,5 +43,5 @@ subdirs-y += ../microcode subdirs-y += ../turbo subdirs-y += ../common -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_306cx/microcode.bin -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_4065x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-3c-*) +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-45-*) diff --git a/src/cpu/intel/model_1067x/Makefile.inc b/src/cpu/intel/model_1067x/Makefile.inc index 451df6ef35..caeab563a4 100644 --- a/src/cpu/intel/model_1067x/Makefile.inc +++ b/src/cpu/intel/model_1067x/Makefile.inc @@ -4,4 +4,4 @@ subdirs-y += ../../x86/name subdirs-y += ../common subdirs-$(CONFIG_SMM_TSEG) += ../smm/gen1 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_1067x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-17-*) diff --git a/src/cpu/intel/model_106cx/Makefile.inc b/src/cpu/intel/model_106cx/Makefile.inc index eec544d79a..a1f2d0d1f0 100644 --- a/src/cpu/intel/model_106cx/Makefile.inc +++ b/src/cpu/intel/model_106cx/Makefile.inc @@ -4,4 +4,4 @@ subdirs-y += ../common subdirs-$(CONFIG_SMM_TSEG) += ../smm/gen1 ramstage-$(CONFIG_PARALLEL_MP) += ../model_1067x/mp_init.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_106cx/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-1c-*) diff --git a/src/cpu/intel/model_2065x/Makefile.inc b/src/cpu/intel/model_2065x/Makefile.inc index 39246c0708..f494e9b049 100644 --- a/src/cpu/intel/model_2065x/Makefile.inc +++ b/src/cpu/intel/model_2065x/Makefile.inc @@ -23,7 +23,7 @@ romstage-y += stage_cache.c ramstage-y += stage_cache.c postcar-y += stage_cache.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_2065x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-25-*) cpu_incs-y += $(src)/cpu/intel/car/non-evict/cache_as_ram.S postcar-y += ../car/non-evict/exit_car.S diff --git a/src/cpu/intel/model_206ax/Makefile.inc b/src/cpu/intel/model_206ax/Makefile.inc index e1fa87989c..78a6283a5d 100644 --- a/src/cpu/intel/model_206ax/Makefile.inc +++ b/src/cpu/intel/model_206ax/Makefile.inc @@ -28,8 +28,8 @@ romstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c postcar-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c ramstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_206ax/microcode.bin -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_306ax/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-2a-*) +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-3a-*) cpu_incs-y += $(src)/cpu/intel/car/non-evict/cache_as_ram.S postcar-y += ../car/non-evict/exit_car.S diff --git a/src/cpu/intel/model_65x/Makefile.inc b/src/cpu/intel/model_65x/Makefile.inc index 05ea68e126..c1f471c33a 100644 --- a/src/cpu/intel/model_65x/Makefile.inc +++ b/src/cpu/intel/model_65x/Makefile.inc @@ -16,4 +16,4 @@ ramstage-y += model_65x_init.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_65x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-05-*) diff --git a/src/cpu/intel/model_67x/Makefile.inc b/src/cpu/intel/model_67x/Makefile.inc index 219a0d24ee..ef68df4346 100644 --- a/src/cpu/intel/model_67x/Makefile.inc +++ b/src/cpu/intel/model_67x/Makefile.inc @@ -16,4 +16,4 @@ ramstage-y += model_67x_init.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_67x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-07-*) diff --git a/src/cpu/intel/model_68x/Makefile.inc b/src/cpu/intel/model_68x/Makefile.inc index 7e09dc6b86..95aacb3fa6 100644 --- a/src/cpu/intel/model_68x/Makefile.inc +++ b/src/cpu/intel/model_68x/Makefile.inc @@ -17,4 +17,4 @@ ramstage-y += model_68x_init.c subdirs-y += ../../x86/name -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_68x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-08-*) diff --git a/src/cpu/intel/model_6bx/Makefile.inc b/src/cpu/intel/model_6bx/Makefile.inc index 81e64e3292..84f4ff02db 100644 --- a/src/cpu/intel/model_6bx/Makefile.inc +++ b/src/cpu/intel/model_6bx/Makefile.inc @@ -1,4 +1,4 @@ ramstage-y += model_6bx_init.c subdirs-y += ../../x86/name -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_6bx/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-0b-*) diff --git a/src/cpu/intel/model_6ex/Makefile.inc b/src/cpu/intel/model_6ex/Makefile.inc index 46ae7c7be2..cef2b0be86 100644 --- a/src/cpu/intel/model_6ex/Makefile.inc +++ b/src/cpu/intel/model_6ex/Makefile.inc @@ -4,4 +4,4 @@ subdirs-y += ../common subdirs-$(CONFIG_SMM_TSEG) += ../smm/gen1 ramstage-y += ../model_1067x/mp_init.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_6ex/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-0e-*) diff --git a/src/cpu/intel/model_6fx/Makefile.inc b/src/cpu/intel/model_6fx/Makefile.inc index 9564bf950e..9121e3b64a 100644 --- a/src/cpu/intel/model_6fx/Makefile.inc +++ b/src/cpu/intel/model_6fx/Makefile.inc @@ -4,4 +4,4 @@ subdirs-y += ../common ramstage-$(CONFIG_PARALLEL_MP) += ../model_1067x/mp_init.c subdirs-$(CONFIG_SMM_TSEG) += ../smm/gen1 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_6fx/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-0f-*) diff --git a/src/cpu/intel/model_6xx/Makefile.inc b/src/cpu/intel/model_6xx/Makefile.inc index 3ac510fa44..b2f87abfbf 100644 --- a/src/cpu/intel/model_6xx/Makefile.inc +++ b/src/cpu/intel/model_6xx/Makefile.inc @@ -1,3 +1,3 @@ ramstage-y += model_6xx_init.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_66x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-06-*) diff --git a/src/cpu/intel/model_f2x/Makefile.inc b/src/cpu/intel/model_f2x/Makefile.inc index 589e49e4b5..9bb5dca626 100644 --- a/src/cpu/intel/model_f2x/Makefile.inc +++ b/src/cpu/intel/model_f2x/Makefile.inc @@ -1,3 +1,3 @@ ramstage-y += model_f2x_init.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_f2x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/0f-02-*) diff --git a/src/cpu/intel/model_f3x/Makefile.inc b/src/cpu/intel/model_f3x/Makefile.inc index 19b2e9302b..ed1eb5f7d8 100644 --- a/src/cpu/intel/model_f3x/Makefile.inc +++ b/src/cpu/intel/model_f3x/Makefile.inc @@ -2,4 +2,4 @@ ramstage-y += model_f3x_init.c subdirs-$(CONFIG_SMM_TSEG) += ../smm/gen1 ramstage-$(CONFIG_PARALLEL_MP) += ../model_1067x/mp_init.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_f3x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/0f-03-*) diff --git a/src/cpu/intel/model_f4x/Makefile.inc b/src/cpu/intel/model_f4x/Makefile.inc index 6fbc9ae2ae..196d63e462 100644 --- a/src/cpu/intel/model_f4x/Makefile.inc +++ b/src/cpu/intel/model_f4x/Makefile.inc @@ -2,4 +2,4 @@ ramstage-y += model_f4x_init.c subdirs-$(CONFIG_SMM_TSEG) += ../smm/gen1 ramstage-$(CONFIG_PARALLEL_MP) += ../model_1067x/mp_init.c -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_f4x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/0f-04-*) diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc index 1fd16038a7..4fc16d5891 100644 --- a/src/soc/intel/apollolake/Makefile.inc +++ b/src/soc/intel/apollolake/Makefile.inc @@ -177,10 +177,10 @@ $(RT5682_RENDER_CAPTURE)-type := raw ifeq ($(CONFIG_SOC_INTEL_GLK),y) # Gemini Lake B0 (706a1) only atm. -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_706ax/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-7a-*) else # Apollo Lake 506c2, B0 (506c9) and E0 (506ca) only atm. -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_506cx/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-5c-*) endif endif # if CONFIG_SOC_INTEL_APOLLOLAKE diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index 679efce396..37e42f30e2 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -16,6 +16,7 @@ config SOC_INTEL_CANNONLAKE_ALTERNATE_HEADERS config SOC_INTEL_CANNONLAKE bool select SOC_INTEL_CANNONLAKE_BASE + select MICROCODE_BLOB_NOT_IN_BLOB_REPO help Intel Cannonlake support @@ -34,6 +35,7 @@ config SOC_INTEL_WHISKEYLAKE config SOC_INTEL_COMETLAKE bool select SOC_INTEL_CANNONLAKE_BASE + select MICROCODE_BLOB_UNDISCLOSED help Intel Cometlake support diff --git a/src/soc/intel/cannonlake/Makefile.inc b/src/soc/intel/cannonlake/Makefile.inc index 5017410234..8a4a8b71f2 100644 --- a/src/soc/intel/cannonlake/Makefile.inc +++ b/src/soc/intel/cannonlake/Makefile.inc @@ -90,10 +90,24 @@ smm-y += gpio.c verstage-y += gpio.c endif -# Coffeelake U43e D0 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_806ex/microcode.bin -# Coffeelake H/S/E3 B0 U0 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_906ex/microcode.bin +ifeq ($(CONFIG_SOC_INTEL_CANNONLAKE),y) +# Not yet in intel-microcode repo +#cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-66-*) +else ifeq ($(CONFIG_SOC_INTEL_COFFEELAKE),y) +ifeq ($(CONFIG_SOC_INTEL_CANNONLAKE_PCH_H),y) +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-9e-0a +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-9e-0b +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-9e-0c +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-9e-0d +else +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-8e-0a +endif +else ifeq ($(CONFIG_SOC_INTEL_WHISKEYLAKE),y) +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-8e-0b +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-8e-0c +else ifeq ($(CONFIG_SOC_INTEL_COMETLAKE),y) +# TODO +endif CPPFLAGS_common += -I$(src)/soc/intel/cannonlake CPPFLAGS_common += -I$(src)/soc/intel/cannonlake/include diff --git a/src/soc/intel/fsp_broadwell_de/Makefile.inc b/src/soc/intel/fsp_broadwell_de/Makefile.inc index 0a23170d0c..e8a31890ba 100644 --- a/src/soc/intel/fsp_broadwell_de/Makefile.inc +++ b/src/soc/intel/fsp_broadwell_de/Makefile.inc @@ -39,6 +39,6 @@ CPPFLAGS_common += -I$(src)/soc/intel/fsp_broadwell_de/include CPPFLAGS_common += -I$(src)/soc/intel/fsp_broadwell_de/fsp CPPFLAGS_common += -I$(src)/soc/intel/fsp_broadwell_de/ -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_5066x/microcode.bin +cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-56-*) endif # ifeq ($(CONFIG_SOC_INTEL_FSP_BROADWELL_DE),y) diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc index 985acdf135..25dce05226 100644 --- a/src/soc/intel/skylake/Makefile.inc +++ b/src/soc/intel/skylake/Makefile.inc @@ -83,14 +83,14 @@ postcar-y += uart.c ifeq ($(CONFIG_SKYLAKE_SOC_PCH_H),y) # Skylake H Q0 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_506ex/microcode.bin +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-5e-03 # Kabylake HB0 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_906ex/microcode.bin +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-9e-09 else # Skylake D0 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_406ex/microcode.bin +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-4e-03 # Kabylake H0, Y0 -cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_806ex/microcode.bin +cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-8e-09 endif # Missing for Skylake C0 (0x406e2), Kabylake G0 (0x406e8), Kabylake HA0 (0x506e8) # since those are probably pre-release samples. From b6b5e7fb455933bc2e077e7881e6b907cb9d7571 Mon Sep 17 00:00:00 2001 From: Felix Singer Date: Tue, 25 Jun 2019 15:17:30 +0200 Subject: [PATCH 221/221] mb/up/squared: Add kernel cmdline parameters Since ttyS0 isn't used for UART0, configure ttyS4 as default Change-Id: Ia0469226253b08328807d5401c05633296e43d22 Signed-off-by: Felix Singer Reviewed-on: https://review.coreboot.org/c/coreboot/+/33785 Reviewed-by: Philipp Deppenwiese Reviewed-by: Arthur Heymans Tested-by: build bot (Jenkins) --- src/mainboard/up/squared/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mainboard/up/squared/Kconfig b/src/mainboard/up/squared/Kconfig index fd03b7a2ae..b9f5b27a6d 100644 --- a/src/mainboard/up/squared/Kconfig +++ b/src/mainboard/up/squared/Kconfig @@ -65,6 +65,10 @@ config MAX_CPUS int default 2 +config LINUX_COMMAND_LINE + string + default "console=ttyS4,115200 earlyprintk=ttyS4,115200,keep" if PAYLOAD_LINUXBOOT && UART_FOR_CONSOLE=0 + config UART_FOR_CONSOLE int default 0