diff options
Diffstat (limited to 'config/coreboot/default/patches')
66 files changed, 4172 insertions, 14372 deletions
diff --git a/config/coreboot/default/patches/0001-add-c3-and-clockgen-to-apple-macbook21.patch b/config/coreboot/default/patches/0001-add-c3-and-clockgen-to-apple-macbook21.patch index da4ab420..31c1bb30 100644 --- a/config/coreboot/default/patches/0001-add-c3-and-clockgen-to-apple-macbook21.patch +++ b/config/coreboot/default/patches/0001-add-c3-and-clockgen-to-apple-macbook21.patch @@ -1,7 +1,7 @@ -From f625e31ee3abb867e775ab0cb724550825699c36 Mon Sep 17 00:00:00 2001 +From bd959c38f6ee21db1ff8f4fbb0675e38bfbe1147 Mon Sep 17 00:00:00 2001 From: Vitali64 <5405891-vitali64yt@users.noreply.gitlab.com> Date: Wed, 27 Oct 2021 13:36:01 +0200 -Subject: [PATCH 01/51] add c3 and clockgen to apple/macbook21 +Subject: [PATCH 01/37] add c3 and clockgen to apple/macbook21 --- src/mainboard/apple/macbook21/Kconfig | 1 + diff --git a/config/coreboot/default/patches/0002-lenovo-t400-Enable-all-SATA-ports.patch b/config/coreboot/default/patches/0002-lenovo-t400-Enable-all-SATA-ports.patch index ee605e58..0c2b080f 100644 --- a/config/coreboot/default/patches/0002-lenovo-t400-Enable-all-SATA-ports.patch +++ b/config/coreboot/default/patches/0002-lenovo-t400-Enable-all-SATA-ports.patch @@ -1,7 +1,7 @@ -From 8821f229d4fe48153ec7a45e0e04c3b2a3cd8c7c Mon Sep 17 00:00:00 2001 +From e5eab4c8043b89a325b4a28bf7da456d68475144 Mon Sep 17 00:00:00 2001 From: persmule <persmule@gmail.com> Date: Sun, 31 Oct 2021 23:33:26 +0000 -Subject: [PATCH 02/51] lenovo/t400: Enable all SATA ports +Subject: [PATCH 02/37] lenovo/t400: Enable all SATA ports There are 2 SATA ports on the chassis of t400(s), but at least one dock for t400 contains a port for (P/S)ATA device, and t400s has a eSATA port on its diff --git a/config/coreboot/default/patches/0003-lenovo-x230-set-me_state-Disabled-in-cmos.default.patch b/config/coreboot/default/patches/0003-lenovo-x230-set-me_state-Disabled-in-cmos.default.patch index a4b430fe..4ccde9a6 100644 --- a/config/coreboot/default/patches/0003-lenovo-x230-set-me_state-Disabled-in-cmos.default.patch +++ b/config/coreboot/default/patches/0003-lenovo-x230-set-me_state-Disabled-in-cmos.default.patch @@ -1,7 +1,7 @@ -From 0298639b6e80c8950fbb4484180b7195883ab8c1 Mon Sep 17 00:00:00 2001 +From fd398cc10600cccce3dd4931651a5294ffebde9a Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Mon, 3 Jan 2022 19:06:22 +0000 -Subject: [PATCH 03/51] lenovo/x230: set me_state=Disabled in cmos.default +Subject: [PATCH 03/37] lenovo/x230: set me_state=Disabled in cmos.default I only recently found out about this. It's possible to use me_cleaner to do the same thing, but some people might just flash coreboot and not do diff --git a/config/coreboot/default/patches/0004-set-me_state-Disabled-on-all-cmos.default-files.patch b/config/coreboot/default/patches/0004-set-me_state-Disabled-on-all-cmos.default-files.patch index 71695404..39319d58 100644 --- a/config/coreboot/default/patches/0004-set-me_state-Disabled-on-all-cmos.default-files.patch +++ b/config/coreboot/default/patches/0004-set-me_state-Disabled-on-all-cmos.default-files.patch @@ -1,7 +1,7 @@ -From c697c90ace86edfe724c86bd6a680cf0ae0e4b58 Mon Sep 17 00:00:00 2001 +From 74230d8123cb7c31afd084658720084b1a5ac5d9 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Wed, 2 Mar 2022 21:50:01 +0000 -Subject: [PATCH 04/51] set me_state=Disabled on all cmos.default files! +Subject: [PATCH 04/37] set me_state=Disabled on all cmos.default files! yeah. why the hell isn't this the default diff --git a/config/coreboot/default/patches/0005-util-ifdtool-add-nuke-flag-all-0xFF-on-region.patch b/config/coreboot/default/patches/0005-util-ifdtool-add-nuke-flag-all-0xFF-on-region.patch index b7b514cd..9c00ab79 100644 --- a/config/coreboot/default/patches/0005-util-ifdtool-add-nuke-flag-all-0xFF-on-region.patch +++ b/config/coreboot/default/patches/0005-util-ifdtool-add-nuke-flag-all-0xFF-on-region.patch @@ -1,7 +1,7 @@ -From d2f579b82921c2c35e4cf756db0ca476fbadfac1 Mon Sep 17 00:00:00 2001 +From f592ac32892d7f99fa2e68504bb147e5d06184ca Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sun, 19 Feb 2023 18:21:43 +0000 -Subject: [PATCH 05/51] util/ifdtool: add --nuke flag (all 0xFF on region) +Subject: [PATCH 05/37] util/ifdtool: add --nuke flag (all 0xFF on region) When this option is used, the region's contents are overwritten with all ones (0xFF). @@ -20,10 +20,10 @@ Signed-off-by: Leah Rowe <leah@libreboot.org> 1 file changed, 83 insertions(+), 31 deletions(-) diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c -index 32b2081d93..1473cf058b 100644 +index b21a89c0e1..fc91d4c239 100644 --- a/util/ifdtool/ifdtool.c +++ b/util/ifdtool/ifdtool.c -@@ -2204,6 +2204,7 @@ static void print_usage(const char *name) +@@ -2230,6 +2230,7 @@ static void print_usage(const char *name) " tgl - Tiger Lake\n" " wbg - Wellsburg\n" " -S | --setpchstrap Write a PCH strap\n" @@ -31,7 +31,7 @@ index 32b2081d93..1473cf058b 100644 " -V | --newvalue The new value to write into PCH strap specified by -S\n" " -v | --version: print the version\n" " -h | --help: print this help\n\n" -@@ -2212,6 +2213,60 @@ static void print_usage(const char *name) +@@ -2238,6 +2239,60 @@ static void print_usage(const char *name) "\n"); } @@ -92,15 +92,15 @@ index 32b2081d93..1473cf058b 100644 int main(int argc, char *argv[]) { int opt, option_index = 0; -@@ -2219,6 +2274,7 @@ int main(int argc, char *argv[]) +@@ -2245,6 +2300,7 @@ int main(int argc, char *argv[]) int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0, mode_validate = 0; int mode_layout = 0, mode_newlayout = 0, mode_density = 0, mode_setstrap = 0; int mode_read = 0, mode_altmedisable = 0, altmedisable = 0, mode_fmap_template = 0; + int mode_nuke = 0; int mode_gpr0_disable = 0, mode_gpr0_enable = 0, mode_gpr0_status = 0; - char *region_type_string = NULL, *region_fname = NULL; - const char *layout_fname = NULL; -@@ -2254,6 +2310,7 @@ int main(int argc, char *argv[]) + char *region_type_string = NULL, *region_fname = NULL, *layout_fname = NULL; + char *new_filename = NULL; +@@ -2279,6 +2335,7 @@ int main(int argc, char *argv[]) {"validate", 0, NULL, 't'}, {"setpchstrap", 1, NULL, 'S'}, {"newvalue", 1, NULL, 'V'}, @@ -108,7 +108,7 @@ index 32b2081d93..1473cf058b 100644 {0, 0, 0, 0} }; -@@ -2303,35 +2360,8 @@ int main(int argc, char *argv[]) +@@ -2328,35 +2385,8 @@ int main(int argc, char *argv[]) region_fname++; // Descriptor, BIOS, ME, GbE, Platform // valid type? @@ -146,7 +146,7 @@ index 32b2081d93..1473cf058b 100644 fprintf(stderr, "No such region type: '%s'\n\n", region_type_string); fprintf(stderr, "run '%s -h' for usage\n", argv[0]); -@@ -2508,6 +2538,22 @@ int main(int argc, char *argv[]) +@@ -2533,6 +2563,22 @@ int main(int argc, char *argv[]) case 't': mode_validate = 1; break; @@ -169,7 +169,7 @@ index 32b2081d93..1473cf058b 100644 case 'v': print_version(); exit(EXIT_SUCCESS); -@@ -2524,7 +2570,8 @@ int main(int argc, char *argv[]) +@@ -2552,7 +2598,8 @@ int main(int argc, char *argv[]) if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject + mode_setstrap + mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked | mode_locked) + mode_altmedisable + mode_validate + @@ -179,7 +179,7 @@ index 32b2081d93..1473cf058b 100644 fprintf(stderr, "You may not specify more than one mode.\n\n"); fprintf(stderr, "run '%s -h' for usage\n", argv[0]); exit(EXIT_FAILURE); -@@ -2533,7 +2580,8 @@ int main(int argc, char *argv[]) +@@ -2561,7 +2608,8 @@ int main(int argc, char *argv[]) if ((mode_dump + mode_layout + mode_fmap_template + mode_extract + mode_inject + mode_setstrap + mode_newlayout + mode_spifreq + mode_em100 + mode_locked + mode_unlocked + mode_density + mode_altmedisable + @@ -189,7 +189,7 @@ index 32b2081d93..1473cf058b 100644 fprintf(stderr, "You need to specify a mode.\n\n"); fprintf(stderr, "run '%s -h' for usage\n", argv[0]); exit(EXIT_FAILURE); -@@ -2646,6 +2694,10 @@ int main(int argc, char *argv[]) +@@ -2674,6 +2722,10 @@ int main(int argc, char *argv[]) write_image(new_filename, image, size); } diff --git a/config/coreboot/default/patches/0006-mb-dell-e6400-Enable-01.0-device-in-devicetree-for-d.patch b/config/coreboot/default/patches/0006-mb-dell-e6400-Enable-01.0-device-in-devicetree-for-d.patch index 71f2f22d..ee60c3c8 100644 --- a/config/coreboot/default/patches/0006-mb-dell-e6400-Enable-01.0-device-in-devicetree-for-d.patch +++ b/config/coreboot/default/patches/0006-mb-dell-e6400-Enable-01.0-device-in-devicetree-for-d.patch @@ -1,7 +1,7 @@ -From a5bc59037dabd95b6595c5aaf38b83da2a91de54 Mon Sep 17 00:00:00 2001 +From 18069af7c0c6beedfadb615cca9127e82a0d8007 Mon Sep 17 00:00:00 2001 From: Nicholas Chin <nic.c3.14@gmail.com> Date: Sat, 6 May 2023 15:53:41 -0600 -Subject: [PATCH 06/51] mb/dell/e6400: Enable 01.0 device in devicetree for +Subject: [PATCH 06/37] mb/dell/e6400: Enable 01.0 device in devicetree for dGPU models Change-Id: I9b8e5d3cd1e1f64dc87b682b1e045b6342924aed diff --git a/config/coreboot/default/patches/0007-Remove-warning-for-coreboot-images-built-without-a-p.patch b/config/coreboot/default/patches/0007-Remove-warning-for-coreboot-images-built-without-a-p.patch index fa364ca1..525bd366 100644 --- a/config/coreboot/default/patches/0007-Remove-warning-for-coreboot-images-built-without-a-p.patch +++ b/config/coreboot/default/patches/0007-Remove-warning-for-coreboot-images-built-without-a-p.patch @@ -1,7 +1,7 @@ -From f883599a362f1383f3712b72516f76187d0a9cbe Mon Sep 17 00:00:00 2001 +From 9563c107a4b40e66b610d7205a21590c7c181c78 Mon Sep 17 00:00:00 2001 From: Nicholas Chin <nic.c3.14@gmail.com> Date: Fri, 12 May 2023 19:55:15 -0600 -Subject: [PATCH 07/51] Remove warning for coreboot images built without a +Subject: [PATCH 07/37] Remove warning for coreboot images built without a payload I added this in upstream to prevent people from accidentally flashing diff --git a/config/coreboot/default/patches/0018-HACK-Disable-coreboot-related-BL31-features.patch b/config/coreboot/default/patches/0008-HACK-Disable-coreboot-related-BL31-features.patch index 9592215d..bd2c56bd 100644 --- a/config/coreboot/default/patches/0018-HACK-Disable-coreboot-related-BL31-features.patch +++ b/config/coreboot/default/patches/0008-HACK-Disable-coreboot-related-BL31-features.patch @@ -1,7 +1,7 @@ -From ec27f5414c78d493ec7be4cd055ac877ce9ea178 Mon Sep 17 00:00:00 2001 +From 7f650a19d30fe6157b150c5248d6086007323d72 Mon Sep 17 00:00:00 2001 From: Alper Nebi Yasak <alpernebiyasak@gmail.com> Date: Thu, 22 Jun 2023 16:44:27 +0300 -Subject: [PATCH 18/51] HACK: Disable coreboot related BL31 features +Subject: [PATCH 08/37] HACK: Disable coreboot related BL31 features I don't know why, but removing this BL31 make argument lets gru-kevin power off properly when shut down from Linux. Needs investigation. @@ -10,10 +10,10 @@ power off properly when shut down from Linux. Needs investigation. 1 file changed, 3 deletions(-) diff --git a/src/arch/arm64/Makefile.mk b/src/arch/arm64/Makefile.mk -index cb43897efd..a9e5ff399a 100644 +index f54c6d22fc..b075abfd42 100644 --- a/src/arch/arm64/Makefile.mk +++ b/src/arch/arm64/Makefile.mk -@@ -173,9 +173,6 @@ BL31_MAKEARGS += LOG_LEVEL=40 +@@ -162,9 +162,6 @@ BL31_MAKEARGS += LOG_LEVEL=40 # Always enable crash reporting, even on a release build BL31_MAKEARGS += CRASH_REPORTING=1 diff --git a/config/coreboot/default/patches/0008-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch b/config/coreboot/default/patches/0008-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch deleted file mode 100644 index 48b9d21e..00000000 --- a/config/coreboot/default/patches/0008-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch +++ /dev/null @@ -1,430 +0,0 @@ -From 40545928c415c27d3a30748e4bfdee7f9d8f82f9 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Sat, 19 Aug 2023 16:19:10 -0600 -Subject: [PATCH 08/51] mb/dell: Add Latitude E6530 (Ivy Bridge) - -Mainboard is QALA0/LA-7761P (UMA). The version with a Nvidia dGPU was -not tested. I do not physically have this system; someone with physical -access to one sent me the output of autoport which I then modified to -produce this port. - -I was also sent the vbios obtained using intel_bios_dumper while running -version A22 of the vendor firmware, which I then processed using -`intelvbttool --inoprom vbios.bin --outvbt data.vbt` to obtain data.vbt. - -This was originally tested and found to be working as a standalone board -port in Libreboot, though this variant based port in upstream coreboot -has not been tested. - -This can be internally flashed by sending a command to the EC, which -causes the EC to pull the FDO pin low and the firmware to skip setting -up any chipset based write protections [1]. The EC is the SMSC MEC5055, -which seems to be compatible with the existing MEC5035 code. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: I9fcd73416018574f8934962f92c8222d0101cb71 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 8 + - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e6530/data.vbt | Bin 0 -> 4280 bytes - .../variants/e6530/early_init.c | 14 ++ - .../snb_ivb_latitude/variants/e6530/gpio.c | 192 ++++++++++++++++++ - .../variants/e6530/hda_verb.c | 32 +++ - .../variants/e6530/overridetree.cb | 37 ++++ - 7 files changed, 286 insertions(+) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6530/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6530/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6530/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6530/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6530/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index be9ac37845..03377275f0 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -23,6 +23,12 @@ config BOARD_DELL_LATITUDE_E6430 - select MAINBOARD_USES_IFD_GBE_REGION - select SOUTHBRIDGE_INTEL_C216 - -+config BOARD_DELL_LATITUDE_E6530 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_12288 -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select SOUTHBRIDGE_INTEL_C216 -+ - if BOARD_DELL_SNB_IVB_LATITUDE_COMMON - - config DRAM_RESET_GATE_GPIO -@@ -33,6 +39,7 @@ config MAINBOARD_DIR - - config MAINBOARD_PART_NUMBER - default "Latitude E6430" if BOARD_DELL_LATITUDE_E6430 -+ default "Latitude E6530" if BOARD_DELL_LATITUDE_E6530 - - config OVERRIDE_DEVICETREE - default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb" -@@ -42,6 +49,7 @@ config USBDEBUG_HCD_INDEX - - config VARIANT_DIR - default "e6430" if BOARD_DELL_LATITUDE_E6430 -+ default "e6530" if BOARD_DELL_LATITUDE_E6530 - - config VGA_BIOS_ID - default "8086,0166" -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index 183252630a..d89185d670 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -2,3 +2,6 @@ - - config BOARD_DELL_LATITUDE_E6430 - bool "Latitude E6430" -+ -+config BOARD_DELL_LATITUDE_E6530 -+ bool "Latitude E6530" -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6530/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..af64a913d521fe240ce30e114e90fe75d3841bbc -GIT binary patch -literal 4280 -zcmdT{U2GiH75-*te`aTAcGqJQY$rA+e`ZbWcy_TDH@NC}cbl$*NjAn^RtPm->J7GV -zY_m3jN`RN*h9FvG3Do9+qP$c^s1;PLB3@br9>Ag%La5?TLP`-2DDaR65U2_)=g!QU -zIJ+cPr4+cc-@WIad+wQY&YW{+c1J!nPPgn&^^N3Hy*D37jg0=7CSl@*=mXr>x75gi -zTMlK0$A=H4Mh~QKqCa92jz_;d3rtFqp(o-4gCnzxrJ2}Rw@^!haWp<ahv&+aDb5_3 -zE0-vq=pkms7Ves!pD#^PA#PF^_wjBTO=oC(ayR{asyKURiBdh3?x76Ll#Z5WXklvl -z@M5XFK#OxUXqrdzedca+l4WK~_tG8Hv&HgsX`$Za3pnYy`CpW$@0?nsSh|}MrfK#j -z%y^t^lPNt{p5INwGcz<MWEN<wv`{J^Eluv$Rb2&6%ZgV5Bp(6~Lz2Eoz~@C!!B)bs -z1x-OrK~}*8L07Po(5+xZL6I<}phTEf5QRsVJYHa{f^AXPFaoSsnJ0feXUdB=CJ>Fv -zr&_=Q6YubieL}zoiJ0a+c+(bGwFN5g1pz;^rGP1sM+lHB@UAPM2&F=RB&yv@$caXF -ze~Io&3CQe=cMHr!e{yiokd?~p&F&k`jg99Ex7}WO=$8*Kx8wXv4eSa_CJqKVkyRr& -zCdcqs*@M5!gD84e@fW{|5B#mDGTH;JFw`h^stQcTjf@V3pNe8&f$=NG?-+klRGea* -zX1vOHi}4@EM~qJyfuM>e#%9J&Mjzt`j5OnB#;uGZ<1WTMj3vgSj3*esXZY{I`KqUa -zfbB~~a>piTMAVDNyHR<{<v-=}gXhE(15|emxueb8Kv%5>0{F7}8pool{7_h6u?7yg -zlyNm>-Eq_&WjW{0$9ZHq6x?~W8l2#1g0CyrtN#R-nbWG(?>iNG1zRiZgj;Lm_%rVe -zwZ6i{g#sR5xudpbj~5H9TNIQ3gMikIG@l(Z4IR@^2|Vu|LZteLF5@$KH5`Pr&3_vn -z^!Fn27&z6hSPR+*;D*&lm-)OE=ZgjK*(X&XdBq7RDUd7>|Lou?UMNg6lVCB;TPz{Z -zN4-~p*Rr=uq8OYdlAy38{}dt5%2}aUax{}zWzDRgmsn2|!)=Bp)U35;Ld3H+Ye=*_ -z4S&0{5*TVI!OU-SWz$XUwrrnb%9?NHau^uhn>&;%&X#8O7mt)SIJr8D$u?NS=rUW6 -zCmnxV&FgUDAWX}gZ+1AH&-C4Q=3sl5RX9=OWPfCtcRZi4tkX44YYfRH*@?H7T=Kz= -zG*i-wU2jbJMK%ChTMTXZFJEm~k;KCj*D60g=j!2ns8Q`g%jSRK^?=IwL^|I5-K2zH -z8*A0-mL%Q`R#xatM^u^E=IrX+2&bc;3rv!NipS^G*6zlIRAV(JJDU($OBHuptd&1( -zoNu>t*Q}|siS8#MYavR6j7&(~AEL#OaV(^+gy>YrSPiLfgy{2-p=xT2Mtd}4R8#XB -z-LDysYw8J&{-GJKYwEiif07x7u5QsOr5oeA`ZJxDb>p|XdQzvCb>nSaeP1UfY_x~f -z9bwuRHf|5Ahr{&iu<>+QeI`t=g^e>|^=z1;5o23K?TP5uo%2>aXQWCKr#dH;Qr0*j -z3LecKKarw5`Xblzd$&H4oP%y&l3egyUc<=<Azs)*u}X^*n$F~s2O<-paSF?q*HB+n -zqBfj5;J|x@hM`M(QD20jrkwi8`y3l;8qO;#l8A#CMI8Kg9E{ERsT>TGXaGC^5Cz)J -z4?eb?Kub*nWYdmhV-4?j<o}k#pt-{wK;b3U(B^+`s7-`HYOZOxv<+RG^LulAxKL|9 -z3NH#9{Lg*7U1&gy<zHSG$;LMHby+V=ENlGFVLKjt%kkph7kP1M8|vebT=K5)*E>JW -zjd{Tu*o*CE*QO)}{_J>haU5zn+1QJ^eBg|d5n5-%|DwS@1+<Mtvat=iZ3BF??pZXh -zth4PnnWL*s%}k43fbe34>yaZ_2@Kj<UGt)`2G5>K>)nIBR-xB@+1PQ2*c$lV?Z13o -zbX%CHpm`!1Z4$d28~9k{rfu-0w@xg6{q!u2{)Dm_))4RK$?#7P*t7V+g_9d<V!MD` -zaj`t-?uy6zsjzp<-IdM6g(XhQX2iF<+p?Kmw6?a+f^VMex*PuetNfqf+4_FpD%8TW -eZvUbDHC^NLu5~gtzg|!EqSkX2ep9pg!tpEeo1jDh - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6530/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/early_init.c -new file mode 100644 -index 0000000000..ff83db095b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/early_init.c -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6530/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/gpio.c -new file mode 100644 -index 0000000000..777570765a ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/gpio.c -@@ -0,0 +1,192 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+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_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_NATIVE, -+ .gpio13 = GPIO_MODE_GPIO, -+ .gpio14 = GPIO_MODE_GPIO, -+ .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_NATIVE, -+}; -+ -+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, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio16 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_OUTPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio28 = GPIO_LEVEL_LOW, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+ .gpio30 = GPIO_RESET_RSMRST, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio13 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio46 = GPIO_MODE_NATIVE, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .gpio50 = GPIO_MODE_NATIVE, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_NATIVE, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_NATIVE, -+ .gpio56 = GPIO_MODE_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_INPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_HIGH, -+ .gpio45 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_GPIO, -+ .gpio71 = GPIO_MODE_GPIO, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .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, -+ .gpio70 = GPIO_DIR_INPUT, -+ .gpio71 = 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/dell/snb_ivb_latitude/variants/e6530/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/hda_verb.c -new file mode 100644 -index 0000000000..3ebccff81d ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76df, /* Codec Vendor / Device ID: IDT */ -+ 0x10280535, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x10280535), -+ AZALIA_PIN_CFG(0, 0x0a, 0x03a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0321101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0xd5a30130), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x400000f0), -+ -+ 0x80862806, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6530/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/overridetree.cb -new file mode 100644 -index 0000000000..8b9c82fba4 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6530/overridetree.cb -@@ -0,0 +1,37 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x0535 inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x00000251" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 1, 0 }, -+ { 1, 1, 1 }, -+ { 1, 1, 1 }, -+ { 1, 1, 2 }, -+ { 1, 1, 2 }, -+ { 1, 0, 3 }, -+ { 1, 1, 3 }, -+ { 1, 1, 4 }, -+ { 1, 1, 4 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 2, 6 }, -+ { 1, 2, 6 }, -+ }" -+ -+ device ref xhci on -+ register "superspeed_capable_ports" = "0x0000000f" -+ register "xhci_overcurrent_mapping" = "0x00000c03" -+ register "xhci_switchable_ports" = "0x0000000f" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0019-dell-e6430-use-ME-Soft-Temporary-Disable.patch b/config/coreboot/default/patches/0009-dell-e6430-use-ME-Soft-Temporary-Disable.patch index b3d2d12c..ca3b6264 100644 --- a/config/coreboot/default/patches/0019-dell-e6430-use-ME-Soft-Temporary-Disable.patch +++ b/config/coreboot/default/patches/0009-dell-e6430-use-ME-Soft-Temporary-Disable.patch @@ -1,7 +1,7 @@ -From a15b59616e00c43c05d7853080859d4aefe26c5d Mon Sep 17 00:00:00 2001 +From 3f6f65ed6a435fe49534c8a0b5cb98c3eac71150 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Sun, 5 Nov 2023 11:41:41 +0000 -Subject: [PATCH 19/51] dell/e6430: use ME Soft Temporary Disable +Subject: [PATCH 09/37] dell/e6430: use ME Soft Temporary Disable i overlooked this. it's set on other boards. diff --git a/config/coreboot/default/patches/0009-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch b/config/coreboot/default/patches/0009-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch deleted file mode 100644 index a2a13166..00000000 --- a/config/coreboot/default/patches/0009-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch +++ /dev/null @@ -1,430 +0,0 @@ -From 423e2e28618b08a4107aea0a2fbc1096f5a8be02 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Wed, 31 Jan 2024 22:57:07 -0700 -Subject: [PATCH 09/51] mb/dell: Add Latitude E5530 (Ivy Bridge) - -Mainboard is QXW10/LA-7902P (UMA). I do not physically have this board; -someone with physical access to one sent me the output of autoport which -I then modified to produce this port. I was also sent the VBT binary, -which was obtained from `/sys/kernel/debug/dri/0/i915_vbt` while running -version A21 of the vendor firmware. - -This was originally tested and found to be working as a standalone board -port in Libreboot, but this variant based port in upstream coreboot has -not been tested. - -This can be internally flashed by sending a command to the EC, which -causes the EC to pull the FDO pin low and the firmware to skip setting -up any chipset based write protections [1]. The EC is the SMSC MEC5055, -which seems to be compatible with the existing MEC5035 code. - -Change-Id: Idaf6618df70aa19d8e60b2263088737712dec5f0 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 7 + - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e5530/data.vbt | Bin 0 -> 6144 bytes - .../variants/e5530/early_init.c | 14 ++ - .../snb_ivb_latitude/variants/e5530/gpio.c | 194 ++++++++++++++++++ - .../variants/e5530/hda_verb.c | 32 +++ - .../variants/e5530/overridetree.cb | 39 ++++ - 7 files changed, 289 insertions(+) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5530/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5530/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5530/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5530/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5530/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index 03377275f0..183a67bec3 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -17,6 +17,11 @@ config BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select SYSTEM_TYPE_LAPTOP - select USE_NATIVE_RAMINIT - -+config BOARD_DELL_LATITUDE_E5530 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_12288 -+ select SOUTHBRIDGE_INTEL_C216 -+ - config BOARD_DELL_LATITUDE_E6430 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_12288 -@@ -38,6 +43,7 @@ config MAINBOARD_DIR - default "dell/snb_ivb_latitude" - - config MAINBOARD_PART_NUMBER -+ default "Latitude E5530" if BOARD_DELL_LATITUDE_E5530 - default "Latitude E6430" if BOARD_DELL_LATITUDE_E6430 - default "Latitude E6530" if BOARD_DELL_LATITUDE_E6530 - -@@ -48,6 +54,7 @@ config USBDEBUG_HCD_INDEX - default 2 - - config VARIANT_DIR -+ default "e5530" if BOARD_DELL_LATITUDE_E5530 - default "e6430" if BOARD_DELL_LATITUDE_E6430 - default "e6530" if BOARD_DELL_LATITUDE_E6530 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index d89185d670..c15ef4028f 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -1,5 +1,8 @@ - ## SPDX-License-Identifier: GPL-2.0-only - -+config BOARD_DELL_LATITUDE_E5530 -+ bool "Latitude E5530" -+ - config BOARD_DELL_LATITUDE_E6430 - bool "Latitude E6430" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5530/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..3c54b70be7856a6420d001112d7f17f8bab46ed3 -GIT binary patch -literal 6144 -zcmeHKU2Gdg5dO}0w$JA~+qs02q)iz56C9e5vuQ#oL0l3O+%|395Q2peO{y4(2uX0t -zuMja1N)bPb1cE+5)fYsCK!89MFQAGChyWpk5PuR<K|G+sLmxmOR4}u5=Rg`mj70g7 -zvgdDic6N4dW^QKhynd)>kS^cR)3#-(r*-?zo-O^C(kLvv8XM<+Y3tdt^YY!P?!oTe -zJ^ed-x6w0Lh5fN#jsv5TWE#mtd*_yky}9xDK(kOwLt+C7_AQAd#iwr=o0`gvQZ`{x -z6ZeT`x^^;8+a~jSa^o~PF@8J6N5;o#dhCwebaM;!_oisw1#O9K={qQM<@Oeu$lXeN -z#wJGcW4Y<2)-A{Bot(NoKX%>qdnw-AOi9bKT9Z~HL5|7PJDHz4kGlEx143q+26EH6 -z{4KfB^9;?<fTOaiNPy%=@LovL&q<^d1Qdi+Xex9SvIM^ZLq%9cP{A1rE>#dw(WfA; -zBCR3@pCS1a;A|CZW1h7H*l#mW{%y{bf)9ofiz!EHzyiac@{RpMzz>O-<~{hx5tw%b -z3ZJWD4_g-`iF`tUJb}+Vfe;XI1T2Y4_Y!iVk<<T4ce(^PWKh<?N^a`t+}vgNr25iZ -z`!fTBL)ojYF5G?3y|eW=`9>MLB9et&!A7LDDE7&5ye#|hn%s#IWgagDEPNHHMUhb- -ztc9t?uz{bD#kh#kpsE;AO-wWHV?4olPStRPag^~k<737bjBgm<GlC%vRgBe)4U9I% -zg^XUtcE**A5ylOSn;A2V2N;hso?--U#>t|ufS}_`LGs2bcSKCVBh4s0>G7ZR_@NWx -zkph}GhP}~YR?roT!61GqzQ?gBsuv3jY}UXbmr|alv^VxUqbz5<`5=!hhpaa*7DK~4 -zP4ad6dhH!>nYpc4{J&G-w{UiWo$zXnTz{tAq0|?c_`QJ7pKmCwIpe7Uix$P?9}v*1 -z(aVR6OkMkQ6oM}*UC@j78!~>7=OZCVYXeu|u0SiI4}w$uw6&0P09LF%Hp}O&IA3gl -z4@ap0NfAe+q(ZVm{Bwe*Do~kbCc$Q!x7b3Sk9tLgVmsR<Q4H=9Nl;mmf2xpY<*d*- -z`yI_BR#`La=Oxxt#qgS`3pER^nh^CZ%*qlq2N9@uSAtz-C7AhduB_U|{>#oOrY`tq -z%|?L!zRd2-$V6^@$H<Mj3MXf#F<J+^8%<X2{tnmQTI*aK*ageBrm9^|<Ked3j_s;% -zva<(Dob)BOwdcj8Z67UhYUAjbk==Of9W#D7k!DJobLx$$fXD_wuZyD&Kk-$EIY~S` -zan1ANbFUW8hZ0pUw5)y??*}!;chdgq|0X5;s;m`@YdY{zs4z#z8e;13T6b4tC7gy$ -zTwszEQhk0!U$`3=Qi)ZbY^*|bAyvF>@ml^iaX;uzoVB3JA(|h9tcNKXHdA43N0|18 -z&3$2QE=)(l=6qQDAWT1oO-<KoblR+&{kk@!)1A8ch^`&b>2=+FU)Mg<35IDJ+8Tp; -z40F)Xt}$rVFdsLxLk7KRn4cKhmj<a3vp%A&kI>eLd38j)HbM_Y%!3i_aD?8An8za8 -z@d(AD=Gv&%5;e{}p%i?_q(T*^IwzEx*Eu1wKHV9=lVUvjqv!B@cWER!2fe%`IqO?q -z!=Wf4kzGUaLX8`m#*P^uL?%M#6qc9Qu(YT|ZMb#7UzCc_(DkQYEG<G&Q*QkX`CS`I -z8cwQnl8A#CMH~W79L&{2*Jof_MD5t{bPTAszWUa20yPzD=*wW8)wHSu?avDhffu^! -zL>Q#%k_O0@^DN5S@MXi$D;acJ>#cTV-(U@Offv4ACp4hO4$Ll!WO)s3P4=t9vpWBC -zSckhlcD?xUuX=Gx96Dx{IsQ23r&;o1*+^Cp2RA3nd$A-RIHP2Q7uitC>c67FIR*5} -zB3a%B!?6K=TJ$W+SJv@*9Lms{mTvWmU4Zanj_Z*lSqOGISzYp?yawOqLhVhRt#-E6 -zd)YW~h&meh-5prIE}Cr&7f?MMi&cqTt_^%Fa?>k(=`9jVoIf@}{g+WX#TpWuc+!2v -zPG^>A|NZ2GlGsKdGqN{7>Fr7+Hc_^3z}uBhC4?nzOQ*!QyVugGjkK_~$bvtfY`h79 -z9rOI3;Mt}9)_G{zXTAPw`8T@6=Ut0r9R5;0#Zy|#8F;v4^UAmqft3iXL|`QXD-l?U -Jz~2*rUjdP?m;3+# - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5530/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/early_init.c -new file mode 100644 -index 0000000000..ff83db095b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/early_init.c -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5530/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/gpio.c -new file mode 100644 -index 0000000000..0599f13921 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/gpio.c -@@ -0,0 +1,194 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+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_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_GPIO, -+ .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_NATIVE, -+}; -+ -+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, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio12 = GPIO_DIR_OUTPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio16 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_OUTPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio12 = GPIO_LEVEL_HIGH, -+ .gpio28 = GPIO_LEVEL_LOW, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+ .gpio30 = GPIO_RESET_RSMRST, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio13 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio46 = GPIO_MODE_NATIVE, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .gpio50 = GPIO_MODE_NATIVE, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_GPIO, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_NATIVE, -+ .gpio56 = GPIO_MODE_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_INPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_INPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_INPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio53 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_GPIO, -+ .gpio71 = GPIO_MODE_GPIO, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .gpio73 = GPIO_MODE_NATIVE, -+ .gpio74 = GPIO_MODE_GPIO, -+ .gpio75 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set3 pch_gpio_set3_direction = { -+ .gpio68 = GPIO_DIR_INPUT, -+ .gpio69 = GPIO_DIR_INPUT, -+ .gpio70 = GPIO_DIR_INPUT, -+ .gpio71 = GPIO_DIR_INPUT, -+ .gpio74 = 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/dell/snb_ivb_latitude/variants/e5530/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/hda_verb.c -new file mode 100644 -index 0000000000..3e89a6d75f ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76df, /* Codec Vendor / Device ID: IDT */ -+ 0x1028053d, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x1028053d), -+ AZALIA_PIN_CFG(0, 0x0a, 0x04a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0421101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0xd5a301a0), -+ -+ 0x80862806, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5530/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/overridetree.cb -new file mode 100644 -index 0000000000..85c448d010 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5530/overridetree.cb -@@ -0,0 +1,39 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x053d inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x00000000" -+ register "gpu_pch_backlight" = "0x03d003d0" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 1, 0 }, -+ { 1, 1, 1 }, -+ { 1, 1, 1 }, -+ { 1, 1, 2 }, -+ { 1, 1, 2 }, -+ { 1, 1, 3 }, -+ { 1, 0, 3 }, -+ { 1, 2, 4 }, -+ { 1, 1, 4 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 0, 6 }, -+ { 1, 1, 6 }, -+ }" -+ -+ device ref xhci on -+ register "superspeed_capable_ports" = "0x0000000f" -+ register "xhci_overcurrent_mapping" = "0x00000c03" -+ register "xhci_switchable_ports" = "0x0000000f" -+ end -+ device ref gbe off end -+ device ref pcie_rp7 on end # BCM5761 Ethernet -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0010-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch b/config/coreboot/default/patches/0010-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch deleted file mode 100644 index 80b2c147..00000000 --- a/config/coreboot/default/patches/0010-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch +++ /dev/null @@ -1,435 +0,0 @@ -From 200668a694f1c534a94a0bc8996416e246fe91b0 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Sun, 26 Nov 2023 17:08:52 -0700 -Subject: [PATCH 10/51] mb/dell: Add Latitude E6420 (Sandy Bridge) - -Mainboard is PAL50/LA-6591P (UMA). The version with an Nvidia dGPU was -not tested. I do not physically have this system; someone with physical -access to one sent me the output of autoport which I then modified to -produce this port. I was also sent the VBT binary, which was obtained -from `/sys/kernel/debug/dri/0/i915_vbt` while running version A25 of the -vendor firmware. - -This was originally tested and found to be working as a standalone board -port in Libreboot, but this variant based port in upstream coreboot has -not been tested. - -This can be internally flashed by sending a command to the EC, which -causes the EC to pull the FDO pin low and the firmware to skip setting -up any chipset based write protections [1]. The EC is the SMSC MEC5055, -which seems to be compatible with the existing MEC5035 code. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: Ic48d9ea58172a5b13958c8afebcb19c8929c4394 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 13 +- - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e6420/data.vbt | Bin 0 -> 6144 bytes - .../variants/e6420/early_init.c | 14 ++ - .../snb_ivb_latitude/variants/e6420/gpio.c | 191 ++++++++++++++++++ - .../variants/e6420/hda_verb.c | 32 +++ - .../variants/e6420/overridetree.cb | 35 ++++ - 7 files changed, 287 insertions(+), 1 deletion(-) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6420/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6420/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6420/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6420/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6420/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index 183a67bec3..d2786970ee 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -17,6 +17,12 @@ config BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select SYSTEM_TYPE_LAPTOP - select USE_NATIVE_RAMINIT - -+config BOARD_DELL_LATITUDE_E6420 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_10240 -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ - config BOARD_DELL_LATITUDE_E5530 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_12288 -@@ -43,6 +49,7 @@ config MAINBOARD_DIR - default "dell/snb_ivb_latitude" - - config MAINBOARD_PART_NUMBER -+ default "Latitude E6420" if BOARD_DELL_LATITUDE_E6420 - default "Latitude E5530" if BOARD_DELL_LATITUDE_E5530 - default "Latitude E6430" if BOARD_DELL_LATITUDE_E6430 - default "Latitude E6530" if BOARD_DELL_LATITUDE_E6530 -@@ -54,11 +61,15 @@ config USBDEBUG_HCD_INDEX - default 2 - - config VARIANT_DIR -+ default "e6420" if BOARD_DELL_LATITUDE_E6420 - default "e5530" if BOARD_DELL_LATITUDE_E5530 - default "e6430" if BOARD_DELL_LATITUDE_E6430 - default "e6530" if BOARD_DELL_LATITUDE_E6530 - - config VGA_BIOS_ID -- default "8086,0166" -+ default "8086,0166" if BOARD_DELL_LATITUDE_E5530 -+ default "8086,0126" if BOARD_DELL_LATITUDE_E6420 -+ default "8086,0166" if BOARD_DELL_LATITUDE_E6430 \ -+ || BOARD_DELL_LATITUDE_E6530 - - endif -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index c15ef4028f..257d428a70 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -1,5 +1,8 @@ - ## SPDX-License-Identifier: GPL-2.0-only - -+config BOARD_DELL_LATITUDE_E6420 -+ bool "Latitude E6420" -+ - config BOARD_DELL_LATITUDE_E5530 - bool "Latitude E5530" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6420/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..d3662eea1bc78b60be6d0bd2cc38bb46b654afbd -GIT binary patch -literal 6144 -zcmeHKeQZ-z6hE);wSBvNZ|mO1=*HLC2BQN8uVX6{N9eY)75ORymb$R8!YYuAZEgeE -zKk|S@Fen*n41W-viAF;r%)~^EkpLz-B{2q##)LmGAtoY;7*Qhv_1yPbw$TC$2}G0K -z=6Ao&x#ym9?z!i_&TOh(kLzky2cN8MTpny#R<;VU4Rkn?rBIz(YL~BBw<%b&zGhSH -z$~AQ>@D0d=Xx6RE0BwSxspWdrW9y<FZGD@&x3_JL;p$p!;!BVdcKLkht0=-%(Jj&T -z_GkyztZ%>#t7^)^(T-R<7W?O6ZTI%A+j=`<Jw3Q%dk6N!da<_?7oyiU3)^<~_TiSk -zE$y+=RK3PGQ`gzmXYPRBx>C|f*UP9{h|4>ANrAe~?ymV*)83AaT#FuTjP=C2cg5P~ -zt4w78r$t#300cWY_k)mevmAmFI3&oBfytoAAPQiYK$XEIgHwV@5-gJ-Q-*p8yfTDj -zaDz=1Y!X1B3`OpQ&Ik}bM|0xHn0gYNZw0rT=7AXS2in-q8K^?)0|el+Z6geW7i7MM -zv~!|>HqL-|Fk}EYOa@)R<X)VQ7c}d8R1b@RTn5rq(90|QRg0?wwZZz(6Dz}w>zg9Y -z8;!mD_V*XSjT33~$`o`s>zEGBq8AQ`HaH?y!Fh2QiX1v@aCo4LaENf&DZ_cE2A2qb -z5@cC}X)=S^1RvpXLWs~v*hqMau$!=t@B-mg!XV)|;eEm>!Z6`H;R4|&!d1d`f|S7^ -zli+B98*!TfPE&6~NVM5j3v{N3OTjpnm_L@BPh(}esd(J!gj?~iJP?n|OZZOiTqlql -zg<NWR@g&-*W-E%A7|*1Z_`sVO$K&iAP+VIj9{<1hT%SXsK}IBk8!daftR`6-)EUiS -zvv*HR(#-ZwhA~7wcmxbe4%E?Y7P0y{1q|nqR1L29UR8v@#No^g5MH)7!>{%-$T|cR -zZx5|xm>Fl>;@$m};P{0WC>O~<Nl1`*PLgPN_hP2a^h+L$ls&SYrkDYr+&l*%%S?^Q -ziPSdtHE<LNEnr7cs=ihL-C>-p>*$9CpHRLgN|POkqD^UP4nw|4nf0bc8MOBk<;%js -zfpCAWNzqSPlz@X%j9CGrwZDKUl@K{g6pzqiIIARDQ)#@^RW&0pmNG;XZ?!SlHB?L# -zKRAMgq(R;aQd%@Gy38-LS@ix)fR**(P3B9wI=Uk^&cWmmwB<vf21<0#LBA!;qtAh( -zYe5g_T{+gw^mi8QzPPraBoH~8oCz%r=$nVi1A)`Y8IKqIdqm6MihqxtpFaTggaPxu -zQP07nf#&kPkPp}Cmk$F1g7q7QK;kz~80i&oDN}~wYbPUI6AtG5H+$T!@f5FzUhp21 -z^XiPT3rb%B@sA9g!n88R7BOsLS|?+D3}0v3dyIX|@JFWo&e%<c#V)PV#g@7-=F*;V -zvAr&Q+ogTvVxPM3XP5Smi`f;Nt7uCU)}Y`HMcbpW=M_AuXlE35PQl+4O{7m66&I@7 -zGL@}Sai^*sP}va`KTx$VRQ8REf2*1+lTFH0=UkNx+eN|1rVyipl)Du=h=@%w+iQZG -zT6@-PdW^oyFb44AG`HMZWEnP{&OQ+jC`N4emoS)x;EPN}uaSFOf-Mn8JRRO<WJc -zn6%=L94~PR)%Ua_HTZcfTXD<p{%8p|<N<;Efw$Zb4$}{m8@7c((~<7^thaau&@Wx# -zVGNL)lmH@{o=h*{muXGc!;nXrVgpp3;1V1stMj=4AtxyzX+?SoB~zN}!*r?9Qvs1P -zmV_(CTmt0sY&6=F=_M>E34GYvuh1uQF+BUdWyQC5SaEM1QvKlHBMs13C}n{0SwRxW -ziekMa&kvRFruRcKCevGy5)TxUBDlur@E{TtQ^NQ>nO+Cgl)&Ga(PxqVW?e3TLH-UY -zdL3T{z^xdd`$(STFUb8R*cKa}r>n{Wk+MXRH~o-hN}#9OF*>T#>rfhiRs(Wc-R^9@ -z%F=<}dn(E}ADc03zJ>JvZe;_8f+WFLL4%qNYs`_aa`a$Pl5H;iO^Wt*cP3W(d=(g} -zZ%nKT1$|r-tAv8($u2-BI2Uiz#%OT&!Q3b~Ru2P2j;Gem!@wfPsTR%J>W{8z)oq^J -k^Qm&?O@bFkw4CTocwoW<6CRlGz=Q`TJTT#bN9KWl0rH4|j{pDw - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6420/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/early_init.c -new file mode 100644 -index 0000000000..ff83db095b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/early_init.c -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6420/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/gpio.c -new file mode 100644 -index 0000000000..943c743f48 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/gpio.c -@@ -0,0 +1,191 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+static const struct pch_gpio_set1 pch_gpio_set1_mode = { -+ .gpio0 = GPIO_MODE_GPIO, -+ .gpio1 = GPIO_MODE_NATIVE, -+ .gpio2 = GPIO_MODE_GPIO, -+ .gpio3 = GPIO_MODE_NATIVE, -+ .gpio4 = GPIO_MODE_GPIO, -+ .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_NATIVE, -+ .gpio13 = GPIO_MODE_GPIO, -+ .gpio14 = GPIO_MODE_GPIO, -+ .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_GPIO, -+ .gpio31 = GPIO_MODE_GPIO, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_direction = { -+ .gpio0 = GPIO_DIR_INPUT, -+ .gpio2 = GPIO_DIR_INPUT, -+ .gpio4 = GPIO_DIR_INPUT, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio16 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_INPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+ .gpio30 = GPIO_DIR_OUTPUT, -+ .gpio31 = GPIO_DIR_INPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio30 = GPIO_LEVEL_HIGH, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio46 = GPIO_MODE_NATIVE, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .gpio50 = GPIO_MODE_NATIVE, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_NATIVE, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_NATIVE, -+ .gpio56 = GPIO_MODE_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_OUTPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_HIGH, -+ .gpio45 = GPIO_LEVEL_LOW, -+ .gpio49 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_GPIO, -+ .gpio71 = GPIO_MODE_GPIO, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .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, -+ .gpio70 = GPIO_DIR_INPUT, -+ .gpio71 = 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/dell/snb_ivb_latitude/variants/e6420/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/hda_verb.c -new file mode 100644 -index 0000000000..ede8445aaf ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76e7, /* Codec Vendor / Device ID: IDT */ -+ 0x10280493, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x10280493), -+ AZALIA_PIN_CFG(0, 0x0a, 0x03a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0321101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0xd5a30130), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x400000f0), -+ -+ 0x80862805, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6420/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/overridetree.cb -new file mode 100644 -index 0000000000..3012a3177f ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6420/overridetree.cb -@@ -0,0 +1,35 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x0493 inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x0000054f" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 1, 0 }, -+ { 1, 1, 1 }, -+ { 1, 1, 1 }, -+ { 1, 0, 2 }, -+ { 1, 1, 2 }, -+ { 1, 1, 3 }, -+ { 1, 1, 3 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 1, 7 }, -+ { 1, 1, 6 }, -+ { 1, 0, 6 }, -+ { 1, 0, 7 }, -+ }" -+ -+ device ref sata1 on -+ register "sata_port_map" = "0x3b" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0020-mb-hp-Add-Compaq-Elite-8300-CMT-port.patch b/config/coreboot/default/patches/0010-mb-hp-Add-Compaq-Elite-8300-CMT-port.patch index 46e38925..2a7d5c17 100644 --- a/config/coreboot/default/patches/0020-mb-hp-Add-Compaq-Elite-8300-CMT-port.patch +++ b/config/coreboot/default/patches/0010-mb-hp-Add-Compaq-Elite-8300-CMT-port.patch @@ -1,7 +1,7 @@ -From 440ebbe1e10911dc3d8c53cf9eecb5519c2ecd67 Mon Sep 17 00:00:00 2001 +From b4d48233a8d829d7285501f662d999aad898be21 Mon Sep 17 00:00:00 2001 From: Riku Viitanen <riku.viitanen@protonmail.com> Date: Sat, 23 Dec 2023 19:02:10 +0200 -Subject: [PATCH 20/51] mb/hp: Add Compaq Elite 8300 CMT port +Subject: [PATCH 10/37] mb/hp: Add Compaq Elite 8300 CMT port Based on autoport and Z220 SuperIO code. diff --git a/config/coreboot/default/patches/0011-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch b/config/coreboot/default/patches/0011-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch deleted file mode 100644 index 2b378406..00000000 --- a/config/coreboot/default/patches/0011-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch +++ /dev/null @@ -1,449 +0,0 @@ -From 53abe363f2fa038080a976f2d3a2c63ee8da9022 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Wed, 31 Jan 2024 22:07:25 -0700 -Subject: [PATCH 11/51] mb/dell: Add Latitude E6520 (Sandy Bridge) - -Mainboard is PAL60/LA-6562P (UMA). The version with an Nvidia dGPU was -not tested. I do not physically have this system; someone with physical -access to one sent me the output of autoport which I then modified to -produce this port. I was also sent the VBT binary, which was obtained -from `/sys/kernel/debug/dri/0/i915_vbt` while running version A08 of the -vendor firmware. - -This was originally tested and found to be working as a standalone board -port in Libreboot, but this variant based port in upstream coreboot has -not been tested. - -This can be internally flashed by sending a command to the EC, which -causes the EC to pull the FDO pin low and the firmware to skip setting -up any chipset based write protections [1]. The EC is the SMSC MEC5055, -which seems to be compatible with the existing MEC5035 code. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: Ibdd40cc15642b8d404159d5962670ccc4167a9ec -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 9 + - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e6520/data.vbt | Bin 0 -> 6144 bytes - .../variants/e6520/early_init.c | 31 +++ - .../snb_ivb_latitude/variants/e6520/gpio.c | 190 ++++++++++++++++++ - .../variants/e6520/hda_verb.c | 32 +++ - .../variants/e6520/overridetree.cb | 35 ++++ - 7 files changed, 300 insertions(+) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6520/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6520/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6520/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6520/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6520/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index d2786970ee..72bdc96c0a 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -23,6 +23,12 @@ config BOARD_DELL_LATITUDE_E6420 - select MAINBOARD_USES_IFD_GBE_REGION - select SOUTHBRIDGE_INTEL_BD82X6X - -+config BOARD_DELL_LATITUDE_E6520 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_10240 -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ - config BOARD_DELL_LATITUDE_E5530 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_12288 -@@ -50,6 +56,7 @@ config MAINBOARD_DIR - - config MAINBOARD_PART_NUMBER - default "Latitude E6420" if BOARD_DELL_LATITUDE_E6420 -+ default "Latitude E6520" if BOARD_DELL_LATITUDE_E6520 - default "Latitude E5530" if BOARD_DELL_LATITUDE_E5530 - default "Latitude E6430" if BOARD_DELL_LATITUDE_E6430 - default "Latitude E6530" if BOARD_DELL_LATITUDE_E6530 -@@ -62,11 +69,13 @@ config USBDEBUG_HCD_INDEX - - config VARIANT_DIR - default "e6420" if BOARD_DELL_LATITUDE_E6420 -+ default "e6520" if BOARD_DELL_LATITUDE_E6520 - default "e5530" if BOARD_DELL_LATITUDE_E5530 - default "e6430" if BOARD_DELL_LATITUDE_E6430 - default "e6530" if BOARD_DELL_LATITUDE_E6530 - - config VGA_BIOS_ID -+ default "8086,0116" if BOARD_DELL_LATITUDE_E6520 - default "8086,0166" if BOARD_DELL_LATITUDE_E5530 - default "8086,0126" if BOARD_DELL_LATITUDE_E6420 - default "8086,0166" if BOARD_DELL_LATITUDE_E6430 \ -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index 257d428a70..c7665ac263 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -3,6 +3,9 @@ - config BOARD_DELL_LATITUDE_E6420 - bool "Latitude E6420" - -+config BOARD_DELL_LATITUDE_E6520 -+ bool "Latitude E6520" -+ - config BOARD_DELL_LATITUDE_E5530 - bool "Latitude E5530" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6520/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..0ef16ee7cb482d2cb91ea80c3f419759355f7ba0 -GIT binary patch -literal 6144 -zcmeHKZ){Ul6hE);wSB#PZ|mL$bQ^!}HW(eF@H)0JafGfbqsZ9G21{L7Sg{or$5uN) -z_QgG55e!O(8p8*oBhhF`l$n^QF%rN;rzFNqqcPzFCd5QSB1Y7RKt1=pmTk1aFo9^Y -z+x+gi_nvdlJ@?#m&wZWW=G#bH>ze$J`&!oe*Q|E0r!)d89LYY8b$aowZEoG-uiIF+ -z#n;$ezm6V<nGnvtc?lrGaf)1_);!W0?uqnojdw-1MQM|dwy`OcF?M@A)KgVV*N2}7 -zcXx+--0R}IwzW3-+`f2k?^Av5V7MpRO-q(9rn_R1@Xlz2Ztdy`$Gf6^w6~|bKi!!7 -z9;xq*^~bxmZQn^<^<`+2s=BdSM%VW2#FguN<FO^QuDhGIFquBu677q|cSj>jWFixQ -z)4V8f0Gt`D`+>9Fr~tnJ76EJ`5D_F1cn-`0$RgN9unI6kfYkzIiO?W`ON4+34lv1_ -zNdPDkq1cf$p8^EW;TS*O$CdzNo#1fbIG_Oi0T(ti0jwyt0le_p_HlvX^CFvr)>$b> -zO-z8^CSU`w=mIK7Q)@9fR;XUzrFu{T=rRyygIZBpU9+Or>+?4R9%~G?Y-|g)Z`Sti -z+do(U*Wb-xR~DzjS<75#=Us4sH^C9U2FCbND7L7u$>M|<;t=AnRfI9C0v8c~AVg7t -zIU<3D2oK^>L;%r(*o=4*u?Mja@dDyi#4zFn;(f#^#3*76aUSs#;tJv#La-6YLRdQB -zdcvfERkvH?k~GJlfM<HR476j(@nfm+47<!Ult@^ua5M3h6A}q=C0ognX9aX4mxq)U -zXOhm=DbLene?C%_16Q)2NRV@Yacz`D;{V>Ve-1?&ZXy}n)YwnVAgNlz#zX;=IX)-F -z)9LL3lbEdY5Co)LsK?vP)7s}G(5xduE!Y!#Wgh<IN3(3ey=-oWU(9aEJ_HzV53Jbq -zj5B5RjzLUt>_T&xi$uUA#0e}X3D~`J(bHz;DgTa@GrpW6=>eZwJeNYYo*GjF=``;( -zuoQ3|V5YoKd$j=KK{`uSX*DeU1oJg=+RT6)rLe6%2>Ci^!5ao=*gS}wFN=nUf`fTF -zM?Gb5ycWjM7I?MJ!2;w|LFg=UoLq-ytr2iemG)AsW}bI4X9PK}T5UKsQi7anu=tD6 -zf|={kXkNeQBD>6bQ3taC8XJOJ^e40_ydyfr&a41L^1)jNrK<B_wV}+ZE`p;QK=rDz -zTw`SJ+e`Oc*icaF4INF51Xg*~ts@m)@9ETt(*@N7yy0)Ddce%i9{^k2kbd8=Wns~P -zWBD$~himxDharxF@f!ti^0$~9Zxt{tg`@Dbl_0Ki2Xp_MEw-<z6qgep;XYmR%Dl-F -z%3cBfcN;Avikpz-gmw_6mymu!Unk0YgnUfsk3{*6kQ;=S*p(_fS!JhDyYh^k?6uRk -z?8--W@~NHvY*+ra6SG9iC1s^V)<|@Rqzp*pd5NBslrs`JC(&Oeg~v}CnJ$x+)iP<8 -z=`LA0Ad@39{XkZ}kjXbP{YzHtS!70*yy%LcnJ#cz4u%*Wq!^d*AVMZdr&l=#Qgik~ -ze2l)cX+!kF9EaFhY;0^Uo_#VNC?7K2Tf=ZR1y5);b!mCGG?<cc#M0rtHKYeKi%BE? -z@Y6|P8fx#li}c`Uv24UGyZaM0To;Ep<_AWZA1t~bFgI)uf}&Eq=L_Cs89=>wnT0Vx -z-jp>o1ffJNommZ4?=TIPlePIw0hgQ706f*tBC`#pg>9&zRHe>J2%RxBTrOc6Adh9E -ziJr`?VQH!N!_GkoKaoq|+3$^Ae0#sUxXlmM1Huq~g<=Ls?ILv+nQcH%PQedGOlH=Q -z77rMcJlH4Mkc#U2(IDv>rsm1aHpsdL_RdT^i_ACcQUMIJcSus}*(?CIiy^#^=t=g1 -z+*^Zbh30&^#_bKclSy9pL$<B~pK8m*sLpIdnHM@W$nA7Ea@Z`x27K?aNK<@lCW(2L -zb@kB3H8kKy4W3Hu)NN|kd!DL^o#iR9a{QYV-Wl&r&hmIFX{ezkIV<4zFiVUQ@K>ao -z00DnFy~Uek!JRwhVX!of0)$Sa*X^S~LMQH0<E(UUx}L=|;Kgw(r(4q=nD)T52c|tR -O?SW|zOncy=dEg(6JAK&z - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6520/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/early_init.c -new file mode 100644 -index 0000000000..b6415a428b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/early_init.c -@@ -0,0 +1,31 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+const struct southbridge_usb_port mainboard_usb_ports[] = { -+ { 1, 1, 0 }, -+ { 1, 1, 0 }, -+ { 1, 1, 1 }, -+ { 1, 1, 1 }, -+ { 1, 0, 2 }, -+ { 1, 1, 2 }, -+ { 1, 0, 3 }, -+ { 1, 0, 3 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 1, 7 }, -+ { 1, 1, 6 }, -+ { 1, 0, 6 }, -+ { 1, 0, 7 }, -+}; -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6520/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/gpio.c -new file mode 100644 -index 0000000000..61f01816c4 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/gpio.c -@@ -0,0 +1,190 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+static const struct pch_gpio_set1 pch_gpio_set1_mode = { -+ .gpio0 = GPIO_MODE_GPIO, -+ .gpio1 = GPIO_MODE_NATIVE, -+ .gpio2 = GPIO_MODE_GPIO, -+ .gpio3 = GPIO_MODE_NATIVE, -+ .gpio4 = GPIO_MODE_GPIO, -+ .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_NATIVE, -+ .gpio13 = GPIO_MODE_GPIO, -+ .gpio14 = GPIO_MODE_GPIO, -+ .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_GPIO, -+ .gpio31 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_direction = { -+ .gpio0 = GPIO_DIR_INPUT, -+ .gpio2 = GPIO_DIR_INPUT, -+ .gpio4 = GPIO_DIR_INPUT, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio16 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_INPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+ .gpio30 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio30 = GPIO_LEVEL_HIGH, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio46 = GPIO_MODE_NATIVE, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .gpio50 = GPIO_MODE_NATIVE, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_NATIVE, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_NATIVE, -+ .gpio56 = GPIO_MODE_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_OUTPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_HIGH, -+ .gpio45 = GPIO_LEVEL_LOW, -+ .gpio49 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_GPIO, -+ .gpio71 = GPIO_MODE_GPIO, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .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, -+ .gpio70 = GPIO_DIR_INPUT, -+ .gpio71 = 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/dell/snb_ivb_latitude/variants/e6520/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/hda_verb.c -new file mode 100644 -index 0000000000..ae376691e7 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76e7, /* Codec Vendor / Device ID: IDT */ -+ 0x10280494, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x10280494), -+ AZALIA_PIN_CFG(0, 0x0a, 0x03a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0321101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0x400000f2), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x400000f0), -+ -+ 0x80862805, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6520/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/overridetree.cb -new file mode 100644 -index 0000000000..f90f2dee1f ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6520/overridetree.cb -@@ -0,0 +1,35 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x0494 inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x00001312" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 1, 0 }, -+ { 1, 1, 1 }, -+ { 1, 1, 1 }, -+ { 1, 0, 2 }, -+ { 1, 1, 2 }, -+ { 1, 1, 3 }, -+ { 1, 1, 3 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 1, 7 }, -+ { 1, 1, 6 }, -+ { 1, 0, 6 }, -+ { 1, 0, 7 }, -+ }" -+ -+ device ref sata1 on -+ register "sata_port_map" = "0x3b" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0021-nb-intel-haswell-make-IOMMU-a-runtime-option.patch b/config/coreboot/default/patches/0011-nb-intel-haswell-make-IOMMU-a-runtime-option.patch index b3305e58..f8c56155 100644 --- a/config/coreboot/default/patches/0021-nb-intel-haswell-make-IOMMU-a-runtime-option.patch +++ b/config/coreboot/default/patches/0011-nb-intel-haswell-make-IOMMU-a-runtime-option.patch @@ -1,7 +1,7 @@ -From 4c7577314f19e934d690c4cce3642fe693400c07 Mon Sep 17 00:00:00 2001 +From a16ff494adb1f706d402a2e167d0d53c775d0897 Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sat, 2 Mar 2024 22:51:09 +0000 -Subject: [PATCH 21/51] nb/intel/haswell: make IOMMU a runtime option +Subject: [PATCH 11/37] nb/intel/haswell: make IOMMU a runtime option When I tested graphics cards on a coreboot port for Dell OptiPlex 9020 SFF, I could not use a graphics card unless diff --git a/config/coreboot/default/patches/0022-dell-optiplex_9020-Disable-IOMMU-by-default.patch b/config/coreboot/default/patches/0012-dell-optiplex_9020-Disable-IOMMU-by-default.patch index f18f119e..e578d22a 100644 --- a/config/coreboot/default/patches/0022-dell-optiplex_9020-Disable-IOMMU-by-default.patch +++ b/config/coreboot/default/patches/0012-dell-optiplex_9020-Disable-IOMMU-by-default.patch @@ -1,7 +1,7 @@ -From b5695d0f0dc44ed1eb1feac008e601040feda55d Mon Sep 17 00:00:00 2001 +From 4b0536ce7cd55eedc52d13497bea59d91e8924d8 Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sat, 2 Mar 2024 23:00:09 +0000 -Subject: [PATCH 22/51] dell/optiplex_9020: Disable IOMMU by default +Subject: [PATCH 12/37] dell/optiplex_9020: Disable IOMMU by default Needed to make graphics cards work. Turning it on is recommended if only using iGPU, otherwise leave it off diff --git a/config/coreboot/default/patches/0012-mb-dell-Add-Latitude-E5520-Sandy-Bridge.patch b/config/coreboot/default/patches/0012-mb-dell-Add-Latitude-E5520-Sandy-Bridge.patch deleted file mode 100644 index 4fd3bba2..00000000 --- a/config/coreboot/default/patches/0012-mb-dell-Add-Latitude-E5520-Sandy-Bridge.patch +++ /dev/null @@ -1,442 +0,0 @@ -From 3f8eade6150f582129332f6347e9a685f8a7b500 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Wed, 7 Feb 2024 10:23:38 -0700 -Subject: [PATCH 12/51] mb/dell: Add Latitude E5520 (Sandy Bridge) - -Mainboard is Krug 15". I do not physically have this system; someone -with physical access to one sent me the output of autoport which I then -modified to produce this port. I was also sent the VBT binary, which was -obtained from `/sys/kernel/debug/dri/0/i915_vbt` while running version -A14 of the vendor firmware. - -This was originally tested and found to be working as a standalone -board port in Libreboot, but this variant based port in upstream -coreboot has not been tested. - -This can be internally flashed by sending a command to the EC, which -causes the EC to pull the FDO pin low and the firmware to skip setting -up any chipset based write protections [1]. The EC is the SMSC MEC5055, -which seems to be compatible with the existing MEC5035 code. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: Ic9bfc028d4b8ae01ccc019157bb53e7764671134 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 10 +- - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e5520/data.vbt | Bin 0 -> 6144 bytes - .../variants/e5520/early_init.c | 14 ++ - .../snb_ivb_latitude/variants/e5520/gpio.c | 195 ++++++++++++++++++ - .../variants/e5520/hda_verb.c | 32 +++ - .../variants/e5520/overridetree.cb | 39 ++++ - 7 files changed, 292 insertions(+), 1 deletion(-) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5520/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5520/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5520/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5520/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5520/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index 72bdc96c0a..4e94a7ef80 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -17,6 +17,11 @@ config BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select SYSTEM_TYPE_LAPTOP - select USE_NATIVE_RAMINIT - -+config BOARD_DELL_LATITUDE_E5520 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_6144 -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ - config BOARD_DELL_LATITUDE_E6420 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_10240 -@@ -55,6 +60,7 @@ config MAINBOARD_DIR - default "dell/snb_ivb_latitude" - - config MAINBOARD_PART_NUMBER -+ default "Latitude E5520" if BOARD_DELL_LATITUDE_E5520 - default "Latitude E6420" if BOARD_DELL_LATITUDE_E6420 - default "Latitude E6520" if BOARD_DELL_LATITUDE_E6520 - default "Latitude E5530" if BOARD_DELL_LATITUDE_E5530 -@@ -68,6 +74,7 @@ config USBDEBUG_HCD_INDEX - default 2 - - config VARIANT_DIR -+ default "e5520" if BOARD_DELL_LATITUDE_E5520 - default "e6420" if BOARD_DELL_LATITUDE_E6420 - default "e6520" if BOARD_DELL_LATITUDE_E6520 - default "e5530" if BOARD_DELL_LATITUDE_E5530 -@@ -77,7 +84,8 @@ config VARIANT_DIR - config VGA_BIOS_ID - default "8086,0116" if BOARD_DELL_LATITUDE_E6520 - default "8086,0166" if BOARD_DELL_LATITUDE_E5530 -- default "8086,0126" if BOARD_DELL_LATITUDE_E6420 -+ default "8086,0126" if BOARD_DELL_LATITUDE_E6420 \ -+ || BOARD_DELL_LATITUDE_E5520 - default "8086,0166" if BOARD_DELL_LATITUDE_E6430 \ - || BOARD_DELL_LATITUDE_E6530 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index c7665ac263..7976691f21 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -1,5 +1,8 @@ - ## SPDX-License-Identifier: GPL-2.0-only - -+config BOARD_DELL_LATITUDE_E5520 -+ bool "Latitude E5520" -+ - config BOARD_DELL_LATITUDE_E6420 - bool "Latitude E6420" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5520/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..b511e75262e37fa123d674e9a7b21a8dfe427729 -GIT binary patch -literal 6144 -zcmeHKZ){Ul6hE);wSBvNZ|mL$bmQOM2BTvXUI!}^N9ejTij1vnu+)Wx6<c9(Y_%K6 -zzOV-@f<ehpWB5RHBpMBgG7}RuMuM2=l*E{6G$wq&gqTQ3#E2RZsOP@dvW*rP7>Fjj -z&F`Lj?>YC}bI(2Z+}C+6zKyiGrosQXuW7A+&1%<rN+Y1ck(}dLrx)Ma#^x>lnvFGE -zeD#gB>*#Tq4&j^|7Xcz1r^pp*)g#T}u1Me3ct>Pgls5Qi3!6e2W0%`a-Ic|3efWuR -zXJ@#}wJyGMTXTcY<%@TBKh@(3hP$Gjv}E}rx-%9D_eLXhYe!c&-VyDg-Cdo1>Biji -zNNsnlFW#|jdoOj?mZ43m>cVO%UE9@*E7x|%V~c4`XD4l9GCi~@+7pfMibfX8L?!^I -zc~Rg1I5SxH1DAEZ0{jA41jrJBh#-l;b6^%g7QrThRe)&%tQH_!ggOD7A_PRRgGuI0 -z0zi=n#rCB66d-sO$M~^6wgeb$2fH1|0R`v}xUiWCU`4SF;Dyh&j|mK&6WJWJ&Pq9I -zVgmFQfh+)vE}(KWwHA|Oh3fSkss|;2E(2i}s1?gRRV%8!K7U={vHD=s#+Fd)W^M1j -z{R4$??VSvEWpgT=vCM&1-U$bI6CB~IV3Z$$Vv7o!EDnev4j~R(MHsazZ~^fLLKGF4 -zEfQFOa3dZ?1Q1P#&4?!vyAk^k&m&$z3?WV+-b0*1j37o4=MX<3E+eiYge(Ht2umAW -zOPDmU>UL{flI9u|@JtVvfp#o8ek?VfVV9YP5(%pnZX~{PKq4WoWGmV8t$=Ri@{zLQ -zNYYt4<$0Ry&qIoG;7s-t333)Nu8opN{NG!)&!I@eO(cVx8vBVEBvotJ7%yNl$7iQ_ -zI=xk30+V$ff`F6<wRoF(TK%j9nsr#H23umU%)_7jNOl%*FPU567qbg;4gtp711nj2 -z#+kHw`v4|5cA+`UMIvAl;slnH1nl0v=xH<al>1}ljxDE1dcda^&!do|r^eJkI?aC- -zEQMSfm?<w*Unzumkj_w5>VYL6W4=aCiy4rk%xq~5LV?bi|GL2$G7li<%c7yd;6T34 -zQBN5huZ3~6`ChGkpb$Bg5ITb#2iK-qs|1`=sl6Dhn(Lj&8Agt?S{sTDmmtRj7Jm_1 -zFnt{w&FdFkWS3bl>OeL?eO+*i{)9G!cSI-InGt|U0eEYmRCOHm7|I;#LO8ksRIeJ# -zGe+jTwPg4C4TYuN(9zULV3k+hI$YuPo=%N8oZ#u_4S!3Xelt6N0BmuC`hCNeg+&97 -z6*!>)uHvr%2004GZv?!_-y&|TRmil=9D%Q`1aXBsnD^gov3*UZI34&1_vn(B=T4kZ -z_A>ClXVIBNaS^hd&^DrU6VgZMYeadMkdFxcktn|ra-Gl;n^I{bt86rCQ=YMry*B!$ -zP5ID9KDE)GZOY#^VwPyRq^y+48j0?ZlzxdkC()CV@`*&wO7vGr;qjA3rb}gIwM-gi -zx>HsT$mEDj-<OpyWb%zn|B@A3Hkp<!FT5;hrt_SZiy?*wDaIu{h>%Ir=@rh7)SR;b -zAEWQGv_X1)wq0y5Ha0c~&psIsln<Hiu3;#Lf;%*eI<@?p8cfMJV(IYi8q$NA#iS8` -z_~|4t4b^wtMSAeFST^F8-Tm<zu8D&j^8=&I4;I}Im>aeSK~X8*^Z9SE44_`P#KIUL -zf6^N2f>5HCPWM3N+f0MyWOV^kz~!-wVc4MRXOY>4Jsxd1RyBKEMzNf{RKhesKFdbq -zJ(*d<l2Y#n?E?~iBA39P?~Pr2d#}5=#Sfl-VGzGUF$4U2KcqCIVlwkC(&7PQk_X!a -z8}3Jgq-&U*Co|h1>l)ZQGyW_x->i#;FvQ*=Nv&nG0N5@D@jjv_Q}K}6MP?1A6`JGe -zDwj9pN+x;T4>`I9e5x(uqdK#OGB31ikk@Xv=dxLb4fx(;ktX@rOb~M~?dYQQYiPia -z8r;jUQ?sd2@3||-cb2Eb%JFYfxHsONoaJ^eqoKN{<g9?-%`7oWz+aJS0tEc!^d@hD -z1-I{%hr!Y?0uVZpUbl__37xn@jkD6Z>3SATgBQlEoN7&ZV9Eni9+>jLln16fFy(=V -H=7E0zE^L4Z - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5520/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/early_init.c -new file mode 100644 -index 0000000000..ff83db095b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/early_init.c -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5520/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/gpio.c -new file mode 100644 -index 0000000000..f76b93d9f0 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/gpio.c -@@ -0,0 +1,195 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+static const struct pch_gpio_set1 pch_gpio_set1_mode = { -+ .gpio0 = GPIO_MODE_GPIO, -+ .gpio1 = GPIO_MODE_NATIVE, -+ .gpio2 = GPIO_MODE_GPIO, -+ .gpio3 = GPIO_MODE_GPIO, -+ .gpio4 = GPIO_MODE_GPIO, -+ .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_GPIO, -+ .gpio15 = GPIO_MODE_GPIO, -+ .gpio16 = GPIO_MODE_NATIVE, -+ .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_GPIO, -+ .gpio31 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_direction = { -+ .gpio0 = GPIO_DIR_INPUT, -+ .gpio2 = GPIO_DIR_INPUT, -+ .gpio3 = GPIO_DIR_INPUT, -+ .gpio4 = GPIO_DIR_INPUT, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio12 = GPIO_DIR_OUTPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_INPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+ .gpio30 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio12 = GPIO_LEVEL_HIGH, -+ .gpio30 = GPIO_LEVEL_HIGH, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_NATIVE, -+ .gpio50 = GPIO_MODE_GPIO, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_GPIO, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_GPIO, -+ .gpio56 = GPIO_MODE_GPIO, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_OUTPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio46 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio50 = GPIO_DIR_OUTPUT, -+ .gpio51 = GPIO_DIR_OUTPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio53 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio55 = GPIO_DIR_OUTPUT, -+ .gpio56 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_LOW, -+ .gpio37 = GPIO_LEVEL_LOW, -+ .gpio46 = GPIO_LEVEL_HIGH, -+ .gpio50 = GPIO_LEVEL_HIGH, -+ .gpio51 = GPIO_LEVEL_LOW, -+ .gpio55 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_NATIVE, -+ .gpio69 = GPIO_MODE_NATIVE, -+ .gpio70 = GPIO_MODE_NATIVE, -+ .gpio71 = GPIO_MODE_NATIVE, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .gpio73 = GPIO_MODE_NATIVE, -+ .gpio74 = GPIO_MODE_GPIO, -+ .gpio75 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set3 pch_gpio_set3_direction = { -+ .gpio74 = 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/dell/snb_ivb_latitude/variants/e5520/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/hda_verb.c -new file mode 100644 -index 0000000000..1373975352 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76e7, /* Codec Vendor / Device ID: IDT */ -+ 0x1028049a, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x1028049a), -+ AZALIA_PIN_CFG(0, 0x0a, 0x04a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0421101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0xd5a301a0), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x400000f0), -+ -+ 0x80862805, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5520/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/overridetree.cb -new file mode 100644 -index 0000000000..479d1b696e ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5520/overridetree.cb -@@ -0,0 +1,39 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x049a inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x00000218" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 0, 0, 0, 1, 0 }" -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 1, 0 }, -+ { 1, 1, 1 }, -+ { 1, 1, 1 }, -+ { 1, 1, 2 }, -+ { 1, 1, 2 }, -+ { 1, 1, 3 }, -+ { 1, 1, 3 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 1, 7 }, -+ { 1, 1, 6 }, -+ { 1, 1, 6 }, -+ { 1, 1, 7 }, -+ }" -+ -+ device ref gbe off end -+ device ref pcie_rp4 off end -+ device ref pcie_rp7 on end # Broadcom BCM5761 Gigabit Ethernet -+ device ref sata1 on -+ register "sata_port_map" = "0x3b" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0013-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch b/config/coreboot/default/patches/0013-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch deleted file mode 100644 index 5944535f..00000000 --- a/config/coreboot/default/patches/0013-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch +++ /dev/null @@ -1,442 +0,0 @@ -From bbcd6a7f09ee99f3b26b0931f1dcd70970242ee8 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Mon, 4 Mar 2024 18:05:43 -0700 -Subject: [PATCH 13/51] mb/dell: Add Latitude E5420 (Sandy Bridge) - -Mainboard is Krug 14". I do not physically have this system; someone -with physical access to one sent me the output of autoport which I then -modified to produce this port. I was also sent the VBT binary, which was -obtained from `/sys/kernel/debug/dri/0/i915_vbt` while running version -A02 of the vendor firmware. - -This was originally tested and found to be working as a standalone board -port in Libreboot, but this variant based port in upstream coreboot has -not been tested. - -This can be internally flashed by sending a command to the EC, which -causes the EC to pull the FDO pin low and the firmware to skip setting -up any chipset based write protections [1]. The EC is the SMSC MEC5055, -which seems to be compatible with the existing MEC5035 code. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: I0283653156083768e1fd451bcf539b4e028589f4 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 10 +- - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e5420/data.vbt | Bin 0 -> 6144 bytes - .../variants/e5420/early_init.c | 14 ++ - .../snb_ivb_latitude/variants/e5420/gpio.c | 195 ++++++++++++++++++ - .../variants/e5420/hda_verb.c | 32 +++ - .../variants/e5420/overridetree.cb | 39 ++++ - 7 files changed, 292 insertions(+), 1 deletion(-) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5420/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5420/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5420/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5420/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e5420/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index 4e94a7ef80..e6a21ffb99 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -17,6 +17,11 @@ config BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select SYSTEM_TYPE_LAPTOP - select USE_NATIVE_RAMINIT - -+config BOARD_DELL_LATITUDE_E5420 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_6144 -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ - config BOARD_DELL_LATITUDE_E5520 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_6144 -@@ -60,6 +65,7 @@ config MAINBOARD_DIR - default "dell/snb_ivb_latitude" - - config MAINBOARD_PART_NUMBER -+ default "Latitude E5420" if BOARD_DELL_LATITUDE_E5420 - default "Latitude E5520" if BOARD_DELL_LATITUDE_E5520 - default "Latitude E6420" if BOARD_DELL_LATITUDE_E6420 - default "Latitude E6520" if BOARD_DELL_LATITUDE_E6520 -@@ -74,6 +80,7 @@ config USBDEBUG_HCD_INDEX - default 2 - - config VARIANT_DIR -+ default "e5420" if BOARD_DELL_LATITUDE_E5420 - default "e5520" if BOARD_DELL_LATITUDE_E5520 - default "e6420" if BOARD_DELL_LATITUDE_E6420 - default "e6520" if BOARD_DELL_LATITUDE_E6520 -@@ -82,7 +89,8 @@ config VARIANT_DIR - default "e6530" if BOARD_DELL_LATITUDE_E6530 - - config VGA_BIOS_ID -- default "8086,0116" if BOARD_DELL_LATITUDE_E6520 -+ default "8086,0116" if BOARD_DELL_LATITUDE_E6520 \ -+ || BOARD_DELL_LATITUDE_E5420 - default "8086,0166" if BOARD_DELL_LATITUDE_E5530 - default "8086,0126" if BOARD_DELL_LATITUDE_E6420 \ - || BOARD_DELL_LATITUDE_E5520 -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index 7976691f21..a3fa2b1837 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -1,5 +1,8 @@ - ## SPDX-License-Identifier: GPL-2.0-only - -+config BOARD_DELL_LATITUDE_E5420 -+ bool "Latitude E5420" -+ - config BOARD_DELL_LATITUDE_E5520 - bool "Latitude E5520" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5420/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..98b82fe6110fd295b5749041ec7f8c084ace5f57 -GIT binary patch -literal 6144 -zcmeHKeQZ-z6hE);wSBvNZ!2$ObQ^;MgV6zl*Rhp}BXnCCMZU^_r7jRwT!kfLo8?3H -zk9)u(7?cb(hChhTM57@QFfmbMB!G!dNsO6BW5OSp5EGF^jHnTTdhUBI+h`e+1ft1q -z^SfW?+;h)4_uO+|XEfEV$91)<gOArWE)OnSTD}Ug6?8a~vz+SmQn!4~y3N7b^|hPp -zR<5aEfv-b8M00Lk251!oO|8(YA6XaeXzkt-Z)@Ee!_{@z#Fro^?DqN4SGjRIu8KYp -zZEufuU@5MM@7jv%h;75FS}ezKv?JDzCH}d%tE)A-GuDb*+B%}~w%88r>}c;!*XQ5O -z)OU7u$J@4U+lk)#GSW%c%c)v`%R6?`w)LIyu6bD7-j0o&X9qUMcEsYlW3BU4rZRvt -zqAUpjf*qXuLCCsU0YM2I5@gB1WKd)f1+Yt?%HWd0DZxYumP(K<LxTif8A39+!KMl} -z31FHG)7?qk5g>e?=ER{f^&}W<0k@mxff(?6+Stw+s6y%k1mM$cLk#^FWWI*9bE1GY -z&VY9?WC1u#23^3^UYw5?H0x2S2gN`x18Fko6_x(#MKyuCU_<D!mEp$qO_An}#@>DV -zdkf*li41yW3p$*0Oo3+63kO6S91*KwP#l2i4jnc)JkUirL^$k}VbH0;CBh#BS=OLf -zW-yE3BRon75gG{_2~QIC5cUzCC%i)FCmbidM>tIwAPf>N5Pl?FC0r*+Sq!oXj!keQ -zVKcyK>TL+gc7oLco$28+FpeeXkEP}_Sea=mk#IWUR^m$!BogvszLPu83FJm0k6K<l -z$#$~YiXtY*GpHp#@FvHJ1UnBD*H%d+{_j24XE4nmBa*?5mOWiold28s3}>*}<HaeO -z+1|-8g2)FCfkDZIdb-Ub);z0#;XEbPfGe?A72!{DAUg|$m+Z~(i@h9j4gtm611ni( -z#u>ACcP}M4exU`*MKVwl5+t6JBpTkmm}xWflKUe~7}`!#%z#gAo{NxUrpDAndYktu -zI0}VLU`J7^xmF1AFiz5S^uzp*DPI$%$qq!(ikh0kP+(GKzF|@N?Y%_#Vp@M+xHr$F -z=%+18z`-fT%z)9-TS$~Dh@2yeN7!UIt0h`fWxUu`JvA_ra*8P48l%7KR0&c1;0R75 -z4f0oz(xQ3MWqz5>qW5M4tZWExHs8<H(e1G@4km@5wEzOOP^x<l`YmA|eKs6j3wl8B -z%C%;uygh%<#kGZ{fymL+OlV0!-*T!V5IB>X@p!@CBU=7e{5^Jl{s7by`po-AJqM2l -znk(=^0bHkF0rUw7)^7j;$=_UIs8`6P6b-;vPDZ#U9L)W1_PAYRDP9k~;5$stt5ZiV -zD0>;i-?OlYY2}P9WVnfGos4xee2r=EGWHR}ADH$VV>cO=xU?!4TjIi)OMBYI_PX#b -zm-eBHed5BOT-x6*W>;{IqAga~G6lCQT93k>Q}CpsomJR*1%FjEkv?fuT%c-8RklXO -zU8;6KWk*zeU)4TW+1D!mrE0EhHZfbBeN{4S7X@Pig%};A99QTdA~wZruL*8y?K!jP -zG5R*k=);S}Zn<T;W!Mxt`(!+z7_r@3LVpf|FESauM&4}+wqzXfba-zG>A}on(uzNF -zyu>BcjA})C@bg%<;+Eh2;Sz4heFFCbZ@C{FrXMIbYzu>?Bi-|vZ}JSFU%JA>7$7et -z0Yo%CnOVZm#ZA}4kWZOn15};h5*#OM3b+6vHzgruMP>=5MNJK1y42{YgveP-!j%#( -z0rGe@8t%!=66Ti%K4|Gx=o7gFp83wQ;+s3H7+r^SKlpp3KKcr!3@|n;NCH_=qL=3T -zq3WH?en`b+W-HR-fnrhw*9aZ%M}lHX7@H?E>!6wv_&YQFEHdA$%Z1R--yub>=c@p? -z6@7Fc$&>sAxwiz{BE$1kb$K9Co=ozlA973y^i(^BM|EZ$$^y`0KyHiMJ%O*XbfEX1 -ziZaH>W(1pWL0bo|T!x__N$^$DpmxI=bL6WUK3JGyn?rw-qC4ZA$yGjIB}N(=ldD2O -zAJ@bxp<qR-3lIv<!P~SE8r*#_Ckl?$0|1fZ>2>n}u*mUIYFd>}O_wuwBD^r9<#=!0 -X1LGbT_rSOZ#yv3ZfpHH!G!Og(1Xg~J - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5420/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/early_init.c -new file mode 100644 -index 0000000000..ff83db095b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/early_init.c -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5420/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/gpio.c -new file mode 100644 -index 0000000000..f76b93d9f0 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/gpio.c -@@ -0,0 +1,195 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+static const struct pch_gpio_set1 pch_gpio_set1_mode = { -+ .gpio0 = GPIO_MODE_GPIO, -+ .gpio1 = GPIO_MODE_NATIVE, -+ .gpio2 = GPIO_MODE_GPIO, -+ .gpio3 = GPIO_MODE_GPIO, -+ .gpio4 = GPIO_MODE_GPIO, -+ .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_GPIO, -+ .gpio15 = GPIO_MODE_GPIO, -+ .gpio16 = GPIO_MODE_NATIVE, -+ .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_GPIO, -+ .gpio31 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_direction = { -+ .gpio0 = GPIO_DIR_INPUT, -+ .gpio2 = GPIO_DIR_INPUT, -+ .gpio3 = GPIO_DIR_INPUT, -+ .gpio4 = GPIO_DIR_INPUT, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio12 = GPIO_DIR_OUTPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_INPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+ .gpio30 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio12 = GPIO_LEVEL_HIGH, -+ .gpio30 = GPIO_LEVEL_HIGH, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_NATIVE, -+ .gpio50 = GPIO_MODE_GPIO, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_GPIO, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_GPIO, -+ .gpio56 = GPIO_MODE_GPIO, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_OUTPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio46 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio50 = GPIO_DIR_OUTPUT, -+ .gpio51 = GPIO_DIR_OUTPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio53 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio55 = GPIO_DIR_OUTPUT, -+ .gpio56 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_LOW, -+ .gpio37 = GPIO_LEVEL_LOW, -+ .gpio46 = GPIO_LEVEL_HIGH, -+ .gpio50 = GPIO_LEVEL_HIGH, -+ .gpio51 = GPIO_LEVEL_LOW, -+ .gpio55 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_NATIVE, -+ .gpio69 = GPIO_MODE_NATIVE, -+ .gpio70 = GPIO_MODE_NATIVE, -+ .gpio71 = GPIO_MODE_NATIVE, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .gpio73 = GPIO_MODE_NATIVE, -+ .gpio74 = GPIO_MODE_GPIO, -+ .gpio75 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set3 pch_gpio_set3_direction = { -+ .gpio74 = 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/dell/snb_ivb_latitude/variants/e5420/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/hda_verb.c -new file mode 100644 -index 0000000000..0bc6c35a63 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76e7, /* Codec Vendor / Device ID: IDT */ -+ 0x1028049b, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x1028049b), -+ AZALIA_PIN_CFG(0, 0x0a, 0x04a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0421101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0xd5a30130), -+ -+ 0x80862805, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e5420/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/overridetree.cb -new file mode 100644 -index 0000000000..3f55bfd49d ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e5420/overridetree.cb -@@ -0,0 +1,39 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x049b inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x00000c31" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 0, 0, 0, 1, 0 }" -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 1, 0 }, -+ { 1, 1, 1 }, -+ { 1, 1, 1 }, -+ { 1, 1, 2 }, -+ { 1, 1, 2 }, -+ { 1, 1, 3 }, -+ { 1, 1, 3 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 1, 7 }, -+ { 1, 1, 6 }, -+ { 1, 1, 6 }, -+ { 1, 1, 7 }, -+ }" -+ -+ device ref gbe off end -+ device ref pcie_rp4 off end -+ device ref pcie_rp7 on end # Broadcom BCM5761 Gigabit Ethernet -+ device ref sata1 on -+ register "sata_port_map" = "0x3b" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0023-nb-haswell-Fully-disable-iGPU-when-dGPU-is-used.patch b/config/coreboot/default/patches/0013-nb-haswell-Fully-disable-iGPU-when-dGPU-is-used.patch index f9d80b9f..89584d95 100644 --- a/config/coreboot/default/patches/0023-nb-haswell-Fully-disable-iGPU-when-dGPU-is-used.patch +++ b/config/coreboot/default/patches/0013-nb-haswell-Fully-disable-iGPU-when-dGPU-is-used.patch @@ -1,7 +1,7 @@ -From d86824305f11bc684f1e91e3826158b8c7d7e0ee Mon Sep 17 00:00:00 2001 +From c8329f84b2d06581dcbeecedc38b7c4715a9cba7 Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sat, 6 Apr 2024 01:22:47 +0100 -Subject: [PATCH 23/51] nb/haswell: Fully disable iGPU when dGPU is used +Subject: [PATCH 13/37] nb/haswell: Fully disable iGPU when dGPU is used My earlier patch disabled decode *and* disabled the iGPU itself, but a subsequent revision disabled only VGA decode. Upon revisiting, I diff --git a/config/coreboot/default/patches/0025-ec-dell-mec5035-Add-S3-suspend-SMI-handler.patch b/config/coreboot/default/patches/0014-ec-dell-mec5035-Add-S3-suspend-SMI-handler.patch index ed620a3e..70556090 100644 --- a/config/coreboot/default/patches/0025-ec-dell-mec5035-Add-S3-suspend-SMI-handler.patch +++ b/config/coreboot/default/patches/0014-ec-dell-mec5035-Add-S3-suspend-SMI-handler.patch @@ -1,7 +1,7 @@ -From 2fdd5bbb2bbec76c3c2238c4cd471b9b63073942 Mon Sep 17 00:00:00 2001 +From 73dbf291631fdbae2d8e8a761c147523c8d9e65c Mon Sep 17 00:00:00 2001 From: Nicholas Chin <nic.c3.14@gmail.com> Date: Fri, 3 May 2024 11:03:32 -0600 -Subject: [PATCH 25/51] ec/dell/mec5035: Add S3 suspend SMI handler +Subject: [PATCH 14/37] ec/dell/mec5035: Add S3 suspend SMI handler This is necessary for S3 resume to work on SNB and newer Dell Latitude laptops. If a command isn't sent, the EC cuts power to the DIMMs, diff --git a/config/coreboot/default/patches/0014-mb-dell-Add-Latitude-E6320-Sandy-Bridge.patch b/config/coreboot/default/patches/0014-mb-dell-Add-Latitude-E6320-Sandy-Bridge.patch deleted file mode 100644 index e8c46203..00000000 --- a/config/coreboot/default/patches/0014-mb-dell-Add-Latitude-E6320-Sandy-Bridge.patch +++ /dev/null @@ -1,435 +0,0 @@ -From cd6e699649459fa5ff2623018ccf3585eb3d3821 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Wed, 7 Feb 2024 15:23:46 -0700 -Subject: [PATCH 14/51] mb/dell: Add Latitude E6320 (Sandy Bridge) - -Mainboard is PAL70/LA-6611P. I do not physically have this system; -someone with physical access to one sent me the output of autoport which -I then modified to produce this port. I was also sent the VBT binary, -which was obtained from `/sys/kernel/debug/dri/0/i915_vbt` while running -version A22 of the vendor firmware. This port has not been tested. - -The EC is the SMSC MEC5055, which seems to be compatible with the -existing MEC5035 code. As with the other Dell systems with this EC, this -board is assumed to be internally flashable using an EC command that -tells it to pull the FDO pin low on the next boot, which also tells the -vendor firmware to disable all write protections to the flash [1]. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: I5905f8c6a8dbad56e03bdeedc2179600d0c4ba46 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 11 +- - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e6320/data.vbt | Bin 0 -> 6144 bytes - .../variants/e6320/early_init.c | 17 ++ - .../snb_ivb_latitude/variants/e6320/gpio.c | 190 ++++++++++++++++++ - .../variants/e6320/hda_verb.c | 32 +++ - .../variants/e6320/overridetree.cb | 35 ++++ - 7 files changed, 287 insertions(+), 1 deletion(-) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6320/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6320/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6320/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6320/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6320/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index e6a21ffb99..84ffe1d33a 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -27,6 +27,12 @@ config BOARD_DELL_LATITUDE_E5520 - select BOARD_ROMSIZE_KB_6144 - select SOUTHBRIDGE_INTEL_BD82X6X - -+config BOARD_DELL_LATITUDE_E6320 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_10240 -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ - config BOARD_DELL_LATITUDE_E6420 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_10240 -@@ -67,6 +73,7 @@ config MAINBOARD_DIR - config MAINBOARD_PART_NUMBER - default "Latitude E5420" if BOARD_DELL_LATITUDE_E5420 - default "Latitude E5520" if BOARD_DELL_LATITUDE_E5520 -+ default "Latitude E6320" if BOARD_DELL_LATITUDE_E6320 - default "Latitude E6420" if BOARD_DELL_LATITUDE_E6420 - default "Latitude E6520" if BOARD_DELL_LATITUDE_E6520 - default "Latitude E5530" if BOARD_DELL_LATITUDE_E5530 -@@ -82,6 +89,7 @@ config USBDEBUG_HCD_INDEX - config VARIANT_DIR - default "e5420" if BOARD_DELL_LATITUDE_E5420 - default "e5520" if BOARD_DELL_LATITUDE_E5520 -+ default "e6320" if BOARD_DELL_LATITUDE_E6320 - default "e6420" if BOARD_DELL_LATITUDE_E6420 - default "e6520" if BOARD_DELL_LATITUDE_E6520 - default "e5530" if BOARD_DELL_LATITUDE_E5530 -@@ -93,7 +101,8 @@ config VGA_BIOS_ID - || BOARD_DELL_LATITUDE_E5420 - default "8086,0166" if BOARD_DELL_LATITUDE_E5530 - default "8086,0126" if BOARD_DELL_LATITUDE_E6420 \ -- || BOARD_DELL_LATITUDE_E5520 -+ || BOARD_DELL_LATITUDE_E5520 \ -+ || BOARD_DELL_LATITUDE_E6320 - default "8086,0166" if BOARD_DELL_LATITUDE_E6430 \ - || BOARD_DELL_LATITUDE_E6530 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index a3fa2b1837..ef6a1329a9 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -6,6 +6,9 @@ config BOARD_DELL_LATITUDE_E5420 - config BOARD_DELL_LATITUDE_E5520 - bool "Latitude E5520" - -+config BOARD_DELL_LATITUDE_E6320 -+ bool "Latitude E6320" -+ - config BOARD_DELL_LATITUDE_E6420 - bool "Latitude E6420" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6320/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..471a9e29da639dd496f3ecebd5d0754a9045c00b -GIT binary patch -literal 6144 -zcmeHKeP|p-6#wn*-rZ(yH@R-odPzTgZEU>S#_pv}j2iKhT+^%8_DtJw21|4GP8*0x -zyw;EYW49Xozz<Rt@ek1mic(N32r8oZ0U9lcR8a)~s33wLV8yCftLK~DJJWb)8w-j; -z=J?H<nfK<+n>TOX?48xuwV5_`Zb)3w)w?dSc1`nTL|NF_SMw&<<)v%g#!cH2otrzi -zb*<mneJMSLdC1iK_7#v-6w7R}+t1&W8P4wBo*&F!lcNn?)F-EqWZV#oQEb%`x-4^5 -zW@sogOik1`n9Wc#r82|0A!=-0LD!FFGrMwG+CDg($q(js(#Y`8?s79ubEJD@ba#I6 -znjO0++P#czvh8NBR?)iQUA%txNPhHO>Kq!PUMaJadUHE-`5SWCb4_6i;5Aj(6hQGK -zcq^2uUt5sS5YSMiL+CJcs0#cVOdTN|K@D>?tkF=dqenwjM^Z-^K2z~&z+xRs!o^Jx -zkUGd?>QtXw8V(I09OiMb0DZy>`=tO^#BCssw{}bkOnj=#Ic!~!6!J*{`jbEv5O4)- -zg-UBlIa$c9Pg4C;0_-wq3t+dbZfn1wBi@zhNnWx()w{Vb-G8OC_m*478gTrX3U*a1 -zHr@y<Lcbct?Wzy^)OH+FC$S`8V@n`{QN~@2dxJU-1ucBe_>rOO78dFPXES1q3mHj9 -zFXKwa)r^}Mw=nKzJjj?}>}NdBc$G29IK=pr@de`u;}}D$5~yYbw&Hlf=OF0X?I=Y$ -z$D`mgy>}U$hl}G6m&PmXveHnY5DenC!g~=E3i?HIrEpyk>_(-IsVtEqUEoqxrDFdq -zrYwhOv0o^NgW$OKN}=$7Z-w5*Vuv?T3~uuFGwP92?Qr8n0iQp=u*7rep9Q8dW#?ZI -zFly1ww^^l*+YC6t16l_{g}tVVpVZ0fDk%5+`|+*688vr-<Lw_SRc^+avHI{BCpdYb -z70yLEI0-45%t;z||GKzov+|VFW6hab&NAG9FD+h6sBu$cX`r0eJ%T`kvK4+(wT`0= -z$fxKG+om?Ge1-EhbNc*Xjy1opKZSaiv-EL~GvOa&&bx~z##3W;F2{b=<HQ4!<1CFk -z17i)$X+`=C=0udOPOx3$IjzopqwQzLr*jT4C)(jmj2>uYP8$M=#caX6OWA1Ez395U -z%x<yAs)6-Ascr5<x*>CIZibyRlE~I0-ianVaz~q|EMlL7hc1U5w?}Kekws6fyy@`e -z4NdX%L#2`A#c_N4ftGmuwbDo=incwf=WnBJk6)fYz%6Cmy>HwK$Y|iP`Y7sgjDPhQ -zR|wv367k}1g)-G@kXq(X;{Bjt998b9{cpD9zGhOQ5%$4OSMtc2(<dx@0O}7_G+$WF -zLYyaPtFT6d*e&Q$VLd0r%Yr@=*7rjEDyT7JwT8sSA<BiU8$)7mh@K2tFNMULA^I|8 -z{Sp#>gO(fCMTS^w(6xrO#}IcK^sHgMZis^heP>uIf6|z=%Cy#)Vxvjdo7U~7*k{rU -zruB{~J}~KL(+X9Kxz*-5M>NNGSaIfXi19({d4mrk?K50@R0%Wn*PP9d(MMIzI2~RX -z)(4h&8(YL@UyKJ*)4o${n5ZGd(hDf+)cv8sSBxWen|f*u<-sgt(u+U-bkd}Tj+5@9 -zJosfSdvPo8zGnluemJg=E7A{=N<Rc#KYYEg?^p`+_?~aU(kEmFus{DshA~iA(onLY -zvIfpBJt;KWP4n8&`n1##c($WnDo|=?rlHBz&}36&HPWwp8op_i8c-**(TSd{Y{SZ? -z_=^K$27e+q;^vRNU3~a=cd;V{%O=iuo*&xwXyg19${Ap0yO@a|N-<e^7iIClF{vUn -z&4$y_V7MA)=E=%7n63u!J9FY$RK8hXHDE%%Lx$ZgX902-<9r|4lkx>QwFch>PUO1w -z=6JffnB-kQ)VLb>sSZdDrI@U2!?HLA9Mlek!*k>;&jx<)xfnBiY^I6DRt*l*`n8ly -zu!h)b?sRV1==Nf*Cw9&&i7n^9Nts>wk>adaY&E5OdW*A?iI}v+E6GGlsR<+#%jpl^ -zGz<Q^vpj>qhDjj3zr60Bgh=l{NzJp$x#fCR%*8!ZR?fC&JuvHmSr5#5VAcb(9+>sO -IzvhA80TAzedH?_b - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6320/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/early_init.c -new file mode 100644 -index 0000000000..b0c4638858 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/early_init.c -@@ -0,0 +1,17 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+const struct southbridge_usb_port mainboard_usb_ports[] = { -+}; -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6320/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/gpio.c -new file mode 100644 -index 0000000000..61f01816c4 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/gpio.c -@@ -0,0 +1,190 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+static const struct pch_gpio_set1 pch_gpio_set1_mode = { -+ .gpio0 = GPIO_MODE_GPIO, -+ .gpio1 = GPIO_MODE_NATIVE, -+ .gpio2 = GPIO_MODE_GPIO, -+ .gpio3 = GPIO_MODE_NATIVE, -+ .gpio4 = GPIO_MODE_GPIO, -+ .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_NATIVE, -+ .gpio13 = GPIO_MODE_GPIO, -+ .gpio14 = GPIO_MODE_GPIO, -+ .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_GPIO, -+ .gpio31 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_direction = { -+ .gpio0 = GPIO_DIR_INPUT, -+ .gpio2 = GPIO_DIR_INPUT, -+ .gpio4 = GPIO_DIR_INPUT, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio16 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_INPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+ .gpio30 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio30 = GPIO_LEVEL_HIGH, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio46 = GPIO_MODE_NATIVE, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .gpio50 = GPIO_MODE_NATIVE, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_NATIVE, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_NATIVE, -+ .gpio56 = GPIO_MODE_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_OUTPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_HIGH, -+ .gpio45 = GPIO_LEVEL_LOW, -+ .gpio49 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_GPIO, -+ .gpio71 = GPIO_MODE_GPIO, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .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, -+ .gpio70 = GPIO_DIR_INPUT, -+ .gpio71 = 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/dell/snb_ivb_latitude/variants/e6320/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/hda_verb.c -new file mode 100644 -index 0000000000..2e3f7fa697 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76e7, /* Codec Vendor / Device ID: IDT */ -+ 0x10280492, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x10280492), -+ AZALIA_PIN_CFG(0, 0x0a, 0x03a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0321101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0xd5a30130), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x400000f0), -+ -+ 0x80862805, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6320/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/overridetree.cb -new file mode 100644 -index 0000000000..3bfe6b57ed ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6320/overridetree.cb -@@ -0,0 +1,35 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x0492 inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x00000622" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 0, 0 }, -+ { 1, 1, 1 }, -+ { 1, 0, 1 }, -+ { 1, 1, 2 }, -+ { 1, 1, 2 }, -+ { 1, 1, 3 }, -+ { 1, 1, 3 }, -+ { 1, 0, 5 }, -+ { 1, 0, 5 }, -+ { 1, 1, 7 }, -+ { 1, 1, 6 }, -+ { 1, 0, 6 }, -+ { 1, 0, 7 }, -+ }" -+ -+ device ref sata1 on -+ register "sata_port_map" = "0x3b" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0015-mb-dell-Add-Latitude-E6220-Sandy-Bridge.patch b/config/coreboot/default/patches/0015-mb-dell-Add-Latitude-E6220-Sandy-Bridge.patch deleted file mode 100644 index e2be42c9..00000000 --- a/config/coreboot/default/patches/0015-mb-dell-Add-Latitude-E6220-Sandy-Bridge.patch +++ /dev/null @@ -1,438 +0,0 @@ -From a32431d5f7574ffa6391221c7740f1739203eaa7 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Fri, 8 Mar 2024 09:27:36 -0700 -Subject: [PATCH 15/51] mb/dell: Add Latitude E6220 (Sandy Bridge) - -Mainboard is codenamed Vida. I do not physically have this system; -someone with physical access to one sent me the output of autoport which -I then modified to produce this port. The VBT was obtained using -intelvbttool while running version A14 (latest available version) of the -vendor firmware. - -Tested and found to boot as part of a libreboot build based on upstream -coreboot commit b7341da191 with additional patches, though these do not -appear to affect SNB/IVB. The base E6430 patch was tested against -coreboot main. - -The EC is the SMSC MEC5055, which seems to be compatible with the -existing MEC5035 code. As with the other Dell systems with this EC, this -board is assumed to be internally flashable using an EC command that -tells it to pull the FDO pin low on the next boot, which also tells the -vendor firmware to disable all write protections to the flash [1]. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: I570023b0837521b75aac6d5652c74030c06b8a4c -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 9 + - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e6220/data.vbt | Bin 0 -> 3985 bytes - .../variants/e6220/early_init.c | 14 ++ - .../snb_ivb_latitude/variants/e6220/gpio.c | 192 ++++++++++++++++++ - .../variants/e6220/hda_verb.c | 32 +++ - .../variants/e6220/overridetree.cb | 37 ++++ - 7 files changed, 287 insertions(+) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6220/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6220/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6220/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6220/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6220/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index 84ffe1d33a..baa83baa41 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -27,6 +27,12 @@ config BOARD_DELL_LATITUDE_E5520 - select BOARD_ROMSIZE_KB_6144 - select SOUTHBRIDGE_INTEL_BD82X6X - -+config BOARD_DELL_LATITUDE_E6220 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_10240 -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ - config BOARD_DELL_LATITUDE_E6320 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_10240 -@@ -73,6 +79,7 @@ config MAINBOARD_DIR - config MAINBOARD_PART_NUMBER - default "Latitude E5420" if BOARD_DELL_LATITUDE_E5420 - default "Latitude E5520" if BOARD_DELL_LATITUDE_E5520 -+ default "Latitude E6220" if BOARD_DELL_LATITUDE_E6220 - default "Latitude E6320" if BOARD_DELL_LATITUDE_E6320 - default "Latitude E6420" if BOARD_DELL_LATITUDE_E6420 - default "Latitude E6520" if BOARD_DELL_LATITUDE_E6520 -@@ -89,6 +96,7 @@ config USBDEBUG_HCD_INDEX - config VARIANT_DIR - default "e5420" if BOARD_DELL_LATITUDE_E5420 - default "e5520" if BOARD_DELL_LATITUDE_E5520 -+ default "e6220" if BOARD_DELL_LATITUDE_E6220 - default "e6320" if BOARD_DELL_LATITUDE_E6320 - default "e6420" if BOARD_DELL_LATITUDE_E6420 - default "e6520" if BOARD_DELL_LATITUDE_E6520 -@@ -102,6 +110,7 @@ config VGA_BIOS_ID - default "8086,0166" if BOARD_DELL_LATITUDE_E5530 - default "8086,0126" if BOARD_DELL_LATITUDE_E6420 \ - || BOARD_DELL_LATITUDE_E5520 \ -+ || BOARD_DELL_LATITUDE_E6220 \ - || BOARD_DELL_LATITUDE_E6320 - default "8086,0166" if BOARD_DELL_LATITUDE_E6430 \ - || BOARD_DELL_LATITUDE_E6530 -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index ef6a1329a9..349ee7f79e 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -6,6 +6,9 @@ config BOARD_DELL_LATITUDE_E5420 - config BOARD_DELL_LATITUDE_E5520 - bool "Latitude E5520" - -+config BOARD_DELL_LATITUDE_E6220 -+ bool "Latitude E6220" -+ - config BOARD_DELL_LATITUDE_E6320 - bool "Latitude E6320" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6220/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..548075a74500b5d159108089ee29cff802d07db7 -GIT binary patch -literal 3985 -zcmdT{eP|p-6#wn*-rZ(yH@R-odPzTgZQ6LXjonL|7&YQ0xu#d`$C=h}21|4GP8*0x -zyjE@hv0Dv(P?c0g{G(_DMJZ@22r8oZ0U9lcR8a)~s33wOSg|T<^?b8?XBzL?#)6`A -z{N~Nfd-LYan>TOv7WZ{+rcIq264!S1u1&02-MpSC3mf}u-r~BvbgkXEX=|c$bLZBs -zbsM{{q9-s1nVR3f2C|A`nJsqvC7UwC+1=angV`H%w4sao<P?&OTVpYbtz1OwGuLN^ -zhBCv{M16zV3^h|KGn^Zu#@6L@%V;*UGnb`pgTtBpU~UJE3=i!tH{%>fx<^KL=Lc`x -zzLTQeOW7vdZsuwwtsUOU>vxajM=zqzp&{y(GCQa@w<DLoHJ81}6s7=PS9MJR6hDG@ -zLaF+#1qlrS4OKdX4nv2kz^}p75z-OVFk8cF4b?h&G(>eIb%fzF6`uwy)UhaB+ynus -zBRr-~^|__t=m5fD9tR81r@XLV3UEc-2I6>o`;@@MXS$rj)&)r+pA?|K2vh+9SHM=N -zw3d{Uh1~iK)juV`E`v4?cFU@^_DehBU5TFLmFrTyoBPuJ*ExIdxO1!lC!eceSG8i} -z&A<Zmt5Mvo`mkSZ$5C|>ivl*T2}Cf;*vEJvsN-nR!WWDm8M<y^zAkV9BgVLlk!18T -zu4CN5*u}VmaUbIm#suRa;|0cRj7i2(#%GK#8OIsFFtjRxYDQoSP8NI)g09_;Qlzsy -z3O>^Zmcltu96wMRudvHXLxn;xh~EqEM^Gr}m&=vHbwRKjl{%)fM2d8tOI4MM{l!dK -z4$)%2P!LDJaqX2t;s4$Wy@Q1gZ=x97<n3qFBc<Bm#;F26e|~<6=hD9lOk>K<zaU`L -zqML8CN*#9@aDs=m4ulGOO%*?>lhsvF9`g6&TYocZ_JQN=A1hUE#+kAD@E9jJd7%}~ -zMLIYMDVoel8h1}$+_YJF%DJ&-O)X~`ZoroouO-yDsj)OrPU{{+ph4LJKdD;Bi3a3T -zbe?Tf8&<r^`I<R>elW+H+t;5$y~|nhq{o@?k1^-Hg%jhcu{xJyzvgk`0m*Te#GQe$ -z2IjOP{U&oF$`&WsuJN2!=fTnT^W)PwhnW-Ya3)3%H!`OUfy6?#V9r%+wCY}TU0!Cl -z*kjeex}MZl_aWVoxhXfp&Ur~>>k;onlO4II%~KY!FT|r)!;agdwcf~rXIAVwc6CEj -zJpE{CBzZ;L-gdYp9)G<w5{aU1kLvl`XxrnL=MQj88F%j+w*oR6c&t8(di=t_dW<Us -z?>C8f@wZ%=YBfkLb0_gZP%us?_tgG3TXJ7BDbWb~V23Mt{QT(?mOc#ihbo#YtY#rD -z7PLiJBSP#J^tiB|7vdE`p9|}IA$}9o7_wSJ;))RELe^~|u{T6dhpd-F;;j&U6|#N} -z3BN(h4C``3tTE^&!`fqrdks2dSZ^5Oh(X^Omdc+rCapBB)uz~J(k-TSw<-3U^rC6K -zYl;s|`q{KX)nazFdEs%*@f}l~SsY?~kb2(WgGl=fm!43<O#L+%@MH9Gl`~Gq=7;rx -zMc&31@YxsRfz-6`>>4I&2(k1$iaK?FYVZ}~h~1{1T|;>=%b4`yk3XF>siEVHyC@HS -z8OvVW%DeB`K&~H7>f?&^gQU_A0oM<l8+N5oZ4)iV>;p0b*k61j!x*S5X(-unS`9rZ -zG}=vb+R*x})DSq-Q7;uJwKLPuG`Ej6G}#nch4dSqhHo0B2Gq%HbgCyS+pwZ3{?fph -z!Jo*Dxcw7v7a#rIU2IRmVn4KE$x~88+a7J4zd|_!%xo9z$+P;Q6qA*AQ5FvzlPW^f -zY&aJUhO1#_o~&$x>1qJKGpC+K<(u_&1197<WZ2zu79e*q&i9c$DPNGYYw%s_L~d?x -zj;EW8N#6BCjjMs5>VVWxipk10ERAEpLG3^|JWI~<Y~c5vi!sB;W|~-R<=`-_TSLhN -zYlyAlPUkfn-CnHq)Xv2vv1R->DYG*_Qk)fwt)g^KZ*f*K5tEj9C7Ea`HGyPe8U4wd -nX2Iz@%Q6UTm;}-X%j^D0i1fiT)I6)4TdrsMY}`L(<y7krryzQ} - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6220/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/early_init.c -new file mode 100644 -index 0000000000..ff83db095b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/early_init.c -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6220/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/gpio.c -new file mode 100644 -index 0000000000..2306e4cf0a ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/gpio.c -@@ -0,0 +1,192 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+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_NATIVE, -+ .gpio4 = GPIO_MODE_GPIO, -+ .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_NATIVE, -+ .gpio13 = GPIO_MODE_GPIO, -+ .gpio14 = GPIO_MODE_GPIO, -+ .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_GPIO, -+ .gpio31 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_direction = { -+ .gpio0 = GPIO_DIR_INPUT, -+ .gpio1 = GPIO_DIR_INPUT, -+ .gpio2 = GPIO_DIR_INPUT, -+ .gpio4 = GPIO_DIR_INPUT, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio16 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_INPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+ .gpio30 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio30 = GPIO_LEVEL_HIGH, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio1 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio46 = GPIO_MODE_NATIVE, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .gpio50 = GPIO_MODE_NATIVE, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_NATIVE, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_NATIVE, -+ .gpio56 = GPIO_MODE_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_OUTPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_HIGH, -+ .gpio45 = GPIO_LEVEL_LOW, -+ .gpio49 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_GPIO, -+ .gpio71 = GPIO_MODE_GPIO, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .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, -+ .gpio70 = GPIO_DIR_INPUT, -+ .gpio71 = 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/dell/snb_ivb_latitude/variants/e6220/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/hda_verb.c -new file mode 100644 -index 0000000000..0c69f0bd0e ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76e7, /* Codec Vendor / Device ID: IDT */ -+ 0x102804a9, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x102804a9), -+ AZALIA_PIN_CFG(0, 0x0a, 0x03a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0321101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0xd5a30130), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x400000f0), -+ -+ 0x80862805, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6220/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/overridetree.cb -new file mode 100644 -index 0000000000..9faf27e27b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6220/overridetree.cb -@@ -0,0 +1,37 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x04a9 inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x0000046a" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 0, 0, 0, 0, 0 }" -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 0, 0 }, -+ { 1, 1, 1 }, -+ { 1, 0, 1 }, -+ { 1, 1, 2 }, -+ { 1, 1, 2 }, -+ { 1, 1, 3 }, -+ { 1, 1, 3 }, -+ { 1, 0, 5 }, -+ { 1, 0, 5 }, -+ { 1, 1, 7 }, -+ { 1, 1, 6 }, -+ { 1, 0, 6 }, -+ { 1, 0, 7 }, -+ }" -+ -+ device ref pcie_rp4 off end -+ device ref sata1 on -+ register "sata_port_map" = "0x3b" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0026-nb-haswell-lock-policy-regs-when-disabling-IOMMU.patch b/config/coreboot/default/patches/0015-nb-haswell-lock-policy-regs-when-disabling-IOMMU.patch index fe9034b0..9525b8ce 100644 --- a/config/coreboot/default/patches/0026-nb-haswell-lock-policy-regs-when-disabling-IOMMU.patch +++ b/config/coreboot/default/patches/0015-nb-haswell-lock-policy-regs-when-disabling-IOMMU.patch @@ -1,7 +1,7 @@ -From ce7d65790b9b8656ebbaa0ca715adff6a9c25588 Mon Sep 17 00:00:00 2001 +From a507fe609a2e99c95218ec430916eaf4c3cb61d9 Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sat, 4 May 2024 02:00:53 +0100 -Subject: [PATCH 26/51] nb/haswell: lock policy regs when disabling IOMMU +Subject: [PATCH 15/37] nb/haswell: lock policy regs when disabling IOMMU Angel Pons told me I should do it. See comments here: https://review.coreboot.org/c/coreboot/+/81016 diff --git a/config/coreboot/default/patches/0016-mb-dell-Add-Latitude-E6330-Ivy-Bridge.patch b/config/coreboot/default/patches/0016-mb-dell-Add-Latitude-E6330-Ivy-Bridge.patch deleted file mode 100644 index 7d2133ef..00000000 --- a/config/coreboot/default/patches/0016-mb-dell-Add-Latitude-E6330-Ivy-Bridge.patch +++ /dev/null @@ -1,436 +0,0 @@ -From 0889cc6b6f62cba616feff5ae8558be31f298069 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Fri, 8 Mar 2024 09:33:03 -0700 -Subject: [PATCH 16/51] mb/dell: Add Latitude E6330 (Ivy Bridge) - -Mainboard is QAL70/LA-7741P. I do not physically have this system; -someone with physical access to one sent me the output of autoport which -I then modified to produce this port. I was also sent the VBT binary, -which was obtained from `/sys/kernel/debug/dri/0/i915_vbt` while running -version A21 of the vendor firmware. This port has not been tested. - -The EC is the SMSC MEC5055, which seems to be compatible with the -existing MEC5035 code. As with the other Dell systems with this EC, this -board is assumed to be internally flashable using an EC command that -tells it to pull the FDO pin low on the next boot, which also tells the -vendor firmware to disable all write protections to the flash [1]. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: I827826e9ff8a9a534c50250458b399104478e06c -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 11 +- - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e6330/data.vbt | Bin 0 -> 6144 bytes - .../variants/e6330/early_init.c | 14 ++ - .../snb_ivb_latitude/variants/e6330/gpio.c | 192 ++++++++++++++++++ - .../variants/e6330/hda_verb.c | 32 +++ - .../variants/e6330/overridetree.cb | 37 ++++ - 7 files changed, 288 insertions(+), 1 deletion(-) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6330/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6330/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6330/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6330/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6330/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index baa83baa41..49bf225fe2 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -56,6 +56,12 @@ config BOARD_DELL_LATITUDE_E5530 - select BOARD_ROMSIZE_KB_12288 - select SOUTHBRIDGE_INTEL_C216 - -+config BOARD_DELL_LATITUDE_E6330 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_12288 -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select SOUTHBRIDGE_INTEL_C216 -+ - config BOARD_DELL_LATITUDE_E6430 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_12288 -@@ -84,6 +90,7 @@ config MAINBOARD_PART_NUMBER - default "Latitude E6420" if BOARD_DELL_LATITUDE_E6420 - default "Latitude E6520" if BOARD_DELL_LATITUDE_E6520 - default "Latitude E5530" if BOARD_DELL_LATITUDE_E5530 -+ default "Latitude E6330" if BOARD_DELL_LATITUDE_E6330 - default "Latitude E6430" if BOARD_DELL_LATITUDE_E6430 - default "Latitude E6530" if BOARD_DELL_LATITUDE_E6530 - -@@ -101,13 +108,15 @@ config VARIANT_DIR - default "e6420" if BOARD_DELL_LATITUDE_E6420 - default "e6520" if BOARD_DELL_LATITUDE_E6520 - default "e5530" if BOARD_DELL_LATITUDE_E5530 -+ default "e6330" if BOARD_DELL_LATITUDE_E6330 - default "e6430" if BOARD_DELL_LATITUDE_E6430 - default "e6530" if BOARD_DELL_LATITUDE_E6530 - - config VGA_BIOS_ID - default "8086,0116" if BOARD_DELL_LATITUDE_E6520 \ - || BOARD_DELL_LATITUDE_E5420 -- default "8086,0166" if BOARD_DELL_LATITUDE_E5530 -+ default "8086,0166" if BOARD_DELL_LATITUDE_E5530 \ -+ || BOARD_DELL_LATITUDE_E6330 - default "8086,0126" if BOARD_DELL_LATITUDE_E6420 \ - || BOARD_DELL_LATITUDE_E5520 \ - || BOARD_DELL_LATITUDE_E6220 \ -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index 349ee7f79e..d6fc8eb224 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -21,6 +21,9 @@ config BOARD_DELL_LATITUDE_E6520 - config BOARD_DELL_LATITUDE_E5530 - bool "Latitude E5530" - -+config BOARD_DELL_LATITUDE_E6330 -+ bool "Latitude E6330" -+ - config BOARD_DELL_LATITUDE_E6430 - bool "Latitude E6430" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6330/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..18856746656058651c571ecbb3708e0543b19d62 -GIT binary patch -literal 6144 -zcmeHKU2GiH75-*tc6WAmW_LYygMSkDB*E^Q*zv5f7dLg)@$NQV2a{}!yImnfyvQ4D -z;n-$v0!RpNi<_o@ktI-@2a590stC0zRi%iRR%stvi&hAs3R<K}X~hFddB_6@s8W`5 -zXJ!q~E{TOme<a`8@BW;7?l<?GIp@yo&H2<M-FZ0GKbBAR-Ekx}HvVOrhK1*2?{QsU -zQe#K%JeC=q96gpAKa#$keu^D99ee*0FfB=@F_0J<9-Ch-&BZ5r1T6`{$;1%Fm+qfk -zTr5pfAz@KB*NGlFzEGx2aqh%IxkQOuX*`{wy~+KQo+-}XSE7aaxko77OBtFgoh;4K -z(#-7f<x+WxmKSK)vQFgtt^L+?s+Z<V57E7|^TqOPX{mn0n<VLl#Yf7s_suL*Jl#VB -zmSyz~ScwEVTc-3vd2v6D&dt$;&{?91(o(5>vNXNl&<qW@AghW5NPYw#ha~-b0Dc7_ -z6}t(eHgpwn6<HNi1Vcp^p-07-iXve~MTs!0A_ku!`4nKciajxJYXsOYuuT4N%smA! -zPazgl&bNRSrvAz|_6r3+B;r1=!7D;RUUw8Ke+vNt7E3`(BA-woPvJFBK^3Gzfh4Nk -zOX!J0PJNB)Mk&Z_i?S2ez+iItz=)m79LydX&rM9`3wPaJ`T92=Uv0;g-!<4*M6z%+ -z*omwb#VI+CU&%iFS{_DGS;sE}7G4juqRMCww!+k6=+abJj4v>Dsr*z_6HAP5GJeST -znX2JD;{xLa#;c6KGychVn-L6YXkv6Qx)}Y8&ok1DI~ZSM6dCt39%QUAzRh@o@gqjy -zL0qZ&DhN8ZR3xu$a$Cd{oasU3DNp{CCl6f~PYlq!Hte;Ia0^wn8Vut7>Wl1)s`^E- -z1DhGx<x<9D%6jd%)5>zr8&7h}dMJ3~YBe;)!vVf-T&?{PoMvvRR{!67;Xhz^g^loX -zja+*c-KJJoxbsm3pTE4THs`cgD{Pt+ga3en-i$P#9Wsra(oqRMr;H$4{gxr)9eF(x -zg0v@a7aj}rA^Kf#sNb*>at^>P)5li%ycOq*4e;3~RUj$i1e8=rHi&<Y^Hc>Y_gP4= -zxz9^%q0dLXqC&Bq<&sDScZwvatjRxB=rcJJiYb?w#4Iy2KTk1F6T>T}E@(DNGa>5R -z7&Yv)JdHrRI};pfsKLVj=FE=U*=*T4#ncVktknoGelT||SDY`+9WI_IZE<i@7SnC8 -zN6~Gyo=&><wpzE~>`_>@wb<-RI-lu(_~Oy_Zo6={Cdq!uw(fmyz_u^cB&~5IS7g`U -zdUC}N$J5-C)|`CfUO+?xptr@*hJW$ZhBZk%JaMh_<8!ZGj)z*WU9fcg2`>dT##_?q -z=Ksx}uxo3jTHTq%E1}97UECE@r}nt3I=3R(HOL7jNg>teSM-g$aU#`3jk}#qh;D?6 -zw=CYuA2#mS+vU%0P&u8RCn4)$8VH-2uy#01%VG0WSX&Fz`LMYj)?N<NyJ1t)wHBQY -z=;pYt<#l>gH_zzWS)G2Pn=k3wYdU|DnWmxbG$>`5lZJMWL92%O14BD!(C-cNFNXFH -zgVc!G9?@=&(4mNVcSJiLq3=b^rz6@k5qdFVUW{m$A{2|7d!kxz)VSrcQt@4sDoq^f -z98hXm=YS~qbf<kwigD|YevaR}^`7Jy^x~4_g75ka=c0r}VJF2aEv{=ilPf-mNQBNI -zEMK3YKB+`*xOu>iR|LbzHLa*mLXlH${^b4c9%>9%)HO-?LA1gT0mlz!M}8&;(;^x| -z*H2<VyY>2;juB|7F+k?y(_2~3@STqQ@f^sqD2c8g3x>ciM%siMq~;pKwfE57kw2K@ -z!-ZN0QTVOP@aA5@fEGKjy2+D`t?2KzpPyRQ`JcmHJoc(<#h<UT;@W$t_d{|;S>vyF -zewtgef*II~y;k>*B!+(8*blXsY-~kcJa9zG2yfcMCt+|-0ex$pY`h1<*#rEv=~*<+ -ztV``Um!q33-Aap9fUshX^N~GS2@X3^U9+MwgYQ74^?~6&yU^#oY#cvC9R_}P2d<wN -zJvOE)Xr7A2n#3x14}2_g(YN^0+oYDbb#|V{ze3pzGb9FiF#6Ra&L}bT(ZOvswS7RY -zxLjWFRwWXHR5&={t;%K+Vkd6NX2iF<SF)LXv@y472OmG!_W%Ni*ZDuev-S0%b!dfW -wz4{IL!+uT9t2XI4@_L@?Ri*bc_<n8A+wHaowmq=zfo%_LdtloGpN<DU00~N<ApigX - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6330/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/early_init.c -new file mode 100644 -index 0000000000..ff83db095b ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/early_init.c -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN -+ | KBC_LPC_EN | FDD_LPC_EN | LPT_LPC_EN -+ | COMB_LPC_EN | COMA_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6330/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/gpio.c -new file mode 100644 -index 0000000000..777570765a ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/gpio.c -@@ -0,0 +1,192 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+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_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_NATIVE, -+ .gpio13 = GPIO_MODE_GPIO, -+ .gpio14 = GPIO_MODE_GPIO, -+ .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_NATIVE, -+}; -+ -+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, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio16 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_OUTPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio28 = GPIO_LEVEL_LOW, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+ .gpio30 = GPIO_RESET_RSMRST, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio13 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio46 = GPIO_MODE_NATIVE, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .gpio50 = GPIO_MODE_NATIVE, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_NATIVE, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_NATIVE, -+ .gpio56 = GPIO_MODE_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_INPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_HIGH, -+ .gpio45 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_GPIO, -+ .gpio71 = GPIO_MODE_GPIO, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .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, -+ .gpio70 = GPIO_DIR_INPUT, -+ .gpio71 = 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/dell/snb_ivb_latitude/variants/e6330/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/hda_verb.c -new file mode 100644 -index 0000000000..804733b172 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76df, /* Codec Vendor / Device ID: IDT */ -+ 0x10280533, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x10280533), -+ AZALIA_PIN_CFG(0, 0x0a, 0x03a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0321101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0xd5a30130), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x400000f0), -+ -+ 0x80862806, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6330/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/overridetree.cb -new file mode 100644 -index 0000000000..4125159367 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6330/overridetree.cb -@@ -0,0 +1,37 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x0533 inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x00001312" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "usb_port_config" = "{ -+ { 1, 2, 0 }, -+ { 1, 0, 0 }, -+ { 1, 0, 1 }, -+ { 1, 1, 1 }, -+ { 1, 1, 2 }, -+ { 1, 1, 2 }, -+ { 1, 2, 3 }, -+ { 1, 2, 3 }, -+ { 1, 2, 4 }, -+ { 1, 1, 4 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 2, 6 }, -+ { 1, 0, 6 }, -+ }" -+ -+ device ref xhci on -+ register "superspeed_capable_ports" = "0x0000000f" -+ register "xhci_overcurrent_mapping" = "0x00000c03" -+ register "xhci_switchable_ports" = "0x0000000f" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0027-nb-intel-gm45-Make-DDR2-raminit-work.patch b/config/coreboot/default/patches/0016-nb-intel-gm45-Make-DDR2-raminit-work.patch index 28fc679f..091a15c4 100644 --- a/config/coreboot/default/patches/0027-nb-intel-gm45-Make-DDR2-raminit-work.patch +++ b/config/coreboot/default/patches/0016-nb-intel-gm45-Make-DDR2-raminit-work.patch @@ -1,7 +1,7 @@ -From c6181fe0c8b58cb5a4523d5763fc5fcdf61b3f10 Mon Sep 17 00:00:00 2001 +From 9e0a6aa376db81f9409eda92b6783a8262c1fedb Mon Sep 17 00:00:00 2001 From: Angel Pons <th3fanbus@gmail.com> Date: Mon, 10 May 2021 22:40:59 +0200 -Subject: [PATCH 27/51] nb/intel/gm45: Make DDR2 raminit work +Subject: [PATCH 16/37] nb/intel/gm45: Make DDR2 raminit work List of changes: - Update some timing and ODT values diff --git a/config/coreboot/default/patches/0017-mb-dell-Add-Latitude-E6230-Ivy-Bridge.patch b/config/coreboot/default/patches/0017-mb-dell-Add-Latitude-E6230-Ivy-Bridge.patch deleted file mode 100644 index 412b8471..00000000 --- a/config/coreboot/default/patches/0017-mb-dell-Add-Latitude-E6230-Ivy-Bridge.patch +++ /dev/null @@ -1,440 +0,0 @@ -From 84d7f3201eb4492acd7d290a02d19c4850c85791 Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Thu, 26 Oct 2017 21:26:43 +0800 -Subject: [PATCH 17/51] mb/dell: Add Latitude E6230 (Ivy Bridge) - -This was adapted from CB:22693 from Iru Cai, which was based on -autoport. I do not physically have this system. Someone with physical -access to an E6230 running version A11 of the vendor firmware sent me -the VBT after running the command `intelvbttool --inlegacy --outvbt -data.vbt`. This new version of the port has not yet been tested. - -The EC is the SMSC MEC5055, which seems to be compatible with the -existing MEC5035 code. As with the other Dell systems with this EC, this -board is assumed to be internally flashable using an EC command that -tells it to pull the FDO pin low on the next boot, which also tells the -vendor firmware to disable all write protections to the flash [1]. - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Original-Change-Id: I8cdc01e902e670310628809416290045c2102340 -Change-Id: I32927beea7c29b96a851ab77ed15b0160f16d369 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/snb_ivb_latitude/Kconfig | 11 +- - .../dell/snb_ivb_latitude/Kconfig.name | 3 + - .../snb_ivb_latitude/variants/e6230/data.vbt | Bin 0 -> 4280 bytes - .../variants/e6230/early_init.c | 12 ++ - .../snb_ivb_latitude/variants/e6230/gpio.c | 193 ++++++++++++++++++ - .../variants/e6230/hda_verb.c | 32 +++ - .../variants/e6230/overridetree.cb | 40 ++++ - 7 files changed, 290 insertions(+), 1 deletion(-) - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6230/data.vbt - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6230/early_init.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6230/gpio.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6230/hda_verb.c - create mode 100644 src/mainboard/dell/snb_ivb_latitude/variants/e6230/overridetree.cb - -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig b/src/mainboard/dell/snb_ivb_latitude/Kconfig -index 49bf225fe2..f6e097930b 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig -@@ -56,6 +56,12 @@ config BOARD_DELL_LATITUDE_E5530 - select BOARD_ROMSIZE_KB_12288 - select SOUTHBRIDGE_INTEL_C216 - -+config BOARD_DELL_LATITUDE_E6230 -+ select BOARD_DELL_SNB_IVB_LATITUDE_COMMON -+ select BOARD_ROMSIZE_KB_12288 -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select SOUTHBRIDGE_INTEL_C216 -+ - config BOARD_DELL_LATITUDE_E6330 - select BOARD_DELL_SNB_IVB_LATITUDE_COMMON - select BOARD_ROMSIZE_KB_12288 -@@ -90,6 +96,7 @@ config MAINBOARD_PART_NUMBER - default "Latitude E6420" if BOARD_DELL_LATITUDE_E6420 - default "Latitude E6520" if BOARD_DELL_LATITUDE_E6520 - default "Latitude E5530" if BOARD_DELL_LATITUDE_E5530 -+ default "Latitude E6230" if BOARD_DELL_LATITUDE_E6230 - default "Latitude E6330" if BOARD_DELL_LATITUDE_E6330 - default "Latitude E6430" if BOARD_DELL_LATITUDE_E6430 - default "Latitude E6530" if BOARD_DELL_LATITUDE_E6530 -@@ -108,6 +115,7 @@ config VARIANT_DIR - default "e6420" if BOARD_DELL_LATITUDE_E6420 - default "e6520" if BOARD_DELL_LATITUDE_E6520 - default "e5530" if BOARD_DELL_LATITUDE_E5530 -+ default "e6230" if BOARD_DELL_LATITUDE_E6230 - default "e6330" if BOARD_DELL_LATITUDE_E6330 - default "e6430" if BOARD_DELL_LATITUDE_E6430 - default "e6530" if BOARD_DELL_LATITUDE_E6530 -@@ -121,7 +129,8 @@ config VGA_BIOS_ID - || BOARD_DELL_LATITUDE_E5520 \ - || BOARD_DELL_LATITUDE_E6220 \ - || BOARD_DELL_LATITUDE_E6320 -- default "8086,0166" if BOARD_DELL_LATITUDE_E6430 \ -+ default "8086,0166" if BOARD_DELL_LATITUDE_E6230 \ -+ || BOARD_DELL_LATITUDE_E6430 \ - || BOARD_DELL_LATITUDE_E6530 - - endif -diff --git a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -index d6fc8eb224..cb7bbd5cdb 100644 ---- a/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -+++ b/src/mainboard/dell/snb_ivb_latitude/Kconfig.name -@@ -21,6 +21,9 @@ config BOARD_DELL_LATITUDE_E6520 - config BOARD_DELL_LATITUDE_E5530 - bool "Latitude E5530" - -+config BOARD_DELL_LATITUDE_E6230 -+ bool "Latitude E6230" -+ - config BOARD_DELL_LATITUDE_E6330 - bool "Latitude E6330" - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6230/data.vbt b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..45ce8f435eea647a0bddaab3fd1e9282c87afc66 -GIT binary patch -literal 4280 -zcmdT{Yiu0V75-*tAG5PFyX&zDekA7P<*tbx&o1`j23L%CmvkLWvN7(mLa6alZ?J`9 -zo3#m4YVlG`2;w12Ajppt<qra(R;8*G@uw*8gIcsg2vxi!q_pBkmGUD$s9IGi+jD1T -zO`Kg43n@JA>~|mMp8L%`XU@4ZyCa_(r`z|Z`bP4p-rEkOMn-R;Ntk#o`b)0sOKRl6 -z?T0eM<HLtiqX*Kr(o5Kc<Iyk90h5ws=!y8i;K=M^X(l$-Eoeyyj>ZS*@LZWP#hD{> -z<r2jcJ;b8e!oAb;^QB2D#7*krI^IpA=?ra8?xvqj6=&}$QL2a1J(QuD($UfkElf=x -zUM!UtXmO4PP4h^;&)jWJvd(Pj0lIs7wpgAnE!1!MB1w8~{^#ZCd!`mCmhPs6X_~zW -zGae^<%aoog&+n$;nHd@rItw&bS}2u|mL_-Ws;&ZOWW_51k`IALAW8pAz~@C!!B)bs -z1x-OrK~}*8L07Po(5+xZL6I<}phTEf5QRsVJYHa{f^AWEV+2@lvrPVS%snsOn?N)w -zpKbvwOnk&Q_6Y?aB;r1=!TYwts;yA@BnbFfECo!7JVJq7g^yhYMUV;wlBjksp(hI2 -z^<}E7r698{-pw!*{mH>SLslxYH@j~%H#VLx+<8~!;a@$n+>Q%xHrQ8KGI21_iL4sI -zF*$}m$R7Mr9z@Z*ir@Q9eClsSmC+t(g`q~VQ&nIxZenav_^Buc78s8*o@e|<QE{4a -zhVeGz1IFJN|784&5eTYiVstQeGWr-lWTY9lG45a#8TT^oXDl%uXFS9BHN$^DE>t}g -z1Z-O>lG`>pEuvmL-HpmgSANo!2hWQq2B>Zua$8%tfvQ>!1n@=m9ri_4`H|Rx#SH9n -zDdRF_-FDP&WjW`L$GK%a6x?yO8l2!^g0HJrtA7TknNzCO?|U!wCv2^-5pJ%LW6!+P -z)anX%E>`gP%3Er4c6+J9x=Atk1{Abrr1|WSY3P`SO5j!R5F*vbbQ%AaSHnR_+x&Op -zA%8C-Pk=-Hs+FL90B)E*y3FUTIA1J)&pxRF$tzAkNr7a6_-8v$@j~G~3keqYd5I<T -z`Kb3Q@LKkANhE_aMG_R&<ewt+nVbp5l*3G7mYJEKr<kXS;TA&^G;5`q5b>;y8g^P< -zfWO_D2@EyVVBxnpv*}hgTeeRzWz9BoISh>M%^k`WXG=5ti$_Wu99)~lWE-qubeXNk -zla9Tu=Jhyn5T<3$H#?Hfm-`+(d$7IBDx9cEvNv1i-LEDr>r7438bfkPcKod+mwd22 -z%{^(w&NuG)MKl0fTMTXZFJEm~k;KCj*D60g=j!2jsP)<fOUGaEZa`&xE*)?FZuW#- -z8!Of7<|N(^R#xcjmZ&nZ%~{pC5y_T*PB2LdDjuI#Te}-4Qccvj+u4N3TBx|oVy*mP -z<9xfFziy4n?sPv3Sqo7jWMo3>{tzvOjAJ2nB}At~#%f4?FGT+d8LFnXXtYN&Mm06B -z(JwUPX-z$$(d(M=uBLvh@h6#K=;~&jQo1p&t3TCgSvQ{3)l)jXr5hjW>fd!z!bW>o -z-4UjJVdJi_dN@o^hK(1(>dRqzCv2PztLMTLjTqY^YEMMJ{=B#1IV)9~IMg|yl(NPF -zQSfMX`?(b5)))B!zjy0B$ua20CCLTPl^IS&2=T&Zid9-1*K{VAJP?rxjYC+zGDCe* -ziQI7VfF17@3`3W-qCN>lPC5CL_c?p0F<ekqB;g0q3P1R5KNubPsT>TGXaGB3i~{ZE -zr=QtIprytDnU7C*Wj%x0k)O{Y%nUnl%}K%F|J_iVaD&ubW4Qbtx;pZEb9}f^Yd;Ea -zI1Ha{7Yt~z{LAY++1QG{F6*_4WsUziY{x?%I9B}i5-Tphhk8FGm%J<d_0CUoV^%N& -zTe02j+LXk=ZyWoe7L$#wsEY@VC>f!3d-ysG_9>uk%#)4xpxb+ZkJdel#+h}l9j9`1 -zt*M!5u?i4YtZ+WECo6$LJF06|G-mMZskGiV*lQJf-ItB+hltI<?{5E<^P=0rL<P+g -z(P)!c<?MlvMK0O~UwZ4*;x|ms(&&#Vn_-4{KM#g~a=;$N2QD7mSX0{t<cf>sId@e& -z-cN<SWA3VKCN6g3lx#+PySpWu*+pw}>vr(fgI)K*zkikg6TDJi?^}ghc*U*%A%EGg -Y$$8Z}9a~<{Q@y10T!W`-d%n2+Kj)*Kg#Z8m - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6230/early_init.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/early_init.c -new file mode 100644 -index 0000000000..24c1b32467 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/early_init.c -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCH_LPC_DEV, LPC_EN, CNF1_LPC_EN | MC_LPC_EN | KBC_LPC_EN); -+ mec5035_early_init(); -+} -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6230/gpio.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/gpio.c -new file mode 100644 -index 0000000000..c07e4b1c56 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/gpio.c -@@ -0,0 +1,193 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <southbridge/intel/common/gpio.h> -+ -+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_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_NATIVE, -+ .gpio13 = GPIO_MODE_GPIO, -+ .gpio14 = GPIO_MODE_GPIO, -+ .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_NATIVE, -+}; -+ -+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, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio13 = GPIO_DIR_INPUT, -+ .gpio14 = GPIO_DIR_INPUT, -+ .gpio15 = GPIO_DIR_INPUT, -+ .gpio16 = GPIO_DIR_INPUT, -+ .gpio17 = GPIO_DIR_OUTPUT, -+ .gpio19 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_OUTPUT, -+ .gpio29 = GPIO_DIR_INPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio17 = GPIO_LEVEL_HIGH, -+ .gpio28 = GPIO_LEVEL_LOW, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+ .gpio30 = GPIO_RESET_RSMRST, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio0 = GPIO_INVERT, -+ .gpio8 = GPIO_INVERT, -+ .gpio13 = GPIO_INVERT, -+ .gpio14 = 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_NATIVE, -+ .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_GPIO, -+ .gpio46 = GPIO_MODE_NATIVE, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .gpio50 = GPIO_MODE_NATIVE, -+ .gpio51 = GPIO_MODE_GPIO, -+ .gpio52 = GPIO_MODE_GPIO, -+ .gpio53 = GPIO_MODE_NATIVE, -+ .gpio54 = GPIO_MODE_GPIO, -+ .gpio55 = GPIO_MODE_NATIVE, -+ .gpio56 = GPIO_MODE_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_NATIVE, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_INPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio36 = GPIO_DIR_INPUT, -+ .gpio37 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_OUTPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_INPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_INPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio34 = GPIO_LEVEL_HIGH, -+ .gpio45 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+}; -+ -+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_GPIO, -+ .gpio71 = GPIO_MODE_GPIO, -+ .gpio72 = GPIO_MODE_NATIVE, -+ .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, -+ .gpio70 = GPIO_DIR_INPUT, -+ .gpio71 = 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/dell/snb_ivb_latitude/variants/e6230/hda_verb.c b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/hda_verb.c -new file mode 100644 -index 0000000000..f6876f9e09 ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/hda_verb.c -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76df, /* Codec Vendor / Device ID: IDT */ -+ 0x10280532, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x10280532), -+ AZALIA_PIN_CFG(0, 0x0a, 0x03a11020), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0321101f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x23011050), -+ AZALIA_PIN_CFG(0, 0x0f, 0x23a1102e), -+ AZALIA_PIN_CFG(0, 0x10, 0x400000f3), -+ AZALIA_PIN_CFG(0, 0x11, 0xd5a30130), -+ AZALIA_PIN_CFG(0, 0x1f, 0x400000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x400000f0), -+ -+ 0x80862806, /* Codec Vendor / Device ID: Intel */ -+ 0x80860101, /* Subsystem ID */ -+ 4, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(3, 0x80860101), -+ AZALIA_PIN_CFG(3, 0x05, 0x18560010), -+ AZALIA_PIN_CFG(3, 0x06, 0x18560020), -+ AZALIA_PIN_CFG(3, 0x07, 0x18560030), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/snb_ivb_latitude/variants/e6230/overridetree.cb b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/overridetree.cb -new file mode 100644 -index 0000000000..3a0fa720da ---- /dev/null -+++ b/src/mainboard/dell/snb_ivb_latitude/variants/e6230/overridetree.cb -@@ -0,0 +1,40 @@ -+## SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ device domain 0 on -+ subsystemid 0x1028 0x0532 inherit -+ -+ device ref igd on -+ register "gpu_cpu_backlight" = "0x000009e9" -+ register "gpu_pch_backlight" = "0x13121312" -+ end -+ -+ chip southbridge/intel/bd82x6x -+ register "usb_port_config" = "{ -+ { 1, 1, 0 }, -+ { 1, 1, 0 }, -+ { 1, 0, 1 }, -+ { 1, 2, 1 }, -+ { 1, 0, 2 }, -+ { 1, 0, 2 }, -+ { 1, 0, 3 }, -+ { 1, 1, 3 }, -+ { 1, 2, 4 }, -+ { 1, 1, 4 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 2, 6 }, -+ { 1, 0, 6 }, -+ }" -+ -+ device ref xhci on -+ register "superspeed_capable_ports" = "0x0000000f" -+ register "xhci_overcurrent_mapping" = "0x00000c03" -+ register "xhci_switchable_ports" = "0x0000000f" -+ end -+ device ref sata1 on -+ register "sata_port_map" = "0x31" -+ end -+ end -+ end -+end --- -2.39.5 - diff --git a/config/coreboot/default/patches/0028-nb-gm45-Fix-Angel-s-DDR2-RCOMP-fix-on-DDR3-boards.patch b/config/coreboot/default/patches/0017-nb-gm45-Fix-Angel-s-DDR2-RCOMP-fix-on-DDR3-boards.patch index 92e59129..4ba74757 100644 --- a/config/coreboot/default/patches/0028-nb-gm45-Fix-Angel-s-DDR2-RCOMP-fix-on-DDR3-boards.patch +++ b/config/coreboot/default/patches/0017-nb-gm45-Fix-Angel-s-DDR2-RCOMP-fix-on-DDR3-boards.patch @@ -1,7 +1,7 @@ -From b6f75374fa38e0b097c9eadb4916112707cb6747 Mon Sep 17 00:00:00 2001 +From 6acc310c1d695d47c148296da9da189de21d58be Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Tue, 6 Aug 2024 00:50:24 +0100 -Subject: [PATCH 28/51] nb/gm45: Fix Angel's DDR2 RCOMP fix on DDR3 boards +Subject: [PATCH 17/37] nb/gm45: Fix Angel's DDR2 RCOMP fix on DDR3 boards We add this patch: diff --git a/config/coreboot/default/patches/0029-mb-dell-e6400-Use-100-MHz-reference-clock-for-displa.patch b/config/coreboot/default/patches/0018-mb-dell-e6400-Use-100-MHz-reference-clock-for-displa.patch index e31cb64c..1cf7c0ac 100644 --- a/config/coreboot/default/patches/0029-mb-dell-e6400-Use-100-MHz-reference-clock-for-displa.patch +++ b/config/coreboot/default/patches/0018-mb-dell-e6400-Use-100-MHz-reference-clock-for-displa.patch @@ -1,7 +1,7 @@ -From d3045b3dcebd94b78df2129cd81a20adf215e46a Mon Sep 17 00:00:00 2001 +From 7461210ecc7c8e41f3f941bd5ce7943e5f66c711 Mon Sep 17 00:00:00 2001 From: Nicholas Chin <nic.c3.14@gmail.com> Date: Mon, 20 May 2024 10:24:16 -0600 -Subject: [PATCH 29/51] mb/dell/e6400: Use 100 MHz reference clock for display +Subject: [PATCH 18/37] mb/dell/e6400: Use 100 MHz reference clock for display The E6400 uses a 100 MHz reference clock for spread spectrum support on LVDS, whereas libgfxinit previously assumed a 96 MHz input clock. For @@ -33,7 +33,7 @@ index 417d95fd5d..6fe1b1c456 100644 default "dell/e6400" diff --git a/src/northbridge/intel/gm45/Kconfig b/src/northbridge/intel/gm45/Kconfig -index 8059e7ee80..5df5a93296 100644 +index fef0d735b3..fc5df8b11a 100644 --- a/src/northbridge/intel/gm45/Kconfig +++ b/src/northbridge/intel/gm45/Kconfig @@ -14,6 +14,10 @@ config NORTHBRIDGE_INTEL_GM45 diff --git a/config/coreboot/default/patches/0047-nb-x4x-define-INTEL_GMA_DPLL_REF_FREQ.patch b/config/coreboot/default/patches/0019-nb-x4x-define-INTEL_GMA_DPLL_REF_FREQ.patch index 988ae4e6..2edfaae3 100644 --- a/config/coreboot/default/patches/0047-nb-x4x-define-INTEL_GMA_DPLL_REF_FREQ.patch +++ b/config/coreboot/default/patches/0019-nb-x4x-define-INTEL_GMA_DPLL_REF_FREQ.patch @@ -1,7 +1,7 @@ -From 53f2d47ee6ebaa8d47b076a6c2a1514c91247b95 Mon Sep 17 00:00:00 2001 +From a683dffd774dbbe25cc77c0f7d3853232c17c2bf Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Mon, 12 Aug 2024 02:15:24 +0100 -Subject: [PATCH 47/51] nb/x4x: define INTEL_GMA_DPLL_REF_FREQ +Subject: [PATCH 19/37] nb/x4x: define INTEL_GMA_DPLL_REF_FREQ set it to 96MHz. fixes the following build error when building for x4x boards e.g. gigabyte ga-g41m-es2l: @@ -33,7 +33,7 @@ Signed-off-by: Leah Rowe <info@minifree.org> 1 file changed, 4 insertions(+) diff --git a/src/northbridge/intel/x4x/Kconfig b/src/northbridge/intel/x4x/Kconfig -index 9af063819b..93ba575b95 100644 +index 097e11126c..6430319f6a 100644 --- a/src/northbridge/intel/x4x/Kconfig +++ b/src/northbridge/intel/x4x/Kconfig @@ -14,6 +14,10 @@ config NORTHBRIDGE_INTEL_X4X diff --git a/config/coreboot/default/patches/0048-mb-dell-Convert-E6400-into-a-variant.patch b/config/coreboot/default/patches/0020-mb-dell-Convert-E6400-into-a-variant.patch index 156d5c8d..a0068142 100644 --- a/config/coreboot/default/patches/0048-mb-dell-Convert-E6400-into-a-variant.patch +++ b/config/coreboot/default/patches/0020-mb-dell-Convert-E6400-into-a-variant.patch @@ -1,7 +1,7 @@ -From 92556743e92cc02524296b653de5241160876218 Mon Sep 17 00:00:00 2001 +From a48ba23bb4a24730fa49b5a10b56c9de873dea8a Mon Sep 17 00:00:00 2001 From: Nicholas Chin <nic.c3.14@gmail.com> Date: Thu, 26 Sep 2024 19:48:26 -0600 -Subject: [PATCH 48/51] mb/dell: Convert E6400 into a variant +Subject: [PATCH 20/37] mb/dell: Convert E6400 into a variant All the GM45 Dell Latitudes should be nearly identical, so convert the E6400 port into a variant so that future ports for the other systems can diff --git a/config/coreboot/default/patches/0049-mb-dell-gm45_latitudes-Add-E4300-variant.patch b/config/coreboot/default/patches/0021-mb-dell-gm45_latitudes-Add-E4300-variant.patch index 2cdcd499..af893982 100644 --- a/config/coreboot/default/patches/0049-mb-dell-gm45_latitudes-Add-E4300-variant.patch +++ b/config/coreboot/default/patches/0021-mb-dell-gm45_latitudes-Add-E4300-variant.patch @@ -1,7 +1,7 @@ -From ac8ac2543e3ebbc05f79f37d1460cde532a7ee1c Mon Sep 17 00:00:00 2001 +From b87e6774f0407ea48610c83ea54ab6a4b4a78a24 Mon Sep 17 00:00:00 2001 From: Nicholas Chin <nic.c3.14@gmail.com> Date: Thu, 26 Sep 2024 19:51:25 -0600 -Subject: [PATCH 49/51] mb/dell/gm45_latitudes: Add E4300 variant +Subject: [PATCH 21/37] mb/dell/gm45_latitudes: Add E4300 variant Change-Id: I0f2059501b11be103187e3ce1a7c04ab85ae63d2 Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> diff --git a/config/coreboot/default/patches/0050-mb-dell-Add-S3-SMI-handler-for-Dell-Latitudes.patch b/config/coreboot/default/patches/0022-mb-dell-Add-S3-SMI-handler-for-Dell-Latitudes.patch index 71cc67c1..bbdce358 100644 --- a/config/coreboot/default/patches/0050-mb-dell-Add-S3-SMI-handler-for-Dell-Latitudes.patch +++ b/config/coreboot/default/patches/0022-mb-dell-Add-S3-SMI-handler-for-Dell-Latitudes.patch @@ -1,7 +1,7 @@ -From 5e8b899654c31fe771e4b1e96c74c93d4509c3b2 Mon Sep 17 00:00:00 2001 +From 0bc9ca409793836dcdb386db97b7a9464d92a973 Mon Sep 17 00:00:00 2001 From: Nicholas Chin <nic.c3.14@gmail.com> Date: Fri, 3 May 2024 16:31:12 -0600 -Subject: [PATCH 50/51] mb/dell: Add S3 SMI handler for Dell Latitudes +Subject: [PATCH 22/37] mb/dell: Add S3 SMI handler for Dell Latitudes Integrate the previously added mec5035_smi_sleep() function into mainboard code to fix S3 suspend on the SNB/IVB Latitudes and the E7240. diff --git a/config/coreboot/default/patches/0051-ec-dell-mec5035-Route-power-button-event-to-host.patch b/config/coreboot/default/patches/0023-ec-dell-mec5035-Route-power-button-event-to-host.patch index 65f90e2c..ab01c935 100644 --- a/config/coreboot/default/patches/0051-ec-dell-mec5035-Route-power-button-event-to-host.patch +++ b/config/coreboot/default/patches/0023-ec-dell-mec5035-Route-power-button-event-to-host.patch @@ -1,7 +1,7 @@ -From 1a342c20b8705bbea02d27a73e383ee2808f2558 Mon Sep 17 00:00:00 2001 +From d91dc168d6b8eca5e78aef9e48571d6edb156d45 Mon Sep 17 00:00:00 2001 From: Nicholas Chin <nic.c3.14@gmail.com> Date: Tue, 18 Jun 2024 21:31:08 -0600 -Subject: [PATCH 51/51] ec/dell/mec5035: Route power button event to host +Subject: [PATCH 23/37] ec/dell/mec5035: Route power button event to host If command 0x3e with an argument of 1 isn't sent to the EC, pressing the power button results in the EC powering off the system without letting diff --git a/config/coreboot/default/patches/0052-Disable-compression-on-refcode-insertion.patch b/config/coreboot/default/patches/0024-Disable-compression-on-refcode-insertion.patch index 1c089279..c557e9d7 100644 --- a/config/coreboot/default/patches/0052-Disable-compression-on-refcode-insertion.patch +++ b/config/coreboot/default/patches/0024-Disable-compression-on-refcode-insertion.patch @@ -1,7 +1,7 @@ -From 1e72e6df7f5d71fd41350e34d0a8bd5230349235 Mon Sep 17 00:00:00 2001 +From b6bd33b0430f72c2fce16a3b1e41927ef540923b Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Tue, 31 Dec 2024 14:42:24 +0000 -Subject: [PATCH 1/1] Disable compression on refcode insertion +Subject: [PATCH 24/37] Disable compression on refcode insertion Compression is not reliably reproducible. In an lbmk release context, this means we cannot rely on vendorfile insertion. @@ -14,10 +14,10 @@ Signed-off-by: Leah Rowe <info@minifree.org> 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.mk b/Makefile.mk -index e9ad2ccbb2..6a96d45a83 100644 +index 3969bfbd05..15346569f8 100644 --- a/Makefile.mk +++ b/Makefile.mk -@@ -1364,7 +1364,7 @@ endif +@@ -1392,7 +1392,7 @@ endif cbfs-files-$(CONFIG_HAVE_REFCODE_BLOB) += $(CONFIG_CBFS_PREFIX)/refcode $(CONFIG_CBFS_PREFIX)/refcode-file := $(REFCODE_BLOB) $(CONFIG_CBFS_PREFIX)/refcode-type := stage diff --git a/config/coreboot/default/patches/0024-ec-dell-mec5035-Replace-defines-with-enums.patch b/config/coreboot/default/patches/0024-ec-dell-mec5035-Replace-defines-with-enums.patch deleted file mode 100644 index 6c1118bb..00000000 --- a/config/coreboot/default/patches/0024-ec-dell-mec5035-Replace-defines-with-enums.patch +++ /dev/null @@ -1,91 +0,0 @@ -From a1566875789469ebd91e472301be4b359aac0a4c Mon Sep 17 00:00:00 2001 -From: Nicholas Chin <nic.c3.14@gmail.com> -Date: Tue, 28 May 2024 17:23:21 -0600 -Subject: [PATCH 24/51] ec/dell/mec5035: Replace defines with enums - -Instead of using defines for command IDs and argument values, use enums -to provide more type safety. This also has the effect of moving the -command IDs to a more central location instead of defines spread out -throughout the header. - -Change-Id: I788531e8b70e79541213853f177326d217235ef2 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> -Reviewed-on: https://review.coreboot.org/c/coreboot/+/82998 -Tested-by: build bot (Jenkins) <no-reply@coreboot.org> -Reviewed-by: Felix Singer <service+coreboot-gerrit@felixsinger.de> ---- - src/ec/dell/mec5035/mec5035.c | 10 +++++----- - src/ec/dell/mec5035/mec5035.h | 20 ++++++++++++-------- - 2 files changed, 17 insertions(+), 13 deletions(-) - -diff --git a/src/ec/dell/mec5035/mec5035.c b/src/ec/dell/mec5035/mec5035.c -index 68b6b2f7fb..dffbb7960c 100644 ---- a/src/ec/dell/mec5035/mec5035.c -+++ b/src/ec/dell/mec5035/mec5035.c -@@ -66,17 +66,17 @@ static enum cb_err write_mailbox_regs(const u8 *data, u8 start, u8 count) - return CB_SUCCESS; - } - --static void ec_command(u8 cmd) -+static void ec_command(enum mec5035_cmd cmd) - { - outb(0, MAILBOX_INDEX); -- outb(cmd, MAILBOX_DATA); -+ outb((u8)cmd, MAILBOX_DATA); - wait_ec(); - } - --u8 mec5035_mouse_touchpad(u8 setting) -+u8 mec5035_mouse_touchpad(enum ec_mouse_setting setting) - { -- u8 buf[15] = {0}; -- write_mailbox_regs(&setting, 2, 1); -+ u8 buf[15] = {(u8)setting}; -+ write_mailbox_regs(buf, 2, 1); - ec_command(CMD_MOUSE_TP); - /* The vendor firmware reads 15 bytes starting at index 1, presumably - to get some sort of return code. Though I don't know for sure if -diff --git a/src/ec/dell/mec5035/mec5035.h b/src/ec/dell/mec5035/mec5035.h -index fa15a9d621..32f791cb01 100644 ---- a/src/ec/dell/mec5035/mec5035.h -+++ b/src/ec/dell/mec5035/mec5035.h -@@ -7,16 +7,20 @@ - - #define NUM_REGISTERS 32 - -+enum mec5035_cmd { -+ CMD_MOUSE_TP = 0x1a, -+ CMD_RADIO_CTRL = 0x2b, -+ CMD_CPU_OK = 0xc2, -+}; -+ - /* Touchpad (TP) and mouse related. The EC seems to - default to 0 which results in the TP not working. */ --#define CMD_MOUSE_TP 0x1a --#define SERIAL_MOUSE 0 /* Disable TP, force use of a serial mouse */ --#define PS2_MOUSE 1 /* Disable TP when using a PS/2 mouse */ --#define TP_PS2_MOUSE 2 /* Leave TP enabled when using a PS/2 mouse */ -- --#define CMD_CPU_OK 0xc2 -+enum ec_mouse_setting { -+ SERIAL_MOUSE = 0, /* Disable TP, force use of a serial mouse */ -+ PS2_MOUSE, /* Disable TP when using a PS/2 mouse */ -+ TP_PS2_MOUSE /* Leave TP enabled when using a PS/2 mouse */ -+}; - --#define CMD_RADIO_CTRL 0x2b - #define RADIO_CTRL_NUM_ARGS 3 - enum ec_radio_dev { - RADIO_WLAN = 0, -@@ -29,7 +33,7 @@ enum ec_radio_state { - RADIO_ON - }; - --u8 mec5035_mouse_touchpad(u8 setting); -+u8 mec5035_mouse_touchpad(enum ec_mouse_setting setting); - void mec5035_cpu_ok(void); - void mec5035_early_init(void); - void mec5035_control_radio(enum ec_radio_dev device, enum ec_radio_state state); --- -2.39.5 - diff --git a/config/coreboot/default/patches/0025-nb-intel-Disable-stack-overflow-debug-options.patch b/config/coreboot/default/patches/0025-nb-intel-Disable-stack-overflow-debug-options.patch new file mode 100644 index 00000000..696be518 --- /dev/null +++ b/config/coreboot/default/patches/0025-nb-intel-Disable-stack-overflow-debug-options.patch @@ -0,0 +1,187 @@ +From fc4c65f3bb807b9fc766745a70f92729b0b8d99e Mon Sep 17 00:00:00 2001 +From: Leah Rowe <leah@libreboot.org> +Date: Mon, 21 Apr 2025 02:58:47 +0100 +Subject: [PATCH 25/37] nb/intel/*: Disable stack overflow debug options + +Signed-off-by: Leah Rowe <leah@libreboot.org> +--- + src/northbridge/intel/e7505/Kconfig | 9 +++++++++ + src/northbridge/intel/gm45/Kconfig | 9 +++++++++ + src/northbridge/intel/haswell/Kconfig | 9 +++++++++ + src/northbridge/intel/i440bx/Kconfig | 13 +++++++++++++ + src/northbridge/intel/i945/Kconfig | 9 +++++++++ + src/northbridge/intel/ironlake/Kconfig | 9 +++++++++ + src/northbridge/intel/pineview/Kconfig | 9 +++++++++ + src/northbridge/intel/sandybridge/Kconfig | 9 +++++++++ + src/northbridge/intel/x4x/Kconfig | 9 +++++++++ + 9 files changed, 85 insertions(+) + +diff --git a/src/northbridge/intel/e7505/Kconfig b/src/northbridge/intel/e7505/Kconfig +index 039a7396f8..ddcb986f10 100644 +--- a/src/northbridge/intel/e7505/Kconfig ++++ b/src/northbridge/intel/e7505/Kconfig +@@ -7,3 +7,12 @@ config NORTHBRIDGE_INTEL_E7505 + select NO_CBFS_MCACHE + select SMM_TSEG + select NEED_SMALL_2MB_PAGE_TABLES ++ ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n +diff --git a/src/northbridge/intel/gm45/Kconfig b/src/northbridge/intel/gm45/Kconfig +index fc5df8b11a..95e3644b73 100644 +--- a/src/northbridge/intel/gm45/Kconfig ++++ b/src/northbridge/intel/gm45/Kconfig +@@ -58,4 +58,13 @@ config FIXED_DMIBAR_MMIO_BASE + config FIXED_EPBAR_MMIO_BASE + default 0xfed19000 + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + endif +diff --git a/src/northbridge/intel/haswell/Kconfig b/src/northbridge/intel/haswell/Kconfig +index 6191cb6ccf..0f5b5c7241 100644 +--- a/src/northbridge/intel/haswell/Kconfig ++++ b/src/northbridge/intel/haswell/Kconfig +@@ -10,6 +10,15 @@ config NORTHBRIDGE_INTEL_HASWELL + + if NORTHBRIDGE_INTEL_HASWELL + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + config USE_NATIVE_RAMINIT + bool "[NOT COMPLETE] Use native raminit" + default n +diff --git a/src/northbridge/intel/i440bx/Kconfig b/src/northbridge/intel/i440bx/Kconfig +index dbb2d7436b..5e9418b6a9 100644 +--- a/src/northbridge/intel/i440bx/Kconfig ++++ b/src/northbridge/intel/i440bx/Kconfig +@@ -19,3 +19,16 @@ config SDRAMPWR_4DIMM + If your board has 4 DIMM slots, you must use select this option, in + your Kconfig file of the board. On boards with 3 DIMM slots, + do _not_ select this option. ++ ++if NORTHBRIDGE_INTEL_I440BX ++ ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ ++endif +diff --git a/src/northbridge/intel/i945/Kconfig b/src/northbridge/intel/i945/Kconfig +index 32eff1a611..9479d75c07 100644 +--- a/src/northbridge/intel/i945/Kconfig ++++ b/src/northbridge/intel/i945/Kconfig +@@ -89,4 +89,13 @@ config FIXED_DMIBAR_MMIO_BASE + config FIXED_EPBAR_MMIO_BASE + default 0xfed19000 + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + endif +diff --git a/src/northbridge/intel/ironlake/Kconfig b/src/northbridge/intel/ironlake/Kconfig +index 2bafebf92e..16b81705bb 100644 +--- a/src/northbridge/intel/ironlake/Kconfig ++++ b/src/northbridge/intel/ironlake/Kconfig +@@ -63,4 +63,13 @@ config FIXED_DMIBAR_MMIO_BASE + config FIXED_EPBAR_MMIO_BASE + default 0xfed19000 + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + endif +diff --git a/src/northbridge/intel/pineview/Kconfig b/src/northbridge/intel/pineview/Kconfig +index 59cfcd5e0a..a3ad8d3425 100644 +--- a/src/northbridge/intel/pineview/Kconfig ++++ b/src/northbridge/intel/pineview/Kconfig +@@ -42,4 +42,13 @@ config FIXED_EPBAR_MMIO_BASE + config DOMAIN_RESOURCE_32BIT_LIMIT + default 0xfec00000 + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + endif +diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig +index 973eed8bbd..6387cf926d 100644 +--- a/src/northbridge/intel/sandybridge/Kconfig ++++ b/src/northbridge/intel/sandybridge/Kconfig +@@ -208,4 +208,13 @@ config IGD_DEFAULT_UMA_INDEX + default 2 if IGD_DEFAULT_UMA_SIZE_96MB + default 3 if IGD_DEFAULT_UMA_SIZE_128MB + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + endif +diff --git a/src/northbridge/intel/x4x/Kconfig b/src/northbridge/intel/x4x/Kconfig +index 6430319f6a..1803ef5733 100644 +--- a/src/northbridge/intel/x4x/Kconfig ++++ b/src/northbridge/intel/x4x/Kconfig +@@ -53,4 +53,13 @@ config FIXED_DMIBAR_MMIO_BASE + config FIXED_EPBAR_MMIO_BASE + default 0xfed19000 + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + endif +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0026-soc-intel-skylake-configure-usb-acpi.patch b/config/coreboot/default/patches/0026-soc-intel-skylake-configure-usb-acpi.patch new file mode 100644 index 00000000..c411c18b --- /dev/null +++ b/config/coreboot/default/patches/0026-soc-intel-skylake-configure-usb-acpi.patch @@ -0,0 +1,94 @@ +From 14002b2575d73d3edbc72584502a463e6802cba6 Mon Sep 17 00:00:00 2001 +From: Felix Singer <felixsinger@posteo.net> +Date: Wed, 26 Jun 2024 04:24:31 +0200 +Subject: [PATCH 26/37] soc/intel/skylake: configure usb acpi + +Change-Id: I53fc73046e4b107064fa8c3c617ba6d9b807b71d +Signed-off-by: Felix Singer <felixsinger@posteo.net> +--- + src/soc/intel/skylake/Kconfig | 1 + + src/soc/intel/skylake/chipset.cb | 56 +++++++++++++++++++++++++++++++- + 2 files changed, 56 insertions(+), 1 deletion(-) + +diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig +index 4ad33496b2..9191ed0ff8 100644 +--- a/src/soc/intel/skylake/Kconfig ++++ b/src/soc/intel/skylake/Kconfig +@@ -10,6 +10,7 @@ config SOC_INTEL_COMMON_SKYLAKE_BASE + select CPU_INTEL_COMMON + select CPU_INTEL_FIRMWARE_INTERFACE_TABLE + select CPU_SUPPORTS_PM_TIMER_EMULATION ++ select DRIVERS_USB_ACPI + select EDK2_CPU_TIMER_LIB if PAYLOAD_EDK2 + select FSP_COMPRESS_FSP_S_LZ4 + select FSP_M_XIP +diff --git a/src/soc/intel/skylake/chipset.cb b/src/soc/intel/skylake/chipset.cb +index 6538a1475b..dfb81d496e 100644 +--- a/src/soc/intel/skylake/chipset.cb ++++ b/src/soc/intel/skylake/chipset.cb +@@ -13,7 +13,61 @@ chip soc/intel/skylake + device pci 07.0 alias chap off end + device pci 08.0 alias gmm off end # Gaussian Mixture Model + device pci 13.0 alias ish off end # SensorHub +- device pci 14.0 alias south_xhci off ops usb_xhci_ops end ++ device pci 14.0 alias south_xhci off ops usb_xhci_ops ++ chip drivers/usb/acpi ++ register "type" = "UPC_TYPE_HUB" ++ device usb 0.0 alias xhci_root_hub off ++ chip drivers/usb/acpi ++ device usb 2.0 alias usb2_port1 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.1 alias usb2_port2 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.2 alias usb2_port3 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.3 alias usb2_port4 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.4 alias usb2_port5 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.5 alias usb2_port6 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.6 alias usb2_port7 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.7 alias usb2_port8 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.8 alias usb2_port9 off end ++ end ++ chip drivers/usb/acpi ++ device usb 2.9 alias usb2_port10 off end ++ end ++ chip drivers/usb/acpi ++ device usb 3.0 alias usb3_port1 off end ++ end ++ chip drivers/usb/acpi ++ device usb 3.1 alias usb3_port2 off end ++ end ++ chip drivers/usb/acpi ++ device usb 3.2 alias usb3_port3 off end ++ end ++ chip drivers/usb/acpi ++ device usb 3.3 alias usb3_port4 off end ++ end ++ chip drivers/usb/acpi ++ device usb 3.4 alias usb3_port5 off end ++ end ++ chip drivers/usb/acpi ++ device usb 3.5 alias usb3_port6 off end ++ end ++ end ++ end ++ end + device pci 14.1 alias south_xdci off ops usb_xdci_ops end + device pci 14.2 alias thermal off end + device pci 14.3 alias cio off end +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0027-soc-intel-skylake-Enable-4E-4F-PNP-I-O-ports-in-boot.patch b/config/coreboot/default/patches/0027-soc-intel-skylake-Enable-4E-4F-PNP-I-O-ports-in-boot.patch new file mode 100644 index 00000000..9d75cec6 --- /dev/null +++ b/config/coreboot/default/patches/0027-soc-intel-skylake-Enable-4E-4F-PNP-I-O-ports-in-boot.patch @@ -0,0 +1,30 @@ +From 3bb65b7f2a02ecb93e15ae037da38ad8f812747b Mon Sep 17 00:00:00 2001 +From: Mate Kukri <km@mkukri.xyz> +Date: Fri, 22 Nov 2024 21:26:48 +0000 +Subject: [PATCH 27/37] soc/intel/skylake: Enable 4E/4F PNP I/O ports in + bootblock + +Change-Id: I57c9d8a9513a268e2ca6a0abd1306cd038598173 +Signed-off-by: Mate Kukri <km@mkukri.xyz> +--- + src/soc/intel/skylake/bootblock/pch.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/soc/intel/skylake/bootblock/pch.c b/src/soc/intel/skylake/bootblock/pch.c +index df00bb85a9..beaece960b 100644 +--- a/src/soc/intel/skylake/bootblock/pch.c ++++ b/src/soc/intel/skylake/bootblock/pch.c +@@ -100,8 +100,8 @@ static void soc_config_pwrmbase(void) + + void pch_early_iorange_init(void) + { +- uint16_t io_enables = LPC_IOE_SUPERIO_2E_2F | LPC_IOE_KBC_60_64 | +- LPC_IOE_EC_62_66; ++ uint16_t io_enables = LPC_IOE_EC_4E_4F | LPC_IOE_SUPERIO_2E_2F | ++ LPC_IOE_KBC_60_64 | LPC_IOE_EC_62_66; + + const config_t *config = config_of_soc(); + +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0028-mb-lenovo-Add-ThinkPad-T480-and-ThinkPad-T480s.patch b/config/coreboot/default/patches/0028-mb-lenovo-Add-ThinkPad-T480-and-ThinkPad-T480s.patch new file mode 100644 index 00000000..df71dc47 --- /dev/null +++ b/config/coreboot/default/patches/0028-mb-lenovo-Add-ThinkPad-T480-and-ThinkPad-T480s.patch @@ -0,0 +1,2232 @@ +From b515ba5b0cd02dc1771f27eaa716582b0827a638 Mon Sep 17 00:00:00 2001 +From: Mate Kukri <km@mkukri.xyz> +Date: Tue, 31 Dec 2024 22:49:15 +0000 +Subject: [PATCH 28/37] mb/lenovo: Add ThinkPad T480 and ThinkPad T480s + +These machine have BootGuard fused and requires deguard to +boot coreboot. + +Known issues: +- Alpine Ridge Thunderbolt 3 controller does not work +- Some Fn+F{1-12} keys aren't handled correctly +- Nvidia dGPU is finicky + - Needs option ROM + - Power enable code is buggy + - Nouveau only works on linux 6.8-6.9 +- Headphone jack isn't detected as plugged in despite correct verbs + +Thanks to Leah Rowe for helping with the T480s. + +Signed-off-by: Mate Kukri <km@mkukri.xyz> +Change-Id: I19d421412c771c1f242f6ff39453f824fa866163 +--- + src/device/pci_rom.c | 4 +- + src/ec/lenovo/h8/acpi/ec.asl | 2 +- + src/ec/lenovo/h8/bluetooth.c | 6 +- + src/ec/lenovo/h8/wwan.c | 6 +- + src/mainboard/lenovo/sklkbl_thinkpad/Kconfig | 57 +++++ + .../lenovo/sklkbl_thinkpad/Kconfig.name | 7 + + .../lenovo/sklkbl_thinkpad/Makefile.mk | 73 +++++++ + .../lenovo/sklkbl_thinkpad/acpi/ec.asl | 12 ++ + .../lenovo/sklkbl_thinkpad/acpi/superio.asl | 3 + + .../lenovo/sklkbl_thinkpad/bootblock.c | 60 ++++++ + .../lenovo/sklkbl_thinkpad/devicetree.cb | 71 ++++++ + src/mainboard/lenovo/sklkbl_thinkpad/dsdt.asl | 33 +++ + src/mainboard/lenovo/sklkbl_thinkpad/ec.c | 153 +++++++++++++ + src/mainboard/lenovo/sklkbl_thinkpad/ec.h | 99 +++++++++ + src/mainboard/lenovo/sklkbl_thinkpad/gpio.h | 8 + + .../lenovo/sklkbl_thinkpad/ramstage.c | 105 +++++++++ + .../sklkbl_thinkpad/variants/t480/data.vbt | Bin 0 -> 4106 bytes + .../variants/t480/gma-mainboard.ads | 19 ++ + .../sklkbl_thinkpad/variants/t480/gpio.c | 203 ++++++++++++++++++ + .../sklkbl_thinkpad/variants/t480/hda_verb.c | 90 ++++++++ + .../variants/t480/memory_init_params.c | 20 ++ + .../variants/t480/overridetree.cb | 103 +++++++++ + .../sklkbl_thinkpad/variants/t480s/data.vbt | Bin 0 -> 4106 bytes + .../variants/t480s/gma-mainboard.ads | 19 ++ + .../sklkbl_thinkpad/variants/t480s/gpio.c | 199 +++++++++++++++++ + .../sklkbl_thinkpad/variants/t480s/hda_verb.c | 90 ++++++++ + .../variants/t480s/memory_init_params.c | 44 ++++ + .../variants/t480s/overridetree.cb | 103 +++++++++ + .../variants/t480s/spd/spd_0.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_1.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_10.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_11.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_12.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_13.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_14.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_15.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_16.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_17.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_18.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_19.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_2.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_20.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_3.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_4.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_5.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_6.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_7.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_8.bin | Bin 0 -> 512 bytes + .../variants/t480s/spd/spd_9.bin | Bin 0 -> 512 bytes + 49 files changed, 1583 insertions(+), 6 deletions(-) + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/Kconfig + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/Kconfig.name + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/Makefile.mk + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/acpi/ec.asl + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/acpi/superio.asl + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/bootblock.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/devicetree.cb + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/dsdt.asl + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/ec.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/ec.h + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/gpio.h + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/ramstage.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/data.vbt + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/gma-mainboard.ads + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/gpio.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/hda_verb.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/memory_init_params.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/overridetree.cb + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/data.vbt + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/gma-mainboard.ads + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/gpio.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/hda_verb.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/memory_init_params.c + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/overridetree.cb + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_0.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_1.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_10.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_11.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_12.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_13.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_14.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_15.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_16.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_17.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_18.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_19.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_2.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_20.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_3.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_4.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_5.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_6.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_7.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_8.bin + create mode 100644 src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_9.bin + +diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c +index dc41ef14ce..bba98d9dea 100644 +--- a/src/device/pci_rom.c ++++ b/src/device/pci_rom.c +@@ -396,14 +396,16 @@ void pci_rom_ssdt(const struct device *device) + rom = cbrom; + } + ++#if 0 + const char *scope = acpi_device_path(device); + if (!scope) { + printk(BIOS_ERR, "%s: Missing ACPI scope\n", dev_path(device)); + return; + } ++#endif + + /* write _ROM method */ +- acpigen_write_scope(scope); ++ acpigen_write_scope("\\_SB.PCI0.RP01.PEGP"); + acpigen_write_rom((void *)rom, rom->size * 512); + acpigen_pop_len(); /* pop scope */ + } +diff --git a/src/ec/lenovo/h8/acpi/ec.asl b/src/ec/lenovo/h8/acpi/ec.asl +index bc54d3b422..8f4a8e1986 100644 +--- a/src/ec/lenovo/h8/acpi/ec.asl ++++ b/src/ec/lenovo/h8/acpi/ec.asl +@@ -331,7 +331,7 @@ Device(EC) + #include "sleepbutton.asl" + #include "lid.asl" + #include "beep.asl" +-#include "thermal.asl" ++//#include "thermal.asl" + #include "systemstatus.asl" + #include "thinkpad.asl" + } +diff --git a/src/ec/lenovo/h8/bluetooth.c b/src/ec/lenovo/h8/bluetooth.c +index 16fc8dce39..be71a24ced 100644 +--- a/src/ec/lenovo/h8/bluetooth.c ++++ b/src/ec/lenovo/h8/bluetooth.c +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + +-#include <southbridge/intel/common/gpio.h> ++// #include <southbridge/intel/common/gpio.h> + #include <console/console.h> + #include <device/device.h> + #include <ec/acpi/ec.h> +@@ -28,16 +28,18 @@ bool h8_has_bdc(const struct device *dev) + { + struct ec_lenovo_h8_config *conf = dev->chip_info; + +- if (!conf->has_bdc_detection) { ++ if (1 || !conf->has_bdc_detection) { + printk(BIOS_INFO, "H8: BDC detection not implemented. " + "Assuming BDC installed\n"); + return true; + } + ++#if 0 + if (get_gpio(conf->bdc_gpio_num) == conf->bdc_gpio_lvl) { + printk(BIOS_INFO, "H8: BDC installed\n"); + return true; + } ++#endif + + printk(BIOS_INFO, "H8: BDC not installed\n"); + return false; +diff --git a/src/ec/lenovo/h8/wwan.c b/src/ec/lenovo/h8/wwan.c +index 685886fcce..5cdcf77406 100644 +--- a/src/ec/lenovo/h8/wwan.c ++++ b/src/ec/lenovo/h8/wwan.c +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + +-#include <southbridge/intel/common/gpio.h> ++// #include <southbridge/intel/common/gpio.h> + #include <console/console.h> + #include <device/device.h> + #include <ec/acpi/ec.h> +@@ -26,16 +26,18 @@ bool h8_has_wwan(const struct device *dev) + { + struct ec_lenovo_h8_config *conf = dev->chip_info; + +- if (!conf->has_wwan_detection) { ++ if (1 || !conf->has_wwan_detection) { + printk(BIOS_INFO, "H8: WWAN detection not implemented. " + "Assuming WWAN installed\n"); + return true; + } + ++#if 0 + if (get_gpio(conf->wwan_gpio_num) == conf->wwan_gpio_lvl) { + printk(BIOS_INFO, "H8: WWAN installed\n"); + return true; + } ++#endif + + printk(BIOS_INFO, "H8: WWAN not installed\n"); + return false; +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/Kconfig b/src/mainboard/lenovo/sklkbl_thinkpad/Kconfig +new file mode 100644 +index 0000000000..4998672943 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/Kconfig +@@ -0,0 +1,57 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++config BOARD_LENOVO_SKLKBL_THINKPAD_COMMON ++ bool ++ select BOARD_ROMSIZE_KB_16384 ++ select EC_LENOVO_H8 ++ select EC_LENOVO_PMH7 ++ select H8_HAS_BAT_THRESHOLDS_IMPL ++ select H8_HAS_LEDLOGO ++ select H8_HAS_PRIMARY_FN_KEYS ++ select HAVE_ACPI_RESUME ++ select HAVE_ACPI_TABLES ++ select INTEL_GMA_HAVE_VBT ++ select INTEL_INT15 ++ select MAINBOARD_HAS_LIBGFXINIT ++ select MAINBOARD_HAS_TPM2 ++ select MAINBOARD_USES_IFD_GBE_REGION ++ select MEMORY_MAPPED_TPM ++ select SOC_INTEL_COMMON_BLOCK_HDA_VERB ++ select SOC_INTEL_KABYLAKE ++ select SPD_READ_BY_WORD ++ select SYSTEM_TYPE_LAPTOP ++ ++config BOARD_LENOVO_T480 ++ bool ++ select BOARD_LENOVO_SKLKBL_THINKPAD_COMMON ++ ++config BOARD_LENOVO_T480S ++ bool ++ select BOARD_LENOVO_SKLKBL_THINKPAD_COMMON ++ ++if BOARD_LENOVO_SKLKBL_THINKPAD_COMMON ++ ++config MAINBOARD_DIR ++ default "lenovo/sklkbl_thinkpad" ++ ++config VARIANT_DIR ++ default "t480" if BOARD_LENOVO_T480 ++ default "t480s" if BOARD_LENOVO_T480S ++ ++config OVERRIDE_DEVICETREE ++ default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb" ++ ++config MAINBOARD_PART_NUMBER ++ default "T480" if BOARD_LENOVO_T480 ++ default "T480s" if BOARD_LENOVO_T480S ++ ++config CBFS_SIZE ++ default 0x900000 ++ ++config DIMM_MAX ++ default 2 ++ ++config DIMM_SPD_SIZE ++ default 512 # DDR4 ++ ++endif +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/Kconfig.name b/src/mainboard/lenovo/sklkbl_thinkpad/Kconfig.name +new file mode 100644 +index 0000000000..abc273f387 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/Kconfig.name +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++config BOARD_LENOVO_T480 ++ bool "ThinkPad T480" ++ ++config BOARD_LENOVO_T480S ++ bool "ThinkPad T480s" +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/Makefile.mk b/src/mainboard/lenovo/sklkbl_thinkpad/Makefile.mk +new file mode 100644 +index 0000000000..c308239177 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/Makefile.mk +@@ -0,0 +1,73 @@ ++## SPDX-License-Identifier: GPL-2.0-only ++ ++bootblock-y += bootblock.c ec.c ++ ++romstage-y += variants/$(VARIANT_DIR)/memory_init_params.c ++ ++ramstage-y += ramstage.c ec.c ++ramstage-y += variants/$(VARIANT_DIR)/gpio.c variants/$(VARIANT_DIR)/hda_verb.c ++ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += variants/$(VARIANT_DIR)/gma-mainboard.ads ++ ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_0.bin ++spd_0.bin-file := variants/$(VARIANT_DIR)/spd/spd_0.bin ++spd_0.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_1.bin ++spd_1.bin-file := variants/$(VARIANT_DIR)/spd/spd_1.bin ++spd_1.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_2.bin ++spd_2.bin-file := variants/$(VARIANT_DIR)/spd/spd_2.bin ++spd_2.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_3.bin ++spd_3.bin-file := variants/$(VARIANT_DIR)/spd/spd_3.bin ++spd_3.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_4.bin ++spd_4.bin-file := variants/$(VARIANT_DIR)/spd/spd_4.bin ++spd_4.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_5.bin ++spd_5.bin-file := variants/$(VARIANT_DIR)/spd/spd_5.bin ++spd_5.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_6.bin ++spd_6.bin-file := variants/$(VARIANT_DIR)/spd/spd_6.bin ++spd_6.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_7.bin ++spd_7.bin-file := variants/$(VARIANT_DIR)/spd/spd_7.bin ++spd_7.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_8.bin ++spd_8.bin-file := variants/$(VARIANT_DIR)/spd/spd_8.bin ++spd_8.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_9.bin ++spd_9.bin-file := variants/$(VARIANT_DIR)/spd/spd_9.bin ++spd_9.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_10.bin ++spd_10.bin-file := variants/$(VARIANT_DIR)/spd/spd_10.bin ++spd_10.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_11.bin ++spd_11.bin-file := variants/$(VARIANT_DIR)/spd/spd_11.bin ++spd_11.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_12.bin ++spd_12.bin-file := variants/$(VARIANT_DIR)/spd/spd_12.bin ++spd_12.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_13.bin ++spd_13.bin-file := variants/$(VARIANT_DIR)/spd/spd_13.bin ++spd_13.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_14.bin ++spd_14.bin-file := variants/$(VARIANT_DIR)/spd/spd_14.bin ++spd_14.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_15.bin ++spd_15.bin-file := variants/$(VARIANT_DIR)/spd/spd_15.bin ++spd_15.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_16.bin ++spd_16.bin-file := variants/$(VARIANT_DIR)/spd/spd_16.bin ++spd_16.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_17.bin ++spd_17.bin-file := variants/$(VARIANT_DIR)/spd/spd_17.bin ++spd_17.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_18.bin ++spd_18.bin-file := variants/$(VARIANT_DIR)/spd/spd_18.bin ++spd_18.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_19.bin ++spd_19.bin-file := variants/$(VARIANT_DIR)/spd/spd_19.bin ++spd_19.bin-type := raw ++cbfs-files-$(CONFIG_BOARD_LENOVO_T480S) += spd_20.bin ++spd_20.bin-file := variants/$(VARIANT_DIR)/spd/spd_20.bin ++spd_20.bin-type := raw +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/acpi/ec.asl b/src/mainboard/lenovo/sklkbl_thinkpad/acpi/ec.asl +new file mode 100644 +index 0000000000..3a949a2fca +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/acpi/ec.asl +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB ++#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB ++#define THINKPAD_EC_GPE 22 ++ ++Name(\TCRT, 100) ++Name(\TPSV, 90) ++Name(\FLVL, 0) ++ ++#include <ec/lenovo/h8/acpi/ec.asl> ++#include <ec/lenovo/h8/acpi/thinkpad_bat_thresholds_b0.asl> +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/acpi/superio.asl b/src/mainboard/lenovo/sklkbl_thinkpad/acpi/superio.asl +new file mode 100644 +index 0000000000..55b1db5b11 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/acpi/superio.asl +@@ -0,0 +1,3 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <drivers/pc80/pc/ps2_controller.asl> +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/bootblock.c b/src/mainboard/lenovo/sklkbl_thinkpad/bootblock.c +new file mode 100644 +index 0000000000..fb660dbdfa +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/bootblock.c +@@ -0,0 +1,60 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <arch/io.h> ++#include <bootblock_common.h> ++#include <device/pci.h> ++#include <soc/pci_devs.h> ++#include "ec.h" ++ ++static void configure_uart(uint16_t port, uint16_t iobase, uint8_t irqno) ++{ ++ microchip_pnp_enter_conf_state(port); ++ ++ // Select LPC I/F LDN ++ pnp_write(port, PNP_LDN_SELECT, LDN_LPCIF); ++ // Write UART BAR ++ pnp_write_le32(port, LPCIF_BAR_UART, (uint32_t) iobase << 16 | 0x8707); ++ // Set SIRQ4 to UART ++ pnp_write(port, LPCIF_SIRQ(irqno), LDN_UART); ++ ++ // Configure UART LDN ++ pnp_write(port, PNP_LDN_SELECT, LDN_UART); ++ pnp_write(port, UART_ACTIVATE, 0x01); ++ pnp_write(port, UART_CONFIG_SELECT, 0x00); ++ ++ microchip_pnp_exit_conf_state(port); ++ ++#ifdef CONFIG_BOARD_LENOVO_T480 ++ // Supply debug unlock key ++ debug_write_key(DEBUG_RW_KEY_IDX, debug_rw_key); ++ ++ // Use debug writes to set UART_TX and UART_RX GPIOs ++ debug_write_dword(0xf0c400 + 0x110, 0x00001000); ++ debug_write_dword(0xf0c400 + 0x114, 0x00001000); ++#endif ++} ++ ++ ++#define UART_PORT 0x3f8 ++#define UART_IRQ 4 ++ ++void bootblock_mainboard_early_init(void) ++{ ++ // Tell EC via BIOS Debug Port 1 that the world isn't on fire ++ ++ // Let the EC know that BIOS code is running ++ outb(0x11, 0x86); ++ outb(0x6e, 0x86); ++ ++ // Enable accesses to EC1 interface ++ ec0_write(0, ec0_read(0) | 0x20); ++ ++ // Reset LEDs to power on state ++ // (Without this warm reboot leaves LEDs off) ++ ec0_write(0x0c, 0x80); ++ ec0_write(0x0c, 0x07); ++ ec0_write(0x0c, 0x8a); ++ ++ // Setup debug UART ++ configure_uart(EC_CFG_PORT, UART_PORT, UART_IRQ); ++} +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/devicetree.cb b/src/mainboard/lenovo/sklkbl_thinkpad/devicetree.cb +new file mode 100644 +index 0000000000..c07d4d53ca +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/devicetree.cb +@@ -0,0 +1,71 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++chip soc/intel/skylake ++ # IGD Displays ++ register "gfx" = "GMA_STATIC_DISPLAYS(0)" ++ ++ register "panel_cfg" = "{ ++ .up_delay_ms = 200, ++ .down_delay_ms = 50, ++ .cycle_delay_ms = 600, ++ .backlight_on_delay_ms = 1, ++ .backlight_off_delay_ms = 200, ++ .backlight_pwm_hz = 200, ++ }" ++ ++ # Power ++ register "PmConfigSlpS3MinAssert" = "2" # 50ms ++ register "PmConfigSlpS4MinAssert" = "1" # 1s ++ register "PmConfigSlpSusMinAssert" = "3" # 500ms ++ register "PmConfigSlpAMinAssert" = "3" # 2s ++ ++ device domain 0 on ++ device ref igpu on end ++ device ref sa_thermal on end ++ device ref thermal on end ++ device ref south_xhci on end ++ device ref lpc_espi on ++ register "serirq_mode" = "SERIRQ_CONTINUOUS" ++ ++ register "gen1_dec" = "0x007c1601" ++ register "gen2_dec" = "0x000c15e1" ++ ++ chip ec/lenovo/pmh7 ++ register "backlight_enable" = "true" ++ register "dock_event_enable" = "true" ++ device pnp ff.1 on end # dummy ++ end ++ ++ chip ec/lenovo/h8 ++ register "beepmask0" = "0x00" ++ register "beepmask1" = "0x86" ++ register "config0" = "0xa6" ++ register "config1" = "0x0d" ++ register "config2" = "0xa8" ++ register "config3" = "0xc4" ++ register "has_keyboard_backlight" = "1" ++ register "event2_enable" = "0xff" ++ register "event3_enable" = "0xff" ++ register "event4_enable" = "0xd0" ++ register "event5_enable" = "0x3c" ++ register "event7_enable" = "0x01" ++ register "event8_enable" = "0x7b" ++ register "event9_enable" = "0xff" ++ register "eventc_enable" = "0xff" ++ register "eventd_enable" = "0xff" ++ register "evente_enable" = "0x9d" ++ device pnp ff.2 on # dummy ++ io 0x60 = 0x62 ++ io 0x62 = 0x66 ++ io 0x64 = 0x1600 ++ io 0x66 = 0x1604 ++ end ++ end ++ ++ chip drivers/pc80/tpm ++ device pnp 0c31.0 on end ++ end ++ end ++ device ref hda on end ++ end ++end +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/dsdt.asl b/src/mainboard/lenovo/sklkbl_thinkpad/dsdt.asl +new file mode 100644 +index 0000000000..aa4d4de2a6 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/dsdt.asl +@@ -0,0 +1,33 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <acpi/acpi.h> ++DefinitionBlock( ++ "dsdt.aml", ++ "DSDT", ++ ACPI_DSDT_REV_2, ++ OEM_ID, ++ ACPI_TABLE_CREATOR, ++ 0x20110725 ++) ++{ ++ #include <acpi/dsdt_top.asl> ++ #include <soc/intel/common/block/acpi/acpi/globalnvs.asl> ++ #include <cpu/intel/common/acpi/cpu.asl> ++ ++ Device (\_SB.PCI0) ++ { ++ #include <soc/intel/skylake/acpi/systemagent.asl> ++ #include <soc/intel/skylake/acpi/pch.asl> ++ #include <drivers/intel/gma/acpi/default_brightness_levels.asl> ++ } ++ ++ Scope (\_SB.PCI0.RP01) ++ { ++ Device (PEGP) ++ { ++ Name (_ADR, Zero) ++ } ++ } ++ ++ #include <southbridge/intel/common/acpi/sleepstates.asl> ++} +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/ec.c b/src/mainboard/lenovo/sklkbl_thinkpad/ec.c +new file mode 100644 +index 0000000000..adb6a60324 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/ec.c +@@ -0,0 +1,153 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <arch/io.h> ++#include "ec.h" ++ ++#define MICROCHIP_CONFIGURATION_ENTRY_KEY 0x55 ++#define MICROCHIP_CONFIGURATION_EXIT_KEY 0xaa ++ ++void microchip_pnp_enter_conf_state(uint16_t port) ++{ ++ outb(MICROCHIP_CONFIGURATION_ENTRY_KEY, port); ++} ++ ++void microchip_pnp_exit_conf_state(uint16_t port) ++{ ++ outb(MICROCHIP_CONFIGURATION_EXIT_KEY, port); ++} ++ ++uint8_t pnp_read(uint16_t port, uint8_t index) ++{ ++ outb(index, port); ++ return inb(port + 1); ++} ++ ++uint32_t pnp_read_le32(uint16_t port, uint8_t index) ++{ ++ return (uint32_t) pnp_read(port, index) | ++ (uint32_t) pnp_read(port, index + 1) << 8 | ++ (uint32_t) pnp_read(port, index + 2) << 16 | ++ (uint32_t) pnp_read(port, index + 3) << 24; ++} ++ ++void pnp_write(uint16_t port, uint8_t index, uint8_t value) ++{ ++ outb(index, port); ++ outb(value, port + 1); ++} ++ ++void pnp_write_le32(uint16_t port, uint8_t index, uint32_t value) ++{ ++ pnp_write(port, index, value & 0xff); ++ pnp_write(port, index + 1, value >> 8 & 0xff); ++ pnp_write(port, index + 2, value >> 16 & 0xff); ++ pnp_write(port, index + 3, value >> 24 & 0xff); ++} ++ ++static void ecN_clear_out_queue(uint16_t cmd_port, uint16_t data_port) ++{ ++ while (inb(cmd_port) & EC_OBF) ++ inb(data_port); ++} ++ ++static void ecN_wait_to_send(uint16_t cmd_port, uint16_t data_port) ++{ ++ while (inb(cmd_port) & EC_IBF) ++ ; ++} ++ ++static void ecN_wait_to_recv(uint16_t cmd_port, uint16_t data_port) ++{ ++ while (!(inb(cmd_port) & EC_OBF)) ++ ; ++} ++ ++uint8_t ecN_read(uint16_t cmd_port, uint16_t data_port, uint8_t addr) ++{ ++ ecN_clear_out_queue(cmd_port, data_port); ++ ecN_wait_to_send(cmd_port, data_port); ++ outb(EC_READ, cmd_port); ++ ecN_wait_to_send(cmd_port, data_port); ++ outb(addr, data_port); ++ ecN_wait_to_recv(cmd_port, data_port); ++ return inb(data_port); ++} ++ ++void ecN_write(uint16_t cmd_port, uint16_t data_port, uint8_t addr, uint8_t val) ++{ ++ ecN_clear_out_queue(cmd_port, data_port); ++ ecN_wait_to_send(cmd_port, data_port); ++ outb(EC_WRITE, cmd_port); ++ ecN_wait_to_send(cmd_port, data_port); ++ outb(addr, data_port); ++ ecN_wait_to_send(cmd_port, data_port); ++ outb(val, data_port); ++} ++ ++uint8_t eeprom_read(uint16_t addr) ++{ ++ ecN_clear_out_queue(EC2_CMD, EC2_DATA); ++ ecN_wait_to_send(EC2_CMD, EC2_DATA); ++ outl(1, EC2_CMD); ++ ecN_wait_to_send(EC2_CMD, EC2_DATA); ++ outl(addr, EC2_DATA); ++ ecN_wait_to_recv(EC2_CMD, EC2_DATA); ++ return inl(EC2_DATA); ++} ++ ++void eeprom_write(uint16_t addr, uint8_t val) ++{ ++ ecN_clear_out_queue(EC2_CMD, EC2_DATA); ++ ecN_wait_to_send(EC2_CMD, EC2_DATA); ++ outl(2, EC2_CMD); ++ ecN_wait_to_send(EC2_CMD, EC2_DATA); ++ outl((uint32_t) addr | (uint32_t) val << 16, EC2_DATA); ++ ecN_wait_to_recv(EC2_CMD, EC2_DATA); ++ inl(EC2_DATA); ++} ++ ++uint16_t debug_loaded_keys(void) ++{ ++ return (uint16_t) ec0_read(0x87) << 8 | (uint16_t) ec0_read(0x86); ++} ++ ++static void debug_cmd(uint8_t cmd) ++{ ++ ec0_write(EC_DEBUG_CMD, cmd); ++ while (ec0_read(EC_DEBUG_CMD) & 0x80) ++ ; ++} ++ ++void debug_read_key(uint8_t i, uint8_t *key) ++{ ++ debug_cmd(0x80 | (i & 0xf)); ++ for (int j = 0; j < 8; ++j) ++ key[j] = ec0_read(0x3e + j); ++} ++ ++void debug_write_key(uint8_t i, const uint8_t *key) ++{ ++ for (int j = 0; j < 8; ++j) ++ ec0_write(0x3e + j, key[j]); ++ debug_cmd(0xc0 | (i & 0xf)); ++} ++ ++uint32_t debug_read_dword(uint32_t addr) ++{ ++ ecN_clear_out_queue(EC3_CMD, EC3_DATA); ++ ecN_wait_to_send(EC3_CMD, EC3_DATA); ++ outl(addr << 8 | 0xE2, EC3_DATA); ++ ecN_wait_to_recv(EC3_CMD, EC3_DATA); ++ return inl(EC3_DATA); ++} ++ ++void debug_write_dword(uint32_t addr, uint32_t val) ++{ ++ ecN_clear_out_queue(EC3_CMD, EC3_DATA); ++ ecN_wait_to_send(EC3_CMD, EC3_DATA); ++ outl(addr << 8 | 0xEA, EC3_DATA); ++ ecN_wait_to_send(EC3_CMD, EC3_DATA); ++ outl(val, EC3_DATA); ++} ++ ++const uint8_t debug_rw_key[8] = { 0x7a, 0x41, 0xb1, 0x49, 0xfe, 0x21, 0x01, 0xcf }; +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/ec.h b/src/mainboard/lenovo/sklkbl_thinkpad/ec.h +new file mode 100644 +index 0000000000..d2963c8962 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/ec.h +@@ -0,0 +1,99 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef SKLKBL_THINKPAD_EC_H ++#define SKLKBL_THINKPAD_EC_H ++ ++// EC configuration base address ++#define EC_CFG_PORT 0x4e ++ ++// Chip global registers ++#define PNP_LDN_SELECT 0x07 ++# define LDN_UART 0x07 ++# define LDN_LPCIF 0x0c ++#define EC_DEVICE_ID 0x20 ++#define EC_DEVICE_REV 0x21 ++ ++// LPC I/F registers ++#define LPCIF_SIRQ(i) (0x40 + (i)) ++ ++#define LPCIF_BAR_CFG 0x60 ++#define LPCIF_BAR_MAILBOX 0x64 ++#define LPCIF_BAR_8042 0x68 ++#define LPCIF_BAR_ACPI_EC0 0x6c ++#define LPCIF_BAR_ACPI_EC1 0x70 ++#define LPCIF_BAR_ACPI_EC2 0x74 ++#define LPCIF_BAR_ACPI_EC3 0x78 ++#define LPCIF_BAR_ACPI_PM0 0x7c ++#define LPCIF_BAR_UART 0x80 ++#define LPCIF_BAR_FAST_KYBD 0x84 ++#define LPCIF_BAR_EMBED_FLASH 0x88 ++#define LPCIF_BAR_GP_SPI 0x8c ++#define LPCIF_BAR_EMI 0x90 ++#define LPCIF_BAR_PMH7 0x94 ++#define LPCIF_BAR_PORT80_DBG0 0x98 ++#define LPCIF_BAR_PORT80_DBG1 0x9c ++#define LPCIF_BAR_RTC 0xa0 ++ ++// UART registers ++#define UART_ACTIVATE 0x30 ++#define UART_CONFIG_SELECT 0xf0 ++ ++void microchip_pnp_enter_conf_state(uint16_t port); ++void microchip_pnp_exit_conf_state(uint16_t port); ++uint8_t pnp_read(uint16_t port, uint8_t index); ++uint32_t pnp_read_le32(uint16_t port, uint8_t index); ++void pnp_write(uint16_t port, uint8_t index, uint8_t value); ++void pnp_write_le32(uint16_t port, uint8_t index, uint32_t value); ++ ++#define EC0_CMD 0x0066 ++#define EC0_DATA 0x0062 ++#define EC1_CMD 0x1604 ++#define EC1_DATA 0x1600 ++#define EC2_CMD 0x1634 ++#define EC2_DATA 0x1630 ++#define EC3_CMD 0x161c ++#define EC3_DATA 0x1618 ++ ++#define EC_OBF (1 << 0) ++#define EC_IBF (1 << 1) ++ ++#define EC_READ 0x80 ++#define EC_WRITE 0x81 ++ ++uint8_t ecN_read(uint16_t cmd_port, uint16_t data_port, uint8_t addr); ++ ++void ecN_write(uint16_t cmd_port, uint16_t data_port, uint8_t addr, uint8_t val); ++ ++// EC0 and EC1 mostly are useful with the READ/WRITE commands ++#define ec0_read(addr) ecN_read(EC0_CMD, EC0_DATA, addr) ++#define ec0_write(addr, val) ecN_write(EC0_CMD, EC0_DATA, addr, val) ++#define ec1_read(addr) ecN_read(EC1_CMD, EC1_DATA, addr) ++#define ec1_write(addr, val) ecN_write(EC1_CMD, EC1_DATA, addr, val) ++ ++// Read from the emulated EEPROM ++uint8_t eeprom_read(uint16_t addr); ++ ++// Write to the emulated EEPROM ++void eeprom_write(uint16_t addr, uint8_t val); ++ ++// Read loaded debug key mask ++uint16_t debug_loaded_keys(void); ++ ++// The following location (via either EC0 or EC1) can be used to interact with the debug interface ++#define EC_DEBUG_CMD 0x3d ++ ++void debug_read_key(uint8_t i, uint8_t *key); ++ ++void debug_write_key(uint8_t i, const uint8_t *key); ++ ++uint32_t debug_read_dword(uint32_t addr); ++ ++void debug_write_dword(uint32_t addr, uint32_t val); ++ ++// RW unlock key index ++#define DEBUG_RW_KEY_IDX 1 ++ ++// RW unlock key for EC version N24HT37W ++extern const uint8_t debug_rw_key[8]; ++ ++#endif +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/gpio.h b/src/mainboard/lenovo/sklkbl_thinkpad/gpio.h +new file mode 100644 +index 0000000000..d89ed712d4 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/gpio.h +@@ -0,0 +1,8 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#ifndef GPIO_H ++#define GPIO_H ++ ++void variant_config_gpios(void); ++ ++#endif +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/ramstage.c b/src/mainboard/lenovo/sklkbl_thinkpad/ramstage.c +new file mode 100644 +index 0000000000..44c8578852 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/ramstage.c +@@ -0,0 +1,105 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <arch/io.h> ++#include <device/device.h> ++#include <drivers/intel/gma/int15.h> ++#include <option.h> ++#include <soc/ramstage.h> ++#include "ec.h" ++#include "gpio.h" ++ ++#define GPIO_GPU_RST GPP_E22 // active low ++#define GPIO_1R8VIDEO_AON_ON GPP_E23 ++ ++#define GPIO_DGFX_PWRGD GPP_F3 ++ ++#define GPIO_DISCRETE_PRESENCE GPP_D9 // active low ++#define GPIO_DGFX_VRAM_ID0 GPP_D11 ++#define GPIO_DGFX_VRAM_ID1 GPP_D12 ++ ++void mainboard_silicon_init_params(FSP_SIL_UPD *params) ++{ ++ static const char * const dgfx_vram_id_str[] = { "1GB", "2GB", "4GB", "N/A" }; ++ ++ int dgfx_vram_id; ++ ++ // Setup GPIOs ++ variant_config_gpios(); ++ ++ // Detect and enable dGPU ++ if (gpio_get(GPIO_DISCRETE_PRESENCE) == 0) { // active low ++ dgfx_vram_id = gpio_get(GPIO_DGFX_VRAM_ID0) | gpio_get(GPIO_DGFX_VRAM_ID1) << 1; ++ printk(BIOS_DEBUG, "Discrete GPU present with %s VRAM\n", dgfx_vram_id_str[dgfx_vram_id]); ++ ++ // NOTE: i pulled this GPU enable sequence from thin air ++ // it sometimes works but is buggy and the GPU disappears in some cases so disabling it by default. ++ // also unrelated to this enable sequence the nouveau driver only works on 6.8-6.9 kernels ++ if (get_uint_option("dgpu_enable", 0)) { ++ printk(BIOS_DEBUG, "Enabling discrete GPU\n"); ++ gpio_set(GPIO_1R8VIDEO_AON_ON, 1); // Enable GPU power rail ++ while (!gpio_get(GPIO_DGFX_PWRGD)) // Wait for power good signal from GPU ++ ; ++ gpio_set(GPIO_GPU_RST, 1); // Release GPU from reset ++ } else { ++ printk(BIOS_DEBUG, "Discrete GPU will remain disabled\n"); ++ } ++ ++ } else { ++ printk(BIOS_DEBUG, "Discrete GPU not present\n"); ++ } ++} ++ ++static void dump_ec_cfg(uint16_t port) ++{ ++ microchip_pnp_enter_conf_state(port); ++ ++ // Device info ++ printk(BIOS_DEBUG, "Device id %02x\n", pnp_read(port, EC_DEVICE_ID)); ++ printk(BIOS_DEBUG, "Device rev %02x\n", pnp_read(port, EC_DEVICE_REV)); ++ ++ // Switch to LPCIF LDN ++ pnp_write(port, PNP_LDN_SELECT, LDN_LPCIF); ++ ++ // Dump SIRQs ++ for (int i = 0; i <= 15; i += 1) ++ printk(BIOS_DEBUG, "SIRQ%d = %02x\n", i, pnp_read(port, LPCIF_SIRQ(i))); ++ ++ // Dump BARs ++ printk(BIOS_DEBUG, "BAR CFG = %08x\n", pnp_read_le32(port, LPCIF_BAR_CFG)); ++ printk(BIOS_DEBUG, "BAR MAILBOX = %08x\n", pnp_read_le32(port, LPCIF_BAR_MAILBOX)); ++ printk(BIOS_DEBUG, "BAR 8042 = %08x\n", pnp_read_le32(port, LPCIF_BAR_8042)); ++ printk(BIOS_DEBUG, "BAR ACPI_EC0 = %08x\n", pnp_read_le32(port, LPCIF_BAR_ACPI_EC0)); ++ printk(BIOS_DEBUG, "BAR ACPI_EC1 = %08x\n", pnp_read_le32(port, LPCIF_BAR_ACPI_EC1)); ++ printk(BIOS_DEBUG, "BAR ACPI_EC2 = %08x\n", pnp_read_le32(port, LPCIF_BAR_ACPI_EC2)); ++ printk(BIOS_DEBUG, "BAR ACPI_EC3 = %08x\n", pnp_read_le32(port, LPCIF_BAR_ACPI_EC3)); ++ printk(BIOS_DEBUG, "BAR ACPI_PM0 = %08x\n", pnp_read_le32(port, LPCIF_BAR_ACPI_PM0)); ++ printk(BIOS_DEBUG, "BAR UART = %08x\n", pnp_read_le32(port, LPCIF_BAR_UART)); ++ printk(BIOS_DEBUG, "BAR FAST_KYBD = %08x\n", pnp_read_le32(port, LPCIF_BAR_FAST_KYBD)); ++ printk(BIOS_DEBUG, "BAR EMBED_FLASH = %08x\n", pnp_read_le32(port, LPCIF_BAR_EMBED_FLASH)); ++ printk(BIOS_DEBUG, "BAR GP_SPI = %08x\n", pnp_read_le32(port, LPCIF_BAR_GP_SPI)); ++ printk(BIOS_DEBUG, "BAR EMI = %08x\n", pnp_read_le32(port, LPCIF_BAR_EMI)); ++ printk(BIOS_DEBUG, "BAR PMH7 = %08x\n", pnp_read_le32(port, LPCIF_BAR_PMH7)); ++ printk(BIOS_DEBUG, "BAR PORT80_DBG0 = %08x\n", pnp_read_le32(port, LPCIF_BAR_PORT80_DBG0)); ++ printk(BIOS_DEBUG, "BAR PORT80_DBG1 = %08x\n", pnp_read_le32(port, LPCIF_BAR_PORT80_DBG1)); ++ printk(BIOS_DEBUG, "BAR RTC = %08x\n", pnp_read_le32(port, LPCIF_BAR_RTC)); ++ ++ microchip_pnp_exit_conf_state(port); ++} ++ ++static void mainboard_enable(struct device *dev) ++{ ++ if (CONFIG(VGA_ROM_RUN)) ++ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_EDP, ++ GMA_INT15_PANEL_FIT_DEFAULT, ++ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); ++} ++ ++static void mainboard_init(void *chip_info) ++{ ++ dump_ec_cfg(EC_CFG_PORT); ++} ++ ++struct chip_operations mainboard_ops = { ++ .enable_dev = mainboard_enable, ++ .init = mainboard_init, ++}; +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/data.vbt b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/data.vbt +new file mode 100644 +index 0000000000000000000000000000000000000000..4db4202961d0be67b75f52b28f2111d5655595c3 +GIT binary patch +literal 4106 +zcmeHJU2GIp6h5=FKeKmc=rAo()>4l^U|XP_ZDGYy!|YE>mu}hZ4|PdQy1<TF-O}0? +zDF)LeX(GlTYoZ2xkUp4bc(Fbi;|s>bV0gipVB&+pHzmFpc`=IXxii}qiqH*)7}PU+ +z?woV)x!<09?wNbfhQa6n_IK}3M!Gw&OgS)sY2Q$LJ4F+z{-JneATkt9refXr6+8sr +zR{e1eASVcGl#mf_O&p%I^1;3af=xDeN0ZnydT=;zHOH-q=O;(UFda)^<j^52Z;c<A +zv~t)#xI2OzS7p&7!}%QUJu-688gD}mM%EbG*3`NU(Fiq%!p$v4=y8%;+qQ?>LXW8| +z-Vsanq!Y==Kq9plQ+*gu^hf&pJ9?tY{h01cbtR&SfsVM!_*!D4W5>papLuo?gRur| +zF$`lX;f2t48Dpd4V@(*z=dq95OkkfiVU53N<(gE+=U)KHEdU4}@R=aMjTTTOcb8-a +zC9IXSxZB*|#u~SlHnpsY25L#Sxy6ljl16gI)H0f>for?qaszCX;ESpG=pqROFWR~Z +zTqQzcH(berra`9K(R~0OJ_eeA<Ovbd&vdN3&y}qtJ`q3y6wpP2V}*{Dbi8b357>=> +z&R-)LYP^U3@%6h}+0)7m-mEOhOM92<j^WbYrTU_kNXz~GCDNT`I|IC3AsFzURKM6k +zQdYbOof5*Zq``6G)5LxcgKFZn#G8mi#5;*Qh*QM-i4PHv5FaHzLHru=Tg2yx{aFHb +z(R2S=c8RBfL#5J#E-BTphw@OA+GpyZ;G1*r11OzSMVJD%l2Wuxx^l~w*1QYefHUN4 +zpSM~1{wGHQJOdv7$#vPs;Ii+!aI*SVDadZ``zyQq-N$35E%P{WT}(AcpKmkH*)gyF +z|NhTLpsow9_zOk6x>l32>zpvu-&@ZkPf<>~Bsv&Oy1O(`pbLUf3vt*0HIRk0U3EzI +zIeSaIE9*jps%6qP7$EQo8=K#f^K_mFpy5prkNNSOU;oI@KK0}Ge*G6eyWz+6OyADf +zE`}D<k1}?G;rmSggt5;V{>b#-81u-uS=OJB*=`v}WPMs@ugdtLtbZo6OEUf}>!QL` +z1zQ!pLt!Zek0|;p3VTDrj}`q(g?+8yuZk|KY?X>TRlP@LPpbH`s-ITbSygS+Jq6cQ +zp|Em=T_#B53Y|R}mtw!K3mUyWRhytxx_wi^(}HurDkx@L%OlKIA%rq@7%bE{p{Wl~ +zJJ%lV6&>fxBjnbA8G(&P?a8o%P#c~Wo$7|%1UE-$r;6jwt1uejOfMLwF-BDgC-Q+N +za!Hx;1S&$9!rlNCTsI*IMZ0#Y5aEO7sjIz#jb`S|q7OpRYx`h&=PK}_YnN#poNF=7 +z3yTO|pc0N&G3cozl21Q6c)l0vjm~0uFL)%2_T5RYR1$~dO~u)4px!jFycZNnchPVA +z!0+Vc_afL{m>rv2PY8{Cma`W{yG~JNJu?;L!#fSLmwRW{8R@gD7Z5~{xvZGpN)U`j +z^I~=;XVmtVzgSv@Na@HC?lC8A1l2+CU<IqV7J%6_t~L}S#%I}a5R3FZk`D#n4m*-O +z$?u%iuC_w$3p=)&nXQX^AwrdnK*hRu`Mqc`AzOgztfsBxvm77j5G7KQo#~<Ufx}jQ +z?|~8PU!d?s-JLd{0Ph}c6J*Zsxd^=dPINEGPS4+NOQoUG&E#4_TUNoTPI5CrmHR%r +VymGKbcpH8Yo8|ycF3<xZ{s}94r0@U$ + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/gma-mainboard.ads b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/gma-mainboard.ads +new file mode 100644 +index 0000000000..fcfbd75a92 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/gma-mainboard.ads +@@ -0,0 +1,19 @@ ++-- SPDX-License-Identifier: GPL-2.0-or-later ++ ++with HW.GFX.GMA; ++with HW.GFX.GMA.Display_Probing; ++ ++use HW.GFX.GMA; ++use HW.GFX.GMA.Display_Probing; ++ ++private package GMA.Mainboard is ++ ++ ports : constant Port_List := ++ (eDP, ++ DP1, ++ DP2, ++ HDMI1, ++ HDMI2, ++ others => Disabled); ++ ++end GMA.Mainboard; +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/gpio.c b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/gpio.c +new file mode 100644 +index 0000000000..f7c29e1f39 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/gpio.c +@@ -0,0 +1,203 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <soc/gpio.h> ++#include "../../gpio.h" ++ ++/* FIXME: There are multiple GPIOs here that should be locked to prevent "TPM GPIO fail" style ++ * attacks. Unfortunately SKL/KBL GPIO locking *does not* work currently. */ ++ ++static const struct pad_config gpio_table[] = { ++ ++ /* ------- GPIO Community 0 ------- */ ++ ++ /* ------- GPIO Group GPP_A ------- */ ++ PAD_CFG_NF(GPP_A0, NONE, DEEP, NF1), /* -KBRC */ ++ PAD_CFG_NF(GPP_A1, NATIVE, DEEP, NF1), /* LPC_AD0 */ ++ PAD_CFG_NF(GPP_A2, NATIVE, DEEP, NF1), /* LPC_AD1 */ ++ PAD_CFG_NF(GPP_A3, NATIVE, DEEP, NF1), /* LPC_AD2 */ ++ PAD_CFG_NF(GPP_A4, NATIVE, DEEP, NF1), /* LPC_AD3 */ ++ PAD_CFG_NF(GPP_A5, NONE, DEEP, NF1), /* -LPC_FRAME */ ++ PAD_CFG_NF(GPP_A6, NONE, DEEP, NF1), /* IRQSER */ ++ PAD_CFG_NF(GPP_A7, NONE, DEEP, NF1), /* -TPM_IRQ */ ++ PAD_CFG_NF(GPP_A8, NONE, DEEP, NF1), /* -CLKRUN */ ++ PAD_CFG_NF(GPP_A9, NATIVE, DEEP, NF1), /* LPCCLK_EC_24M */ ++ PAD_CFG_NF(GPP_A10, NATIVE, DEEP, NF1), /* LPCCLK_DEBUG_24M */ ++ PAD_NC(GPP_A11, NONE), ++ PAD_NC(GPP_A12, NONE), ++ PAD_CFG_NF(GPP_A13, NATIVE, DEEP, NF1), /* -SUSWARN */ ++ PAD_CFG_NF(GPP_A14, NATIVE, DEEP, NF1), /* -SUS_STAT */ ++ PAD_CFG_NF(GPP_A15, NATIVE, DEEP, NF1), /* -SUSWARN */ ++ PAD_NC(GPP_A16, NONE), ++ PAD_NC(GPP_A17, NONE), ++ PAD_NC(GPP_A18, NONE), ++ PAD_NC(GPP_A19, NONE), ++ PAD_NC(GPP_A20, NONE), ++ PAD_NC(GPP_A21, NONE), ++ PAD_NC(GPP_A22, NONE), ++ PAD_NC(GPP_A23, NONE), ++ ++ /* ------- GPIO Group GPP_B ------- */ ++ PAD_NC(GPP_B0, NONE), ++ PAD_NC(GPP_B1, NONE), ++ PAD_NC(GPP_B2, NONE), ++ PAD_NC(GPP_B3, NONE), ++ PAD_CFG_GPI_SCI(GPP_B4, NONE, DEEP, EDGE_SINGLE, INVERT), /* -TBT_PLUG_EVENT */ ++ PAD_CFG_NF(GPP_B5, NONE, DEEP, NF1), /* -CLKREQ_PCIE0 */ ++ PAD_CFG_NF(GPP_B6, NONE, DEEP, NF1), /* -CLKREQ_PCIE4 */ ++ PAD_CFG_NF(GPP_B7, NONE, DEEP, NF1), /* -CLKREQ_PCIE5 */ ++ PAD_CFG_NF(GPP_B8, NONE, DEEP, NF1), /* -CLKREQ_PCIE6 */ ++ PAD_CFG_NF(GPP_B9, NONE, DEEP, NF1), /* -CLKREQ_PCIE8 */ ++ PAD_CFG_NF(GPP_B10, NONE, DEEP, NF1), /* -CLKREQ_PCIE10 */ ++ PAD_NC(GPP_B11, NONE), ++ PAD_CFG_NF(GPP_B12, NONE, DEEP, NF1), /* -PCH_SLP_S0 */ ++ PAD_CFG_NF(GPP_B13, NONE, DEEP, NF1), /* -PLTRST */ ++ PAD_CFG_NF(GPP_B14, NATIVE, DEEP, NF1), /* PCH_SPKR */ ++ PAD_CFG_GPO(GPP_B15, 1, DEEP), /* NFC_DLREQ */ ++ PAD_NC(GPP_B16, NONE), ++ PAD_NC(GPP_B17, NONE), ++ PAD_NC(GPP_B18, NONE), ++ PAD_NC(GPP_B19, NONE), ++ PAD_NC(GPP_B20, NONE), ++ PAD_NC(GPP_B21, NONE), ++ PAD_NC(GPP_B22, NONE), ++ PAD_NC(GPP_B23, NONE), ++ ++ /* ------- GPIO Community 1 ------- */ ++ ++ /* ------- GPIO Group GPP_C ------- */ ++ PAD_CFG_NF(GPP_C0, NONE, DEEP, NF1), /* SMB_CLK */ ++ PAD_CFG_NF(GPP_C1, NONE, DEEP, NF1), /* SMB_DATA */ ++ PAD_NC(GPP_C2, NONE), ++ PAD_CFG_NF(GPP_C3, NONE, DEEP, NF1), /* SML0_CLK */ ++ PAD_CFG_NF(GPP_C4, NONE, DEEP, NF1), /* SML0_DATA */ ++ PAD_NC(GPP_C5, NONE), ++ PAD_CFG_NF(GPP_C6, NONE, DEEP, NF1), /* EC_SCL2 */ ++ PAD_CFG_NF(GPP_C7, NONE, DEEP, NF1), /* EC_SDA2 */ ++ PAD_NC(GPP_C8, NONE), ++ PAD_NC(GPP_C9, NONE), ++ PAD_NC(GPP_C10, NONE), ++ PAD_NC(GPP_C11, NONE), ++ PAD_NC(GPP_C12, NONE), ++ PAD_NC(GPP_C13, NONE), ++ PAD_NC(GPP_C14, NONE), ++ PAD_NC(GPP_C15, NONE), ++ PAD_CFG_NF(GPP_C16, NONE, DEEP, NF1), /* I2C0_DATA */ ++ PAD_CFG_NF(GPP_C17, NONE, DEEP, NF1), /* I2C0_CLK */ ++ PAD_NC(GPP_C18, NONE), ++ PAD_NC(GPP_C19, NONE), ++ PAD_CFG_GPO(GPP_C20, 0, DEEP), /* EPRIVACY_ON */ ++ PAD_CFG_GPO(GPP_C21, 0, DEEP), /* TBT_FORCE_PWR */ ++ PAD_CFG_GPI_SCI(GPP_C22, NONE, DEEP, EDGE_SINGLE, INVERT), /* -EC_SCI */ ++ PAD_CFG_GPI_SCI(GPP_C23, NONE, DEEP, EDGE_SINGLE, INVERT), /* -EC_WAKE */ ++ ++ /* ------- GPIO Group GPP_D ------- */ ++ PAD_NC(GPP_D0, NONE), ++ PAD_NC(GPP_D1, NONE), ++ PAD_NC(GPP_D2, NONE), ++ PAD_NC(GPP_D3, NONE), ++ PAD_NC(GPP_D4, NONE), ++ PAD_NC(GPP_D5, NONE), ++ PAD_NC(GPP_D6, NONE), ++ PAD_NC(GPP_D7, NONE), ++ PAD_NC(GPP_D8, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_D9, UP_20K, DEEP, OFF, ACPI), /* -DISCRETE_PRESENCE */ ++ PAD_NC(GPP_D10, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_D11, UP_20K, DEEP, OFF, ACPI), /* DGFX_VRAM_ID0 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_D12, UP_20K, DEEP, OFF, ACPI), /* DGFX_VRAM_ID1 */ ++ PAD_NC(GPP_D13, NONE), ++ PAD_NC(GPP_D14, NONE), ++ PAD_NC(GPP_D15, NONE), ++ PAD_NC(GPP_D16, NONE), ++ PAD_CFG_GPO(GPP_D17, 0, DEEP), /* DDI_PRIORITY1 */ ++ PAD_NC(GPP_D18, NONE), ++ PAD_NC(GPP_D19, NONE), ++ PAD_NC(GPP_D20, NONE), ++ PAD_NC(GPP_D21, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_D22, UP_20K, DEEP, OFF, ACPI), /* -NFC_DTCT */ ++ PAD_NC(GPP_D23, NONE), ++ ++ /* ------- GPIO Group GPP_E ------- */ ++ PAD_NC(GPP_E0, NONE), ++ PAD_CFG_NF(GPP_E1, NONE, DEEP, NF1), /* -WWAN_SATA_DTCT (always HIGH) */ ++ PAD_CFG_NF(GPP_E2, NONE, DEEP, NF1), /* -PE_DTCT */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_E3, NONE, DEEP, EDGE_SINGLE, ACPI), /* -TBT_PLUG_EVENT */ ++ PAD_CFG_GPO(GPP_E4, 1, DEEP), /* NFC_ON */ ++ PAD_NC(GPP_E5, NONE), ++ PAD_CFG_NF(GPP_E6, NONE, RSMRST, NF1), /* SATA2_DEVSLP */ ++ PAD_NC(GPP_E7, NONE), ++ PAD_NC(GPP_E8, NONE), ++ PAD_CFG_NF(GPP_E9, NONE, DEEP, NF1), /* -USB_PORT0_OC0 (AON port) */ ++ PAD_CFG_NF(GPP_E10, NONE, DEEP, NF1), /* -USB_PORT1_OC1 (regular port) */ ++ PAD_NC(GPP_E11, NONE), ++ PAD_CFG_GPI_APIC_HIGH(GPP_E12, NONE, DEEP), /* NFC_INT */ ++ PAD_CFG_NF(GPP_E13, NONE, DEEP, NF1), /* DDIP1_HPD */ ++ PAD_CFG_NF(GPP_E14, NONE, DEEP, NF1), /* DDIP2_HPD */ ++ PAD_NC(GPP_E15, NONE), ++ PAD_NC(GPP_E16, NONE), ++ PAD_CFG_NF(GPP_E17, NONE, DEEP, NF1), /* EDP_HPD */ ++ PAD_NC(GPP_E18, NONE), ++ PAD_NC(GPP_E19, NONE), ++ PAD_CFG_NF(GPP_E20, NONE, DEEP, NF1), /* DDIP2_CTRLCLK */ ++ PAD_CFG_NF(GPP_E21, NONE, DEEP, NF1), /* DDIP2_CTRLDATA */ ++ PAD_CFG_TERM_GPO(GPP_E22, 0, UP_20K, RSMRST), /* -GPU_RST */ ++ PAD_CFG_TERM_GPO(GPP_E23, 0, UP_20K, RSMRST), /* 1R8VIDEO_AON_ON */ ++ ++ /* ------- GPIO Community 2 ------- */ ++ ++ /* -------- GPIO Group GPD -------- */ ++ PAD_CFG_NF(GPD0, NONE, PWROK, NF1), /* -BATLOW */ ++ PAD_CFG_NF(GPD1, NATIVE, PWROK, NF1), /* AC_PRESENT */ ++ PAD_CFG_NF(GPD2, NATIVE, PWROK, NF1), /* -LANWAKE */ ++ PAD_CFG_NF(GPD3, UP_20K, PWROK, NF1), /* -PWRSW_EC */ ++ PAD_CFG_NF(GPD4, NONE, PWROK, NF1), /* -PCH_SLP_S3 */ ++ PAD_CFG_NF(GPD5, NONE, PWROK, NF1), /* -PCH_SLP_S4 */ ++ PAD_CFG_NF(GPD6, NONE, PWROK, NF1), /* -PCH_SLP_M */ ++ PAD_NC(GPD7, NONE), ++ PAD_CFG_NF(GPD8, NONE, PWROK, NF1), /* SUSCLK_32K */ ++ PAD_CFG_NF(GPD9, NONE, PWROK, NF1), /* -PCH_SLP_WLAN */ ++ PAD_CFG_NF(GPD10, NONE, PWROK, NF1), /* -PCH_SLP_S5 */ ++ PAD_CFG_NF(GPD11, NONE, PWROK, NF1), /* LANPHYPC */ ++ ++ /* ------- GPIO Community 3 ------- */ ++ ++ /* ------- GPIO Group GPP_F ------- */ ++ PAD_NC(GPP_F0, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_F1, NONE, DEEP, OFF, ACPI), /* GC6_FB_EN */ ++ PAD_CFG_GPO(GPP_F2, 1, DEEP), /* -GPU_EVENT */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F3, NONE, DEEP, OFF, ACPI), /* DGFX_PWRGD */ ++ PAD_CFG_GPO(GPP_F4, 1, DEEP), /* -WWAN_RESET */ ++ PAD_NC(GPP_F5, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_F6, UP_20K, DEEP, OFF, ACPI), /* -MIC_HW_EN (R961 to GND) */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F7, UP_20K, DEEP, OFF, ACPI), /* -INT_MIC_DTCT */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F8, UP_20K, DEEP, OFF, ACPI), /* WWAN_CFG0 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F9, UP_20K, DEEP, OFF, ACPI), /* WWAN_CFG1 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F10, UP_20K, DEEP, OFF, ACPI), /* WWAN_CFG2 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F11, UP_20K, DEEP, OFF, ACPI), /* WWAN_CFG3 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F12, UP_20K, DEEP, OFF, ACPI), /* PLANARID0 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F13, UP_20K, DEEP, OFF, ACPI), /* PLANARID1 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F14, UP_20K, DEEP, OFF, ACPI), /* PLANARID2 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F15, UP_20K, DEEP, OFF, ACPI), /* PLANARID3 */ ++ PAD_NC(GPP_F16, NONE), ++ PAD_NC(GPP_F17, NONE), ++ PAD_NC(GPP_F18, NONE), ++ PAD_NC(GPP_F19, NONE), ++ PAD_NC(GPP_F20, NONE), ++ PAD_NC(GPP_F21, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_F22, UP_20K, DEEP, OFF, ACPI), /* -INTRUDER_PCH */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F23, UP_20K, DEEP, OFF, ACPI), /* -SC_DTCT */ ++ ++ /* ------- GPIO Group GPP_G ------- */ ++ PAD_NC(GPP_G0, NONE), ++ PAD_NC(GPP_G1, NONE), ++ PAD_NC(GPP_G2, NONE), ++ PAD_NC(GPP_G3, NONE), ++ PAD_CFG_GPO(GPP_G4, 0, DEEP), /* TBT_RTD3_PWR_EN */ ++ PAD_CFG_GPO(GPP_G5, 0, DEEP), /* TBT_FORCE_USB_PWR */ ++ PAD_CFG_GPO(GPP_G6, 0, DEEP), /* -TBT_PERST */ ++ PAD_CFG_GPI_SCI(GPP_G7, NONE, DEEP, LEVEL, INVERT), /* -TBT_PCIE_WAKE */ ++}; ++ ++void variant_config_gpios(void) ++{ ++ gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); ++} +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/hda_verb.c b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/hda_verb.c +new file mode 100644 +index 0000000000..3a951ce0da +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/hda_verb.c +@@ -0,0 +1,90 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <device/azalia_device.h> ++ ++const u32 cim_verb_data[] = { ++ 0x10ec0257, // Vendor/Device ID: Realtek ALC257 ++ 0x17aa225d, // Subsystem ID ++ 11, ++ AZALIA_SUBVENDOR(0, 0x17aa225d), ++ ++ AZALIA_PIN_CFG(0, 0x12, AZALIA_PIN_DESC( ++ AZALIA_INTEGRATED, ++ AZALIA_INTERNAL, ++ AZALIA_MIC_IN, ++ AZALIA_OTHER_DIGITAL, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_NO_JACK_PRESENCE_DETECT, ++ 2, 0 ++ )), ++ AZALIA_PIN_CFG(0, 0x13, 0x40000000), // does not describe a jack or internal device ++ AZALIA_PIN_CFG(0, 0x14, AZALIA_PIN_DESC( ++ AZALIA_INTEGRATED, ++ AZALIA_INTERNAL, ++ AZALIA_SPEAKER, ++ AZALIA_OTHER_ANALOG, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_NO_JACK_PRESENCE_DETECT, ++ 1, 0 ++ )), ++ AZALIA_PIN_CFG(0, 0x18, AZALIA_PIN_CFG_NC(0)), ++ AZALIA_PIN_CFG(0, 0x19, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_EXTERNAL_PRIMARY_CHASSIS | AZALIA_RIGHT, ++ AZALIA_MIC_IN, ++ AZALIA_STEREO_MONO_1_8, ++ AZALIA_BLACK, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 3, 0 ++ )), ++ AZALIA_PIN_CFG(0, 0x1a, AZALIA_PIN_CFG_NC(0)), ++ AZALIA_PIN_CFG(0, 0x1b, AZALIA_PIN_CFG_NC(0)), ++ AZALIA_PIN_CFG(0, 0x1d, 0x40661b45), // does not describe a jack or internal device ++ AZALIA_PIN_CFG(0, 0x1e, AZALIA_PIN_CFG_NC(0)), ++ AZALIA_PIN_CFG(0, 0x21, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_EXTERNAL_PRIMARY_CHASSIS | AZALIA_RIGHT, ++ AZALIA_HP_OUT, ++ AZALIA_STEREO_MONO_1_8, ++ AZALIA_BLACK, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 1, 15 ++ )), ++ ++ 0x8086280b, // Vendor/Device ID: Intel Kabylake HDMI ++ 0x80860101, // Subsystem ID ++ 4, ++ AZALIA_SUBVENDOR(2, 0x80860101), ++ ++ AZALIA_PIN_CFG(2, 0x05, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_DIGITAL_DISPLAY, ++ AZALIA_DIGITAL_OTHER_OUT, ++ AZALIA_OTHER_DIGITAL, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 1, 0 ++ )), ++ AZALIA_PIN_CFG(2, 0x06, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_DIGITAL_DISPLAY, ++ AZALIA_DIGITAL_OTHER_OUT, ++ AZALIA_OTHER_DIGITAL, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 2, 0 ++ )), ++ AZALIA_PIN_CFG(2, 0x07, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_DIGITAL_DISPLAY, ++ AZALIA_DIGITAL_OTHER_OUT, ++ AZALIA_OTHER_DIGITAL, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 3, 0 ++ )), ++}; ++ ++const u32 pc_beep_verbs[] = {}; ++ ++AZALIA_ARRAY_SIZES; +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/memory_init_params.c b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/memory_init_params.c +new file mode 100644 +index 0000000000..5252a402f9 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/memory_init_params.c +@@ -0,0 +1,20 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <soc/romstage.h> ++#include <spd_bin.h> ++ ++void mainboard_memory_init_params(FSPM_UPD *mupd) ++{ ++ FSP_M_CONFIG *mem_cfg = &mupd->FspmConfig; ++ mem_cfg->DqPinsInterleaved = true; /* DDR_DQ in interleave mode */ ++ mem_cfg->CaVrefConfig = 2; /* VREF_CA to CH_A and VREF_DQ_B to CH_B */ ++ mem_cfg->MemorySpdDataLen = CONFIG_DIMM_SPD_SIZE; ++ ++ /* Get SPD for memory slots */ ++ struct spd_block blk = { .addr_map = { 0x50, 0x51, } }; ++ get_spd_smbus(&blk); ++ dump_spd_info(&blk); ++ ++ mem_cfg->MemorySpdPtr00 = (uintptr_t)blk.spd_array[0]; ++ mem_cfg->MemorySpdPtr10 = (uintptr_t)blk.spd_array[1]; ++} +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/overridetree.cb b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/overridetree.cb +new file mode 100644 +index 0000000000..bf66bd3a69 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480/overridetree.cb +@@ -0,0 +1,103 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++chip soc/intel/skylake ++ device domain 0 on ++ device ref south_xhci on ++ register "usb2_ports" = "{ ++ [0] = USB2_PORT_MID(OC1), // USB-A ++ [1] = USB2_PORT_MID(OC0), // USB-A (always on) ++ [2] = USB2_PORT_MID(OC_SKIP), // JSC-1 (smartcard slot) ++ [3] = USB2_PORT_MID(OC_SKIP), // USB-C (charging port) ++ [4] = USB2_PORT_MID(OC_SKIP), // JCAM1 (IR camera) ++ [5] = USB2_PORT_MID(OC_SKIP), // JWWAN1 (M.2 WWAN USB) ++ [6] = USB2_PORT_MID(OC_SKIP), // JWLAN1 (M.2 WLAN USB) ++ [7] = USB2_PORT_MID(OC_SKIP), // JCAM1 (webcam) ++ [8] = USB2_PORT_MID(OC_SKIP), // JFPR1 (fingerprint reader) ++ [9] = USB2_PORT_MID(OC_SKIP), // JLCD1 (touch panel) ++ }" ++ register "usb3_ports" = "{ ++ [0] = USB3_PORT_DEFAULT(OC1), // USB-A ++ [1] = USB3_PORT_DEFAULT(OC0), // USB-A (always on) ++ [2] = USB3_PORT_DEFAULT(OC_SKIP), // RTS5344S (SD card reader) ++ [3] = USB3_PORT_DEFAULT(OC_SKIP), // USB-C (charging port) ++ }" ++ end ++ ++ device ref sata on ++ # SATA_2 - JHDD1 SATA SSD ++ register "SataPortsEnable[2]" = "1" ++ register "SataPortsDevSlp[2]" = "1" ++ end ++ ++ # PCIe controller 1 - 1x4 ++ # PCIE 1-4 - RP1 - dGPU - CLKOUT0 - CLKREQ0 ++ # ++ # PCIe controller 2 - 2x1+1x2 (lane reversal) ++ # PCIE 5 - GBE - GBE - CLKOUT1 - CLKREQ1 (clobbers RP8) ++ # PCIE 6 - RP7 - WLAN - CLKOUT2 - CLKREQ2 ++ # PCIE 7-8 - RP5 - WWAN - CLKOUT3 - CLKREQ3 ++ # ++ # PCIe controller 3 - 2x2 ++ # PCIE 9-10 - RP9 - TB3 - CLKOUT4 - CLKREQ4 ++ # PCIE 11-12 - RP11 - SSD - CLKOUT5 - CLKREQ5 ++ ++ # dGPU - x4 ++ device ref pcie_rp1 on ++ register "PcieRpEnable[0]" = "1" ++ register "PcieRpClkReqSupport[0]" = "1" ++ register "PcieRpClkReqNumber[0]" = "0" ++ register "PcieRpClkSrcNumber[0]" = "0" ++ register "PcieRpAdvancedErrorReporting[0]" = "1" ++ register "PcieRpLtrEnable[0]" = "1" ++ end ++ ++ # Ethernet (clobbers RP8) ++ device ref gbe on ++ register "LanClkReqSupported" = "1" ++ register "LanClkReqNumber" = "1" ++ register "EnableLanLtr" = "1" ++ register "EnableLanK1Off" = "1" ++ end ++ ++ # M.2 WLAN - x1 ++ device ref pcie_rp7 on ++ register "PcieRpEnable[6]" = "1" ++ register "PcieRpClkReqSupport[6]" = "1" ++ register "PcieRpClkReqNumber[6]" = "2" ++ register "PcieRpClkSrcNumber[6]" = "2" ++ register "PcieRpAdvancedErrorReporting[6]" = "1" ++ register "PcieRpLtrEnable[6]" = "1" ++ end ++ ++ # M.2 WWAN - x2 ++ device ref pcie_rp5 on ++ register "PcieRpEnable[4]" = "1" ++ register "PcieRpClkReqSupport[4]" = "1" ++ register "PcieRpClkReqNumber[4]" = "3" ++ register "PcieRpClkSrcNumber[4]" = "3" ++ register "PcieRpAdvancedErrorReporting[4]" = "1" ++ register "PcieRpLtrEnable[4]" = "1" ++ end ++ ++ # TB3 (Alpine Ridge LP) - x2 ++ device ref pcie_rp9 on ++ register "PcieRpEnable[8]" = "1" ++ register "PcieRpClkReqSupport[8]" = "1" ++ register "PcieRpClkReqNumber[8]" = "4" ++ register "PcieRpClkSrcNumber[8]" = "4" ++ register "PcieRpAdvancedErrorReporting[8]" = "1" ++ register "PcieRpLtrEnable[8]" = "1" ++ register "PcieRpHotPlug[8]" = "1" ++ end ++ ++ # M.2 2280 caddy - x2 ++ device ref pcie_rp11 on ++ register "PcieRpEnable[10]" = "1" ++ register "PcieRpClkReqSupport[10]" = "1" ++ register "PcieRpClkReqNumber[10]" = "5" ++ register "PcieRpClkSrcNumber[10]" = "5" ++ register "PcieRpAdvancedErrorReporting[10]" = "1" ++ register "PcieRpLtrEnable[10]" = "1" ++ end ++ end ++end +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/data.vbt b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/data.vbt +new file mode 100644 +index 0000000000000000000000000000000000000000..47732e37d5b2bad4e674fd10eafa605d26f97840 +GIT binary patch +literal 4106 +zcmeHJUu+a*5TCu>yW9JAmoD2P<t%lC2CfC#y%tU^HSGOq>9tqx`iFWXCLD09R<E?S +zMT)`nNScT-%9*GEA8a2?G`v`!jPV6yVlcd5OnC6Y;F}U&jJz1db9VRID@E)DLk#NN +z&9^i2&Hiq_`R2ZF8ipf7IM{nI5$^585@kULrrx0OPKv~ngNI__q41$dA{p()ui+v1 +zw(9rm09lUPAP4nOTm0CRnF|aw5^SQSH<G}<u_Gfnvn6IuK0h@!j;UxI!$*&rIdkIh +zl$piB;eBDWa1|CgK9bAg{^O%Z%!ziiz{neeJDb~fBI?1GV5p^44?a$ETl=n1d+;%Z +z#X6(OzEnIB9*QUTV{!mv@xk!mU}s+>aS&4j$?kY0KGYdgn6;MZ*!anbk!PNr!a%eU +zTXkLEL3ly5L&oUX#CS7?b2%Kad?s<goHQq1G_%bLv);c5qQC)gZtxnw!L3%1MWI_X +z0wUImYD_R11gsI%l%Zw})KN_c#&!YgM3v;Up{7+s1=lXlB>-#@;mhg8>>>#S&)d2I +zmP&-g0$k02szSQj(Y*j}YYtQnDH0;2ui<!ko-28Y){6ilAcrmz951v4RTWQ_ye!or +z4xOJya#Sr7{o)%XFUfJCndM%KM(c^ol_hzlb*1h&uC%Vy%U(P!_qUfwcb4r;SmPQ_ +zhxf($vVo)we+jxogb`7NQ^aS9eQpNT#2bmX5(kO*5O)$Mi4PJVB_1U{L42C{HR894 +z=ZJk70(Q~o{*COiRR#_fix0XaS3?igAuo2!)<NF8ARGWF&M7=h16xZaS|UxpZA)w3 +z1CQUC@^&oxtbG2HGk&WA9=_qa;$?8fdy_j;eY+H3ciR5U?|$2?oT;mPoV=Dx&CwUf +zv~zYWs{cR#vl*!ChO54O0k3UT#mpur4fXeCdE_aoNtZ|mgF!ck3Nmy<0BRuy4NwCa +zNZDP7XrHsU<-0NyB2=wXwgEqZPukelExAY+hyWVj0{)~A=X~17KK7XpzxQcB``9fX +zZf4pp#`ZEanRbG)(+odg+NX?t!SF|>{mPhI!flfFgv9nqI4Wr~5_?s`k0kALiCvcP +zCrRUFrpVYPYn?Jn%6MGXUXj_GGJYa!U&-tn8Gn&ANnz_0+@olH3VTw)mlf@-!p<v7 +zljhF5u5tObYwR{boRI14NxNkGd6QG=>8{!e#p0ct5}M(h16D>p?OGjSz6v3juERjS +z#z{?mXvVqrXs_rvUmYR40gNzg(QD6y9E94?4DWO|6eb83LI-smcVC6x1n2reH}rAp +zLM);f=tWDCr``UF5T>!;PYu^H1g>EBP8A}2*fM>s-@nC3pDV|}6+CtfhG(II7`pcw +z`jLfJ!?;*R@Bp=Nw2EPOC7FEs(cugIP_K6tN_$~tvS8nx6iOv|IMrO3&-m*N9ZP#b +znG^~>I|l1cUVSeD9r^k3h0TP}WWD9=MZxY<<azgO1@-W5<NTHW*-d)t{Q4yX9_+?a +zHawLe=uO6@%xqS#?JxafX%#$`BhkIqq>Z3B2yU!k71#YRpThOJtVheMDA50rV#s@U +z+nKbA{O(olYR}icuzQD*-cjBQ9;%!eMDVP>7mWsF@=%>o)wSgq=n%DHNOYwRr4Ao6 +zbNdgEn*RdDS>Rud+fIY0N8JkP3q6;>8o%R(CE2n3?Xg%qP+U%~6|{XFyxv7Y#;J2Z +XK$lk*wsY^m4}9|iz?mg_AjCfat$CyH + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/gma-mainboard.ads b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/gma-mainboard.ads +new file mode 100644 +index 0000000000..fcfbd75a92 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/gma-mainboard.ads +@@ -0,0 +1,19 @@ ++-- SPDX-License-Identifier: GPL-2.0-or-later ++ ++with HW.GFX.GMA; ++with HW.GFX.GMA.Display_Probing; ++ ++use HW.GFX.GMA; ++use HW.GFX.GMA.Display_Probing; ++ ++private package GMA.Mainboard is ++ ++ ports : constant Port_List := ++ (eDP, ++ DP1, ++ DP2, ++ HDMI1, ++ HDMI2, ++ others => Disabled); ++ ++end GMA.Mainboard; +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/gpio.c b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/gpio.c +new file mode 100644 +index 0000000000..a98dd2bc4e +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/gpio.c +@@ -0,0 +1,199 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <soc/gpio.h> ++#include "../../gpio.h" ++ ++static const struct pad_config gpio_table[] = { ++ /* ------- GPIO Community 0 ------- */ ++ ++ /* ------- GPIO Group GPP_A ------- */ ++ PAD_CFG_NF(GPP_A0, NONE, DEEP, NF1), /* -KBRC */ ++ PAD_CFG_NF(GPP_A1, NATIVE, DEEP, NF1), /* LPC_AD0 */ ++ PAD_CFG_NF(GPP_A2, NATIVE, DEEP, NF1), /* LPC_AD1 */ ++ PAD_CFG_NF(GPP_A3, NATIVE, DEEP, NF1), /* LPC_AD2 */ ++ PAD_CFG_NF(GPP_A4, NATIVE, DEEP, NF1), /* LPC_AD3 */ ++ PAD_CFG_NF(GPP_A5, NONE, DEEP, NF1), /* -LPC_FRAME */ ++ PAD_CFG_NF(GPP_A6, NONE, DEEP, NF1), /* IRQSER */ ++ PAD_CFG_NF(GPP_A7, NONE, DEEP, NF1), /* -TPM_IRQ */ ++ PAD_CFG_NF(GPP_A8, NONE, DEEP, NF1), /* -CLKRUN */ ++ PAD_CFG_NF(GPP_A9, DN_20K, DEEP, NF1), /* LPCCLK_EC_24M */ ++ PAD_CFG_NF(GPP_A10, DN_20K, DEEP, NF1), /* LPCCLK_DEBUG_24M */ ++ PAD_NC(GPP_A11, NONE), ++ PAD_NC(GPP_A12, NONE), ++ PAD_CFG_NF(GPP_A13, NONE, DEEP, NF1), /* -SUSWARN */ ++ PAD_CFG_NF(GPP_A14, NONE, DEEP, NF1), /* -SUS_STAT */ ++ PAD_CFG_NF(GPP_A15, UP_20K, DEEP, NF1), /* -SUSWARN */ ++ PAD_NC(GPP_A16, NONE), ++ PAD_NC(GPP_A17, NONE), ++ PAD_NC(GPP_A18, NONE), ++ PAD_NC(GPP_A19, NONE), ++ PAD_NC(GPP_A20, NONE), ++ PAD_NC(GPP_A21, NONE), ++ PAD_NC(GPP_A22, NONE), ++ PAD_NC(GPP_A23, NONE), ++ ++ /* ------- GPIO Group GPP_B ------- */ ++ PAD_CFG_NF(GPP_B0, NONE, DEEP, NF1), ++ PAD_CFG_NF(GPP_B1, NONE, DEEP, NF1), ++ PAD_NC(GPP_B2, NONE), ++ PAD_NC(GPP_B3, NONE), ++ PAD_CFG_GPI_SCI(GPP_B4, NONE, DEEP, EDGE_SINGLE, INVERT), /* -TBT_PLUG_EVENT */ ++ PAD_CFG_NF(GPP_B5, NONE, DEEP, NF1), /* -CLKREQ_PCIE0 (dGPU) */ ++ PAD_CFG_NF(GPP_B6, NONE, DEEP, NF1), /* -CLKREQ_PCIE3 (WWAN) */ ++ PAD_CFG_NF(GPP_B7, NONE, DEEP, NF1), /* -CLKREQ_PCIE4 (GBE) */ ++ PAD_CFG_NF(GPP_B8, NONE, DEEP, NF1), /* -CLKREQ_PCIE5 (WLAN) */ ++ PAD_CFG_NF(GPP_B9, NONE, DEEP, NF1), /* -CLKREQ_PCIE6 (TB3) */ ++ PAD_CFG_NF(GPP_B10, NONE, DEEP, NF1), /* -CLKREQ_PCIE8 (SSD) */ ++ PAD_NC(GPP_B11, NONE), ++ PAD_CFG_NF(GPP_B12, NONE, DEEP, NF1), /* -PCH_SLP_S0 */ ++ PAD_CFG_NF(GPP_B13, NONE, DEEP, NF1), /* -PLTRST */ ++ PAD_CFG_NF(GPP_B14, NONE, DEEP, NF1), /* PCH_SPKR */ ++ PAD_CFG_GPO(GPP_B15, 0, DEEP), /* NFC_DLREQ */ ++ PAD_NC(GPP_B16, NONE), ++ PAD_NC(GPP_B17, NONE), ++ PAD_NC(GPP_B18, NONE), ++ PAD_NC(GPP_B19, NONE), ++ PAD_NC(GPP_B20, NONE), ++ PAD_NC(GPP_B21, NONE), ++ PAD_NC(GPP_B22, NONE), ++ PAD_NC(GPP_B23, NONE), ++ ++ /* ------- GPIO Community 1 ------- */ ++ ++ /* ------- GPIO Group GPP_C ------- */ ++ PAD_CFG_NF(GPP_C0, NONE, DEEP, NF1), /* SMB_CLK */ ++ PAD_CFG_NF(GPP_C1, NONE, DEEP, NF1), /* SMB_DATA */ ++ PAD_CFG_GPO(GPP_C2, 1, DEEP), ++ PAD_CFG_NF(GPP_C3, NONE, DEEP, NF1), /* SML0_CLK */ ++ PAD_CFG_NF(GPP_C4, NONE, DEEP, NF1), /* SML0_DATA */ ++ PAD_NC(GPP_C5, NONE), ++ PAD_CFG_NF(GPP_C6, NONE, DEEP, NF1), /* EC_SCL2 */ ++ PAD_CFG_NF(GPP_C7, NONE, DEEP, NF1), /* EC_SDA2 */ ++ PAD_NC(GPP_C8, NONE), ++ PAD_NC(GPP_C9, NONE), ++ PAD_NC(GPP_C10, NONE), ++ PAD_NC(GPP_C11, NONE), ++ PAD_NC(GPP_C12, NONE), ++ PAD_NC(GPP_C13, NONE), ++ PAD_NC(GPP_C14, NONE), ++ PAD_NC(GPP_C15, NONE), ++ PAD_CFG_NF(GPP_C16, NONE, DEEP, NF1), /* I2C0_DATA */ ++ PAD_CFG_NF(GPP_C17, NONE, DEEP, NF1), /* I2C0_CLK */ ++ PAD_NC(GPP_C18, NONE), ++ PAD_NC(GPP_C19, NONE), ++ PAD_CFG_GPO(GPP_C20, 0, DEEP), /* EPRIVACY_ON */ ++ PAD_CFG_GPO(GPP_C21, 0, DEEP), /* TBT_FORCE_PWR */ ++ PAD_CFG_GPI_SCI(GPP_C22, NONE, DEEP, EDGE_SINGLE, INVERT), /* -EC_SCI */ ++ PAD_CFG_GPI_SCI(GPP_C23, NONE, DEEP, EDGE_SINGLE, INVERT), /* -EC_WAKE */ ++ ++ /* ------- GPIO Group GPP_D ------- */ ++ PAD_NC(GPP_D0, NONE), ++ PAD_NC(GPP_D1, NONE), ++ PAD_NC(GPP_D2, NONE), ++ PAD_NC(GPP_D3, NONE), ++ PAD_NC(GPP_D4, NONE), ++ PAD_NC(GPP_D5, NONE), ++ PAD_NC(GPP_D6, NONE), ++ PAD_NC(GPP_D7, NONE), ++ PAD_NC(GPP_D8, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_D9, UP_20K, DEEP, OFF, ACPI), /* -DISCRETE_PRESENCE */ ++ PAD_NC(GPP_D10, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_D11, UP_20K, DEEP, OFF, ACPI), /* DGFX_VRAM_ID0 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_D12, UP_20K, DEEP, OFF, ACPI), /* DGFX_VRAM_ID1 */ ++ PAD_NC(GPP_D13, NONE), ++ PAD_NC(GPP_D14, NONE), ++ PAD_NC(GPP_D15, NONE), ++ PAD_NC(GPP_D16, NONE), ++ PAD_CFG_GPO(GPP_D17, 0, DEEP), /* DDI_PRIORITY */ ++ PAD_NC(GPP_D18, NONE), ++ PAD_NC(GPP_D19, NONE), ++ PAD_NC(GPP_D20, NONE), ++ PAD_NC(GPP_D21, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_D22, UP_20K, DEEP, OFF, ACPI), /* -NFC_DTCT */ ++ PAD_NC(GPP_D23, NONE), ++ ++ /* ------- GPIO Group GPP_E ------- */ ++ PAD_CFG_GPO(GPP_E0, 1, DEEP), /* BDC_ON */ ++ PAD_NC(GPP_E1, NONE), ++ PAD_CFG_NF(GPP_E2, NONE, DEEP, NF1), /* -SATA2_DTCT */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_E3, NONE, DEEP, EDGE_SINGLE, ACPI), /* -TBT_PLUG_EVENT */ ++ PAD_CFG_GPO(GPP_E4, 1, DEEP), /* NFC_ON */ ++ PAD_NC(GPP_E5, NONE), ++ PAD_CFG_NF(GPP_E6, NONE, RSMRST, NF1), /* SATA2_DEVSLP */ ++ PAD_NC(GPP_E7, NONE), ++ PAD_NC(GPP_E8, NONE), ++ PAD_CFG_NF(GPP_E9, NONE, DEEP, NF1), /* -USB_PORT0_OC0 */ ++ PAD_CFG_NF(GPP_E10, NONE, DEEP, NF1), /* -USB_PORT1_OC1 */ ++ PAD_NC(GPP_E11, NONE), ++ PAD_CFG_GPI_APIC_HIGH(GPP_E12, NONE, DEEP), /* NFC_INT */ ++ PAD_CFG_NF(GPP_E13, NONE, DEEP, NF1), /* DDIP1_HPD */ ++ PAD_CFG_NF(GPP_E14, NONE, DEEP, NF1), /* DDIP2_HPD */ ++ PAD_NC(GPP_E15, NONE), ++ PAD_NC(GPP_E16, NONE), ++ PAD_CFG_NF(GPP_E17, NONE, DEEP, NF1), /* EDP_HPD */ ++ PAD_NC(GPP_E18, NONE), ++ PAD_CFG_GPO(GPP_E19, 0, DEEP), ++ PAD_CFG_NF(GPP_E20, NONE, DEEP, NF1), /* DDIP2_CTRLCLK */ ++ PAD_CFG_NF(GPP_E21, NONE, DEEP, NF1), /* DDIP2_CTRLDATA */ ++ PAD_CFG_TERM_GPO(GPP_E22, 0, UP_20K, RSMRST), /* -GPU_RST */ ++ PAD_CFG_TERM_GPO(GPP_E23, 0, UP_20K, RSMRST), /* 1R8VIDEO_AON_ON */ ++ ++ /* ------- GPIO Community 2 ------- */ ++ ++ /* -------- GPIO Group GPD -------- */ ++ PAD_CFG_NF(GPD0, NONE, PWROK, NF1), /* -BATLOW */ ++ PAD_CFG_NF(GPD1, NATIVE, PWROK, NF1), /* AC_PRESENT */ ++ PAD_CFG_NF(GPD2, NATIVE, PWROK, NF1), /* -LANWAKE */ ++ PAD_CFG_NF(GPD3, UP_20K, PWROK, NF1), /* -PWRSW_EC */ ++ PAD_CFG_NF(GPD4, NONE, PWROK, NF1), /* -PCH_SLP_S3 */ ++ PAD_CFG_NF(GPD5, NONE, PWROK, NF1), /* -PCH_SLP_S4 */ ++ PAD_CFG_NF(GPD6, NONE, PWROK, NF1), /* -PCH_SLP_M */ ++ PAD_NC(GPD7, NONE), ++ PAD_CFG_NF(GPD8, NONE, PWROK, NF1), /* SUSCLK_32K */ ++ PAD_CFG_NF(GPD9, NONE, PWROK, NF1), /* -PCH_SLP_WLAN */ ++ PAD_CFG_NF(GPD10, NONE, PWROK, NF1), /* -PCH_SLP_S5 */ ++ PAD_CFG_NF(GPD11, NONE, PWROK, NF1), /* LANPHYPC */ ++ ++ /* ------- GPIO Community 3 ------- */ ++ ++ /* ------- GPIO Group GPP_F ------- */ ++ PAD_CFG_GPO(GPP_F0, 0, DEEP), ++ PAD_CFG_GPI_TRIG_OWN(GPP_F1, NONE, DEEP, OFF, ACPI), /* GC6_FB_EN */ ++ PAD_CFG_GPO(GPP_F2, 1, DEEP), /* -GPU_EVENT */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F3, NONE, PLTRST, OFF, ACPI), /* DGFX_PWRGD */ ++ PAD_NC(GPP_F4, NONE), /* -WWAN_RESET */ ++ PAD_NC(GPP_F5, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_F6, UP_20K, DEEP, OFF, ACPI), /* -MIC_HW_EN (R37 to GND) */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F7, UP_20K, DEEP, OFF, ACPI), /* -INT_MIC_DTCT */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F8, UP_20K, DEEP, OFF, ACPI), /* WWAN_CFG0 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F9, UP_20K, DEEP, OFF, ACPI), /* WWAN_CFG1 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F10, UP_20K, DEEP, OFF, ACPI), /* WWAN_CFG2 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F11, UP_20K, DEEP, OFF, ACPI), /* WWAN_CFG3 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F12, UP_20K, DEEP, OFF, ACPI), /* PLANARID0 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F13, UP_20K, DEEP, OFF, ACPI), /* PLANARID1 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F14, UP_20K, DEEP, OFF, ACPI), /* PLANARID2 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F15, UP_20K, DEEP, OFF, ACPI), /* PLANARID3 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F16, UP_20K, DEEP, OFF, ACPI), /* MEMORYID0 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F17, UP_20K, DEEP, OFF, ACPI), /* MEMORYID1 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F18, UP_20K, DEEP, OFF, ACPI), /* MEMORYID2 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F19, UP_20K, DEEP, OFF, ACPI), /* MEMORYID3 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F20, UP_20K, DEEP, OFF, ACPI), /* MEMORYID4 */ ++ PAD_NC(GPP_F21, NONE), ++ PAD_CFG_GPI_TRIG_OWN(GPP_F22, UP_20K, DEEP, OFF, ACPI), /* -TAMPER_SW_DTCT */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F23, UP_20K, DEEP, OFF, ACPI), /* -SC_DTCT */ ++ ++ /* ------- GPIO Group GPP_G ------- */ ++ PAD_NC(GPP_G0, NONE), ++ PAD_NC(GPP_G1, NONE), ++ PAD_NC(GPP_G2, NONE), ++ PAD_NC(GPP_G3, NONE), ++ PAD_CFG_GPO(GPP_G4, 0, DEEP), /* TBT_RTD3_PWR_EN */ ++ PAD_CFG_GPO(GPP_G5, 0, DEEP), /* TBT_FORCE_USB_PWR */ ++ PAD_CFG_GPO(GPP_G6, 0, DEEP), /* -TBT_PERST */ ++ PAD_CFG_GPI_SCI(GPP_G7, NONE, DEEP, LEVEL, INVERT), /* -TBT_PCIE_WAKE */ ++}; ++ ++void variant_config_gpios(void) ++{ ++ gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table)); ++} +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/hda_verb.c b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/hda_verb.c +new file mode 100644 +index 0000000000..b1d96c5a76 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/hda_verb.c +@@ -0,0 +1,90 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <device/azalia_device.h> ++ ++const u32 cim_verb_data[] = { ++ 0x10ec0257, // Vendor/Device ID: Realtek ALC257 ++ 0x17aa2258, // Subsystem ID ++ 11, ++ AZALIA_SUBVENDOR(0, 0x17aa2258), ++ ++ AZALIA_PIN_CFG(0, 0x12, AZALIA_PIN_DESC( ++ AZALIA_INTEGRATED, ++ AZALIA_INTERNAL, ++ AZALIA_MIC_IN, ++ AZALIA_OTHER_DIGITAL, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_NO_JACK_PRESENCE_DETECT, ++ 2, 0 ++ )), ++ AZALIA_PIN_CFG(0, 0x13, 0x40000000), // does not describe a jack or internal device ++ AZALIA_PIN_CFG(0, 0x14, AZALIA_PIN_DESC( ++ AZALIA_INTEGRATED, ++ AZALIA_INTERNAL, ++ AZALIA_SPEAKER, ++ AZALIA_OTHER_ANALOG, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_NO_JACK_PRESENCE_DETECT, ++ 1, 0 ++ )), ++ AZALIA_PIN_CFG(0, 0x18, AZALIA_PIN_CFG_NC(0)), ++ AZALIA_PIN_CFG(0, 0x19, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_EXTERNAL_PRIMARY_CHASSIS | AZALIA_RIGHT, ++ AZALIA_MIC_IN, ++ AZALIA_STEREO_MONO_1_8, ++ AZALIA_BLACK, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 3, 0 ++ )), ++ AZALIA_PIN_CFG(0, 0x1a, AZALIA_PIN_CFG_NC(0)), ++ AZALIA_PIN_CFG(0, 0x1b, AZALIA_PIN_CFG_NC(0)), ++ AZALIA_PIN_CFG(0, 0x1d, 0x40661b45), // does not describe a jack or internal device ++ AZALIA_PIN_CFG(0, 0x1e, AZALIA_PIN_CFG_NC(0)), ++ AZALIA_PIN_CFG(0, 0x21, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_EXTERNAL_PRIMARY_CHASSIS | AZALIA_RIGHT, ++ AZALIA_HP_OUT, ++ AZALIA_STEREO_MONO_1_8, ++ AZALIA_BLACK, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 1, 15 ++ )), ++ ++ 0x8086280b, // Vendor/Device ID: Intel Kabylake HDMI ++ 0x80860101, // Subsystem ID ++ 4, ++ AZALIA_SUBVENDOR(2, 0x80860101), ++ ++ AZALIA_PIN_CFG(2, 0x05, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_DIGITAL_DISPLAY, ++ AZALIA_DIGITAL_OTHER_OUT, ++ AZALIA_OTHER_DIGITAL, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 1, 0 ++ )), ++ AZALIA_PIN_CFG(2, 0x06, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_DIGITAL_DISPLAY, ++ AZALIA_DIGITAL_OTHER_OUT, ++ AZALIA_OTHER_DIGITAL, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 1, 0 ++ )), ++ AZALIA_PIN_CFG(2, 0x07, AZALIA_PIN_DESC( ++ AZALIA_JACK, ++ AZALIA_DIGITAL_DISPLAY, ++ AZALIA_DIGITAL_OTHER_OUT, ++ AZALIA_OTHER_DIGITAL, ++ AZALIA_COLOR_UNKNOWN, ++ AZALIA_JACK_PRESENCE_DETECT, ++ 1, 0 ++ )), ++}; ++ ++const u32 pc_beep_verbs[] = {}; ++ ++AZALIA_ARRAY_SIZES; +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/memory_init_params.c b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/memory_init_params.c +new file mode 100644 +index 0000000000..001e934b3a +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/memory_init_params.c +@@ -0,0 +1,44 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <cbfs.h> ++#include <gpio.h> ++#include <soc/gpio.h> ++#include <soc/romstage.h> ++#include <spd_bin.h> ++#include <stdio.h> ++ ++static const struct pad_config memory_id_gpio_table[] = { ++ PAD_CFG_GPI_TRIG_OWN(GPP_F16, UP_20K, DEEP, OFF, ACPI), /* MEMORYID0 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F17, UP_20K, DEEP, OFF, ACPI), /* MEMORYID1 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F18, UP_20K, DEEP, OFF, ACPI), /* MEMORYID2 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F19, UP_20K, DEEP, OFF, ACPI), /* MEMORYID3 */ ++ PAD_CFG_GPI_TRIG_OWN(GPP_F20, UP_20K, DEEP, OFF, ACPI), /* MEMORYID4 */ ++}; ++ ++void mainboard_memory_init_params(FSPM_UPD *mupd) ++{ ++ int spd_idx; ++ char spd_name[20]; ++ size_t spd_size; ++ ++ FSP_M_CONFIG *mem_cfg = &mupd->FspmConfig; ++ mem_cfg->DqPinsInterleaved = true; /* DDR_DQ in interleave mode */ ++ mem_cfg->CaVrefConfig = 2; /* VREF_CA to CH_A and VREF_DQ_B to CH_B */ ++ mem_cfg->MemorySpdDataLen = CONFIG_DIMM_SPD_SIZE; ++ ++ /* Get SPD for soldered RAM SPD (CH A) */ ++ gpio_configure_pads(memory_id_gpio_table, ARRAY_SIZE(memory_id_gpio_table)); ++ ++ spd_idx = gpio_get(GPP_F16) | gpio_get(GPP_F17) << 1 | gpio_get(GPP_F18) << 2 | ++ gpio_get(GPP_F19) << 3 | gpio_get(GPP_F20) << 4; ++ printk(BIOS_DEBUG, "Detected MEMORY_ID = %d\n", spd_idx); ++ snprintf(spd_name, sizeof(spd_name), "spd_%d.bin", spd_idx); ++ mem_cfg->MemorySpdPtr00 = (uintptr_t)cbfs_map(spd_name, &spd_size); ++ ++ /* Get SPD for memory slot (CH B) */ ++ struct spd_block blk = { .addr_map = { [1] = 0x51, } }; ++ get_spd_smbus(&blk); ++ dump_spd_info(&blk); ++ ++ mem_cfg->MemorySpdPtr10 = (uintptr_t)blk.spd_array[1]; ++} +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/overridetree.cb b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/overridetree.cb +new file mode 100644 +index 0000000000..d4afca20c4 +--- /dev/null ++++ b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/overridetree.cb +@@ -0,0 +1,103 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++chip soc/intel/skylake ++ device domain 0 on ++ device ref south_xhci on ++ register "usb2_ports" = "{ ++ [0] = USB2_PORT_MID(OC0), // JUSB1 (USB-A always on) ++ [1] = USB2_PORT_MID(OC1), // JUSB2 (USB-A) ++ [2] = USB2_PORT_MID(OC_SKIP), // JFPR (smartcard slot) ++ [3] = USB2_PORT_MID(OC_SKIP), // JUSBC (USB-C) ++ [4] = USB2_PORT_MID(OC_SKIP), // JCAM (IR camera) ++ [5] = USB2_PORT_MID(OC_SKIP), // JWWAN (M.2 WWAN USB) ++ [6] = USB2_PORT_MID(OC_SKIP), // JWLAN (M.2 WLAN USB) ++ [7] = USB2_PORT_MID(OC_SKIP), // JCAM (webcam) ++ [8] = USB2_PORT_MID(OC_SKIP), // JFPR (fingerprint reader) ++ [9] = USB2_PORT_MID(OC_SKIP), // JLCD (touch panel) ++ }" ++ register "usb3_ports" = "{ ++ [0] = USB3_PORT_DEFAULT(OC0), // JUSB1 (USB-A always on) ++ [1] = USB3_PORT_DEFAULT(OC1), // JUSB2 (USB-A) ++ [2] = USB3_PORT_DEFAULT(OC_SKIP), // JSD (SD card reader) ++ [3] = USB3_PORT_DEFAULT(OC_SKIP), // JUSBC (USB-C) ++ }" ++ end ++ ++ device ref sata on ++ # SATA_2 - Main M.2 SATA SSD ++ register "SataPortsEnable[2]" = "1" ++ register "SataPortsDevSlp[2]" = "1" ++ end ++ ++ # PCIe controller 1 - 1x2+2x1 ++ # PCIE 1-2 - RP1 - dGPU - CLKOUT0 - CLKREQ0 ++ # PCIE 4 - RP4 - WWAN - CLKOUT1 - CLKREQ1 ++ # ++ # PCIe controller 2 - 2x1+1x2 (lane reversal) ++ # PCIE 5 - GBE - GBE - CLKOUT2 - CLKREQ2 (clobbers RP8) ++ # PCIE 6 - RP7 - WLAN - CLKOUT3 - CLKREQ3 ++ # PCIE 7-8 - RP5 - TB3 - CLKOUT4 - CLKREQ4 ++ # ++ # PCIe controller 3 - 1x4 (lane reversal) ++ # PCIE 9-12 - RP9 - SSD - CLKOUT5 - CLKREQ5 ++ ++ # dGPU - x2 ++ device ref pcie_rp1 on ++ register "PcieRpEnable[0]" = "1" ++ register "PcieRpClkReqSupport[0]" = "1" ++ register "PcieRpClkReqNumber[0]" = "0" ++ register "PcieRpClkSrcNumber[0]" = "0" ++ register "PcieRpAdvancedErrorReporting[0]" = "1" ++ register "PcieRpLtrEnable[0]" = "1" ++ end ++ ++ # M.2 WWAN - x1 ++ device ref pcie_rp4 on ++ register "PcieRpEnable[3]" = "1" ++ register "PcieRpClkReqSupport[3]" = "1" ++ register "PcieRpClkReqNumber[3]" = "1" ++ register "PcieRpClkSrcNumber[3]" = "1" ++ register "PcieRpAdvancedErrorReporting[3]" = "1" ++ register "PcieRpLtrEnable[3]" = "1" ++ end ++ ++ # Ethernet (clobbers RP8) ++ device ref gbe on ++ register "LanClkReqSupported" = "1" ++ register "LanClkReqNumber" = "2" ++ register "EnableLanLtr" = "1" ++ register "EnableLanK1Off" = "1" ++ end ++ ++ # M.2 WLAN - x1 ++ device ref pcie_rp7 on ++ register "PcieRpEnable[6]" = "1" ++ register "PcieRpClkReqSupport[6]" = "1" ++ register "PcieRpClkReqNumber[6]" = "3" ++ register "PcieRpClkSrcNumber[6]" = "3" ++ register "PcieRpAdvancedErrorReporting[6]" = "1" ++ register "PcieRpLtrEnable[6]" = "1" ++ end ++ ++ # TB3 (Alpine Ridge LP) - x2 ++ device ref pcie_rp5 on ++ register "PcieRpEnable[4]" = "1" ++ register "PcieRpClkReqSupport[4]" = "1" ++ register "PcieRpClkReqNumber[4]" = "4" ++ register "PcieRpClkSrcNumber[4]" = "4" ++ register "PcieRpAdvancedErrorReporting[4]" = "1" ++ register "PcieRpLtrEnable[4]" = "1" ++ register "PcieRpHotPlug[4]" = "1" ++ end ++ ++ # M.2 2280 SSD - x2 ++ device ref pcie_rp9 on ++ register "PcieRpEnable[8]" = "1" ++ register "PcieRpClkReqSupport[8]" = "1" ++ register "PcieRpClkReqNumber[8]" = "5" ++ register "PcieRpClkSrcNumber[8]" = "5" ++ register "PcieRpAdvancedErrorReporting[8]" = "1" ++ register "PcieRpLtrEnable[8]" = "1" ++ end ++ end ++end +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_0.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_0.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..86f39ddb55ea9fb58d5e5699637636ef597c734e +GIT binary patch +literal 512 +zcmY!u;9+)EWZ+<6U|?oq29gXMJYRrxPEL*>N67~+1r7#Qh7a1t+8`-(puhlu3{YAD +YT>%dM8_BI;nL`dsaHtp+rc($20I8n}l>h($ + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_1.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_1.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..df0f6e58b79286a4aeb690c5027adf7a1f5f668b +GIT binary patch +literal 512 +zcmY!u;9+i6oWQ}rz`)GN3?vyic)kGXoSYm%j*<^t3LFfq3@hZcwLwzoK!E`Q8KATR +Yx&j>hH(SqvWezd%<4`dwOs5b40B_I==>Px# + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_10.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_10.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..24f0d8992bc5244c62488da9633e4885f52f3e22 +GIT binary patch +literal 512 +zcmY!u<Y9JIWZ+;(U|?oqW&i?q-XHu740(BZf(&^dxD+@TSQ$QOn`kgpFo@WI<Pkv3 +zjN25185j^Oge*SRoUI_)=hwI&^9wTJQ%GaE+Z>cy&~OfFg0G3Wp`)phiHWn5fv$6q +PvjPw>z-1}5hGzN!nb#F$ + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_11.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_11.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..59b6b9e78263c42aae367ab7d4a784d888f30efe +GIT binary patch +literal 512 +zcmY!u<Y8`AWZ+;(U|?osW&i?q-XHu740(BZf(&^dxD+@TSQ%DGYiKZ3Fo@WI<Pm^J +zTbD)5RGF87L5G`J#gvCx7a@nAHD@bG{`ob#fBb?9_?6OB_I)U&#y6aUn&4|<Zs=&} +YZDQ=?WT@*L<g5S$3~*UWt)ZEI0F{0fq5uE@ + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_12.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_12.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..93be0ac94fc57222cd29e34eee11042d7842ac25 +GIT binary patch +literal 512 +zcmY!u<Y9JIWZ+;(U|?oqW&i?q-XHu740(BZf(&^dxD+@TSQ$QOn`kgpFo@WI<Pkv3 +zjN25185j^Oge*SRoUI_)=hwI&^9wTJQ%GaE+Z>cy(6E*fVuXjUqlKwqu$iM<keQ!u +VsD}a&Ff^?FkI#a;_$28g2LQ`x7jOUo + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_13.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_13.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..171a272bc734b72395622bf889d24972ef2d14f7 +GIT binary patch +literal 512 +zcmY!u<Y8`AWZ+;(U|?osW&i?q-XHu740(BZf(&^dxD+@TSQ%DGYiKZ3Fo@WI<Pkv3 +zjN25185j^Oge*SRoUI_)=hr%!_!*h-DWtL7fk%{D(6E*fVuXjUqob)|u$iN8keQ!u +VsD}a&Ff^?FkI#a;_$28g2LP>g7pDLK + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_14.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_14.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..a2a64a5e1adada3fc00b2e4edc60c77e610881a9 +GIT binary patch +literal 512 +zcmY!u<Y9JIWZ+;(U|?oqW&i><-XH%N8S?V-1R3%^a4B#wurhqmHql_HU=XnZ$x{Q& +z*$Oh{IYWaWKO+-03?$Qx1CPkm2-nu217(^xhPas;8kw1RMCls2o4FbS#SI&DT;VDQ +GCj$V){1T)9 + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_15.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_15.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..a2a64a5e1adada3fc00b2e4edc60c77e610881a9 +GIT binary patch +literal 512 +zcmY!u<Y9JIWZ+;(U|?oqW&i><-XH%N8S?V-1R3%^a4B#wurhqmHql_HU=XnZ$x{Q& +z*$Oh{IYWaWKO+-03?$Qx1CPkm2-nu217(^xhPas;8kw1RMCls2o4FbS#SI&DT;VDQ +GCj$V){1T)9 + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_16.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_16.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..a64a5a93fb4aef4d5f63d79cb2582731b9ac5063 +GIT binary patch +literal 512 +NcmZQz7zHCa1ONg600961 + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_17.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_17.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..5f23e86606094d3e5d2011db902ebd4a500bbffa +GIT binary patch +literal 512 +zcmY!u<Y9JIWZ+;(U|?oqW&i><-XHc140(BZf(&^dxD+@TSQ$QOn`kgpFo@WI<Pkv3 +zjN25185j^Oge*SRoUI_)=M3$7{ESTa6w+Akz#~d6Xjsb#F~Y;w(ZbX)*v#20$jnbS +V%v%8n7#i08$7jJ^e3JB$0{}ZV7fApB + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_18.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_18.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..05633943eb5af166da66a2e1f4e74948f75782fb +GIT binary patch +literal 512 +zcmY!u<Y9JIoXEkDz`)GN%m4&zyg%$281nM+1R3%^a4B#wurhqmHql_HU=XnZ$s>T6 +z8Mi42GcX`n2w8lrIa@)p&l&!{<7bq|r;x^SwThHl(6E*fVuXjUqobjFu$i-OkeQ!u +Vn70BDFf^?FkI#a;_$28g2LNS*7)Ag9 + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_19.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_19.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..857da9c9828cdac842329f6cef4539283777268b +GIT binary patch +literal 512 +zcmY!u<Y9JIWZ+;(U|?oqW&i?K-XH(98S?V-1R3%^a4B#wurhqmHql_HU=XnZ$x{Q& +z*$Oh{Il~1>enuv07)YiW2Og2B5w5L42g)>Y3~@6xG%_>sh|)E7H}WzBiW@fQc)?W; +GP6hy+m=i1j + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_2.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_2.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..b5b14cf2dfa06ae183b0379da4dc825129e1589f +GIT binary patch +literal 512 +zcmY!u;9+)EWZ+<6U|?oq29gXMJU@VRUS6IcN7)B11r7#Qh7a1tdLSuupuhlu3{YAD +XT>%b$v*cE=%%S%6I8=-Z(<uZ1pPdSg + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_20.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_20.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..a64a5a93fb4aef4d5f63d79cb2582731b9ac5063 +GIT binary patch +literal 512 +NcmZQz7zHCa1ONg600961 + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_3.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_3.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..d73736008af1eb67456b2fd66f7dec3b6669a442 +GIT binary patch +literal 512 +zcmY!u;9+i&oWQ}rz`)GN3?vyic)kGXoSYm%juHh92G#;*h81$!dLSuupuhlu3{YAD +YT>%b$+tzbnnL|62aHtp+rc($20QGqazW@LL + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_4.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_4.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..829f149547bc24859646c33d5926938d7a1b90cb +GIT binary patch +literal 512 +zcmY!u;9+)EWZ+<6U|?oq29gXMJYRrxPEL*>N67~+1r7#Qh7a1tdLSuupuhlu3{YAD +XT>%b$o8(ro%%OI594bbI=@bG0z{d&v + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_5.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_5.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..a64a5a93fb4aef4d5f63d79cb2582731b9ac5063 +GIT binary patch +literal 512 +NcmZQz7zHCa1ONg600961 + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_6.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_6.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..a64a5a93fb4aef4d5f63d79cb2582731b9ac5063 +GIT binary patch +literal 512 +NcmZQz7zHCa1ONg600961 + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_7.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_7.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..940f1e3cd8e5bd9ea32a82a14edcdcbc8132d8c7 +GIT binary patch +literal 512 +zcmY!u<Y8`AWZ+;(U|?osW&i><-XH%N8S?V-1R3%^a4B#wurjQW(9mG0U=XnZ$x{Q& +z0UPq1A)%L_QJxwGl4(Y*BAFWD+8T7AOcTeDU_*B^6OSleBX=`bLy)jxgN`d)<=|uh +E020*^DF6Tf + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_8.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_8.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..30c84410d417ef7afa8705c93cdb64a9f4e915a0 +GIT binary patch +literal 512 +zcmY!u<Y9JIWZ+;(U|?oqW&i?q-XHZ040(BZf(&^dxD+@TSQ$QOn`kgpFo@WI<f#GX +zYz3L}{MzzRenxp}7)YiWinU~FgllWifig`TL)=Uajm%6uqI8Yijh&1X6cmgabe!NS +H2PXpn6CD!Q + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_9.bin b/src/mainboard/lenovo/sklkbl_thinkpad/variants/t480s/spd/spd_9.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..7facef55b93fe1f67411c00bab84862769461f63 +GIT binary patch +literal 512 +zcmY!u<Y8`AWZ+;(U|?osW&i?q-XHZ040(BZf(&^dxD+@TSQ%DGYiKZ3Fo@WI<f#GX +zYz3L}{F>W!enxp}7)YiWinU~FgllWifig`TLxK(6%}hL^bdB7N9Ss$Lz^FmT39fQ* +FG5`?&65ap+ + +literal 0 +HcmV?d00001 + +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0029-mb-dell-Add-Optiplex-780-MT-x4x-ICH10.patch b/config/coreboot/default/patches/0029-mb-dell-Add-Optiplex-780-MT-x4x-ICH10.patch new file mode 100644 index 00000000..eb9263b9 --- /dev/null +++ b/config/coreboot/default/patches/0029-mb-dell-Add-Optiplex-780-MT-x4x-ICH10.patch @@ -0,0 +1,708 @@ +From 75cc0ea09234064318046624845b0afc5afb0ce5 Mon Sep 17 00:00:00 2001 +From: Nicholas Chin <nic.c3.14@gmail.com> +Date: Mon, 30 Sep 2024 20:44:38 -0400 +Subject: [PATCH 29/37] mb/dell: Add Optiplex 780 MT (x4x/ICH10) + +Change-Id: Idb45737ce95bfd26e978323c650de7d308b5079c +Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> +--- + src/mainboard/dell/optiplex_780/Kconfig | 40 ++++ + src/mainboard/dell/optiplex_780/Kconfig.name | 4 + + src/mainboard/dell/optiplex_780/Makefile.mk | 10 + + src/mainboard/dell/optiplex_780/acpi/ec.asl | 5 + + .../dell/optiplex_780/acpi/ich10_pci_irqs.asl | 32 ++++ + .../dell/optiplex_780/acpi/superio.asl | 18 ++ + .../dell/optiplex_780/board_info.txt | 6 + + src/mainboard/dell/optiplex_780/cmos.default | 8 + + src/mainboard/dell/optiplex_780/cmos.layout | 72 ++++++++ + src/mainboard/dell/optiplex_780/cstates.c | 8 + + src/mainboard/dell/optiplex_780/devicetree.cb | 63 +++++++ + src/mainboard/dell/optiplex_780/dsdt.asl | 26 +++ + .../dell/optiplex_780/gma-mainboard.ads | 16 ++ + .../optiplex_780/variants/780_mt/data.vbt | Bin 0 -> 1917 bytes + .../optiplex_780/variants/780_mt/early_init.c | 12 ++ + .../dell/optiplex_780/variants/780_mt/gpio.c | 174 ++++++++++++++++++ + .../optiplex_780/variants/780_mt/hda_verb.c | 26 +++ + .../variants/780_mt/overridetree.cb | 10 + + 18 files changed, 530 insertions(+) + create mode 100644 src/mainboard/dell/optiplex_780/Kconfig + create mode 100644 src/mainboard/dell/optiplex_780/Kconfig.name + create mode 100644 src/mainboard/dell/optiplex_780/Makefile.mk + create mode 100644 src/mainboard/dell/optiplex_780/acpi/ec.asl + create mode 100644 src/mainboard/dell/optiplex_780/acpi/ich10_pci_irqs.asl + create mode 100644 src/mainboard/dell/optiplex_780/acpi/superio.asl + create mode 100644 src/mainboard/dell/optiplex_780/board_info.txt + create mode 100644 src/mainboard/dell/optiplex_780/cmos.default + create mode 100644 src/mainboard/dell/optiplex_780/cmos.layout + create mode 100644 src/mainboard/dell/optiplex_780/cstates.c + create mode 100644 src/mainboard/dell/optiplex_780/devicetree.cb + create mode 100644 src/mainboard/dell/optiplex_780/dsdt.asl + create mode 100644 src/mainboard/dell/optiplex_780/gma-mainboard.ads + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_mt/data.vbt + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_mt/early_init.c + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_mt/gpio.c + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_mt/hda_verb.c + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_mt/overridetree.cb + +diff --git a/src/mainboard/dell/optiplex_780/Kconfig b/src/mainboard/dell/optiplex_780/Kconfig +new file mode 100644 +index 0000000000..2d06c75c9a +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/Kconfig +@@ -0,0 +1,40 @@ ++## SPDX-License-Identifier: GPL-2.0-only ++ ++config BOARD_DELL_OPTIPLEX_780_COMMON ++ def_bool n ++ select BOARD_ROMSIZE_KB_8192 ++ select CPU_INTEL_SOCKET_LGA775 ++ select DRIVERS_I2C_CK505 ++ select HAVE_ACPI_RESUME ++ select HAVE_ACPI_TABLES ++ select HAVE_CMOS_DEFAULT ++ select HAVE_OPTION_TABLE ++ select INTEL_GMA_HAVE_VBT ++ select MAINBOARD_HAS_LIBGFXINIT ++ select MAINBOARD_USES_IFD_GBE_REGION ++ select NORTHBRIDGE_INTEL_X4X ++ select PCIEXP_ASPM ++ select PCIEXP_CLK_PM ++ select SOUTHBRIDGE_INTEL_I82801JX ++ ++config BOARD_DELL_OPTIPLEX_780_MT ++ select BOARD_DELL_OPTIPLEX_780_COMMON ++ ++if BOARD_DELL_OPTIPLEX_780_COMMON ++ ++config VGA_BIOS_ID ++ default "8086,2e22" ++ ++config MAINBOARD_DIR ++ default "dell/optiplex_780" ++ ++config MAINBOARD_PART_NUMBER ++ default "OptiPlex 780 MT" if BOARD_DELL_OPTIPLEX_780_MT ++ ++config OVERRIDE_DEVICETREE ++ default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb" ++ ++config VARIANT_DIR ++ default "780_mt" if BOARD_DELL_OPTIPLEX_780_MT ++ ++endif # BOARD_DELL_OPTIPLEX_780_COMMON +diff --git a/src/mainboard/dell/optiplex_780/Kconfig.name b/src/mainboard/dell/optiplex_780/Kconfig.name +new file mode 100644 +index 0000000000..db7f2e8fe3 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/Kconfig.name +@@ -0,0 +1,4 @@ ++## SPDX-License-Identifier: GPL-2.0-only ++ ++config BOARD_DELL_OPTIPLEX_780_MT ++ bool "OptiPlex 780 MT" +diff --git a/src/mainboard/dell/optiplex_780/Makefile.mk b/src/mainboard/dell/optiplex_780/Makefile.mk +new file mode 100644 +index 0000000000..d462995d75 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/Makefile.mk +@@ -0,0 +1,10 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++ramstage-y += cstates.c ++romstage-y += variants/$(VARIANT_DIR)/gpio.c ++ ++bootblock-y += variants/$(VARIANT_DIR)/early_init.c ++romstage-y += variants/$(VARIANT_DIR)/early_init.c ++ ++ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads ++ramstage-y += variants/$(VARIANT_DIR)/hda_verb.c +diff --git a/src/mainboard/dell/optiplex_780/acpi/ec.asl b/src/mainboard/dell/optiplex_780/acpi/ec.asl +new file mode 100644 +index 0000000000..479296cb76 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/acpi/ec.asl +@@ -0,0 +1,5 @@ ++/* SPDX-License-Identifier: CC-PDDC */ ++ ++/* Please update the license if adding licensable material. */ ++ ++/* dummy */ +diff --git a/src/mainboard/dell/optiplex_780/acpi/ich10_pci_irqs.asl b/src/mainboard/dell/optiplex_780/acpi/ich10_pci_irqs.asl +new file mode 100644 +index 0000000000..b7588dcc41 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/acpi/ich10_pci_irqs.asl +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++/* This is board specific information: ++ * IRQ routing for the 0:1e.0 PCI bridge of the ICH10 ++ */ ++ ++If (PICM) { ++ Return (Package() { ++ /* PCI slot */ ++ Package() { 0x0001ffff, 0, 0, 0x14}, ++ Package() { 0x0001ffff, 1, 0, 0x15}, ++ Package() { 0x0001ffff, 2, 0, 0x16}, ++ Package() { 0x0001ffff, 3, 0, 0x17}, ++ ++ Package() { 0x0002ffff, 0, 0, 0x15}, ++ Package() { 0x0002ffff, 1, 0, 0x16}, ++ Package() { 0x0002ffff, 2, 0, 0x17}, ++ Package() { 0x0002ffff, 3, 0, 0x14}, ++ }) ++} Else { ++ Return (Package() { ++ Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKE, 0}, ++ Package() { 0x0001ffff, 1, \_SB.PCI0.LPCB.LNKF, 0}, ++ Package() { 0x0001ffff, 2, \_SB.PCI0.LPCB.LNKG, 0}, ++ Package() { 0x0001ffff, 3, \_SB.PCI0.LPCB.LNKH, 0}, ++ ++ Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKF, 0}, ++ Package() { 0x0002ffff, 1, \_SB.PCI0.LPCB.LNKG, 0}, ++ Package() { 0x0002ffff, 2, \_SB.PCI0.LPCB.LNKH, 0}, ++ Package() { 0x0002ffff, 3, \_SB.PCI0.LPCB.LNKE, 0}, ++ }) ++} +diff --git a/src/mainboard/dell/optiplex_780/acpi/superio.asl b/src/mainboard/dell/optiplex_780/acpi/superio.asl +new file mode 100644 +index 0000000000..9f3900b86c +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/acpi/superio.asl +@@ -0,0 +1,18 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#undef SUPERIO_DEV ++#undef SUPERIO_PNP_BASE ++#undef IT8720F_SHOW_SP1 ++#undef IT8720F_SHOW_SP2 ++#undef IT8720F_SHOW_EC ++#undef IT8720F_SHOW_KBCK ++#undef IT8720F_SHOW_KBCM ++#undef IT8720F_SHOW_GPIO ++#undef IT8720F_SHOW_CIR ++#define SUPERIO_DEV SIO0 ++#define SUPERIO_PNP_BASE 0x2e ++#define IT8720F_SHOW_EC 1 ++#define IT8720F_SHOW_KBCK 1 ++#define IT8720F_SHOW_KBCM 1 ++#define IT8720F_SHOW_GPIO 1 ++#include <superio/ite/it8720f/acpi/superio.asl> +diff --git a/src/mainboard/dell/optiplex_780/board_info.txt b/src/mainboard/dell/optiplex_780/board_info.txt +new file mode 100644 +index 0000000000..aaf657b583 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/board_info.txt +@@ -0,0 +1,6 @@ ++Category: desktop ++Board URL: https://www.acer.com/ac/en/GB/content/support-product/1137?b=1 ++ROM package: SOIC-8 ++ROM protocol: SPI ++ROM socketed: n ++Flashrom support: y +diff --git a/src/mainboard/dell/optiplex_780/cmos.default b/src/mainboard/dell/optiplex_780/cmos.default +new file mode 100644 +index 0000000000..23f0e55f3e +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/cmos.default +@@ -0,0 +1,8 @@ ++## SPDX-License-Identifier: GPL-2.0-only ++ ++boot_option=Fallback ++debug_level=Debug ++power_on_after_fail=Disable ++nmi=Enable ++sata_mode=AHCI ++gfx_uma_size=64M +diff --git a/src/mainboard/dell/optiplex_780/cmos.layout b/src/mainboard/dell/optiplex_780/cmos.layout +new file mode 100644 +index 0000000000..9f5012adb4 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/cmos.layout +@@ -0,0 +1,72 @@ ++## SPDX-License-Identifier: GPL-2.0-only ++ ++# ----------------------------------------------------------------- ++entries ++ ++# ----------------------------------------------------------------- ++0 120 r 0 reserved_memory ++ ++# ----------------------------------------------------------------- ++# RTC_BOOT_BYTE (coreboot hardcoded) ++384 1 e 4 boot_option ++388 4 h 0 reboot_counter ++ ++# ----------------------------------------------------------------- ++# coreboot config options: console ++395 4 e 6 debug_level ++ ++# coreboot config options: southbridge ++408 1 e 10 sata_mode ++409 2 e 7 power_on_after_fail ++411 1 e 1 nmi ++ ++# coreboot config options: cpu ++ ++# coreboot config options: northbridge ++432 4 e 11 gfx_uma_size ++ ++# coreboot config options: check sums ++984 16 h 0 check_sum ++ ++# ----------------------------------------------------------------- ++ ++enumerations ++ ++#ID value text ++1 0 Disable ++1 1 Enable ++2 0 Enable ++2 1 Disable ++4 0 Fallback ++4 1 Normal ++6 0 Emergency ++6 1 Alert ++6 2 Critical ++6 3 Error ++6 4 Warning ++6 5 Notice ++6 6 Info ++6 7 Debug ++6 8 Spew ++7 0 Disable ++7 1 Enable ++7 2 Keep ++10 0 AHCI ++10 1 Compatible ++11 1 4M ++11 2 8M ++11 3 16M ++11 4 32M ++11 5 48M ++11 6 64M ++11 7 128M ++11 8 256M ++11 9 96M ++11 10 160M ++11 11 224M ++11 12 352M ++ ++# ----------------------------------------------------------------- ++checksums ++ ++checksum 392 983 984 +diff --git a/src/mainboard/dell/optiplex_780/cstates.c b/src/mainboard/dell/optiplex_780/cstates.c +new file mode 100644 +index 0000000000..4adf0edc63 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/cstates.c +@@ -0,0 +1,8 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <acpi/acpigen.h> ++ ++int get_cst_entries(const acpi_cstate_t **entries) ++{ ++ return 0; ++} +diff --git a/src/mainboard/dell/optiplex_780/devicetree.cb b/src/mainboard/dell/optiplex_780/devicetree.cb +new file mode 100644 +index 0000000000..95e3bd517c +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/devicetree.cb +@@ -0,0 +1,63 @@ ++# SPDX-License-Identifier: GPL-2.0-or-later ++ ++chip northbridge/intel/x4x ++ device cpu_cluster 0 on ops x4x_cpu_bus_ops end # APIC cluster ++ device domain 0 on ++ ops x4x_pci_domain_ops # PCI domain ++ subsystemid 0x8086 0x0028 inherit ++ device pci 0.0 on end # Host Bridge ++ device pci 1.0 on end # PCIe x16 2.0 slot ++ device pci 2.0 on end # Integrated graphics controller ++ device pci 2.1 on end # Integrated graphics controller 2 ++ device pci 3.0 off end # ME ++ device pci 3.1 off end # ME ++ chip southbridge/intel/i82801jx # ICH10 ++ register "gpe0_en" = "0x40" ++ ++ # Set AHCI mode. ++ register "sata_port_map" = "0x3f" ++ register "sata_clock_request" = "1" ++ ++ # Enable PCIe ports 0,1 as slots. ++ register "pcie_slot_implemented" = "0x3" ++ ++ device pci 19.0 on end # GBE ++ device pci 1a.0 on end # USB ++ device pci 1a.1 on end # USB ++ device pci 1a.2 on end # USB ++ device pci 1a.7 on end # USB ++ device pci 1b.0 on end # Audio ++ device pci 1c.0 off end # PCIe 1 ++ device pci 1c.1 off end # PCIe 2 ++ device pci 1c.2 off end # PCIe 3 ++ device pci 1c.3 off end # PCIe 4 ++ device pci 1c.4 off end # PCIe 5 ++ device pci 1c.5 off end # PCIe 6 ++ device pci 1d.0 on end # USB ++ device pci 1d.1 on end # USB ++ device pci 1d.2 on end # USB ++ device pci 1d.7 on end # USB ++ device pci 1e.0 on end # PCI bridge ++ device pci 1f.0 on end # LPC bridge ++ device pci 1f.2 on end # SATA (IDE: port 0-3, AHCI/RAID: 0-5) ++ device pci 1f.3 on # SMBus ++ chip drivers/i2c/ck505 # IDT CV194 ++ register "mask" = "{ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff }" ++ register "regs" = "{ 0x15, 0x82, 0xff, 0xff, ++ 0xff, 0x00, 0x00, 0x95, ++ 0x00, 0x65, 0x7d, 0x56, ++ 0x13, 0xc0, 0x00, 0x07, ++ 0x01, 0x0a, 0x64 }" ++ device i2c 69 on end ++ end ++ end ++ device pci 1f.4 off end ++ device pci 1f.5 off end # SATA 2 (for port 4-5 in IDE mode) ++ device pci 1f.6 off end # Thermal Subsystem ++ end ++ end ++end +diff --git a/src/mainboard/dell/optiplex_780/dsdt.asl b/src/mainboard/dell/optiplex_780/dsdt.asl +new file mode 100644 +index 0000000000..9ad70469de +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/dsdt.asl +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <acpi/acpi.h> ++DefinitionBlock( ++ "dsdt.aml", ++ "DSDT", ++ ACPI_DSDT_REV_2, ++ OEM_ID, ++ ACPI_TABLE_CREATOR, ++ 0x20090811 // OEM revision ++) ++{ ++ #include <acpi/dsdt_top.asl> ++ ++ OSYS = 2002 ++ // global NVS and variables ++ #include <southbridge/intel/common/acpi/platform.asl> ++ ++ Device (\_SB.PCI0) ++ { ++ #include <northbridge/intel/x4x/acpi/x4x.asl> ++ #include <southbridge/intel/i82801jx/acpi/ich10.asl> ++ } ++ ++ #include <southbridge/intel/common/acpi/sleepstates.asl> ++} +diff --git a/src/mainboard/dell/optiplex_780/gma-mainboard.ads b/src/mainboard/dell/optiplex_780/gma-mainboard.ads +new file mode 100644 +index 0000000000..bc81cf4a40 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/gma-mainboard.ads +@@ -0,0 +1,16 @@ ++-- SPDX-License-Identifier: GPL-2.0-or-later ++ ++with HW.GFX.GMA; ++with HW.GFX.GMA.Display_Probing; ++ ++use HW.GFX.GMA; ++use HW.GFX.GMA.Display_Probing; ++ ++private package GMA.Mainboard is ++ ++ ports : constant Port_List := ++ (DP2, ++ Analog, ++ others => Disabled); ++ ++end GMA.Mainboard; +diff --git a/src/mainboard/dell/optiplex_780/variants/780_mt/data.vbt b/src/mainboard/dell/optiplex_780/variants/780_mt/data.vbt +new file mode 100644 +index 0000000000000000000000000000000000000000..fefda9d6f226b88ab67c5b044de30a707df22fbf +GIT binary patch +literal 1917 +zcmd6nO>7%Q6vzLwGv0Mv$FUpJ*ik4iQd_wnX*X`M0y3~p?8a$~>ZXxZMU`4dc9RGb +zTXq_i1Bwd~aNr{c4i)r(goF^M-nek+sY0sMa}Sk>xFFy_FTEfX^Y+7unt+OgkeJbX +zznS;`v-5V=o<pVaS;}Q53%NpOI!8{cz{K0eVfK65_|*A}SF)Me%$4!N`H5-z90%~a +zvGog3fe5LjnM&o#3$<#k{6>{ZwwmnN>gY?}>{`7^JBpP$l`EBIwbi0*k&aU)n@v)E +znI_A1T57efS5MG<y}m-_+CrVKE#0VADDft%nb#Y<<ao9;Mf?!XvM)_$Xla>NN5_ut +zt=x`G)EjR#mlhURC^2!A3p33TcBg4-d8JyTiF&hfk}|a#&Dfe2%~V^}=4!QavNzBh +z0Pae^5`gfb?<R!YN+PQ)U7<%H;73qF3iyQT71$?W2s|f{69_4sRY(x>7Q)c(LsP)8 +zQy)2gw<F#IP`I}U>gG1S^>aw&0D}Z+-SCcJJF;s)yXJeQ|4N{SU?$I`#$HZa<Jq(M +zbA{r}Z0XY6<@U{Y-d!KWR>9dWBuxA$6X;VK;%W?Y>I;0P`|*vwAK$S(VB2JSq6g4n +z>oEf8XCt;_Y-iYBWz#<re{?il1^f{S#nht`VW!62^5R*KQ6_?#8e&Qw=9%`og2x!s +z&J)wlZ=a<yoJkutfwu4%aVXlu?i^8v?R77IyGvKcD|M`CFG$6FUmK8q<|o>3T9EmJ +z2x?*GPeN%?=Fj3+fv~4%I(nv~XF7VOqi5RsAt%13JtW>q=<<<Gei4)FzWqGEt6P8D +zA9m}s>;0IkLPSUGL%_1h)2kjaZzuV;`43yCV;I=#Jcyyw@xKE8GGX39@am|0GKhH` +zawsKv^FvHqm+<DDPT)%}_kZ8^eT88YGmG-#)X3=RRB|L^Uj_{yd%JeO<1HRZVz=Fz +z+aqUCWdF3_={#Q&&k)eF1i=WV`AbSlzo*bP?x?ir5BVVO`R34f89jWL{Z}or^BwmG +z-E;A_iWVUUWnWQl3L|~0xA@rHJRA-;7V)Y6B5=@E8R@?(?5{Eh23RefpSOGX_F{8A +z1PtU+iNng^h#C7J<vufJ9>c8*FfFsu??w)Oed@;Mg~21%rCZ%d{x!>-zmv4AyWL1E +xfz+CGUnQ7Y^TD}&c_cQRYlBC+`?m?k6Nuw??s04gg4@4`<@FO{XEbO(<xf!`#Pk3F + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/dell/optiplex_780/variants/780_mt/early_init.c b/src/mainboard/dell/optiplex_780/variants/780_mt/early_init.c +new file mode 100644 +index 0000000000..e2fa05cd8f +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/variants/780_mt/early_init.c +@@ -0,0 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++ ++#include <northbridge/intel/x4x/x4x.h> ++ ++void mb_get_spd_map(u8 spd_map[4]) ++{ ++ // BTX form factor ++ spd_map[0] = 0x53; ++ spd_map[1] = 0x52; ++ spd_map[2] = 0x51; ++ spd_map[3] = 0x50; ++} +diff --git a/src/mainboard/dell/optiplex_780/variants/780_mt/gpio.c b/src/mainboard/dell/optiplex_780/variants/780_mt/gpio.c +new file mode 100644 +index 0000000000..9993f17c55 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/variants/780_mt/gpio.c +@@ -0,0 +1,174 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <southbridge/intel/common/gpio.h> ++ ++static const struct pch_gpio_set1 pch_gpio_set1_mode = { ++ .gpio0 = GPIO_MODE_NATIVE, ++ .gpio1 = GPIO_MODE_NATIVE, ++ .gpio2 = GPIO_MODE_GPIO, ++ .gpio3 = GPIO_MODE_GPIO, ++ .gpio4 = GPIO_MODE_GPIO, ++ .gpio5 = GPIO_MODE_GPIO, ++ .gpio6 = GPIO_MODE_GPIO, ++ .gpio7 = GPIO_MODE_NATIVE, ++ .gpio8 = GPIO_MODE_NATIVE, ++ .gpio9 = GPIO_MODE_GPIO, ++ .gpio10 = GPIO_MODE_GPIO, ++ .gpio11 = GPIO_MODE_NATIVE, ++ .gpio12 = GPIO_MODE_NATIVE, ++ .gpio13 = GPIO_MODE_GPIO, ++ .gpio14 = GPIO_MODE_GPIO, ++ .gpio15 = GPIO_MODE_NATIVE, ++ .gpio16 = GPIO_MODE_GPIO, ++ .gpio17 = GPIO_MODE_NATIVE, ++ .gpio18 = GPIO_MODE_GPIO, ++ .gpio19 = GPIO_MODE_GPIO, ++ .gpio20 = GPIO_MODE_GPIO, ++ .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_GPIO, ++ .gpio31 = GPIO_MODE_GPIO, ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_direction = { ++ .gpio2 = GPIO_DIR_INPUT, ++ .gpio3 = GPIO_DIR_INPUT, ++ .gpio4 = GPIO_DIR_INPUT, ++ .gpio5 = GPIO_DIR_INPUT, ++ .gpio6 = GPIO_DIR_INPUT, ++ .gpio9 = GPIO_DIR_OUTPUT, ++ .gpio10 = GPIO_DIR_INPUT, ++ .gpio13 = GPIO_DIR_INPUT, ++ .gpio14 = GPIO_DIR_INPUT, ++ .gpio16 = GPIO_DIR_INPUT, ++ .gpio18 = GPIO_DIR_OUTPUT, ++ .gpio19 = GPIO_DIR_INPUT, ++ .gpio20 = GPIO_DIR_OUTPUT, ++ .gpio21 = GPIO_DIR_INPUT, ++ .gpio22 = GPIO_DIR_INPUT, ++ .gpio24 = GPIO_DIR_INPUT, ++ .gpio27 = GPIO_DIR_INPUT, ++ .gpio28 = GPIO_DIR_OUTPUT, ++ .gpio29 = GPIO_DIR_INPUT, ++ .gpio30 = GPIO_DIR_INPUT, ++ .gpio31 = GPIO_DIR_INPUT, ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_level = { ++ .gpio9 = GPIO_LEVEL_HIGH, ++ .gpio18 = GPIO_LEVEL_HIGH, ++ .gpio20 = GPIO_LEVEL_HIGH, ++ .gpio28 = GPIO_LEVEL_LOW, ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_blink = { ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_invert = { ++ .gpio13 = GPIO_INVERT, ++}; ++ ++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_GPIO, ++ .gpio55 = GPIO_MODE_NATIVE, ++ .gpio56 = GPIO_MODE_GPIO, ++ .gpio57 = GPIO_MODE_GPIO, ++ .gpio58 = GPIO_MODE_NATIVE, ++ .gpio59 = GPIO_MODE_NATIVE, ++ .gpio60 = GPIO_MODE_GPIO, ++ .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_INPUT, ++ .gpio33 = GPIO_DIR_INPUT, ++ .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_OUTPUT, ++ .gpio54 = GPIO_DIR_INPUT, ++ .gpio56 = GPIO_DIR_OUTPUT, ++ .gpio57 = GPIO_DIR_INPUT, ++ .gpio60 = GPIO_DIR_OUTPUT, ++}; ++ ++static const struct pch_gpio_set2 pch_gpio_set2_level = { ++ .gpio35 = GPIO_LEVEL_LOW, ++ .gpio49 = GPIO_LEVEL_HIGH, ++ .gpio56 = GPIO_LEVEL_HIGH, ++ .gpio60 = GPIO_LEVEL_LOW, ++}; ++ ++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_NATIVE, ++ .gpio69 = GPIO_MODE_NATIVE, ++ .gpio70 = GPIO_MODE_NATIVE, ++ .gpio71 = GPIO_MODE_NATIVE, ++ .gpio72 = GPIO_MODE_GPIO, ++}; ++ ++static const struct pch_gpio_set3 pch_gpio_set3_direction = { ++ .gpio72 = GPIO_DIR_INPUT, ++}; ++ ++static const struct pch_gpio_set3 pch_gpio_set3_level = { ++}; ++ ++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, ++ }, ++ .set2 = { ++ .mode = &pch_gpio_set2_mode, ++ .direction = &pch_gpio_set2_direction, ++ .level = &pch_gpio_set2_level, ++ }, ++ .set3 = { ++ .mode = &pch_gpio_set3_mode, ++ .direction = &pch_gpio_set3_direction, ++ .level = &pch_gpio_set3_level, ++ }, ++}; +diff --git a/src/mainboard/dell/optiplex_780/variants/780_mt/hda_verb.c b/src/mainboard/dell/optiplex_780/variants/780_mt/hda_verb.c +new file mode 100644 +index 0000000000..4158bcf899 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/variants/780_mt/hda_verb.c +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++ ++#include <device/azalia_device.h> ++ ++const u32 cim_verb_data[] = { ++ /* coreboot specific header */ ++ 0x11d4194a, /* Analog Devices AD1984A */ ++ 0xbfd40000, /* Subsystem ID */ ++ 10, /* Number of entries */ ++ ++ /* Pin Widget Verb Table */ ++ AZALIA_PIN_CFG(0, 0x11, 0x032140f0), ++ AZALIA_PIN_CFG(0, 0x12, 0x21214010), ++ AZALIA_PIN_CFG(0, 0x13, 0x901701f0), ++ AZALIA_PIN_CFG(0, 0x14, 0x03a190f0), ++ AZALIA_PIN_CFG(0, 0x15, 0xb7a70121), ++ AZALIA_PIN_CFG(0, 0x16, 0x9933012e), ++ AZALIA_PIN_CFG(0, 0x17, 0x97a601f0), ++ AZALIA_PIN_CFG(0, 0x1a, 0x90f301f0), ++ AZALIA_PIN_CFG(0, 0x1b, 0x014510f0), ++ AZALIA_PIN_CFG(0, 0x1c, 0x21a19020), ++}; ++ ++const u32 pc_beep_verbs[0] = {}; ++ ++AZALIA_ARRAY_SIZES; +diff --git a/src/mainboard/dell/optiplex_780/variants/780_mt/overridetree.cb b/src/mainboard/dell/optiplex_780/variants/780_mt/overridetree.cb +new file mode 100644 +index 0000000000..555b1c1f5c +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/variants/780_mt/overridetree.cb +@@ -0,0 +1,10 @@ ++## SPDX-License-Identifier: GPL-2.0-or-later ++ ++chip northbridge/intel/x4x ++ device domain 0 on ++ chip southbridge/intel/i82801jx ++ device pci 1c.0 on end # PCIe 1 ++ device pci 1c.1 on end # PCIe 2 ++ end ++ end ++end +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch b/config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch deleted file mode 100644 index a1cf9b75..00000000 --- a/config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch +++ /dev/null @@ -1,348 +0,0 @@ -From 0966980e52286985fcd0fac6325bdd99f35ebcb8 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Thu, 11 Apr 2024 17:25:07 +0200 -Subject: [PATCH 30/51] haswell NRI: Initialise MPLL - -Add code to initialise the MPLL (Memory PLL). The procedure is similar -to the one for Sandy/Ivy Bridge, but it is not worth factoring out. - -Change-Id: I978c352de68f6d8cecc76f4ae3c12daaf4be9ed6 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 2 + - .../intel/haswell/native_raminit/init_mpll.c | 210 ++++++++++++++++++ - .../haswell/native_raminit/io_comp_control.c | 22 ++ - .../haswell/native_raminit/raminit_main.c | 3 +- - .../haswell/native_raminit/raminit_native.h | 11 + - .../intel/haswell/registers/mchbar.h | 3 + - 6 files changed, 250 insertions(+), 1 deletion(-) - create mode 100644 src/northbridge/intel/haswell/native_raminit/init_mpll.c - create mode 100644 src/northbridge/intel/haswell/native_raminit/io_comp_control.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index ebf7abc6ec..c125d84f0b 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -1,5 +1,7 @@ - ## SPDX-License-Identifier: GPL-2.0-or-later - -+romstage-y += init_mpll.c -+romstage-y += io_comp_control.c - romstage-y += raminit_main.c - romstage-y += raminit_native.c - romstage-y += spd_bitmunching.c -diff --git a/src/northbridge/intel/haswell/native_raminit/init_mpll.c b/src/northbridge/intel/haswell/native_raminit/init_mpll.c -new file mode 100644 -index 0000000000..1f3f2c29a9 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/init_mpll.c -@@ -0,0 +1,210 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <delay.h> -+#include <device/pci_ops.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+static uint32_t get_mem_multiplier(const struct sysinfo *ctrl) -+{ -+ const uint32_t mult = NS2MHZ_DIV256 / (ctrl->tCK * ctrl->base_freq); -+ -+ if (ctrl->base_freq == 100) -+ return clamp_u32(7, mult, 12); -+ -+ if (ctrl->base_freq == 133) -+ return clamp_u32(3, mult, 10); -+ -+ die("Unsupported base frequency\n"); -+} -+ -+static void normalize_tck(struct sysinfo *ctrl, const bool pll_ref100) -+{ -+ /** TODO: Haswell supports up to DDR3-2600 **/ -+ if (ctrl->tCK <= TCK_1200MHZ) { -+ ctrl->tCK = TCK_1200MHZ; -+ ctrl->base_freq = 133; -+ ctrl->mem_clock_mhz = 1200; -+ -+ } else if (ctrl->tCK <= TCK_1100MHZ) { -+ ctrl->tCK = TCK_1100MHZ; -+ ctrl->base_freq = 100; -+ ctrl->mem_clock_mhz = 1100; -+ -+ } else if (ctrl->tCK <= TCK_1066MHZ) { -+ ctrl->tCK = TCK_1066MHZ; -+ ctrl->base_freq = 133; -+ ctrl->mem_clock_mhz = 1066; -+ -+ } else if (ctrl->tCK <= TCK_1000MHZ) { -+ ctrl->tCK = TCK_1000MHZ; -+ ctrl->base_freq = 100; -+ ctrl->mem_clock_mhz = 1000; -+ -+ } else if (ctrl->tCK <= TCK_933MHZ) { -+ ctrl->tCK = TCK_933MHZ; -+ ctrl->base_freq = 133; -+ ctrl->mem_clock_mhz = 933; -+ -+ } else if (ctrl->tCK <= TCK_900MHZ) { -+ ctrl->tCK = TCK_900MHZ; -+ ctrl->base_freq = 100; -+ ctrl->mem_clock_mhz = 900; -+ -+ } else if (ctrl->tCK <= TCK_800MHZ) { -+ ctrl->tCK = TCK_800MHZ; -+ ctrl->base_freq = 133; -+ ctrl->mem_clock_mhz = 800; -+ -+ } else if (ctrl->tCK <= TCK_700MHZ) { -+ ctrl->tCK = TCK_700MHZ; -+ ctrl->base_freq = 100; -+ ctrl->mem_clock_mhz = 700; -+ -+ } else if (ctrl->tCK <= TCK_666MHZ) { -+ ctrl->tCK = TCK_666MHZ; -+ ctrl->base_freq = 133; -+ ctrl->mem_clock_mhz = 666; -+ -+ } else if (ctrl->tCK <= TCK_533MHZ) { -+ ctrl->tCK = TCK_533MHZ; -+ ctrl->base_freq = 133; -+ ctrl->mem_clock_mhz = 533; -+ -+ } else if (ctrl->tCK <= TCK_400MHZ) { -+ ctrl->tCK = TCK_400MHZ; -+ ctrl->base_freq = 133; -+ ctrl->mem_clock_mhz = 400; -+ -+ } else { -+ ctrl->tCK = 0; -+ ctrl->base_freq = 1; -+ ctrl->mem_clock_mhz = 0; -+ return; -+ } -+ if (!pll_ref100 && ctrl->base_freq == 100) { -+ /* Skip unsupported frequency */ -+ ctrl->tCK++; -+ normalize_tck(ctrl, pll_ref100); -+ } -+} -+ -+#define MIN_CAS 4 -+#define MAX_CAS 24 -+ -+static uint8_t find_compatible_cas(struct sysinfo *ctrl) -+{ -+ printk(RAM_DEBUG, "With tCK %u, try CAS: ", ctrl->tCK); -+ const uint8_t cas_lower = MAX(MIN_CAS, DIV_ROUND_UP(ctrl->tAA, ctrl->tCK)); -+ const uint8_t cas_upper = MIN(MAX_CAS, 19); /* JEDEC MR0 limit */ -+ -+ if (!(ctrl->cas_supported >> (cas_lower - MIN_CAS))) { -+ printk(RAM_DEBUG, "DIMMs do not support CAS >= %u\n", cas_lower); -+ ctrl->tCK++; -+ return 0; -+ } -+ for (uint8_t cas = cas_lower; cas <= cas_upper; cas++) { -+ printk(RAM_DEBUG, "%u ", cas); -+ if (ctrl->cas_supported & BIT(cas - MIN_CAS)) { -+ printk(RAM_DEBUG, "OK\n"); -+ return cas; -+ } -+ } -+ return 0; -+} -+ -+static enum raminit_status find_cas_tck(struct sysinfo *ctrl) -+{ -+ /** TODO: Honor all possible PLL_REF100_CFG values **/ -+ uint8_t pll_ref100 = (pci_read_config32(HOST_BRIDGE, CAPID0_B) >> 21) & 0x7; -+ printk(RAM_DEBUG, "PLL_REF100_CFG value: 0x%x\n", pll_ref100); -+ printk(RAM_DEBUG, "100MHz reference clock support: %s\n", pll_ref100 ? "yes" : "no"); -+ -+ uint8_t selected_cas; -+ while (true) { -+ /* Round tCK up so that it is a multiple of either 133 or 100 MHz */ -+ normalize_tck(ctrl, pll_ref100); -+ if (!ctrl->tCK) { -+ printk(BIOS_ERR, "Couldn't find compatible clock / CAS settings\n"); -+ return RAMINIT_STATUS_MPLL_INIT_FAILURE; -+ } -+ selected_cas = find_compatible_cas(ctrl); -+ if (selected_cas) -+ break; -+ -+ ctrl->tCK++; -+ } -+ printk(BIOS_DEBUG, "Found compatible clock / CAS settings\n"); -+ printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", NS2MHZ_DIV256 / ctrl->tCK); -+ printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", selected_cas); -+ ctrl->multiplier = get_mem_multiplier(ctrl); -+ return RAMINIT_STATUS_SUCCESS; -+} -+ -+enum raminit_status initialise_mpll(struct sysinfo *ctrl) -+{ -+ if (ctrl->tCK > TCK_400MHZ) { -+ printk(BIOS_ERR, "tCK is too slow. Increasing to 400 MHz as last resort\n"); -+ ctrl->tCK = TCK_400MHZ; -+ } -+ while (true) { -+ if (!ctrl->qclkps) { -+ const enum raminit_status status = find_cas_tck(ctrl); -+ if (status) -+ return status; -+ } -+ -+ /* -+ * Unlike previous generations, Haswell's MPLL won't shut down if the -+ * requested frequency isn't supported. But we cannot reinitialize it. -+ * Another different thing: MPLL registers are 4-bit instead of 8-bit. -+ */ -+ -+ /** FIXME: Obtain current clock frequency if we want to skip this **/ -+ //if (mchbar_read32(MC_BIOS_DATA) != 0) -+ // break; -+ -+ uint32_t mc_bios_req = ctrl->multiplier; -+ if (ctrl->base_freq == 100) { -+ /* Use 100 MHz reference clock */ -+ mc_bios_req |= BIT(4); -+ } -+ mc_bios_req |= BIT(31); -+ printk(RAM_DEBUG, "MC_BIOS_REQ = 0x%08x\n", mc_bios_req); -+ printk(BIOS_DEBUG, "MPLL busy... "); -+ mchbar_write32(MC_BIOS_REQ, mc_bios_req); -+ -+ for (unsigned int i = 0; i <= 5000; i++) { -+ if (!(mchbar_read32(MC_BIOS_REQ) & BIT(31))) { -+ printk(BIOS_DEBUG, "done in %u us\n", i); -+ break; -+ } -+ udelay(1); -+ } -+ if (mchbar_read32(MC_BIOS_REQ) & BIT(31)) -+ printk(BIOS_DEBUG, "did not lock\n"); -+ -+ /* Verify locked frequency */ -+ const uint32_t mc_bios_data = mchbar_read32(MC_BIOS_DATA); -+ printk(RAM_DEBUG, "MC_BIOS_DATA = 0x%08x\n", mc_bios_data); -+ if ((mc_bios_data & 0xf) >= ctrl->multiplier) -+ break; -+ -+ printk(BIOS_DEBUG, "Retrying at a lower frequency\n\n"); -+ ctrl->tCK++; -+ } -+ if (!ctrl->mem_clock_mhz) { -+ printk(BIOS_ERR, "Could not program MPLL frequency\n"); -+ return RAMINIT_STATUS_MPLL_INIT_FAILURE; -+ } -+ printk(BIOS_DEBUG, "MPLL frequency is set to: %u MHz ", ctrl->mem_clock_mhz); -+ ctrl->mem_clock_fs = 1000000000 / ctrl->mem_clock_mhz; -+ printk(BIOS_DEBUG, "(period: %u femtoseconds)\n", ctrl->mem_clock_fs); -+ ctrl->qclkps = ctrl->mem_clock_fs / 2000; -+ printk(BIOS_DEBUG, "Quadrature clock period: %u picoseconds\n", ctrl->qclkps); -+ return wait_for_first_rcomp(); -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/io_comp_control.c b/src/northbridge/intel/haswell/native_raminit/io_comp_control.c -new file mode 100644 -index 0000000000..d45b608dd3 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/io_comp_control.c -@@ -0,0 +1,22 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <timer.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+enum raminit_status wait_for_first_rcomp(void) -+{ -+ struct stopwatch timer; -+ stopwatch_init_msecs_expire(&timer, 2000); -+ do { -+ if (mchbar_read32(RCOMP_TIMER) & BIT(16)) -+ return RAMINIT_STATUS_SUCCESS; -+ -+ } while (!stopwatch_expired(&timer)); -+ printk(BIOS_ERR, "Timed out waiting for RCOMP to complete\n"); -+ return RAMINIT_STATUS_POLL_TIMEOUT; -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 19ec5859ac..bf745e943f 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -19,7 +19,8 @@ struct task_entry { - }; - - static const struct task_entry cold_boot[] = { -- { collect_spd_info, true, "PROCSPD", }, -+ { collect_spd_info, true, "PROCSPD", }, -+ { initialise_mpll, true, "INITMPLL", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 8078c9c386..15a1550424 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -24,6 +24,8 @@ enum raminit_status { - RAMINIT_STATUS_SUCCESS = 0, - RAMINIT_STATUS_NO_MEMORY_INSTALLED, - RAMINIT_STATUS_UNSUPPORTED_MEMORY, -+ RAMINIT_STATUS_MPLL_INIT_FAILURE, -+ RAMINIT_STATUS_POLL_TIMEOUT, - RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/ - }; - -@@ -83,10 +85,19 @@ struct sysinfo { - uint8_t rankmap[NUM_CHANNELS]; - uint8_t rank_mirrored[NUM_CHANNELS]; - uint32_t channel_size_mb[NUM_CHANNELS]; -+ -+ uint8_t base_freq; /* Memory base frequency, either 100 or 133 MHz */ -+ uint32_t multiplier; -+ uint32_t mem_clock_mhz; -+ uint32_t mem_clock_fs; /* Memory clock period in femtoseconds */ -+ uint32_t qclkps; /* Quadrature clock period in picoseconds */ - }; - - void raminit_main(enum raminit_boot_mode bootmode); - - enum raminit_status collect_spd_info(struct sysinfo *ctrl); -+enum raminit_status initialise_mpll(struct sysinfo *ctrl); -+ -+enum raminit_status wait_for_first_rcomp(void); - - #endif -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 5610e7089a..45f8174995 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -13,6 +13,8 @@ - #define MC_INIT_STATE_G 0x5030 - #define MRC_REVISION 0x5034 /* MRC Revision */ - -+#define RCOMP_TIMER 0x5084 -+ - #define MC_LOCK 0x50fc /* Memory Controller Lock register */ - - #define GFXVTBAR 0x5400 /* Base address for IGD */ -@@ -61,6 +63,7 @@ - - #define BIOS_RESET_CPL 0x5da8 /* 8-bit */ - -+#define MC_BIOS_REQ 0x5e00 /* Memory frequency request register */ - #define MC_BIOS_DATA 0x5e04 /* Miscellaneous information for BIOS */ - #define SAPMCTL 0x5f00 - --- -2.39.5 - diff --git a/config/coreboot/default/patches/0030-mb-dell-optiplex_780-Add-USFF-variant.patch b/config/coreboot/default/patches/0030-mb-dell-optiplex_780-Add-USFF-variant.patch new file mode 100644 index 00000000..8ce7471b --- /dev/null +++ b/config/coreboot/default/patches/0030-mb-dell-optiplex_780-Add-USFF-variant.patch @@ -0,0 +1,326 @@ +From 6725ec0bb976c61cbe87e61bf0e8b02e38d14de9 Mon Sep 17 00:00:00 2001 +From: Nicholas Chin <nic.c3.14@gmail.com> +Date: Wed, 30 Oct 2024 20:55:25 -0600 +Subject: [PATCH 30/37] mb/dell/optiplex_780: Add USFF variant + +Change-Id: I3aa21c743749f4a11a2501f4c121316bd2f1a103 +Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> +--- + src/mainboard/dell/optiplex_780/Kconfig | 5 + + src/mainboard/dell/optiplex_780/Kconfig.name | 3 + + .../optiplex_780/variants/780_usff/data.vbt | Bin 0 -> 1917 bytes + .../variants/780_usff/early_init.c | 9 + + .../optiplex_780/variants/780_usff/gpio.c | 166 ++++++++++++++++++ + .../optiplex_780/variants/780_usff/hda_verb.c | 26 +++ + .../variants/780_usff/overridetree.cb | 10 ++ + 7 files changed, 219 insertions(+) + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_usff/data.vbt + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_usff/early_init.c + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_usff/gpio.c + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_usff/hda_verb.c + create mode 100644 src/mainboard/dell/optiplex_780/variants/780_usff/overridetree.cb + +diff --git a/src/mainboard/dell/optiplex_780/Kconfig b/src/mainboard/dell/optiplex_780/Kconfig +index 2d06c75c9a..fc649e35d5 100644 +--- a/src/mainboard/dell/optiplex_780/Kconfig ++++ b/src/mainboard/dell/optiplex_780/Kconfig +@@ -20,6 +20,9 @@ config BOARD_DELL_OPTIPLEX_780_COMMON + config BOARD_DELL_OPTIPLEX_780_MT + select BOARD_DELL_OPTIPLEX_780_COMMON + ++config BOARD_DELL_OPTIPLEX_780_USFF ++ select BOARD_DELL_OPTIPLEX_780_COMMON ++ + if BOARD_DELL_OPTIPLEX_780_COMMON + + config VGA_BIOS_ID +@@ -30,11 +33,13 @@ config MAINBOARD_DIR + + config MAINBOARD_PART_NUMBER + default "OptiPlex 780 MT" if BOARD_DELL_OPTIPLEX_780_MT ++ default "OptiPlex 780 USFF" if BOARD_DELL_OPTIPLEX_780_USFF + + config OVERRIDE_DEVICETREE + default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb" + + config VARIANT_DIR + default "780_mt" if BOARD_DELL_OPTIPLEX_780_MT ++ default "780_usff" if BOARD_DELL_OPTIPLEX_780_USFF + + endif # BOARD_DELL_OPTIPLEX_780_COMMON +diff --git a/src/mainboard/dell/optiplex_780/Kconfig.name b/src/mainboard/dell/optiplex_780/Kconfig.name +index db7f2e8fe3..bc84c82a79 100644 +--- a/src/mainboard/dell/optiplex_780/Kconfig.name ++++ b/src/mainboard/dell/optiplex_780/Kconfig.name +@@ -2,3 +2,6 @@ + + config BOARD_DELL_OPTIPLEX_780_MT + bool "OptiPlex 780 MT" ++ ++config BOARD_DELL_OPTIPLEX_780_USFF ++ bool "OptiPlex 780 USFF" +diff --git a/src/mainboard/dell/optiplex_780/variants/780_usff/data.vbt b/src/mainboard/dell/optiplex_780/variants/780_usff/data.vbt +new file mode 100644 +index 0000000000000000000000000000000000000000..dbd764f285ed18f7ee9c54bc777560138bd9b5f7 +GIT binary patch +literal 1917 +zcmd6nO>7%Q6vzLwGv3{}j$^l`v7@w1q*9sEq+2(b3K>`@c5#TSx@i<uQKf!)+gO;| +zveT#>P+W+B10OwbsGtX=N(gc4jSGjKDkP+yIUo^nsel8$^ny^9H?td8Ra=EiCEn=G +z@6DV4?!2AdojnUv^Rirgvs$heXUkGs9S+{Jc2WPhP0buTak^BTFP@&N9-E$(UtuSX +zS{r`=b+EX|Ig`2a*^5oDdG>8jE-1BBxs`*jgrf_sj_fP;%L|PwURRcCFBMCroNRQv +zmp$2TUhc}qJMB(u#jDG@x6(N85thC4%Z=8hiN}lj&zb2~``u3C;?lCrPQOTnInFqB +zhvdwqWv?lxTb=fVEH;~RPHDPw&g*&|s$pU<Iv53Rb6YTgMPOY8;~P1Yglh^6Fgt1^ +zCTz|SVPcSpZ44F@&oNPUMO@&BE3y(57YP_Y!4SZhE?GXYa7k+b0(X|s7u3GDRf^1# +zOd2ZCCPO|I&sHEt;p8UshhHtYQ>7!7x2m<d`Gu2<r+Qc4|6pwd8&zFboH_W7XE7uU +zWW-@Cim&mdY2!O{JANR)OTJG2z>LBtAF!g>K`zPnkx!DpPHuk6{_zc*0qi7)Aet$T +z1ks@8hWS#+6cI5)j1oD86{5PX8Zu2(^OC6M`<pE+J?KFZ=&_JVP1YL=#z<-Q*24K4 +zn+$YxrHNJJc`k?_8N=Kres26_#E8GLn2{jfW5P%ge`kL(Btkt=>xo)V)Ow=U6P12c +z=U0uNC9T9v{)-|#h(mSX*hSA8)ZeocL7l4J&!{RSO{6~oTtyn535j!RQh#GA*wTF8 +zvasRbO~d!?*FbM3K`W?lHx=v*(jiARIhWyh4^io|;n?@1H>uqJy>0sjV-Dt)_=%bE +zgNO3D@uE5m+7aqi?Y8b+inye%Z=HUmgBtaZ3Lc%OLt+bo+)5BjVwT<{mxT`nde$vb +zV99s{>`r76L#Hr6XW6r|<iq#4Jr?XsxKyeJKEj7;e4SZ^1B12u&iV_9M0*Kem@fmn +z1C>>HT47I`**Q#Vu0QW!^VP-9S{xXzpq_zS#9k-;aXz?b+S!Ne$Kkk6dq<Gj{q2D( +z>&Hj-x+kx1W-4#E&beDT*S)=&NoSE?<-w!G@~aW()0ZN4O&=Q+nZa)p%Vd$k-_$a= +T#w3FFBiyj<XAh$hb(enud`r7S + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/dell/optiplex_780/variants/780_usff/early_init.c b/src/mainboard/dell/optiplex_780/variants/780_usff/early_init.c +new file mode 100644 +index 0000000000..2a55fc3a6e +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/variants/780_usff/early_init.c +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++ ++#include <northbridge/intel/x4x/x4x.h> ++ ++void mb_get_spd_map(u8 spd_map[4]) ++{ ++ spd_map[0] = 0x50; ++ spd_map[2] = 0x52; ++} +diff --git a/src/mainboard/dell/optiplex_780/variants/780_usff/gpio.c b/src/mainboard/dell/optiplex_780/variants/780_usff/gpio.c +new file mode 100644 +index 0000000000..389f4077d7 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/variants/780_usff/gpio.c +@@ -0,0 +1,166 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <southbridge/intel/common/gpio.h> ++ ++static const struct pch_gpio_set1 pch_gpio_set1_mode = { ++ .gpio0 = GPIO_MODE_NATIVE, ++ .gpio1 = GPIO_MODE_NATIVE, ++ .gpio2 = GPIO_MODE_GPIO, ++ .gpio3 = GPIO_MODE_GPIO, ++ .gpio4 = GPIO_MODE_GPIO, ++ .gpio5 = GPIO_MODE_GPIO, ++ .gpio6 = GPIO_MODE_GPIO, ++ .gpio7 = GPIO_MODE_NATIVE, ++ .gpio8 = GPIO_MODE_NATIVE, ++ .gpio9 = GPIO_MODE_GPIO, ++ .gpio10 = GPIO_MODE_GPIO, ++ .gpio11 = GPIO_MODE_NATIVE, ++ .gpio12 = GPIO_MODE_NATIVE, ++ .gpio13 = GPIO_MODE_GPIO, ++ .gpio14 = GPIO_MODE_GPIO, ++ .gpio15 = GPIO_MODE_NATIVE, ++ .gpio16 = GPIO_MODE_GPIO, ++ .gpio17 = GPIO_MODE_NATIVE, ++ .gpio18 = GPIO_MODE_GPIO, ++ .gpio19 = GPIO_MODE_GPIO, ++ .gpio20 = GPIO_MODE_GPIO, ++ .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_GPIO, ++ .gpio31 = GPIO_MODE_GPIO, ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_direction = { ++ .gpio2 = GPIO_DIR_INPUT, ++ .gpio3 = GPIO_DIR_INPUT, ++ .gpio4 = GPIO_DIR_INPUT, ++ .gpio5 = GPIO_DIR_INPUT, ++ .gpio6 = GPIO_DIR_INPUT, ++ .gpio9 = GPIO_DIR_OUTPUT, ++ .gpio10 = GPIO_DIR_INPUT, ++ .gpio13 = GPIO_DIR_INPUT, ++ .gpio14 = GPIO_DIR_INPUT, ++ .gpio16 = GPIO_DIR_INPUT, ++ .gpio18 = GPIO_DIR_OUTPUT, ++ .gpio19 = GPIO_DIR_INPUT, ++ .gpio20 = GPIO_DIR_OUTPUT, ++ .gpio21 = GPIO_DIR_INPUT, ++ .gpio22 = GPIO_DIR_INPUT, ++ .gpio24 = GPIO_DIR_INPUT, ++ .gpio27 = GPIO_DIR_INPUT, ++ .gpio28 = GPIO_DIR_OUTPUT, ++ .gpio29 = GPIO_DIR_INPUT, ++ .gpio30 = GPIO_DIR_INPUT, ++ .gpio31 = GPIO_DIR_INPUT, ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_level = { ++ .gpio9 = GPIO_LEVEL_HIGH, ++ .gpio18 = GPIO_LEVEL_HIGH, ++ .gpio20 = GPIO_LEVEL_HIGH, ++ .gpio28 = GPIO_LEVEL_HIGH, ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_blink = { ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_invert = { ++ .gpio13 = GPIO_INVERT, ++}; ++ ++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_GPIO, ++ .gpio55 = GPIO_MODE_NATIVE, ++ .gpio56 = GPIO_MODE_GPIO, ++ .gpio57 = GPIO_MODE_GPIO, ++ .gpio58 = GPIO_MODE_NATIVE, ++ .gpio59 = GPIO_MODE_NATIVE, ++ .gpio60 = GPIO_MODE_GPIO, ++ .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_INPUT, ++ .gpio33 = GPIO_DIR_INPUT, ++ .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_OUTPUT, ++ .gpio54 = GPIO_DIR_INPUT, ++ .gpio56 = GPIO_DIR_OUTPUT, ++ .gpio57 = GPIO_DIR_INPUT, ++ .gpio60 = GPIO_DIR_OUTPUT, ++}; ++ ++static const struct pch_gpio_set2 pch_gpio_set2_level = { ++ .gpio35 = GPIO_LEVEL_LOW, ++ .gpio49 = GPIO_LEVEL_HIGH, ++ .gpio56 = GPIO_LEVEL_HIGH, ++ .gpio60 = GPIO_LEVEL_LOW, ++}; ++ ++static const struct pch_gpio_set3 pch_gpio_set3_mode = { ++ .gpio72 = GPIO_MODE_GPIO, ++}; ++ ++static const struct pch_gpio_set3 pch_gpio_set3_direction = { ++ .gpio72 = GPIO_DIR_INPUT, ++}; ++ ++static const struct pch_gpio_set3 pch_gpio_set3_level = { ++}; ++ ++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, ++ }, ++ .set2 = { ++ .mode = &pch_gpio_set2_mode, ++ .direction = &pch_gpio_set2_direction, ++ .level = &pch_gpio_set2_level, ++ }, ++ .set3 = { ++ .mode = &pch_gpio_set3_mode, ++ .direction = &pch_gpio_set3_direction, ++ .level = &pch_gpio_set3_level, ++ }, ++}; +diff --git a/src/mainboard/dell/optiplex_780/variants/780_usff/hda_verb.c b/src/mainboard/dell/optiplex_780/variants/780_usff/hda_verb.c +new file mode 100644 +index 0000000000..c94e06b156 +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/variants/780_usff/hda_verb.c +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++ ++#include <device/azalia_device.h> ++ ++const u32 cim_verb_data[] = { ++ /* coreboot specific header */ ++ 0x11d4194a, /* Analog Devices AD1984A */ ++ 0x10280420, /* Subsystem ID */ ++ 10, /* Number of entries */ ++ ++ /* Pin Widget Verb Table */ ++ AZALIA_PIN_CFG(0, 0x11, 0x02214040), ++ AZALIA_PIN_CFG(0, 0x12, 0x01014010), ++ AZALIA_PIN_CFG(0, 0x13, 0x991301f0), ++ AZALIA_PIN_CFG(0, 0x14, 0x02a19020), ++ AZALIA_PIN_CFG(0, 0x15, 0x01813030), ++ AZALIA_PIN_CFG(0, 0x16, 0x413301f0), ++ AZALIA_PIN_CFG(0, 0x17, 0x41a601f0), ++ AZALIA_PIN_CFG(0, 0x1a, 0x41f301f0), ++ AZALIA_PIN_CFG(0, 0x1b, 0x414501f0), ++ AZALIA_PIN_CFG(0, 0x1c, 0x413301f0), ++}; ++ ++const u32 pc_beep_verbs[0] = {}; ++ ++AZALIA_ARRAY_SIZES; +diff --git a/src/mainboard/dell/optiplex_780/variants/780_usff/overridetree.cb b/src/mainboard/dell/optiplex_780/variants/780_usff/overridetree.cb +new file mode 100644 +index 0000000000..555b1c1f5c +--- /dev/null ++++ b/src/mainboard/dell/optiplex_780/variants/780_usff/overridetree.cb +@@ -0,0 +1,10 @@ ++## SPDX-License-Identifier: GPL-2.0-or-later ++ ++chip northbridge/intel/x4x ++ device domain 0 on ++ chip southbridge/intel/i82801jx ++ device pci 1c.0 on end # PCIe 1 ++ device pci 1c.1 on end # PCIe 2 ++ end ++ end ++end +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0031-dell-3050micro-disable-nvme-hotplug.patch b/config/coreboot/default/patches/0031-dell-3050micro-disable-nvme-hotplug.patch new file mode 100644 index 00000000..c154a9a1 --- /dev/null +++ b/config/coreboot/default/patches/0031-dell-3050micro-disable-nvme-hotplug.patch @@ -0,0 +1,49 @@ +From 4ffaddc37d30d39f25faeaef73046a6e2ce525e8 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <info@minifree.org> +Date: Wed, 11 Dec 2024 01:06:01 +0000 +Subject: [PATCH 31/37] dell/3050micro: disable nvme hotplug + +in my testing, when running my 3050micro for a few days, +the nvme would sometimes randomly rename. + +e.g. nvme0n1 renamed to nvme0n2 + +this might cause crashes in linux, if booting only from the +nvme. in my case, i was booting from mdraid (sata+nvme) and +every few days, the nvme would rename at least once, causing +my RAID to become unsynced. since i'm using RAID1, this was +OK and I could simply re-sync the array, but this is quite +precarious indeed. if you're using raid0, that will potentially +corrupt your RAID array indefinitely. + +this same issue manifested on the T480/T480 thinkpads, and +S3 resume would break because of that, when booting from nvme, +because the nvme would be "unplugged" and appear to linux as a +new device (the one that you booted from). + +the fix there was to disable hotplugging on that pci-e slot +for the nvme, so apply the same fix here for 3050 micro + +Signed-off-by: Leah Rowe <leah@libreboot.org> +--- + src/mainboard/dell/optiplex_3050/devicetree.cb | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/mainboard/dell/optiplex_3050/devicetree.cb b/src/mainboard/dell/optiplex_3050/devicetree.cb +index da11085ab6..2a97306c5d 100644 +--- a/src/mainboard/dell/optiplex_3050/devicetree.cb ++++ b/src/mainboard/dell/optiplex_3050/devicetree.cb +@@ -45,7 +45,9 @@ chip soc/intel/skylake + register "PcieRpAdvancedErrorReporting[20]" = "1" + register "PcieRpLtrEnable[20]" = "true" + register "PcieRpClkSrcNumber[20]" = "3" +- register "PcieRpHotPlug[20]" = "1" ++# disable hotplug on nvme to prevent renaming e.g. nvme0n1 rename to nvme0n2, ++# which could cause crashes in linux if booting from nvme ++ register "PcieRpHotPlug[20]" = "0" + end + + # Realtek LAN +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0031-haswell-NRI-Post-process-selected-timings.patch b/config/coreboot/default/patches/0031-haswell-NRI-Post-process-selected-timings.patch deleted file mode 100644 index 426cef35..00000000 --- a/config/coreboot/default/patches/0031-haswell-NRI-Post-process-selected-timings.patch +++ /dev/null @@ -1,249 +0,0 @@ -From 1dc22174b9b28b9ea9af59183ffd5d86d19a2721 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sat, 7 May 2022 16:29:55 +0200 -Subject: [PATCH 31/51] haswell NRI: Post-process selected timings - -Once the MPLL has been initialised, convert the timings from the SPD to -be in DCLKs, which is what the hardware expects. In addition, calculate -the values for tREFI and tXP. - -Change-Id: Id02caf858f75b9e08016762b3aefda282b274386 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/lookup_timings.c | 62 +++++++++++ - .../haswell/native_raminit/raminit_main.c | 1 + - .../haswell/native_raminit/raminit_native.h | 8 ++ - .../haswell/native_raminit/spd_bitmunching.c | 100 ++++++++++++++++++ - 5 files changed, 172 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/lookup_timings.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index c125d84f0b..2769e0bbb4 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -1,5 +1,6 @@ - ## SPDX-License-Identifier: GPL-2.0-or-later - -+romstage-y += lookup_timings.c - romstage-y += init_mpll.c - romstage-y += io_comp_control.c - romstage-y += raminit_main.c -diff --git a/src/northbridge/intel/haswell/native_raminit/lookup_timings.c b/src/northbridge/intel/haswell/native_raminit/lookup_timings.c -new file mode 100644 -index 0000000000..8b81c7c341 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/lookup_timings.c -@@ -0,0 +1,62 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <commonlib/bsd/clamp.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+struct timing_lookup { -+ uint32_t clock; -+ uint32_t value; -+}; -+ -+static uint32_t lookup_timing( -+ const uint32_t mem_clock_mhz, -+ const struct timing_lookup *const lookup, -+ const size_t length) -+{ -+ /* Fall back to the last index */ -+ size_t i; -+ for (i = 0; i < length - 1; i++) { -+ /* Account for imprecise frequency values */ -+ if ((mem_clock_mhz - 5) <= lookup[i].clock) -+ break; -+ } -+ return lookup[i].value; -+} -+ -+static const uint32_t fmax = UINT32_MAX; -+ -+uint8_t get_tCWL(const uint32_t mem_clock_mhz) -+{ -+ const struct timing_lookup lut[] = { -+ { 400, 5 }, -+ { 533, 6 }, -+ { 666, 7 }, -+ { 800, 8 }, -+ { 933, 9 }, -+ { 1066, 10 }, -+ { 1200, 11 }, -+ { fmax, 12 }, -+ }; -+ return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); -+} -+ -+/* tREFI = 7800 ns * DDR MHz */ -+uint32_t get_tREFI(const uint32_t mem_clock_mhz) -+{ -+ return (mem_clock_mhz * 7800) / 1000; -+} -+ -+uint32_t get_tXP(const uint32_t mem_clock_mhz) -+{ -+ const struct timing_lookup lut[] = { -+ { 400, 3 }, -+ { 666, 4 }, -+ { 800, 5 }, -+ { 933, 6 }, -+ { 1066, 7 }, -+ { fmax, 8 }, -+ }; -+ return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index bf745e943f..2fea658415 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -21,6 +21,7 @@ struct task_entry { - static const struct task_entry cold_boot[] = { - { collect_spd_info, true, "PROCSPD", }, - { initialise_mpll, true, "INITMPLL", }, -+ { convert_timings, true, "CONVTIM", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 15a1550424..e0ebd3a2a7 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -79,6 +79,9 @@ struct sysinfo { - uint32_t tCWL; - uint32_t tCMD; - -+ uint32_t tREFI; -+ uint32_t tXP; -+ - uint8_t lanes; /* 8 or 9 */ - uint8_t chanmap; - uint8_t dpc[NUM_CHANNELS]; /* DIMMs per channel */ -@@ -97,7 +100,12 @@ void raminit_main(enum raminit_boot_mode bootmode); - - enum raminit_status collect_spd_info(struct sysinfo *ctrl); - enum raminit_status initialise_mpll(struct sysinfo *ctrl); -+enum raminit_status convert_timings(struct sysinfo *ctrl); - - enum raminit_status wait_for_first_rcomp(void); - -+uint8_t get_tCWL(uint32_t mem_clock_mhz); -+uint32_t get_tREFI(uint32_t mem_clock_mhz); -+uint32_t get_tXP(uint32_t mem_clock_mhz); -+ - #endif -diff --git a/src/northbridge/intel/haswell/native_raminit/spd_bitmunching.c b/src/northbridge/intel/haswell/native_raminit/spd_bitmunching.c -index eff993800b..4f7fe46494 100644 ---- a/src/northbridge/intel/haswell/native_raminit/spd_bitmunching.c -+++ b/src/northbridge/intel/haswell/native_raminit/spd_bitmunching.c -@@ -204,3 +204,103 @@ enum raminit_status collect_spd_info(struct sysinfo *ctrl) - get_spd_data(ctrl); - return find_common_spd_parameters(ctrl); - } -+ -+#define MIN_CWL 5 -+#define MAX_CWL 12 -+ -+/* Except for tCK, hardware expects all timing values in DCLKs, not nanoseconds */ -+enum raminit_status convert_timings(struct sysinfo *ctrl) -+{ -+ /* -+ * Obtain all required timing values, in DCLKs. -+ */ -+ -+ /* Convert primary timings from nanoseconds to DCLKs */ -+ ctrl->tAA = DIV_ROUND_UP(ctrl->tAA, ctrl->tCK); -+ ctrl->tWR = DIV_ROUND_UP(ctrl->tWR, ctrl->tCK); -+ ctrl->tRCD = DIV_ROUND_UP(ctrl->tRCD, ctrl->tCK); -+ ctrl->tRRD = DIV_ROUND_UP(ctrl->tRRD, ctrl->tCK); -+ ctrl->tRP = DIV_ROUND_UP(ctrl->tRP, ctrl->tCK); -+ ctrl->tRAS = DIV_ROUND_UP(ctrl->tRAS, ctrl->tCK); -+ ctrl->tRC = DIV_ROUND_UP(ctrl->tRC, ctrl->tCK); -+ ctrl->tRFC = DIV_ROUND_UP(ctrl->tRFC, ctrl->tCK); -+ ctrl->tWTR = DIV_ROUND_UP(ctrl->tWTR, ctrl->tCK); -+ ctrl->tRTP = DIV_ROUND_UP(ctrl->tRTP, ctrl->tCK); -+ ctrl->tFAW = DIV_ROUND_UP(ctrl->tFAW, ctrl->tCK); -+ ctrl->tCWL = DIV_ROUND_UP(ctrl->tCWL, ctrl->tCK); -+ ctrl->tCMD = DIV_ROUND_UP(ctrl->tCMD, ctrl->tCK); -+ -+ /* Constrain primary timings to hardware limits */ -+ /** TODO: complain when clamping? **/ -+ ctrl->tAA = clamp_u32(4, ctrl->tAA, 24); -+ ctrl->tWR = clamp_u32(5, ctrl->tWR, 16); -+ ctrl->tRCD = clamp_u32(4, ctrl->tRCD, 20); -+ ctrl->tRRD = clamp_u32(4, ctrl->tRRD, 65535); -+ ctrl->tRP = clamp_u32(4, ctrl->tRP, 15); -+ ctrl->tRAS = clamp_u32(10, ctrl->tRAS, 40); -+ ctrl->tRC = clamp_u32(1, ctrl->tRC, 4095); -+ ctrl->tRFC = clamp_u32(1, ctrl->tRFC, 511); -+ ctrl->tWTR = clamp_u32(4, ctrl->tWTR, 10); -+ ctrl->tRTP = clamp_u32(4, ctrl->tRTP, 15); -+ ctrl->tFAW = clamp_u32(10, ctrl->tFAW, 54); -+ -+ /** TODO: Honor tREFI from XMP **/ -+ ctrl->tREFI = get_tREFI(ctrl->mem_clock_mhz); -+ ctrl->tXP = get_tXP(ctrl->mem_clock_mhz); -+ -+ /* -+ * Check some values, and adjust them if necessary. -+ */ -+ -+ /* If tWR cannot be written into DDR3 MR0, adjust it */ -+ switch (ctrl->tWR) { -+ case 9: -+ case 11: -+ case 13: -+ case 15: -+ ctrl->tWR++; -+ } -+ -+ /* If tCWL is not supported or unspecified, look up a reasonable default */ -+ if (ctrl->tCWL < MIN_CWL || ctrl->tCWL > MAX_CWL) -+ ctrl->tCWL = get_tCWL(ctrl->mem_clock_mhz); -+ -+ /* This is needed to support ODT properly on 2DPC */ -+ if (ctrl->tAA - ctrl->tCWL > 4) -+ ctrl->tCWL = ctrl->tAA - 4; -+ -+ /* If tCMD is invalid, use a guesstimate default */ -+ if (!ctrl->tCMD) { -+ ctrl->tCMD = MAX(ctrl->dpc[0], ctrl->dpc[1]); -+ printk(RAM_DEBUG, "tCMD was zero, picking a guesstimate value\n"); -+ } -+ ctrl->tCMD = clamp_u32(1, ctrl->tCMD, 3); -+ -+ /* -+ * Print final timings. -+ */ -+ -+ /* tCK is special */ -+ printk(BIOS_DEBUG, "Selected tCK : %u ps\n", ctrl->tCK * 1000 / 256); -+ -+ /* Primary timings */ -+ printk(BIOS_DEBUG, "Selected tAA : %uT\n", ctrl->tAA); -+ printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR); -+ printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD); -+ printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD); -+ printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP); -+ printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS); -+ printk(BIOS_DEBUG, "Selected tRC : %uT\n", ctrl->tRC); -+ printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC); -+ printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR); -+ printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP); -+ printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW); -+ printk(BIOS_DEBUG, "Selected tCWL : %uT\n", ctrl->tCWL); -+ printk(BIOS_DEBUG, "Selected tCMD : %uT\n", ctrl->tCMD); -+ -+ /* Derived timings */ -+ printk(BIOS_DEBUG, "Selected tREFI : %uT\n", ctrl->tREFI); -+ printk(BIOS_DEBUG, "Selected tXP : %uT\n", ctrl->tXP); -+ -+ return RAMINIT_STATUS_SUCCESS; -+} --- -2.39.5 - diff --git a/config/coreboot/default/patches/0032-haswell-NRI-Configure-initial-MC-settings.patch b/config/coreboot/default/patches/0032-haswell-NRI-Configure-initial-MC-settings.patch deleted file mode 100644 index e16f4e3d..00000000 --- a/config/coreboot/default/patches/0032-haswell-NRI-Configure-initial-MC-settings.patch +++ /dev/null @@ -1,1594 +0,0 @@ -From a4f5deb78c2d4132bf857c57ffd53684f942ba62 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sat, 7 May 2022 17:22:07 +0200 -Subject: [PATCH 32/51] haswell NRI: Configure initial MC settings - -Program initial memory controller settings. Many of these values will be -adjusted later during training. - -Change-Id: If33846b51cb1bab5d0458fe626e13afb1bdc900e -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 2 + - .../haswell/native_raminit/configure_mc.c | 822 ++++++++++++++++++ - .../haswell/native_raminit/raminit_main.c | 2 + - .../haswell/native_raminit/raminit_native.h | 101 +++ - .../haswell/native_raminit/reg_structs.h | 405 +++++++++ - .../haswell/native_raminit/timings_refresh.c | 13 + - .../intel/haswell/registers/mchbar.h | 94 ++ - 7 files changed, 1439 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/configure_mc.c - create mode 100644 src/northbridge/intel/haswell/native_raminit/reg_structs.h - create mode 100644 src/northbridge/intel/haswell/native_raminit/timings_refresh.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index 2769e0bbb4..fc55277a65 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -1,8 +1,10 @@ - ## SPDX-License-Identifier: GPL-2.0-or-later - -+romstage-y += configure_mc.c - romstage-y += lookup_timings.c - romstage-y += init_mpll.c - romstage-y += io_comp_control.c - romstage-y += raminit_main.c - romstage-y += raminit_native.c - romstage-y += spd_bitmunching.c -+romstage-y += timings_refresh.c -diff --git a/src/northbridge/intel/haswell/native_raminit/configure_mc.c b/src/northbridge/intel/haswell/native_raminit/configure_mc.c -new file mode 100644 -index 0000000000..88249725a7 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/configure_mc.c -@@ -0,0 +1,822 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <assert.h> -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <delay.h> -+#include <lib.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <string.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+static void program_misc_control(struct sysinfo *ctrl) -+{ -+ if (!is_hsw_ult()) -+ return; -+ -+ const union ddr_scram_misc_control_reg ddr_scram_misc_ctrl = { -+ .ddr_no_ch_interleave = !ctrl->dq_pins_interleaved, -+ .lpddr_mode = ctrl->lpddr, -+ .cke_mapping_ch0 = ctrl->lpddr ? ctrl->lpddr_cke_rank_map[0] : 0, -+ .cke_mapping_ch1 = ctrl->lpddr ? ctrl->lpddr_cke_rank_map[1] : 0, -+ }; -+ mchbar_write32(DDR_SCRAM_MISC_CONTROL, ddr_scram_misc_ctrl.raw); -+} -+ -+static void program_mrc_revision(void) -+{ -+ mchbar_write32(MRC_REVISION, 0x01090000); /* MRC 1.9.0 Build 0 */ -+} -+ -+static void program_ranks_used(struct sysinfo *ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ mchbar_write8(MC_INIT_STATE_ch(channel), ctrl->rankmap[channel]); -+ if (!does_ch_exist(ctrl, channel)) { -+ mchbar_write32(DDR_CLK_ch_RANKS_USED(channel), 0); -+ mchbar_write32(DDR_CTL_ch_CTL_RANKS_USED(channel), 0); -+ mchbar_write32(DDR_CKE_ch_CTL_RANKS_USED(channel), 0); -+ continue; -+ } -+ uint32_t clk_ranks_used = ctrl->rankmap[channel]; -+ if (ctrl->lpddr) { -+ /* With LPDDR, the clock usage goes by group instead */ -+ clk_ranks_used = 0; -+ for (uint8_t group = 0; group < NUM_GROUPS; group++) { -+ if (ctrl->dq_byte_map[channel][CT_ITERATION_CLOCK][group]) -+ clk_ranks_used |= BIT(group); -+ } -+ } -+ mchbar_write32(DDR_CLK_ch_RANKS_USED(channel), clk_ranks_used); -+ -+ uint32_t ctl_ranks_used = ctrl->rankmap[channel]; -+ if (is_hsw_ult()) { -+ /* Set ODT disable bits */ -+ /** TODO: May need to do this after JEDEC reset/init **/ -+ if (ctrl->lpddr && ctrl->lpddr_dram_odt) -+ ctl_ranks_used |= 2 << 4; /* ODT is used on rank 0 */ -+ else -+ ctl_ranks_used |= 3 << 4; -+ } -+ mchbar_write32(DDR_CTL_ch_CTL_RANKS_USED(channel), ctl_ranks_used); -+ -+ uint32_t cke_ranks_used = ctrl->rankmap[channel]; -+ if (ctrl->lpddr) { -+ /* Use CKE-to-rank mapping for LPDDR */ -+ const uint8_t cke_rank_map = ctrl->lpddr_cke_rank_map[channel]; -+ cke_ranks_used = 0; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ /* ULT only has 2 ranks per channel */ -+ if (rank >= 2) -+ break; -+ -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t cke = 0; cke < 4; cke++) { -+ if (rank == ((cke_rank_map >> cke) & 1)) -+ cke_ranks_used |= BIT(cke); -+ } -+ } -+ } -+ mchbar_write32(DDR_CKE_ch_CTL_RANKS_USED(channel), cke_ranks_used); -+ } -+} -+ -+static const uint8_t rxb_trad[2][5][4] = { -+ { /* Vdd low */ -+ /* 1067 MT/s, 1333 MT/s, 1600 MT/s, 1867 MT/s, 2133 MT/s, */ -+ {4, 3, 3, 2}, {4, 4, 3, 2}, {5, 4, 3, 3}, {5, 4, 4, 3}, {5, 4, 4, 3}, -+ }, -+ { /* Vdd hi */ -+ /* 1067 MT/s, 1333 MT/s, 1600 MT/s, 1867 MT/s, 2133 MT/s, */ -+ {4, 3, 3, 2}, {4, 4, 3, 2}, {5, 4, 3, 3}, {5, 4, 4, 3}, {4, 4, 3, 3}, -+ }, -+}; -+ -+static const uint8_t rxb_ultx[2][3][4] = { -+ { /* Vdd low */ -+ /* 1067 MT/s, 1333 MT/s, 1600 MT/s, */ -+ {5, 6, 6, 5}, {5, 6, 6, 5}, {4, 6, 6, 6}, -+ }, -+ { /* Vdd hi */ -+ /* 1067 MT/s, 1333 MT/s, 1600 MT/s, */ -+ {7, 6, 6, 5}, {7, 6, 6, 5}, {7, 6, 6, 6}, -+ }, -+}; -+ -+uint8_t get_rx_bias(const struct sysinfo *ctrl) -+{ -+ const bool is_ult = is_hsw_ult(); -+ const bool vddhi = ctrl->vdd_mv > 1350; -+ const uint8_t max_rxf = is_ult ? ARRAY_SIZE(rxb_ultx[0]) : ARRAY_SIZE(rxb_trad[0]); -+ const uint8_t ref_clk = ctrl->base_freq == 133 ? 4 : 6; -+ const uint8_t rx_f = clamp_s8(0, ctrl->multiplier - ref_clk, max_rxf - 1); -+ const uint8_t rx_cb = mchbar_read32(DDR_CLK_CB_STATUS) & 0x3; -+ if (is_ult) -+ return rxb_ultx[vddhi][rx_f][rx_cb]; -+ else -+ return rxb_trad[vddhi][rx_f][rx_cb]; -+} -+ -+static void program_ddr_data(struct sysinfo *ctrl, const bool dis_odt_static, const bool vddhi) -+{ -+ const bool is_ult = is_hsw_ult(); -+ -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!does_rank_exist(ctrl, rank)) -+ continue; -+ -+ const union ddr_data_rx_train_rank_reg rx_train = { -+ .rcven = 64, -+ .dqs_p = 32, -+ .dqs_n = 32, -+ }; -+ mchbar_write32(DDR_DATA_RX_TRAIN_RANK(rank), rx_train.raw); -+ mchbar_write32(DDR_DATA_RX_PER_BIT_RANK(rank), 0x88888888); -+ -+ const union ddr_data_tx_train_rank_reg tx_train = { -+ .tx_eq = TXEQFULLDRV | 11, -+ .dq_delay = 96, -+ .dqs_delay = 64, -+ }; -+ mchbar_write32(DDR_DATA_TX_TRAIN_RANK(rank), tx_train.raw); -+ mchbar_write32(DDR_DATA_TX_PER_BIT_RANK(rank), 0x88888888); -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ ctrl->tx_dq[channel][rank][byte] = tx_train.dq_delay; -+ ctrl->txdqs[channel][rank][byte] = tx_train.dqs_delay; -+ ctrl->tx_eq[channel][rank][byte] = tx_train.tx_eq; -+ -+ ctrl->rcven[channel][rank][byte] = rx_train.rcven; -+ ctrl->rxdqsp[channel][rank][byte] = rx_train.dqs_p; -+ ctrl->rxdqsn[channel][rank][byte] = rx_train.dqs_n; -+ ctrl->rx_eq[channel][rank][byte] = rx_train.rx_eq; -+ } -+ } -+ } -+ mchbar_write32(DDR_DATA_TX_XTALK, 0); -+ mchbar_write32(DDR_DATA_RX_OFFSET_VDQ, 0x88888888); -+ mchbar_write32(DDR_DATA_OFFSET_TRAIN, 0); -+ mchbar_write32(DDR_DATA_OFFSET_COMP, 0); -+ -+ const union ddr_data_control_0_reg data_control_0 = { -+ .internal_clocks_on = !is_ult, -+ .data_vccddq_hi = vddhi, -+ .disable_odt_static = dis_odt_static, -+ .lpddr_mode = ctrl->lpddr, -+ .odt_samp_extend_en = ctrl->lpddr, -+ .early_rleak_en = ctrl->lpddr && ctrl->stepping >= STEPPING_C0, -+ }; -+ mchbar_write32(DDR_DATA_CONTROL_0, data_control_0.raw); -+ -+ const union ddr_data_control_1_reg data_control_1 = { -+ .dll_mask = 1, -+ .rx_bias_ctl = get_rx_bias(ctrl), -+ .odt_delay = -2, -+ .odt_duration = 7, -+ .sense_amp_delay = -2, -+ .sense_amp_duration = 7, -+ }; -+ mchbar_write32(DDR_DATA_CONTROL_1, data_control_1.raw); -+ -+ clear_data_offset_train_all(ctrl); -+ -+ /* Stagger byte turn-on to reduce dI/dT */ -+ const uint8_t byte_stagger[] = { 0, 4, 1, 5, 2, 6, 3, 7, 8 }; -+ const uint8_t latency = 2 * ctrl->tAA - 6; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ union ddr_data_control_2_reg data_control_2 = { -+ .raw = 0, -+ }; -+ if (is_ult) { -+ data_control_2.rx_dqs_amp_offset = 8; -+ data_control_2.rx_clk_stg_num = 0x1f; -+ data_control_2.leaker_comp = ctrl->lpddr ? 3 : 0; -+ } -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const uint8_t stg = latency * byte_stagger[byte] / ctrl->lanes; -+ data_control_2.rx_stagger_ctl = stg & 0x1f; -+ mchbar_write32(DQ_CONTROL_2(channel, byte), data_control_2.raw); -+ ctrl->data_offset_comp[channel][byte] = 0; -+ ctrl->dq_control_1[channel][byte] = data_control_1.raw; -+ ctrl->dq_control_2[channel][byte] = data_control_2.raw; -+ } -+ ctrl->dq_control_0[channel] = data_control_0.raw; -+ } -+} -+ -+static void program_vsshi_control(struct sysinfo *ctrl, const uint16_t vsshi_mv) -+{ -+ const uint32_t vsshi_control_reg = is_hsw_ult() ? 0x366c : 0x306c; -+ const union ddr_comp_vsshi_control_reg ddr_vsshi_control = { -+ .vsshi_target = (vsshi_mv * 192) / ctrl->vdd_mv - 20, -+ .hi_bw_divider = 1, -+ .lo_bw_divider = 1, -+ .bw_error = 2, -+ .panic_driver_en = 1, -+ .panic_voltage = 24 / 8, /* Voltage in 8mV steps */ -+ .gain_boost = 1, -+ }; -+ mchbar_write32(vsshi_control_reg, ddr_vsshi_control.raw); -+ mchbar_write32(DDR_COMP_VSSHI_CONTROL, ddr_vsshi_control.raw); -+} -+ -+static void calc_vt_slope_code(const uint16_t slope, uint8_t *best_a, uint8_t *best_b) -+{ -+ const int16_t coding[] = {0, -125, -62, -31, 250, 125, 62, 31}; -+ *best_a = 0; -+ *best_b = 0; -+ int16_t best_err = slope; -+ for (uint8_t b = 0; b < ARRAY_SIZE(coding); b++) { -+ for (uint8_t a = b; a < ARRAY_SIZE(coding); a++) { -+ int16_t error = slope - (coding[a] + coding[b]); -+ if (error < 0) -+ error = -error; -+ -+ if (error < best_err) { -+ best_err = error; -+ *best_a = a; -+ *best_b = b; -+ } -+ } -+ } -+} -+ -+static void program_dimm_vref(struct sysinfo *ctrl, const uint16_t vccio_mv, const bool vddhi) -+{ -+ const bool is_ult = is_hsw_ult(); -+ -+ /* Static values for ULT */ -+ uint8_t vt_slope_a = 4; -+ uint8_t vt_slope_b = 0; -+ if (!is_ult) { -+ /* On non-ULT, compute best slope code */ -+ const uint16_t vt_slope = 1500 * vccio_mv / ctrl->vdd_mv - 1000; -+ calc_vt_slope_code(vt_slope, &vt_slope_a, &vt_slope_b); -+ } -+ const union ddr_data_vref_control_reg ddr_vref_control = { -+ .hi_bw_divider = is_ult ? 0 : 3, -+ .lo_bw_divider = 3, -+ .sample_divider = is_ult ? 1 : 3, -+ .slow_bw_error = 1, -+ .hi_bw_enable = 1, -+ .vt_slope_b = vt_slope_b, -+ .vt_slope_a = vt_slope_a, -+ .vt_offset = 0, -+ }; -+ mchbar_write32(is_ult ? 0xf68 : 0xf6c, ddr_vref_control.raw); /* Use CH1 byte 7 */ -+ -+ const union ddr_data_vref_adjust_reg ddr_vref_adjust = { -+ .en_dimm_vref_ca = 1, -+ .en_dimm_vref_ch0 = 1, -+ .en_dimm_vref_ch1 = 1, -+ .vccddq_hi_qnnn_h = vddhi, -+ .hi_z_timer_ctrl = 3, -+ }; -+ ctrl->dimm_vref = ddr_vref_adjust; -+ mchbar_write32(DDR_DATA_VREF_ADJUST, ddr_vref_adjust.raw); -+} -+ -+static uint32_t pi_code(const uint32_t code) -+{ -+ return code << 21 | code << 14 | code << 7 | code << 0; -+} -+ -+static void program_ddr_ca(struct sysinfo *ctrl, const bool vddhi) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ const union ddr_clk_controls_reg ddr_clk_controls = { -+ .dll_mask = 1, -+ .vccddq_hi = vddhi, -+ .lpddr_mode = ctrl->lpddr, -+ }; -+ mchbar_write32(DDR_CLK_ch_CONTROLS(channel), ddr_clk_controls.raw); -+ -+ const union ddr_cmd_controls_reg ddr_cmd_controls = { -+ .dll_mask = 1, -+ .vccddq_hi = vddhi, -+ .lpddr_mode = ctrl->lpddr, -+ .early_weak_drive = 3, -+ .cmd_tx_eq = 1, -+ }; -+ mchbar_write32(DDR_CMD_ch_CONTROLS(channel), ddr_cmd_controls.raw); -+ -+ const union ddr_cke_ctl_controls_reg ddr_cke_controls = { -+ .dll_mask = 1, -+ .vccddq_hi = vddhi, -+ .lpddr_mode = ctrl->lpddr, -+ .early_weak_drive = 3, -+ .cmd_tx_eq = 1, -+ .ctl_tx_eq = 1, -+ .ctl_sr_drv = 2, -+ }; -+ mchbar_write32(DDR_CKE_ch_CTL_CONTROLS(channel), ddr_cke_controls.raw); -+ -+ const union ddr_cke_ctl_controls_reg ddr_ctl_controls = { -+ .dll_mask = 1, -+ .vccddq_hi = vddhi, -+ .lpddr_mode = ctrl->lpddr, -+ .ctl_tx_eq = 1, -+ .ctl_sr_drv = 2, -+ .la_drv_en_ovrd = 1, /* Must be set on ULT */ -+ }; -+ mchbar_write32(DDR_CTL_ch_CTL_CONTROLS(channel), ddr_ctl_controls.raw); -+ -+ const uint8_t cmd_pi = ctrl->lpddr ? 96 : 64; -+ mchbar_write32(DDR_CMD_ch_PI_CODING(channel), pi_code(cmd_pi)); -+ mchbar_write32(DDR_CKE_ch_CMD_PI_CODING(channel), pi_code(cmd_pi)); -+ mchbar_write32(DDR_CKE_CTL_ch_CTL_PI_CODING(channel), pi_code(64)); -+ mchbar_write32(DDR_CLK_ch_PI_CODING(channel), pi_code(64)); -+ -+ mchbar_write32(DDR_CMD_ch_COMP_OFFSET(channel), 0); -+ mchbar_write32(DDR_CLK_ch_COMP_OFFSET(channel), 0); -+ mchbar_write32(DDR_CKE_CTL_ch_CTL_COMP_OFFSET(channel), 0); -+ -+ for (uint8_t group = 0; group < NUM_GROUPS; group++) { -+ ctrl->cke_cmd_pi_code[channel][group] = cmd_pi; -+ ctrl->cmd_north_pi_code[channel][group] = cmd_pi; -+ ctrl->cmd_south_pi_code[channel][group] = cmd_pi; -+ } -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ ctrl->clk_pi_code[channel][rank] = 64; -+ ctrl->ctl_pi_code[channel][rank] = 64; -+ } -+ } -+} -+ -+enum { -+ RCOMP_RD_ODT = 0, -+ RCOMP_WR_DS_DQ, -+ RCOMP_WR_DS_CMD, -+ RCOMP_WR_DS_CTL, -+ RCOMP_WR_DS_CLK, -+ RCOMP_MAX_CODES, -+}; -+ -+struct rcomp_info { -+ uint8_t resistor; -+ uint8_t sz_steps; -+ uint8_t target_r; -+ int8_t result; -+}; -+ -+static void program_rcomp_vref(struct sysinfo *ctrl, const bool dis_odt_static) -+{ -+ const bool is_ult = is_hsw_ult(); -+ /* -+ * +-------------------------------+ -+ * | Rcomp resistor values in ohms | -+ * +-----------+------+------+-----+ -+ * | Ball name | Trad | ULTX | Use | -+ * +-----------+------+------+-----+ -+ * | SM_RCOMP0 | 100 | 200 | CMD | -+ * | SM_RCOMP1 | 75 | 120 | DQ | -+ * | SM_RCOMP2 | 100 | 100 | ODT | -+ * +-----------+------+------+-----+ -+ */ -+ struct rcomp_info rcomp_cfg[RCOMP_MAX_CODES] = { -+ [RCOMP_RD_ODT] = { -+ .resistor = 50, -+ .sz_steps = 96, -+ .target_r = 50, -+ }, -+ [RCOMP_WR_DS_DQ] = { -+ .resistor = 25, -+ .sz_steps = 64, -+ .target_r = 33, -+ }, -+ [RCOMP_WR_DS_CMD] = { -+ .resistor = 20, -+ .sz_steps = 64, -+ .target_r = 20, -+ }, -+ [RCOMP_WR_DS_CTL] = { -+ .resistor = 20, -+ .sz_steps = 64, -+ .target_r = 20, -+ }, -+ [RCOMP_WR_DS_CLK] = { -+ .resistor = 25, -+ .sz_steps = 64, -+ .target_r = 29, -+ }, -+ }; -+ if (is_ult) { -+ rcomp_cfg[RCOMP_WR_DS_DQ].resistor = 40; -+ rcomp_cfg[RCOMP_WR_DS_DQ].target_r = 40; -+ rcomp_cfg[RCOMP_WR_DS_CLK].resistor = 40; -+ } else if (ctrl->dpc[0] == 2 || ctrl->dpc[1] == 2) { -+ rcomp_cfg[RCOMP_RD_ODT].target_r = 60; -+ } -+ for (uint8_t i = 0; i < RCOMP_MAX_CODES; i++) { -+ struct rcomp_info *const r = &rcomp_cfg[i]; -+ const int32_t div = 2 * (r->resistor + r->target_r); -+ assert(div); -+ const int32_t vref = (r->sz_steps * (r->resistor - r->target_r)) / div; -+ -+ /* DqOdt is 5 bits wide, the other Rcomp targets are 4 bits wide */ -+ const int8_t comp_limit = i == RCOMP_RD_ODT ? 16 : 8; -+ r->result = clamp_s32(-comp_limit, vref, comp_limit - 1); -+ } -+ const union ddr_comp_ctl_0_reg ddr_comp_ctl_0 = { -+ .disable_odt_static = dis_odt_static, -+ .dq_drv_vref = rcomp_cfg[RCOMP_WR_DS_DQ].result, -+ .dq_odt_vref = rcomp_cfg[RCOMP_RD_ODT].result, -+ .cmd_drv_vref = rcomp_cfg[RCOMP_WR_DS_CMD].result, -+ .ctl_drv_vref = rcomp_cfg[RCOMP_WR_DS_CTL].result, -+ .clk_drv_vref = rcomp_cfg[RCOMP_WR_DS_CLK].result, -+ }; -+ ctrl->comp_ctl_0 = ddr_comp_ctl_0; -+ mchbar_write32(DDR_COMP_CTL_0, ctrl->comp_ctl_0.raw); -+} -+ -+enum { -+ SCOMP_DQ = 0, -+ SCOMP_CMD, -+ SCOMP_CTL, -+ SCOMP_CLK, -+ SCOMP_MAX_CODES, -+}; -+ -+static void program_slew_rates(struct sysinfo *ctrl, const bool vddhi) -+{ -+ const uint8_t min_cycle_delay[SCOMP_MAX_CODES] = { 46, 70, 70, 46 }; -+ uint8_t buffer_stage_delay_ps[SCOMP_MAX_CODES] = { 59, 53, 53, 53 }; -+ uint16_t comp_slew_rate_codes[SCOMP_MAX_CODES]; -+ -+ /* CMD Slew Rate = 1.8 for 2N */ -+ if (ctrl->tCMD == 2) -+ buffer_stage_delay_ps[SCOMP_CMD] = 89; -+ -+ /* CMD Slew Rate = 4 V/ns for double-pumped CMD bus */ -+ if (ctrl->lpddr) -+ buffer_stage_delay_ps[SCOMP_CMD] = 63; -+ -+ for (uint8_t i = 0; i < SCOMP_MAX_CODES; i++) { -+ uint16_t stages = DIV_ROUND_CLOSEST(ctrl->qclkps, buffer_stage_delay_ps[i]); -+ if (stages < 5) -+ stages = 5; -+ -+ bool dll_pc = buffer_stage_delay_ps[i] < min_cycle_delay[i] || stages > 16; -+ -+ /* Lock DLL... */ -+ if (dll_pc) -+ comp_slew_rate_codes[i] = stages / 2 - 1; /* to a phase */ -+ else -+ comp_slew_rate_codes[i] = (stages - 1) | BIT(4); /* to a cycle */ -+ } -+ union ddr_comp_ctl_1_reg ddr_comp_ctl_1 = { -+ .dq_scomp = comp_slew_rate_codes[SCOMP_DQ], -+ .cmd_scomp = comp_slew_rate_codes[SCOMP_CMD], -+ .ctl_scomp = comp_slew_rate_codes[SCOMP_CTL], -+ .clk_scomp = comp_slew_rate_codes[SCOMP_CLK], -+ .vccddq_hi = vddhi, -+ }; -+ ctrl->comp_ctl_1 = ddr_comp_ctl_1; -+ mchbar_write32(DDR_COMP_CTL_1, ctrl->comp_ctl_1.raw); -+} -+ -+static uint32_t ln_x100(const uint32_t input_x100) -+{ -+ uint32_t val = input_x100; -+ uint32_t ret = 0; -+ while (val > 271) { -+ val = (val * 1000) / 2718; -+ ret += 100; -+ } -+ return ret + (-16 * val * val + 11578 * val - 978860) / 10000; -+} -+ -+static uint32_t compute_vsshi_vref(struct sysinfo *ctrl, const uint32_t vsshi_tgt, bool up) -+{ -+ const uint32_t delta = 15; -+ const uint32_t c_die_vsshi = 2000; -+ const uint32_t r_cmd_ref = 100 * 10; -+ const uint32_t offset = up ? 64 : 0; -+ const uint32_t ln_vsshi = ln_x100((100 * vsshi_tgt) / (vsshi_tgt - delta)); -+ const uint32_t r_target = (ctrl->qclkps * 2000) / (c_die_vsshi * ln_vsshi); -+ const uint32_t r_dividend = 128 * (up ? r_cmd_ref : r_target); -+ return r_dividend / (r_cmd_ref + r_target) - offset; -+} -+ -+static void program_vsshi(struct sysinfo *ctrl, const uint16_t vccio_mv, const uint16_t vsshi) -+{ -+ const uint16_t vsshi_down = vsshi + 24; /* Panic threshold of 24 mV */ -+ const uint16_t vsshi_up = vccio_mv - vsshi_down; -+ const union ddr_comp_vsshi_reg ddr_comp_vsshi = { -+ .panic_drv_down_vref = compute_vsshi_vref(ctrl, vsshi_down, false), -+ .panic_drv_up_vref = compute_vsshi_vref(ctrl, vsshi_up, true), -+ .vt_offset = 128 * 450 / vccio_mv / 2, -+ .vt_slope_a = 4, -+ }; -+ mchbar_write32(DDR_COMP_VSSHI, ddr_comp_vsshi.raw); -+} -+ -+static void program_misc(struct sysinfo *ctrl) -+{ -+ ctrl->misc_control_0.raw = mchbar_read32(DDR_SCRAM_MISC_CONTROL); -+ ctrl->misc_control_0.weaklock_latency = 12; -+ ctrl->misc_control_0.wl_sleep_cycles = 5; -+ ctrl->misc_control_0.wl_wake_cycles = 2; -+ mchbar_write32(DDR_SCRAM_MISC_CONTROL, ctrl->misc_control_0.raw); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ /* Keep scrambling disabled for training */ -+ mchbar_write32(DDR_SCRAMBLE_ch(channel), 0); -+ } -+} -+ -+/* Very weird, application-specific function */ -+static void override_comp(uint32_t value, uint32_t width, uint32_t shift, uint32_t offset) -+{ -+ const uint32_t mask = (1 << width) - 1; -+ uint32_t reg32 = mchbar_read32(offset); -+ reg32 &= ~(mask << shift); -+ reg32 |= (value << shift); -+ mchbar_write32(offset, reg32); -+} -+ -+static void program_ls_comp(struct sysinfo *ctrl) -+{ -+ /* Disable periodic COMP */ -+ const union pcu_comp_reg m_comp = { -+ .comp_disable = 1, -+ .comp_interval = COMP_INT, -+ .comp_force = 1, -+ }; -+ mchbar_write32(M_COMP, m_comp.raw); -+ udelay(10); -+ -+ /* Override level shifter compensation */ -+ const uint32_t ls_comp = 2; -+ override_comp(ls_comp, 3, 28, DDR_DATA_RCOMP_DATA_1); -+ override_comp(ls_comp, 3, 24, DDR_CMD_COMP); -+ override_comp(ls_comp, 3, 24, DDR_CKE_CTL_COMP); -+ override_comp(ls_comp, 3, 23, DDR_CLK_COMP); -+ override_comp(ls_comp, 3, 28, DDR_COMP_DATA_COMP_1); -+ override_comp(ls_comp, 3, 24, DDR_COMP_CMD_COMP); -+ override_comp(ls_comp, 4, 24, DDR_COMP_CTL_COMP); -+ override_comp(ls_comp, 4, 23, DDR_COMP_CLK_COMP); -+ override_comp(ls_comp, 3, 24, DDR_COMP_OVERRIDE); -+ -+ /* Manually update the COMP values */ -+ union ddr_scram_misc_control_reg ddr_scram_misc_ctrl = ctrl->misc_control_0; -+ ddr_scram_misc_ctrl.force_comp_update = 1; -+ mchbar_write32(DDR_SCRAM_MISC_CONTROL, ddr_scram_misc_ctrl.raw); -+ -+ /* Use a fixed offset between ODT Up/Dn */ -+ const union ddr_comp_data_comp_1_reg data_comp_1 = { -+ .raw = mchbar_read32(DDR_COMP_DATA_COMP_1), -+ }; -+ const uint32_t odt_offset = data_comp_1.rcomp_odt_down - data_comp_1.rcomp_odt_up; -+ ctrl->comp_ctl_0.odt_up_down_off = odt_offset; -+ ctrl->comp_ctl_0.fixed_odt_offset = 1; -+ mchbar_write32(DDR_COMP_CTL_0, ctrl->comp_ctl_0.raw); -+} -+ -+/** TODO: Deduplicate PCODE stuff, it's already implemented in CPU code **/ -+static bool pcode_ready(void) -+{ -+ const unsigned int delay_step = 10; -+ for (unsigned int i = 0; i < 1000; i += delay_step) { -+ if (!(mchbar_read32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY)) -+ return true; -+ -+ udelay(delay_step); -+ }; -+ return false; -+} -+ -+static uint32_t pcode_mailbox_read(const uint32_t command) -+{ -+ if (!pcode_ready()) { -+ printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready\n"); -+ return 0; -+ } -+ mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY); -+ if (!pcode_ready()) { -+ printk(BIOS_ERR, "PCODE: mailbox timeout on completion\n"); -+ return 0; -+ } -+ return mchbar_read32(BIOS_MAILBOX_DATA); -+} -+ -+static int pcode_mailbox_write(const uint32_t command, const uint32_t data) -+{ -+ if (!pcode_ready()) { -+ printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready\n"); -+ return -1; -+ } -+ mchbar_write32(BIOS_MAILBOX_DATA, data); -+ mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY); -+ if (!pcode_ready()) { -+ printk(BIOS_ERR, "PCODE: mailbox timeout on completion\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static void enable_2x_refresh(struct sysinfo *ctrl) -+{ -+ if (!CONFIG(ENABLE_DDR_2X_REFRESH)) -+ return; -+ -+ printk(BIOS_DEBUG, "Enabling 2x Refresh\n"); -+ const bool asr = ctrl->flags.asr; -+ const bool lpddr = ctrl->lpddr; -+ -+ /* Mutually exclusive */ -+ assert(!asr || !lpddr); -+ if (!asr) { -+ uint32_t reg32 = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_DDR_2X_REFRESH); -+ if (!(reg32 & BIT(31))) { /** TODO: What to do if this is locked? **/ -+ reg32 |= BIT(0); /* Enable 2x refresh */ -+ reg32 |= BIT(31); /* Lock */ -+ -+ if (lpddr) -+ reg32 |= 4 << 1; /* LPDDR MR4 1/2 tREFI */ -+ -+ if (pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_DDR_2X_REFRESH, reg32)) -+ printk(BIOS_ERR, "Could not enable Mailbox 2x Refresh\n"); -+ } -+ if (!lpddr) -+ return; -+ } -+ assert(asr || lpddr); -+ uint16_t refi_reduction = 50; -+ if (lpddr) { -+ refi_reduction = 97; -+ mchbar_clrbits32(PCU_DDR_PTM_CTL, 1 << 7); /* DISABLE_DRAM_TS */ -+ } -+ /** TODO: Remember why this is only done on cold boots **/ -+ if (ctrl->bootmode == BOOTMODE_COLD) { -+ ctrl->tREFI *= refi_reduction; -+ ctrl->tREFI /= 100; -+ } -+} -+ -+static void set_pcu_ddr_voltage(const uint16_t vdd_mv) -+{ -+ /** TODO: Handle other voltages? **/ -+ uint32_t pcu_ddr_voltage; -+ switch (vdd_mv) { -+ case 1200: -+ pcu_ddr_voltage = 3; -+ break; -+ case 1350: -+ pcu_ddr_voltage = 1; -+ break; -+ default: -+ case 1500: -+ pcu_ddr_voltage = 0; -+ break; -+ } -+ /* Set bits 0..2 */ -+ mchbar_write32(PCU_DDR_VOLTAGE, pcu_ddr_voltage); -+} -+ -+static void program_scheduler(struct sysinfo *ctrl) -+{ -+ /* -+ * ZQ calibration needs to be serialized for LPDDR3. Otherwise, -+ * the processor issues LPDDR3 ZQ calibration in parallel when -+ * exiting Package C7 or deeper. This causes problems for dual -+ * and quad die packages since all ranks share the same ZQ pin. -+ * -+ * Erratum HSM94: LPDDR3 ZQ Calibration Following Deep Package -+ * C-state Exit May Lead to Unpredictable System Behavior -+ */ -+ const union mcscheds_cbit_reg mcscheds_cbit = { -+ .dis_write_gap = 1, -+ .dis_odt = is_hsw_ult() && !(ctrl->lpddr && ctrl->lpddr_dram_odt), -+ .serialize_zq = ctrl->lpddr, -+ }; -+ mchbar_write32(MCSCHEDS_CBIT, mcscheds_cbit.raw); -+ mchbar_write32(MCMNTS_SC_WDBWM, 0x553c3038); -+ if (ctrl->lpddr) { -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ union mcmain_command_rate_limit_reg cmd_rate_limit = { -+ .raw = mchbar_read32(COMMAND_RATE_LIMIT_ch(channel)), -+ }; -+ cmd_rate_limit.enable_cmd_limit = 1; -+ cmd_rate_limit.cmd_rate_limit = 3; -+ mchbar_write32(COMMAND_RATE_LIMIT_ch(channel), cmd_rate_limit.raw); -+ } -+ } -+} -+ -+static uint8_t biggest_channel(const struct sysinfo *const ctrl) -+{ -+ _Static_assert(NUM_CHANNELS == 2, "Code assumes exactly two channels"); -+ return !!(ctrl->channel_size_mb[0] < ctrl->channel_size_mb[1]); -+} -+ -+static void dram_zones(struct sysinfo *ctrl) -+{ -+ /** TODO: Activate channel hash here, if enabled **/ -+ const uint8_t biggest = biggest_channel(ctrl); -+ const uint8_t smaller = !biggest; -+ -+ /** TODO: Use stacked mode if Memory Trace is enabled **/ -+ const union mad_chnl_reg mad_channel = { -+ .ch_a = biggest, -+ .ch_b = smaller, -+ .ch_c = 2, -+ .lpddr_mode = ctrl->lpddr, -+ }; -+ mchbar_write32(MAD_CHNL, mad_channel.raw); -+ -+ const uint8_t channel_b_zone_size = ctrl->channel_size_mb[smaller] / 256; -+ const union mad_zr_reg mad_zr = { -+ .ch_b_double = channel_b_zone_size * 2, -+ .ch_b_single = channel_b_zone_size, -+ }; -+ mchbar_write32(MAD_ZR, mad_zr.raw); -+} -+ -+static uint8_t biggest_dimm(const struct raminit_dimm_info *dimms) -+{ -+ _Static_assert(NUM_SLOTS <= 2, "Code assumes at most two DIMMs per channel."); -+ if (NUM_SLOTS == 1) -+ return 0; -+ -+ return !!(dimms[0].data.size_mb < dimms[1].data.size_mb); -+} -+ -+static void dram_dimm_mapping(struct sysinfo *ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) { -+ const union mad_dimm_reg mad_dimm = { -+ .rank_interleave = 1, -+ .enh_interleave = 1, -+ }; -+ mchbar_write32(MAD_DIMM(channel), mad_dimm.raw); -+ continue; -+ } -+ const uint8_t biggest = biggest_dimm(ctrl->dimms[channel]); -+ const uint8_t smaller = !biggest; -+ const struct dimm_attr_ddr3_st *dimm_a = &ctrl->dimms[channel][biggest].data; -+ const struct dimm_attr_ddr3_st *dimm_b = &ctrl->dimms[channel][smaller].data; -+ union mad_dimm_reg mad_dimm = { -+ .dimm_a_size = dimm_a->size_mb / 256, -+ .dimm_b_size = dimm_b->size_mb / 256, -+ .dimm_a_sel = biggest, -+ .dimm_a_ranks = dimm_a->ranks == 2, -+ .dimm_b_ranks = dimm_b->ranks == 2, -+ .dimm_a_width = dimm_a->width == 16, -+ .dimm_b_width = dimm_b->width == 16, -+ .rank_interleave = 1, -+ .enh_interleave = 1, -+ .ecc_mode = 0, /* Do not enable ECC yet */ -+ }; -+ if (is_hsw_ult()) -+ mad_dimm.dimm_b_width = mad_dimm.dimm_a_width; -+ -+ mchbar_write32(MAD_DIMM(channel), mad_dimm.raw); -+ if (ctrl->lpddr) -+ die("%s: Missing LPDDR support (LPDDR_MR_PARAMS)\n", __func__); -+ } -+} -+ -+enum raminit_status configure_mc(struct sysinfo *ctrl) -+{ -+ const uint16_t vccio_mv = 1000; -+ const uint16_t vsshi_mv = ctrl->vdd_mv - 950; -+ const bool dis_odt_static = is_hsw_ult(); /* Disable static ODT legs on ULT */ -+ const bool vddhi = ctrl->vdd_mv > 1350; -+ -+ program_misc_control(ctrl); -+ program_mrc_revision(); -+ program_ranks_used(ctrl); -+ program_ddr_data(ctrl, dis_odt_static, vddhi); -+ program_vsshi_control(ctrl, vsshi_mv); -+ program_dimm_vref(ctrl, vccio_mv, vddhi); -+ program_ddr_ca(ctrl, vddhi); -+ program_rcomp_vref(ctrl, dis_odt_static); -+ program_slew_rates(ctrl, vddhi); -+ program_vsshi(ctrl, vccio_mv, vsshi_mv); -+ program_misc(ctrl); -+ program_ls_comp(ctrl); -+ enable_2x_refresh(ctrl); -+ set_pcu_ddr_voltage(ctrl->vdd_mv); -+ configure_timings(ctrl); -+ configure_refresh(ctrl); -+ program_scheduler(ctrl); -+ dram_zones(ctrl); -+ dram_dimm_mapping(ctrl); -+ -+ return RAMINIT_STATUS_SUCCESS; -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 2fea658415..fcc981ad04 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -22,6 +22,7 @@ static const struct task_entry cold_boot[] = { - { collect_spd_info, true, "PROCSPD", }, - { initialise_mpll, true, "INITMPLL", }, - { convert_timings, true, "CONVTIM", }, -+ { configure_mc, true, "CONFMC", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -@@ -53,6 +54,7 @@ static void initialize_ctrl(struct sysinfo *ctrl) - - ctrl->cpu = cpu_get_cpuid(); - ctrl->stepping = get_stepping(ctrl->cpu); -+ ctrl->vdd_mv = is_hsw_ult() ? 1350 : 1500; /** FIXME: Hardcoded, does it matter? **/ - ctrl->dq_pins_interleaved = cfg->dq_pins_interleaved; - ctrl->bootmode = bootmode; - } -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index e0ebd3a2a7..fffa6d5450 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -3,16 +3,41 @@ - #ifndef HASWELL_RAMINIT_NATIVE_H - #define HASWELL_RAMINIT_NATIVE_H - -+#include <assert.h> - #include <device/dram/ddr3.h> - #include <northbridge/intel/haswell/haswell.h> -+#include <string.h> -+#include <types.h> -+ -+#include "reg_structs.h" - - /** TODO (Angel): Remove this after in-review patches are submitted **/ - #define SPD_LEN SPD_SIZE_MAX_DDR3 - -+/* Each channel has 4 ranks, spread across 2 slots */ -+#define NUM_SLOTRANKS 4 -+ -+#define NUM_GROUPS 2 -+ - /* 8 data lanes + 1 ECC lane */ - #define NUM_LANES 9 - #define NUM_LANES_NO_ECC 8 - -+#define COMP_INT 10 -+ -+/* Always use 12 legs for emphasis (not trained) */ -+#define TXEQFULLDRV (3 << 4) -+ -+enum command_training_iteration { -+ CT_ITERATION_CLOCK = 0, -+ CT_ITERATION_CMD_NORTH, -+ CT_ITERATION_CMD_SOUTH, -+ CT_ITERATION_CKE, -+ CT_ITERATION_CTL, -+ CT_ITERATION_CMD_VREF, -+ MAX_CT_ITERATION, -+}; -+ - enum raminit_boot_mode { - BOOTMODE_COLD, - BOOTMODE_WARM, -@@ -58,6 +83,9 @@ struct sysinfo { - * LPDDR-specific functions have stubs which will halt upon execution. - */ - bool lpddr; -+ bool lpddr_dram_odt; -+ uint8_t lpddr_cke_rank_map[NUM_CHANNELS]; -+ uint8_t dq_byte_map[NUM_CHANNELS][MAX_CT_ITERATION][2]; - - struct raminit_dimm_info dimms[NUM_CHANNELS][NUM_SLOTS]; - union dimm_flags_ddr3_st flags; -@@ -94,16 +122,89 @@ struct sysinfo { - uint32_t mem_clock_mhz; - uint32_t mem_clock_fs; /* Memory clock period in femtoseconds */ - uint32_t qclkps; /* Quadrature clock period in picoseconds */ -+ -+ uint16_t vdd_mv; -+ -+ union ddr_scram_misc_control_reg misc_control_0; -+ -+ union ddr_comp_ctl_0_reg comp_ctl_0; -+ union ddr_comp_ctl_1_reg comp_ctl_1; -+ -+ union ddr_data_vref_adjust_reg dimm_vref; -+ -+ uint32_t data_offset_train[NUM_CHANNELS][NUM_LANES]; -+ uint32_t data_offset_comp[NUM_CHANNELS][NUM_LANES]; -+ -+ uint32_t dq_control_0[NUM_CHANNELS]; -+ uint32_t dq_control_1[NUM_CHANNELS][NUM_LANES]; -+ uint32_t dq_control_2[NUM_CHANNELS][NUM_LANES]; -+ -+ uint16_t tx_dq[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; -+ uint16_t txdqs[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; -+ uint8_t tx_eq[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; -+ -+ uint16_t rcven[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; -+ uint8_t rx_eq[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; -+ uint8_t rxdqsp[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; -+ uint8_t rxdqsn[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; -+ int8_t rxvref[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; -+ -+ uint8_t clk_pi_code[NUM_CHANNELS][NUM_SLOTRANKS]; -+ uint8_t ctl_pi_code[NUM_CHANNELS][NUM_SLOTRANKS]; -+ uint8_t cke_pi_code[NUM_CHANNELS][NUM_SLOTRANKS]; -+ -+ uint8_t cke_cmd_pi_code[NUM_CHANNELS][NUM_GROUPS]; -+ uint8_t cmd_north_pi_code[NUM_CHANNELS][NUM_GROUPS]; -+ uint8_t cmd_south_pi_code[NUM_CHANNELS][NUM_GROUPS]; - }; - -+static inline bool is_hsw_ult(void) -+{ -+ return CONFIG(INTEL_LYNXPOINT_LP); -+} -+ -+static inline bool rank_in_mask(uint8_t rank, uint8_t rankmask) -+{ -+ assert(rank < NUM_SLOTRANKS); -+ return !!(BIT(rank) & rankmask); -+} -+ -+static inline bool does_ch_exist(const struct sysinfo *ctrl, uint8_t channel) -+{ -+ return !!ctrl->dpc[channel]; -+} -+ -+static inline bool does_rank_exist(const struct sysinfo *ctrl, uint8_t rank) -+{ -+ return rank_in_mask(rank, ctrl->rankmap[0] | ctrl->rankmap[1]); -+} -+ -+static inline bool rank_in_ch(const struct sysinfo *ctrl, uint8_t rank, uint8_t channel) -+{ -+ assert(channel < NUM_CHANNELS); -+ return rank_in_mask(rank, ctrl->rankmap[channel]); -+} -+ -+/** TODO: Handling of data_offset_train could be improved, also coupled with reg updates **/ -+static inline void clear_data_offset_train_all(struct sysinfo *ctrl) -+{ -+ memset(ctrl->data_offset_train, 0, sizeof(ctrl->data_offset_train)); -+} -+ - void raminit_main(enum raminit_boot_mode bootmode); - - enum raminit_status collect_spd_info(struct sysinfo *ctrl); - enum raminit_status initialise_mpll(struct sysinfo *ctrl); - enum raminit_status convert_timings(struct sysinfo *ctrl); -+enum raminit_status configure_mc(struct sysinfo *ctrl); -+ -+void configure_timings(struct sysinfo *ctrl); -+void configure_refresh(struct sysinfo *ctrl); - - enum raminit_status wait_for_first_rcomp(void); - -+uint8_t get_rx_bias(const struct sysinfo *ctrl); -+ - uint8_t get_tCWL(uint32_t mem_clock_mhz); - uint32_t get_tREFI(uint32_t mem_clock_mhz); - uint32_t get_tXP(uint32_t mem_clock_mhz); -diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -new file mode 100644 -index 0000000000..d11cda4b3d ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -@@ -0,0 +1,405 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#ifndef HASWELL_RAMINIT_REG_STRUCTS_H -+#define HASWELL_RAMINIT_REG_STRUCTS_H -+ -+union ddr_data_rx_train_rank_reg { -+ struct __packed { -+ uint32_t rcven : 9; // Bits 8:0 -+ uint32_t dqs_p : 6; // Bits 14:9 -+ uint32_t rx_eq : 5; // Bits 19:15 -+ uint32_t dqs_n : 6; // Bits 25:20 -+ int32_t vref : 6; // Bits 31:26 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_data_tx_train_rank_reg { -+ struct __packed { -+ uint32_t dq_delay : 9; // Bits 8:0 -+ uint32_t dqs_delay : 9; // Bits 17:9 -+ uint32_t : 2; // Bits 19:18 -+ uint32_t tx_eq : 6; // Bits 25:20 -+ uint32_t : 6; // Bits 31:26 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_data_control_0_reg { -+ struct __packed { -+ uint32_t rx_training_mode : 1; // Bits 0:0 -+ uint32_t wl_training_mode : 1; // Bits 1:1 -+ uint32_t rl_training_mode : 1; // Bits 2:2 -+ uint32_t samp_train_mode : 1; // Bits 3:3 -+ uint32_t tx_on : 1; // Bits 4:4 -+ uint32_t rf_on : 1; // Bits 5:5 -+ uint32_t rx_pi_on : 1; // Bits 6:6 -+ uint32_t tx_pi_on : 1; // Bits 7:7 -+ uint32_t internal_clocks_on : 1; // Bits 8:8 -+ uint32_t repeater_clocks_on : 1; // Bits 9:9 -+ uint32_t tx_disable : 1; // Bits 10:10 -+ uint32_t rx_disable : 1; // Bits 11:11 -+ uint32_t tx_long : 1; // Bits 12:12 -+ uint32_t rx_dqs_ctle : 2; // Bits 14:13 -+ uint32_t rx_read_pointer : 3; // Bits 17:15 -+ uint32_t driver_segment_enable : 1; // Bits 18:18 -+ uint32_t data_vccddq_hi : 1; // Bits 19:19 -+ uint32_t read_rf_rd : 1; // Bits 20:20 -+ uint32_t read_rf_wr : 1; // Bits 21:21 -+ uint32_t read_rf_rank : 2; // Bits 23:22 -+ uint32_t force_odt_on : 1; // Bits 24:24 -+ uint32_t odt_samp_off : 1; // Bits 25:25 -+ uint32_t disable_odt_static : 1; // Bits 26:26 -+ uint32_t ddr_cr_force_odt_on : 1; // Bits 27:27 -+ uint32_t lpddr_mode : 1; // Bits 28:28 -+ uint32_t en_read_preamble : 1; // Bits 29:29 -+ uint32_t odt_samp_extend_en : 1; // Bits 30:30 -+ uint32_t early_rleak_en : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_data_control_1_reg { -+ struct __packed { -+ int32_t ref_pi : 4; // Bits 3:0 -+ uint32_t dll_mask : 2; // Bits 5:4 -+ uint32_t dll_weaklock : 1; // Bits 6:6 -+ uint32_t sdll_segment_disable : 3; // Bits 9:7 -+ uint32_t rx_bias_ctl : 3; // Bits 12:10 -+ int32_t odt_delay : 4; // Bits 16:13 -+ uint32_t odt_duration : 3; // Bits 19:17 -+ int32_t sense_amp_delay : 4; // Bits 23:20 -+ uint32_t sense_amp_duration : 3; // Bits 26:24 -+ uint32_t burst_end_odt_delay : 3; // Bits 29:27 *** TODO: Check Broadwell *** -+ uint32_t lpddr_long_odt_en : 1; // Bits 30:30 -+ uint32_t : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+/* NOTE: Bits 31:19 are only valid for Broadwell onwards */ -+union ddr_data_control_2_reg { -+ struct __packed { -+ uint32_t rx_stagger_ctl : 5; // Bits 4:0 -+ uint32_t force_bias_on : 1; // Bits 5:5 -+ uint32_t force_rx_on : 1; // Bits 6:6 -+ uint32_t leaker_comp : 2; // Bits 8:7 -+ uint32_t rx_dqs_amp_offset : 4; // Bits 12:9 -+ uint32_t rx_clk_stg_num : 5; // Bits 17:13 -+ uint32_t wl_long_delay : 1; // Bits 18:18 -+ uint32_t enable_vref_pwrdn : 1; // Bits 19:19 -+ uint32_t ddr4_mode : 1; // Bits 20:20 -+ uint32_t en_vddq_odt : 1; // Bits 21:21 -+ uint32_t en_vtt_odt : 1; // Bits 22:22 -+ uint32_t en_const_z_eq_tx : 1; // Bits 23:23 -+ uint32_t tx_eq_dis : 1; // Bits 24:24 -+ uint32_t rx_vref_prog_mfc : 1; // Bits 25:25 -+ uint32_t cben : 3; // Bits 28:26 -+ uint32_t tx_deskew_disable : 1; // Bits 29:29 -+ uint32_t rx_deskew_disable : 1; // Bits 30:30 -+ uint32_t dq_slew_dly_byp : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_comp_data_comp_1_reg { -+ struct __packed { -+ uint32_t rcomp_odt_up : 6; // Bits 5:0 -+ uint32_t : 3; // Bits 8:6 -+ uint32_t rcomp_odt_down : 6; // Bits 14:9 -+ uint32_t : 1; // Bits 15:15 -+ uint32_t panic_drv_down : 6; // Bits 21:16 -+ uint32_t panic_drv_up : 6; // Bits 27:22 -+ uint32_t ls_comp : 3; // Bits 30:28 -+ uint32_t : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_comp_ctl_0_reg { -+ struct __packed { -+ uint32_t : 3; // Bits 2:0 -+ uint32_t disable_odt_static : 1; // Bits 3:3 -+ uint32_t odt_up_down_off : 6; // Bits 9:4 -+ uint32_t fixed_odt_offset : 1; // Bits 10:10 -+ int32_t dq_drv_vref : 4; // Bits 14:11 -+ int32_t dq_odt_vref : 5; // Bits 19:15 -+ int32_t cmd_drv_vref : 4; // Bits 23:20 -+ int32_t ctl_drv_vref : 4; // Bits 27:24 -+ int32_t clk_drv_vref : 4; // Bits 31:28 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_comp_ctl_1_reg { -+ struct __packed { -+ uint32_t dq_scomp : 5; // Bits 4:0 -+ uint32_t cmd_scomp : 5; // Bits 9:5 -+ uint32_t ctl_scomp : 5; // Bits 14:10 -+ uint32_t clk_scomp : 5; // Bits 19:15 -+ uint32_t tco_cmd_offset : 4; // Bits 23:20 -+ uint32_t comp_clk_on : 1; // Bits 24:24 -+ uint32_t vccddq_hi : 1; // Bits 25:25 -+ uint32_t : 3; // Bits 28:26 -+ uint32_t dis_quick_comp : 1; // Bits 29:29 -+ uint32_t sin_step : 1; // Bits 30:30 -+ uint32_t sin_step_adv : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_data_vref_adjust_reg { -+ struct __packed { -+ int32_t ca_vref_ctrl : 7;// Bits 6:0 -+ int32_t ch1_vref_ctrl : 7;// Bits 13:7 -+ int32_t ch0_vref_ctrl : 7;// Bits 20:14 -+ uint32_t en_dimm_vref_ca : 1;// Bits 21:21 -+ uint32_t en_dimm_vref_ch1 : 1;// Bits 22:22 -+ uint32_t en_dimm_vref_ch0 : 1;// Bits 23:23 -+ uint32_t hi_z_timer_ctrl : 2;// Bits 25:24 -+ uint32_t vccddq_hi_qnnn_h : 1;// Bits 26:26 -+ uint32_t : 2;// Bits 28:27 -+ uint32_t ca_slow_bw : 1;// Bits 29:29 -+ uint32_t ch0_slow_bw : 1;// Bits 30:30 -+ uint32_t ch1_slow_bw : 1;// Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_data_vref_control_reg { -+ struct __packed { -+ uint32_t hi_bw_divider : 2; // Bits 1:0 -+ uint32_t lo_bw_divider : 2; // Bits 3:2 -+ uint32_t sample_divider : 3; // Bits 6:4 -+ uint32_t open_loop : 1; // Bits 7:7 -+ uint32_t slow_bw_error : 2; // Bits 9:8 -+ uint32_t hi_bw_enable : 1; // Bits 10:10 -+ uint32_t : 1; // Bits 11:11 -+ uint32_t vt_slope_b : 3; // Bits 14:12 -+ uint32_t vt_slope_a : 3; // Bits 17:15 -+ uint32_t vt_offset : 3; // Bits 20:18 -+ uint32_t sel_code : 3; // Bits 23:21 -+ uint32_t output_code : 8; // Bits 31:24 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_comp_vsshi_reg { -+ struct __packed { -+ uint32_t panic_drv_down_vref : 6; // Bits 5:0 -+ uint32_t panic_drv_up_vref : 6; // Bits 11:6 -+ uint32_t vt_offset : 5; // Bits 16:12 -+ uint32_t vt_slope_a : 3; // Bits 19:17 -+ uint32_t vt_slope_b : 3; // Bits 22:20 -+ uint32_t : 9; // Bits 31:23 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_comp_vsshi_control_reg { -+ struct __packed { -+ uint32_t vsshi_target : 6; // Bits 5:0 -+ uint32_t hi_bw_divider : 2; // Bits 7:6 -+ uint32_t lo_bw_divider : 2; // Bits 9:8 -+ uint32_t sample_divider : 3; // Bits 12:10 -+ uint32_t open_loop : 1; // Bits 13:13 -+ uint32_t bw_error : 2; // Bits 15:14 -+ uint32_t panic_driver_en : 1; // Bits 16:16 -+ uint32_t : 1; // Bits 17:17 -+ uint32_t panic_voltage : 4; // Bits 21:18 -+ uint32_t gain_boost : 1; // Bits 22:22 -+ uint32_t sel_code : 1; // Bits 23:23 -+ uint32_t output_code : 8; // Bits 31:24 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_clk_controls_reg { -+ struct __packed { -+ uint32_t ref_pi : 4; // Bits 3:0 -+ uint32_t dll_mask : 2; // Bits 5:4 -+ uint32_t : 1; // Bits 6:6 -+ uint32_t tx_on : 1; // Bits 7:7 -+ uint32_t internal_clocks_on : 1; // Bits 8:8 -+ uint32_t repeater_clocks_on : 1; // Bits 9:9 -+ uint32_t io_lb_ctl : 2; // Bits 11:10 -+ uint32_t odt_mode : 1; // Bits 12:12 -+ uint32_t : 8; // Bits 20:13 -+ uint32_t rx_vref : 6; // Bits 26:21 -+ uint32_t vccddq_hi : 1; // Bits 27:27 -+ uint32_t dll_weaklock : 1; // Bits 28:28 -+ uint32_t lpddr_mode : 1; // Bits 29:29 -+ uint32_t : 2; // Bits 31:30 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_cmd_controls_reg { -+ struct __packed { -+ int32_t ref_pi : 4; // Bits 3:0 -+ uint32_t dll_mask : 2; // Bits 5:4 -+ uint32_t : 1; // Bits 6:6 -+ uint32_t tx_on : 1; // Bits 7:7 -+ uint32_t internal_clocks_on : 1; // Bits 8:8 -+ uint32_t repeater_clocks_on : 1; // Bits 9:9 -+ uint32_t io_lb_ctl : 2; // Bits 11:10 -+ uint32_t odt_mode : 1; // Bits 12:12 -+ uint32_t cmd_tx_eq : 2; // Bits 14:13 -+ uint32_t early_weak_drive : 2; // Bits 16:15 -+ uint32_t : 4; // Bits 20:17 -+ int32_t rx_vref : 6; // Bits 26:21 -+ uint32_t vccddq_hi : 1; // Bits 27:27 -+ uint32_t dll_weaklock : 1; // Bits 28:28 -+ uint32_t lpddr_mode : 1; // Bits 29:29 -+ uint32_t lpddr_ca_a_dis : 1; // Bits 30:30 -+ uint32_t lpddr_ca_b_dis : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+/* Same register definition for CKE and CTL fubs */ -+union ddr_cke_ctl_controls_reg { -+ struct __packed { -+ int32_t ref_pi : 4; // Bits 3:0 -+ uint32_t dll_mask : 2; // Bits 5:4 -+ uint32_t : 1; // Bits 6:6 -+ uint32_t tx_on : 1; // Bits 7:7 -+ uint32_t internal_clocks_on : 1; // Bits 8:8 -+ uint32_t repeater_clocks_on : 1; // Bits 9:9 -+ uint32_t io_lb_ctl : 2; // Bits 11:10 -+ uint32_t odt_mode : 1; // Bits 12:12 -+ uint32_t cmd_tx_eq : 2; // Bits 14:13 -+ uint32_t early_weak_drive : 2; // Bits 16:15 -+ uint32_t ctl_tx_eq : 2; // Bits 18:17 -+ uint32_t ctl_sr_drv : 2; // Bits 20:19 -+ int32_t rx_vref : 6; // Bits 26:21 -+ uint32_t vccddq_hi : 1; // Bits 27:27 -+ uint32_t dll_weaklock : 1; // Bits 28:28 -+ uint32_t lpddr_mode : 1; // Bits 29:29 -+ uint32_t la_drv_en_ovrd : 1; // Bits 30:30 -+ uint32_t lpddr_ca_a_dis : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union ddr_scram_misc_control_reg { -+ struct __packed { -+ uint32_t wl_wake_cycles : 2; // Bits 1:0 -+ uint32_t wl_sleep_cycles : 3; // Bits 4:2 -+ uint32_t force_comp_update : 1; // Bits 5:5 -+ uint32_t weaklock_latency : 4; // Bits 9:6 -+ uint32_t ddr_no_ch_interleave : 1; // Bits 10:10 -+ uint32_t lpddr_mode : 1; // Bits 11:11 -+ uint32_t cke_mapping_ch0 : 4; // Bits 15:12 -+ uint32_t cke_mapping_ch1 : 4; // Bits 19:16 -+ uint32_t : 12; // Bits 31:20 -+ }; -+ uint32_t raw; -+}; -+ -+union mcscheds_cbit_reg { -+ struct __packed { -+ uint32_t dis_opp_cas : 1; // Bits 0:0 -+ uint32_t dis_opp_is_cas : 1; // Bits 1:1 -+ uint32_t dis_opp_ras : 1; // Bits 2:2 -+ uint32_t dis_opp_is_ras : 1; // Bits 3:3 -+ uint32_t dis_1c_byp : 1; // Bits 4:4 -+ uint32_t dis_2c_byp : 1; // Bits 5:5 -+ uint32_t dis_deprd_opt : 1; // Bits 6:6 -+ uint32_t dis_pt_it : 1; // Bits 7:7 -+ uint32_t dis_prcnt_ring : 1; // Bits 8:8 -+ uint32_t dis_prcnt_sa : 1; // Bits 9:9 -+ uint32_t dis_blkr_ph : 1; // Bits 10:10 -+ uint32_t dis_blkr_pe : 1; // Bits 11:11 -+ uint32_t dis_blkr_pm : 1; // Bits 12:12 -+ uint32_t dis_odt : 1; // Bits 13:13 -+ uint32_t oe_always_off : 1; // Bits 14:14 -+ uint32_t : 1; // Bits 15:15 -+ uint32_t dis_aom : 1; // Bits 16:16 -+ uint32_t block_rpq : 1; // Bits 17:17 -+ uint32_t block_wpq : 1; // Bits 18:18 -+ uint32_t invert_align : 1; // Bits 19:19 -+ uint32_t dis_write_gap : 1; // Bits 20:20 -+ uint32_t dis_zq : 1; // Bits 21:21 -+ uint32_t dis_tt : 1; // Bits 22:22 -+ uint32_t dis_opp_ref : 1; // Bits 23:23 -+ uint32_t long_zq : 1; // Bits 24:24 -+ uint32_t dis_srx_zq : 1; // Bits 25:25 -+ uint32_t serialize_zq : 1; // Bits 26:26 -+ uint32_t zq_fast_exec : 1; // Bits 27:27 -+ uint32_t dis_drive_nop : 1; // Bits 28:28 -+ uint32_t pres_wdb_ent : 1; // Bits 29:29 -+ uint32_t dis_clk_gate : 1; // Bits 30:30 -+ uint32_t : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union mcmain_command_rate_limit_reg { -+ struct __packed { -+ uint32_t enable_cmd_limit : 1; // Bits 0:0 -+ uint32_t cmd_rate_limit : 3; // Bits 3:1 -+ uint32_t reset_on_command : 4; // Bits 7:4 -+ uint32_t reset_delay : 4; // Bits 11:8 -+ uint32_t ck_to_cke_delay : 2; // Bits 13:12 -+ uint32_t : 17; // Bits 30:14 -+ uint32_t init_mrw_2n_cs : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union mad_chnl_reg { -+ struct __packed { -+ uint32_t ch_a : 2; // Bits 1:0 -+ uint32_t ch_b : 2; // Bits 3:2 -+ uint32_t ch_c : 2; // Bits 5:4 -+ uint32_t stacked_mode : 1; // Bits 6:6 -+ uint32_t stkd_mode_bits : 3; // Bits 9:7 -+ uint32_t lpddr_mode : 1; // Bits 10:10 -+ uint32_t : 21; // Bits 31:11 -+ }; -+ uint32_t raw; -+}; -+ -+union mad_dimm_reg { -+ struct __packed { -+ uint32_t dimm_a_size : 8; // Bits 7:0 -+ uint32_t dimm_b_size : 8; // Bits 15:8 -+ uint32_t dimm_a_sel : 1; // Bits 16:16 -+ uint32_t dimm_a_ranks : 1; // Bits 17:17 -+ uint32_t dimm_b_ranks : 1; // Bits 18:18 -+ uint32_t dimm_a_width : 1; // Bits 19:19 -+ uint32_t dimm_b_width : 1; // Bits 20:20 -+ uint32_t rank_interleave : 1; // Bits 21:21 -+ uint32_t enh_interleave : 1; // Bits 22:22 -+ uint32_t : 1; // Bits 23:23 -+ uint32_t ecc_mode : 2; // Bits 25:24 -+ uint32_t hori_mode : 1; // Bits 26:26 -+ uint32_t hori_address : 3; // Bits 29:27 -+ uint32_t : 2; // Bits 31:30 -+ }; -+ uint32_t raw; -+}; -+ -+union mad_zr_reg { -+ struct __packed { -+ uint32_t : 16; // Bits 15:0 -+ uint32_t ch_b_double : 8; // Bits 23:16 -+ uint32_t ch_b_single : 8; // Bits 31:24 -+ }; -+ uint32_t raw; -+}; -+ -+/* Same definition for P_COMP, M_COMP, D_COMP */ -+union pcu_comp_reg { -+ struct __packed { -+ uint32_t comp_disable : 1; // Bits 0:0 -+ uint32_t comp_interval : 4; // Bits 4:1 -+ uint32_t : 3; // Bits 7:5 -+ uint32_t comp_force : 1; // Bits 8:8 -+ uint32_t : 23; // Bits 31:9 -+ }; -+ uint32_t raw; -+}; -+ -+#endif -diff --git a/src/northbridge/intel/haswell/native_raminit/timings_refresh.c b/src/northbridge/intel/haswell/native_raminit/timings_refresh.c -new file mode 100644 -index 0000000000..a9d960f31b ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/timings_refresh.c -@@ -0,0 +1,13 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include "raminit_native.h" -+ -+void configure_timings(struct sysinfo *ctrl) -+{ -+ /** TODO: Stub **/ -+} -+ -+void configure_refresh(struct sysinfo *ctrl) -+{ -+ /** TODO: Stub **/ -+} -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 45f8174995..4c3f399b5d 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -7,9 +7,98 @@ - #define NUM_CHANNELS 2 - #define NUM_SLOTS 2 - -+/* Indexed register helper macros */ -+#define _DDRIO_C_R_B(r, ch, rank, byte) ((r) + 0x100 * (ch) + 0x4 * (rank) + 0x200 * (byte)) -+#define _MCMAIN_C_X(r, ch, x) ((r) + 0x400 * (ch) + 0x4 * (x)) -+#define _MCMAIN_C(r, ch) ((r) + 0x400 * (ch)) -+ - /* Register definitions */ -+ -+/* DDR DATA per-channel per-bytelane */ -+#define DQ_CONTROL_2(ch, byte) _DDRIO_C_R_B(0x0064, ch, 0, byte) -+ -+/* DDR CKE per-channel */ -+#define DDR_CKE_ch_CMD_COMP_OFFSET(ch) _DDRIO_C_R_B(0x1204, ch, 0, 0) -+#define DDR_CKE_ch_CMD_PI_CODING(ch) _DDRIO_C_R_B(0x1208, ch, 0, 0) -+ -+#define DDR_CKE_ch_CTL_CONTROLS(ch) _DDRIO_C_R_B(0x121c, ch, 0, 0) -+#define DDR_CKE_ch_CTL_RANKS_USED(ch) _DDRIO_C_R_B(0x1220, ch, 0, 0) -+ -+/* DDR CTL per-channel */ -+#define DDR_CTL_ch_CTL_CONTROLS(ch) _DDRIO_C_R_B(0x1c1c, ch, 0, 0) -+#define DDR_CTL_ch_CTL_RANKS_USED(ch) _DDRIO_C_R_B(0x1c20, ch, 0, 0) -+ -+/* DDR CLK per-channel */ -+#define DDR_CLK_ch_RANKS_USED(ch) _DDRIO_C_R_B(0x1800, ch, 0, 0) -+#define DDR_CLK_ch_COMP_OFFSET(ch) _DDRIO_C_R_B(0x1808, ch, 0, 0) -+#define DDR_CLK_ch_PI_CODING(ch) _DDRIO_C_R_B(0x180c, ch, 0, 0) -+#define DDR_CLK_ch_CONTROLS(ch) _DDRIO_C_R_B(0x1810, ch, 0, 0) -+ -+/* DDR Scrambler */ -+#define DDR_SCRAMBLE_ch(ch) (0x2000 + 4 * (ch)) -+#define DDR_SCRAM_MISC_CONTROL 0x2008 -+ -+/* DDR CMDN/CMDS per-channel (writes go to both CMDN and CMDS fubs) */ -+#define DDR_CMD_ch_COMP_OFFSET(ch) _DDRIO_C_R_B(0x3204, ch, 0, 0) -+#define DDR_CMD_ch_PI_CODING(ch) _DDRIO_C_R_B(0x3208, ch, 0, 0) -+#define DDR_CMD_ch_CONTROLS(ch) _DDRIO_C_R_B(0x320c, ch, 0, 0) -+ -+/* DDR CKE/CTL per-channel (writes go to both CKE and CTL fubs) */ -+#define DDR_CKE_CTL_ch_CTL_COMP_OFFSET(ch) _DDRIO_C_R_B(0x3414, ch, 0, 0) -+#define DDR_CKE_CTL_ch_CTL_PI_CODING(ch) _DDRIO_C_R_B(0x3418, ch, 0, 0) -+ -+/* DDR DATA broadcast */ -+#define DDR_DATA_RX_TRAIN_RANK(rank) _DDRIO_C_R_B(0x3600, 0, rank, 0) -+#define DDR_DATA_RX_PER_BIT_RANK(rank) _DDRIO_C_R_B(0x3610, 0, rank, 0) -+#define DDR_DATA_TX_TRAIN_RANK(rank) _DDRIO_C_R_B(0x3620, 0, rank, 0) -+#define DDR_DATA_TX_PER_BIT_RANK(rank) _DDRIO_C_R_B(0x3630, 0, rank, 0) -+ -+#define DDR_DATA_RCOMP_DATA_1 0x3644 -+#define DDR_DATA_TX_XTALK 0x3648 -+#define DDR_DATA_RX_OFFSET_VDQ 0x364c -+#define DDR_DATA_OFFSET_COMP 0x365c -+#define DDR_DATA_CONTROL_1 0x3660 -+ -+#define DDR_DATA_OFFSET_TRAIN 0x3670 -+#define DDR_DATA_CONTROL_0 0x3674 -+#define DDR_DATA_VREF_ADJUST 0x3678 -+ -+/* DDR CMD broadcast */ -+#define DDR_CMD_COMP 0x3700 -+ -+/* DDR CKE/CTL broadcast */ -+#define DDR_CKE_CTL_COMP 0x3810 -+ -+/* DDR CLK broadcast */ -+#define DDR_CLK_COMP 0x3904 -+#define DDR_CLK_CONTROLS 0x3910 -+#define DDR_CLK_CB_STATUS 0x3918 -+ -+/* DDR COMP (global) */ -+#define DDR_COMP_DATA_COMP_1 0x3a04 -+#define DDR_COMP_CMD_COMP 0x3a08 -+#define DDR_COMP_CTL_COMP 0x3a0c -+#define DDR_COMP_CLK_COMP 0x3a10 -+#define DDR_COMP_CTL_0 0x3a14 -+#define DDR_COMP_CTL_1 0x3a18 -+#define DDR_COMP_VSSHI 0x3a1c -+#define DDR_COMP_OVERRIDE 0x3a20 -+#define DDR_COMP_VSSHI_CONTROL 0x3a24 -+ -+/* MCMAIN per-channel */ -+#define COMMAND_RATE_LIMIT_ch(ch) _MCMAIN_C(0x4010, ch) -+ -+#define MC_INIT_STATE_ch(ch) _MCMAIN_C(0x42a0, ch) -+ -+/* MCMAIN broadcast */ -+#define MCSCHEDS_CBIT 0x4c20 -+ -+#define MCMNTS_SC_WDBWM 0x4f8c -+ -+/* MCDECS */ - #define MAD_CHNL 0x5000 /* Address Decoder Channel Configuration */ - #define MAD_DIMM(ch) (0x5004 + (ch) * 4) -+#define MAD_ZR 0x5014 - #define MC_INIT_STATE_G 0x5030 - #define MRC_REVISION 0x5034 /* MRC Revision */ - -@@ -28,6 +117,8 @@ - - #define PCU_DDR_PTM_CTL 0x5880 - -+#define PCU_DDR_VOLTAGE 0x58a4 -+ - /* Some power MSRs are also represented in MCHBAR */ - #define MCH_PKG_POWER_LIMIT_LO 0x59a0 - #define MCH_PKG_POWER_LIMIT_HI 0x59a4 -@@ -48,6 +139,8 @@ - #define MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL 0x909 - #define MAILBOX_BIOS_CMD_READ_PCH_POWER 0xa - #define MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT 0xb -+#define MAILBOX_BIOS_CMD_READ_DDR_2X_REFRESH 0x17 -+#define MAILBOX_BIOS_CMD_WRITE_DDR_2X_REFRESH 0x18 - #define MAILBOX_BIOS_CMD_READ_C9C10_VOLTAGE 0x26 - #define MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE 0x27 - -@@ -66,6 +159,7 @@ - #define MC_BIOS_REQ 0x5e00 /* Memory frequency request register */ - #define MC_BIOS_DATA 0x5e04 /* Miscellaneous information for BIOS */ - #define SAPMCTL 0x5f00 -+#define M_COMP 0x5f08 - - #define HDAUDRID 0x6008 - #define UMAGFXCTL 0x6020 --- -2.39.5 - diff --git a/config/coreboot/default/patches/0032-lenovo-Add-Kconfig-option-CONFIG_LENOVO_TBFW_BIN.patch b/config/coreboot/default/patches/0032-lenovo-Add-Kconfig-option-CONFIG_LENOVO_TBFW_BIN.patch new file mode 100644 index 00000000..e60c102f --- /dev/null +++ b/config/coreboot/default/patches/0032-lenovo-Add-Kconfig-option-CONFIG_LENOVO_TBFW_BIN.patch @@ -0,0 +1,78 @@ +From 5d8930edfa1d9537ba80e24c0cf8f0c9e4e9ec72 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <info@minifree.org> +Date: Wed, 18 Dec 2024 02:06:18 +0000 +Subject: [PATCH 32/37] lenovo: Add Kconfig option CONFIG_LENOVO_TBFW_BIN + +This is used by lbmk to know where a tb.bin file goes, +when extracting and padding TBT.bin from Lenovo ThunderBolt +firmware updates on T480/T480s and other machines, grabbing +Lenovo update files. + +Not used in any builds, so it's not relevant for ./mk inject + +However, the ThunderBolt firmware is now auto-downloaded on +T480/T480s. This is not inserted, because it doesn't go in +the main flash, but the resulting ROM image can be flashed +on the TB controller's separate flash chip. + +Locations are as follows: + +vendorfiles/t480s/tb.bin +vendorfiles/t480/tb.bin + +This can be used for other affected ThinkPads when they're +added to Libreboot, but note that Lenovo provides different +TB firmware files for each machine. + +Since I assume it's the same TB controller on all of those +machines, I have to wonder: what difference is there between +the various TBT.bin files provided by Lenovo, and how do they +differ in terms of actual flashed configuration? + +We simply flash the padded TBT.bin when updating the firmware, +flashing externally. That's what this patch is for, so that +lbmk can auto-download them. + +Signed-off-by: Leah Rowe <info@minifree.org> +--- + src/mainboard/lenovo/Kconfig | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/src/mainboard/lenovo/Kconfig b/src/mainboard/lenovo/Kconfig +index 2ffbaab85f..512b326381 100644 +--- a/src/mainboard/lenovo/Kconfig ++++ b/src/mainboard/lenovo/Kconfig +@@ -18,4 +18,30 @@ config MAINBOARD_FAMILY + string + default MAINBOARD_PART_NUMBER + ++config LENOVO_TBFW_BIN ++ string "Lenovo ThunderBolt firmware bin file" ++ default "" ++ help ++ ThunderBolt firmware for certain ThinkPad models e.g. T480. ++ Not used in the actual build. Libreboot's build system uses this ++ along with config/vendor/*/pkg.cfg entries defining a URL to the ++ Lenovo download link and hash. The resulting file when processed by ++ lbmk can be flashed to the ThunderBolt firmware's 25XX NOR device. ++ Earlier versions of this firmware had debug commands enabled that ++ sent logs to said flash IC, and it would quickly fill up, bricking ++ the ThunderBolt controller. With these updates, flashed externally, ++ you can fix the issue if present or otherwise prevent it. The benefit ++ here is that you then don't need to use Windows or a boot disk. You ++ can flash the TB firmware while flashing Libreboot firmware. Easy! ++ Look for these variables in lbmk: ++ TBFW_url TBFW_url_bkup TBFW_hash and look at how it handles that and ++ CONFIG_LENOVO_TBFW_BIN, in lbmk's include/vendor.sh file. ++ The path set by CONFIG_LENOVO_TBFW_BIN is used by lbmk when extracting ++ the firmware, putting it at that desired location. In this way, lbmk ++ can auto-download such firmware. E.g. ./mk -d coreboot t480_fsp_16mb ++ and it appears at vendorfiles/t480/tb.bin fully padded and everything! ++ ++ Just leave this blank if you don't care about this option. It's not ++ useful for every ThinkPad, only certain models. ++ + endif # VENDOR_LENOVO +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0033-haswell-NRI-Add-timings-refresh-programming.patch b/config/coreboot/default/patches/0033-haswell-NRI-Add-timings-refresh-programming.patch deleted file mode 100644 index 3ec3b57b..00000000 --- a/config/coreboot/default/patches/0033-haswell-NRI-Add-timings-refresh-programming.patch +++ /dev/null @@ -1,541 +0,0 @@ -From 8f94c0428eea2145a97de943b093dee29001c4f9 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sat, 7 May 2022 20:59:58 +0200 -Subject: [PATCH 33/51] haswell NRI: Add timings/refresh programming - -Program the registers with timing and refresh parameters. - -Change-Id: Id2ea339d2c9ea8b56c71d6e88ec76949653ff5c2 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../haswell/native_raminit/lookup_timings.c | 102 ++++++++ - .../haswell/native_raminit/raminit_native.h | 14 ++ - .../haswell/native_raminit/reg_structs.h | 93 +++++++ - .../haswell/native_raminit/timings_refresh.c | 233 +++++++++++++++++- - .../intel/haswell/registers/mchbar.h | 12 + - 5 files changed, 452 insertions(+), 2 deletions(-) - -diff --git a/src/northbridge/intel/haswell/native_raminit/lookup_timings.c b/src/northbridge/intel/haswell/native_raminit/lookup_timings.c -index 8b81c7c341..b8d6c1ef40 100644 ---- a/src/northbridge/intel/haswell/native_raminit/lookup_timings.c -+++ b/src/northbridge/intel/haswell/native_raminit/lookup_timings.c -@@ -60,3 +60,105 @@ uint32_t get_tXP(const uint32_t mem_clock_mhz) - }; - return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); - } -+ -+static uint32_t get_lpddr_tCKE(const uint32_t mem_clock_mhz) -+{ -+ const struct timing_lookup lut[] = { -+ { 533, 4 }, -+ { 666, 5 }, -+ { fmax, 6 }, -+ }; -+ return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); -+} -+ -+static uint32_t get_ddr_tCKE(const uint32_t mem_clock_mhz) -+{ -+ const struct timing_lookup lut[] = { -+ { 533, 3 }, -+ { 800, 4 }, -+ { 933, 5 }, -+ { 1200, 6 }, -+ { fmax, 7 }, -+ }; -+ return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); -+} -+ -+uint32_t get_tCKE(const uint32_t mem_clock_mhz, const bool lpddr) -+{ -+ return lpddr ? get_lpddr_tCKE(mem_clock_mhz) : get_ddr_tCKE(mem_clock_mhz); -+} -+ -+uint32_t get_tXPDLL(const uint32_t mem_clock_mhz) -+{ -+ const struct timing_lookup lut[] = { -+ { 400, 10 }, -+ { 533, 13 }, -+ { 666, 16 }, -+ { 800, 20 }, -+ { 933, 23 }, -+ { 1066, 26 }, -+ { 1200, 29 }, -+ { fmax, 32 }, -+ }; -+ return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); -+} -+ -+uint32_t get_tAONPD(const uint32_t mem_clock_mhz) -+{ -+ const struct timing_lookup lut[] = { -+ { 400, 4 }, -+ { 533, 5 }, -+ { 666, 6 }, -+ { 800, 7 }, /* SNB had 8 */ -+ { 933, 8 }, -+ { 1066, 10 }, -+ { 1200, 11 }, -+ { fmax, 12 }, -+ }; -+ return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); -+} -+ -+uint32_t get_tMOD(const uint32_t mem_clock_mhz) -+{ -+ const struct timing_lookup lut[] = { -+ { 800, 12 }, -+ { 933, 14 }, -+ { 1066, 16 }, -+ { 1200, 18 }, -+ { fmax, 20 }, -+ }; -+ return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); -+} -+ -+uint32_t get_tXS_offset(const uint32_t mem_clock_mhz) -+{ -+ return DIV_ROUND_UP(mem_clock_mhz, 100); -+} -+ -+static uint32_t get_lpddr_tZQOPER(const uint32_t mem_clock_mhz) -+{ -+ return (mem_clock_mhz * 360) / 1000; -+} -+ -+static uint32_t get_ddr_tZQOPER(const uint32_t mem_clock_mhz) -+{ -+ const struct timing_lookup lut[] = { -+ { 800, 256 }, -+ { 933, 299 }, -+ { 1066, 342 }, -+ { 1200, 384 }, -+ { fmax, 427 }, -+ }; -+ return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut)); -+} -+ -+/* tZQOPER defines the period required for ZQCL after SR exit */ -+uint32_t get_tZQOPER(const uint32_t mem_clock_mhz, const bool lpddr) -+{ -+ return lpddr ? get_lpddr_tZQOPER(mem_clock_mhz) : get_ddr_tZQOPER(mem_clock_mhz); -+} -+ -+uint32_t get_tZQCS(const uint32_t mem_clock_mhz, const bool lpddr) -+{ -+ return DIV_ROUND_UP(get_tZQOPER(mem_clock_mhz, lpddr), 4); -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index fffa6d5450..5915a2bab0 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -156,6 +156,12 @@ struct sysinfo { - uint8_t cke_cmd_pi_code[NUM_CHANNELS][NUM_GROUPS]; - uint8_t cmd_north_pi_code[NUM_CHANNELS][NUM_GROUPS]; - uint8_t cmd_south_pi_code[NUM_CHANNELS][NUM_GROUPS]; -+ -+ union tc_bank_reg tc_bank[NUM_CHANNELS]; -+ union tc_bank_rank_a_reg tc_bankrank_a[NUM_CHANNELS]; -+ union tc_bank_rank_b_reg tc_bankrank_b[NUM_CHANNELS]; -+ union tc_bank_rank_c_reg tc_bankrank_c[NUM_CHANNELS]; -+ union tc_bank_rank_d_reg tc_bankrank_d[NUM_CHANNELS]; - }; - - static inline bool is_hsw_ult(void) -@@ -201,6 +207,14 @@ enum raminit_status configure_mc(struct sysinfo *ctrl); - void configure_timings(struct sysinfo *ctrl); - void configure_refresh(struct sysinfo *ctrl); - -+uint32_t get_tCKE(uint32_t mem_clock_mhz, bool lpddr); -+uint32_t get_tXPDLL(uint32_t mem_clock_mhz); -+uint32_t get_tAONPD(uint32_t mem_clock_mhz); -+uint32_t get_tMOD(uint32_t mem_clock_mhz); -+uint32_t get_tXS_offset(uint32_t mem_clock_mhz); -+uint32_t get_tZQOPER(uint32_t mem_clock_mhz, bool lpddr); -+uint32_t get_tZQCS(uint32_t mem_clock_mhz, bool lpddr); -+ - enum raminit_status wait_for_first_rcomp(void); - - uint8_t get_rx_bias(const struct sysinfo *ctrl); -diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -index d11cda4b3d..70487e1640 100644 ---- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h -+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -@@ -335,6 +335,99 @@ union mcscheds_cbit_reg { - uint32_t raw; - }; - -+union tc_bank_reg { -+ struct __packed { -+ uint32_t tRCD : 5; // Bits 4:0 -+ uint32_t tRP : 5; // Bits 9:5 -+ uint32_t tRAS : 6; // Bits 15:10 -+ uint32_t tRDPRE : 4; // Bits 19:16 -+ uint32_t tWRPRE : 6; // Bits 25:20 -+ uint32_t tRRD : 4; // Bits 29:26 -+ uint32_t tRPab_ext : 2; // Bits 31:30 -+ }; -+ uint32_t raw; -+}; -+ -+union tc_bank_rank_a_reg { -+ struct __packed { -+ uint32_t tCKE : 4; // Bits 3:0 -+ uint32_t tFAW : 8; // Bits 11:4 -+ uint32_t tRDRD_sr : 3; // Bits 14:12 -+ uint32_t tRDRD_dr : 4; // Bits 18:15 -+ uint32_t tRDRD_dd : 4; // Bits 22:19 -+ uint32_t tRDPDEN : 5; // Bits 27:23 -+ uint32_t : 1; // Bits 28:28 -+ uint32_t cmd_3st_dis : 1; // Bits 29:29 -+ uint32_t cmd_stretch : 2; // Bits 31:30 -+ }; -+ uint32_t raw; -+}; -+ -+union tc_bank_rank_b_reg { -+ struct __packed { -+ uint32_t tWRRD_sr : 6; // Bits 5:0 -+ uint32_t tWRRD_dr : 4; // Bits 9:6 -+ uint32_t tWRRD_dd : 4; // Bits 13:10 -+ uint32_t tWRWR_sr : 3; // Bits 16:14 -+ uint32_t tWRWR_dr : 4; // Bits 20:17 -+ uint32_t tWRWR_dd : 4; // Bits 24:21 -+ uint32_t tWRPDEN : 6; // Bits 30:25 -+ uint32_t dec_wrd : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union tc_bank_rank_c_reg { -+ struct __packed { -+ uint32_t tXPDLL : 6; // Bits 5:0 -+ uint32_t tXP : 4; // Bits 9:6 -+ uint32_t tAONPD : 4; // Bits 13:10 -+ uint32_t tRDWR_sr : 5; // Bits 18:14 -+ uint32_t tRDWR_dr : 5; // Bits 23:19 -+ uint32_t tRDWR_dd : 5; // Bits 28:24 -+ uint32_t : 3; // Bits 31:29 -+ }; -+ uint32_t raw; -+}; -+ -+/* NOTE: Non-ULT only implements the lower 21 bits (odt_write_delay is 2 bits) */ -+union tc_bank_rank_d_reg { -+ struct __packed { -+ uint32_t tAA : 5; // Bits 4:0 -+ uint32_t tCWL : 5; // Bits 9:5 -+ uint32_t tCPDED : 2; // Bits 11:10 -+ uint32_t tPRPDEN : 2; // Bits 13:12 -+ uint32_t odt_read_delay : 3; // Bits 16:14 -+ uint32_t odt_read_duration : 2; // Bits 18:17 -+ uint32_t odt_write_duration : 3; // Bits 21:19 -+ uint32_t odt_write_delay : 3; // Bits 24:22 -+ uint32_t odt_always_rank_0 : 1; // Bits 25:25 -+ uint32_t cmd_delay : 2; // Bits 27:26 -+ uint32_t : 4; // Bits 31:28 -+ }; -+ uint32_t raw; -+}; -+ -+union tc_rftp_reg { -+ struct __packed { -+ uint32_t tREFI : 16; // Bits 15:0 -+ uint32_t tRFC : 9; // Bits 24:16 -+ uint32_t tREFIx9 : 7; // Bits 31:25 -+ }; -+ uint32_t raw; -+}; -+ -+union tc_srftp_reg { -+ struct __packed { -+ uint32_t tXSDLL : 12; // Bits 11:0 -+ uint32_t tXS_offset : 4; // Bits 15:12 -+ uint32_t tZQOPER : 10; // Bits 25:16 -+ uint32_t : 2; // Bits 27:26 -+ uint32_t tMOD : 4; // Bits 31:28 -+ }; -+ uint32_t raw; -+}; -+ - union mcmain_command_rate_limit_reg { - struct __packed { - uint32_t enable_cmd_limit : 1; // Bits 0:0 -diff --git a/src/northbridge/intel/haswell/native_raminit/timings_refresh.c b/src/northbridge/intel/haswell/native_raminit/timings_refresh.c -index a9d960f31b..54fee0121d 100644 ---- a/src/northbridge/intel/haswell/native_raminit/timings_refresh.c -+++ b/src/northbridge/intel/haswell/native_raminit/timings_refresh.c -@@ -1,13 +1,242 @@ - /* SPDX-License-Identifier: GPL-2.0-or-later */ - -+#include <assert.h> -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <delay.h> -+#include <device/pci_ops.h> -+#include <northbridge/intel/haswell/haswell.h> -+ - #include "raminit_native.h" - -+#define BL 8 /* Burst length */ -+#define tCCD 4 -+#define tRPRE 1 -+#define tWPRE 1 -+#define tDLLK 512 -+ -+static bool is_sodimm(const enum spd_dimm_type_ddr3 type) -+{ -+ return type == SPD_DDR3_DIMM_TYPE_SO_DIMM || type == SPD_DDR3_DIMM_TYPE_72B_SO_UDIMM; -+} -+ -+static uint8_t get_odt_stretch(const struct sysinfo *const ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ /* Only stretch with 2 DIMMs per channel */ -+ if (ctrl->dpc[channel] != 2) -+ continue; -+ -+ const struct raminit_dimm_info *dimms = ctrl->dimms[channel]; -+ -+ /* Only stretch when using SO-DIMMs */ -+ if (!is_sodimm(dimms[0].data.dimm_type) || !is_sodimm(dimms[1].data.dimm_type)) -+ continue; -+ -+ /* Only stretch with mismatched card types */ -+ if (dimms[0].data.reference_card == dimms[1].data.reference_card) -+ continue; -+ -+ /* Stretch if one SO-DIMM is card F */ -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) { -+ if (dimms[slot].data.reference_card == 5) -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+static union tc_bank_reg make_tc_bank(struct sysinfo *const ctrl) -+{ -+ return (union tc_bank_reg) { -+ .tRCD = ctrl->tRCD, -+ .tRP = ctrl->tRP, -+ .tRAS = ctrl->tRAS, -+ .tRDPRE = ctrl->tRTP, -+ .tWRPRE = 4 + ctrl->tCWL + ctrl->tWR, -+ .tRRD = ctrl->tRRD, -+ .tRPab_ext = 0, /** TODO: For LPDDR, this is ctrl->tRPab - ctrl->tRP **/ -+ }; -+} -+ -+static union tc_bank_rank_a_reg make_tc_bankrank_a(struct sysinfo *ctrl, uint8_t odt_stretch) -+{ -+ /* Use 3N mode for DDR during training, but always use 1N mode for LPDDR */ -+ const uint32_t tCMD = ctrl->lpddr ? 0 : 3; -+ const uint32_t tRDRD_drdd = BL / 2 + 1 + tRPRE + odt_stretch + !!ctrl->lpddr; -+ -+ return (union tc_bank_rank_a_reg) { -+ .tCKE = get_tCKE(ctrl->mem_clock_mhz, ctrl->lpddr), -+ .tFAW = ctrl->tFAW, -+ .tRDRD_sr = tCCD, -+ .tRDRD_dr = tRDRD_drdd, -+ .tRDRD_dd = tRDRD_drdd, -+ .tRDPDEN = ctrl->tAA + BL / 2 + 1, -+ .cmd_3st_dis = 1, /* Disable command tri-state before training */ -+ .cmd_stretch = tCMD, -+ }; -+} -+ -+static union tc_bank_rank_b_reg make_tc_bankrank_b(struct sysinfo *const ctrl) -+{ -+ const uint8_t tWRRD_drdd = ctrl->tCWL - ctrl->tAA + BL / 2 + 2 + tRPRE; -+ const uint8_t tWRWR_drdd = BL / 2 + 2 + tWPRE; -+ -+ return (union tc_bank_rank_b_reg) { -+ .tWRRD_sr = tCCD + ctrl->tCWL + ctrl->tWTR + 2, -+ .tWRRD_dr = ctrl->lpddr ? 8 : tWRRD_drdd, -+ .tWRRD_dd = ctrl->lpddr ? 8 : tWRRD_drdd, -+ .tWRWR_sr = tCCD, -+ .tWRWR_dr = tWRWR_drdd, -+ .tWRWR_dd = tWRWR_drdd, -+ .tWRPDEN = ctrl->tWR + ctrl->tCWL + BL / 2, -+ .dec_wrd = ctrl->tCWL >= 6, -+ }; -+} -+ -+static uint32_t get_tRDWR_sr(const struct sysinfo *ctrl) -+{ -+ if (ctrl->lpddr) { -+ const uint32_t tdqsck_max = DIV_ROUND_UP(5500, ctrl->qclkps * 2); -+ return ctrl->tAA - ctrl->tCWL + tCCD + tWPRE + tdqsck_max + 1; -+ } else { -+ const bool fast_clock = ctrl->mem_clock_mhz > 666; -+ return ctrl->tAA - ctrl->tCWL + tCCD + tWPRE + 2 + fast_clock; -+ } -+} -+ -+static union tc_bank_rank_c_reg make_tc_bankrank_c(struct sysinfo *ctrl, uint8_t odt_stretch) -+{ -+ const uint32_t tRDWR_sr = get_tRDWR_sr(ctrl); -+ const uint32_t tRDWR_drdd = tRDWR_sr + odt_stretch; -+ -+ return (union tc_bank_rank_c_reg) { -+ .tXPDLL = get_tXPDLL(ctrl->mem_clock_mhz), -+ .tXP = MAX(ctrl->tXP, 7), /* Use a higher tXP for training */ -+ .tAONPD = get_tAONPD(ctrl->mem_clock_mhz), -+ .tRDWR_sr = tRDWR_sr, -+ .tRDWR_dr = tRDWR_drdd, -+ .tRDWR_dd = tRDWR_drdd, -+ }; -+} -+ -+static union tc_bank_rank_d_reg make_tc_bankrank_d(struct sysinfo *ctrl, uint8_t odt_stretch) -+{ -+ const uint32_t odt_rd_delay = ctrl->tAA - ctrl->tCWL; -+ if (!ctrl->lpddr) { -+ return (union tc_bank_rank_d_reg) { -+ .tAA = ctrl->tAA, -+ .tCWL = ctrl->tCWL, -+ .tCPDED = 1, -+ .tPRPDEN = 1, -+ .odt_read_delay = odt_rd_delay, -+ .odt_read_duration = odt_stretch, -+ }; -+ } -+ -+ /* tCWL has 1 extra clock because of tDQSS, subtract it here */ -+ const uint32_t tCWL_lpddr = ctrl->tCWL - 1; -+ const uint32_t odt_wr_delay = tCWL_lpddr + DIV_ROUND_UP(3500, ctrl->qclkps * 2); -+ const uint32_t odt_wr_duration = DIV_ROUND_UP(3500 - 1750, ctrl->qclkps * 2) + 1; -+ -+ return (union tc_bank_rank_d_reg) { -+ .tAA = ctrl->tAA, -+ .tCWL = tCWL_lpddr, -+ .tCPDED = 2, /* Required by JEDEC LPDDR3 spec */ -+ .tPRPDEN = 1, -+ .odt_read_delay = odt_rd_delay, -+ .odt_read_duration = odt_stretch, -+ .odt_write_delay = odt_wr_delay, -+ .odt_write_duration = odt_wr_duration, -+ .odt_always_rank_0 = ctrl->lpddr_dram_odt -+ }; -+} -+ -+/* ZQCS period values, in (tREFI * 128) units */ -+#define ZQCS_PERIOD_DDR3 128 /* tREFI * 128 = 7.8 us * 128 = 1ms */ -+#define ZQCS_PERIOD_LPDDR3 256 /* tREFI * 128 = 3.9 us * 128 = 0.5ms */ -+ -+static uint32_t make_tc_zqcal(const struct sysinfo *const ctrl) -+{ -+ const uint32_t zqcs_period = ctrl->lpddr ? ZQCS_PERIOD_LPDDR3 : ZQCS_PERIOD_DDR3; -+ const uint32_t tZQCS = get_tZQCS(ctrl->mem_clock_mhz, ctrl->lpddr); -+ return tZQCS << (is_hsw_ult() ? 10 : 8) | zqcs_period; -+} -+ -+static union tc_rftp_reg make_tc_rftp(const struct sysinfo *const ctrl) -+{ -+ /* -+ * The tREFIx9 field should be programmed to minimum of 8.9 * tREFI (to allow -+ * for possible delays from ZQ or isoc) and tRASmax (70us) divided by 1024. -+ */ -+ return (union tc_rftp_reg) { -+ .tREFI = ctrl->tREFI, -+ .tRFC = ctrl->tRFC, -+ .tREFIx9 = ctrl->tREFI * 89 / 10240, -+ }; -+} -+ -+static union tc_srftp_reg make_tc_srftp(const struct sysinfo *const ctrl) -+{ -+ return (union tc_srftp_reg) { -+ .tXSDLL = tDLLK, -+ .tXS_offset = get_tXS_offset(ctrl->mem_clock_mhz), -+ .tZQOPER = get_tZQOPER(ctrl->mem_clock_mhz, ctrl->lpddr), -+ .tMOD = get_tMOD(ctrl->mem_clock_mhz) - 8, -+ }; -+} -+ - void configure_timings(struct sysinfo *ctrl) - { -- /** TODO: Stub **/ -+ if (ctrl->lpddr) -+ die("%s: Missing support for LPDDR\n", __func__); -+ -+ const uint8_t odt_stretch = get_odt_stretch(ctrl); -+ const union tc_bank_reg tc_bank = make_tc_bank(ctrl); -+ const union tc_bank_rank_a_reg tc_bank_rank_a = make_tc_bankrank_a(ctrl, odt_stretch); -+ const union tc_bank_rank_b_reg tc_bank_rank_b = make_tc_bankrank_b(ctrl); -+ const union tc_bank_rank_c_reg tc_bank_rank_c = make_tc_bankrank_c(ctrl, odt_stretch); -+ const union tc_bank_rank_d_reg tc_bank_rank_d = make_tc_bankrank_d(ctrl, odt_stretch); -+ -+ const uint8_t wr_delay = tc_bank_rank_b.dec_wrd + 1; -+ uint8_t sc_wr_add_delay = 0; -+ sc_wr_add_delay |= wr_delay << 0; -+ sc_wr_add_delay |= wr_delay << 2; -+ sc_wr_add_delay |= wr_delay << 4; -+ sc_wr_add_delay |= wr_delay << 6; -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ ctrl->tc_bank[channel] = tc_bank; -+ ctrl->tc_bankrank_a[channel] = tc_bank_rank_a; -+ ctrl->tc_bankrank_b[channel] = tc_bank_rank_b; -+ ctrl->tc_bankrank_c[channel] = tc_bank_rank_c; -+ ctrl->tc_bankrank_d[channel] = tc_bank_rank_d; -+ -+ mchbar_write32(TC_BANK_ch(channel), ctrl->tc_bank[channel].raw); -+ mchbar_write32(TC_BANK_RANK_A_ch(channel), ctrl->tc_bankrank_a[channel].raw); -+ mchbar_write32(TC_BANK_RANK_B_ch(channel), ctrl->tc_bankrank_b[channel].raw); -+ mchbar_write32(TC_BANK_RANK_C_ch(channel), ctrl->tc_bankrank_c[channel].raw); -+ mchbar_write32(TC_BANK_RANK_D_ch(channel), ctrl->tc_bankrank_d[channel].raw); -+ mchbar_write8(SC_WR_ADD_DELAY_ch(channel), sc_wr_add_delay); -+ } - } - - void configure_refresh(struct sysinfo *ctrl) - { -- /** TODO: Stub **/ -+ const union tc_srftp_reg tc_srftp = make_tc_srftp(ctrl); -+ const union tc_rftp_reg tc_rftp = make_tc_rftp(ctrl); -+ const uint32_t tc_zqcal = make_tc_zqcal(ctrl); -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ mchbar_setbits32(TC_RFP_ch(channel), 0xff); -+ mchbar_write32(TC_RFTP_ch(channel), tc_rftp.raw); -+ mchbar_write32(TC_SRFTP_ch(channel), tc_srftp.raw); -+ mchbar_write32(TC_ZQCAL_ch(channel), tc_zqcal); -+ } - } -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 4c3f399b5d..2acc5cbbc8 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -86,9 +86,21 @@ - #define DDR_COMP_VSSHI_CONTROL 0x3a24 - - /* MCMAIN per-channel */ -+#define TC_BANK_ch(ch) _MCMAIN_C(0x4000, ch) -+#define TC_BANK_RANK_A_ch(ch) _MCMAIN_C(0x4004, ch) -+#define TC_BANK_RANK_B_ch(ch) _MCMAIN_C(0x4008, ch) -+#define TC_BANK_RANK_C_ch(ch) _MCMAIN_C(0x400c, ch) - #define COMMAND_RATE_LIMIT_ch(ch) _MCMAIN_C(0x4010, ch) -+#define TC_BANK_RANK_D_ch(ch) _MCMAIN_C(0x4014, ch) -+#define SC_ROUNDT_LAT_ch(ch) _MCMAIN_C(0x4024, ch) - -+#define SC_WR_ADD_DELAY_ch(ch) _MCMAIN_C(0x40d0, ch) -+ -+#define TC_ZQCAL_ch(ch) _MCMAIN_C(0x4290, ch) -+#define TC_RFP_ch(ch) _MCMAIN_C(0x4294, ch) -+#define TC_RFTP_ch(ch) _MCMAIN_C(0x4298, ch) - #define MC_INIT_STATE_ch(ch) _MCMAIN_C(0x42a0, ch) -+#define TC_SRFTP_ch(ch) _MCMAIN_C(0x42a4, ch) - - /* MCMAIN broadcast */ - #define MCSCHEDS_CBIT 0x4c20 --- -2.39.5 - diff --git a/config/coreboot/default/patches/0033-soc-intel-skylake-Don-t-compress-FSP-S.patch b/config/coreboot/default/patches/0033-soc-intel-skylake-Don-t-compress-FSP-S.patch new file mode 100644 index 00000000..a7ab5a96 --- /dev/null +++ b/config/coreboot/default/patches/0033-soc-intel-skylake-Don-t-compress-FSP-S.patch @@ -0,0 +1,36 @@ +From 49cee334bc7fe9a78b9355b5256a37984bac385a Mon Sep 17 00:00:00 2001 +From: Leah Rowe <info@minifree.org> +Date: Thu, 26 Dec 2024 19:45:20 +0000 +Subject: [PATCH 33/37] soc/intel/skylake: Don't compress FSP-S + +Build systems like lbmk need to reproducibly insert +certain vendor files on release images. + +Compression isn't always reproducible, and making it +so costs a lot more time than simply disabling compression. + +With this change, the FSP-S module will now be inserted +without compression, which means that there will now be +about 40KB of extra space used in the flash. + +Signed-off-by: Leah Rowe <info@minifree.org> +--- + src/soc/intel/skylake/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig +index 9191ed0ff8..d51ffaef7b 100644 +--- a/src/soc/intel/skylake/Kconfig ++++ b/src/soc/intel/skylake/Kconfig +@@ -12,7 +12,7 @@ config SOC_INTEL_COMMON_SKYLAKE_BASE + select CPU_SUPPORTS_PM_TIMER_EMULATION + select DRIVERS_USB_ACPI + select EDK2_CPU_TIMER_LIB if PAYLOAD_EDK2 +- select FSP_COMPRESS_FSP_S_LZ4 ++# select FSP_COMPRESS_FSP_S_LZ4 + select FSP_M_XIP + select GENERIC_GPIO_LIB + select HAVE_FSP_GOP +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0034-haswell-NRI-Program-memory-map.patch b/config/coreboot/default/patches/0034-haswell-NRI-Program-memory-map.patch deleted file mode 100644 index bb3ed03d..00000000 --- a/config/coreboot/default/patches/0034-haswell-NRI-Program-memory-map.patch +++ /dev/null @@ -1,263 +0,0 @@ -From ded914f236f76715aa43cb439a3de7df9a3dfa11 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sat, 7 May 2022 21:24:50 +0200 -Subject: [PATCH 34/51] haswell NRI: Program memory map - -This is very similar to Sandy/Ivy Bridge, except that there's several -registers to program in GDXCBAR. One of these GDXCBAR registers has a -lock bit that must be set in order for the memory controller to allow -normal access to DRAM. And it took me four months to realize this one -bit was the only reason why native raminit did not work. - -Change-Id: I3af73a018a7ba948701a542e661e7fefd57591fe -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../intel/haswell/native_raminit/memory_map.c | 183 ++++++++++++++++++ - .../haswell/native_raminit/raminit_main.c | 1 + - .../haswell/native_raminit/raminit_native.h | 1 + - .../intel/haswell/registers/host_bridge.h | 2 + - 5 files changed, 188 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/memory_map.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index fc55277a65..37d527e972 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -4,6 +4,7 @@ romstage-y += configure_mc.c - romstage-y += lookup_timings.c - romstage-y += init_mpll.c - romstage-y += io_comp_control.c -+romstage-y += memory_map.c - romstage-y += raminit_main.c - romstage-y += raminit_native.c - romstage-y += spd_bitmunching.c -diff --git a/src/northbridge/intel/haswell/native_raminit/memory_map.c b/src/northbridge/intel/haswell/native_raminit/memory_map.c -new file mode 100644 -index 0000000000..e3aded2b37 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/memory_map.c -@@ -0,0 +1,183 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <device/pci_ops.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <southbridge/intel/lynxpoint/me.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+/* GDXCBAR */ -+#define MPCOHTRK_GDXC_MOT_ADDRESS_LO 0x10 -+#define MPCOHTRK_GDXC_MOT_ADDRESS_HI 0x14 -+#define MPCOHTRK_GDXC_MOT_REGION 0x18 -+ -+#define MPCOHTRK_GDXC_OCLA_ADDRESS_LO 0x20 -+#define MPCOHTRK_GDXC_OCLA_ADDRESS_HI 0x24 -+#define MPCOHTRK_GDXC_OCLA_REGION 0x28 -+ -+/* This lock bit made me lose what little sanity I had left. - Angel Pons */ -+#define MPCOHTRK_GDXC_OCLA_ADDRESS_HI_LOCK BIT(2) -+ -+static inline uint32_t gdxcbar_read32(const uintptr_t offset) -+{ -+ return read32p((mchbar_read32(GDXCBAR) & ~1) + offset); -+} -+ -+static inline void gdxcbar_write32(const uintptr_t offset, const uint32_t value) -+{ -+ write32p((mchbar_read32(GDXCBAR) & ~1) + offset, value); -+} -+ -+static inline void gdxcbar_clrsetbits32(const uintptr_t offset, uint32_t clear, uint32_t set) -+{ -+ const uintptr_t address = (mchbar_read32(GDXCBAR) & ~1) + offset; -+ clrsetbits32((void *)address, clear, set); -+} -+ -+#define gdxcbar_setbits32(offset, set) gdxcbar_clrsetbits32(offset, 0, set) -+#define gdxcbar_clrbits32(offset, clear) gdxcbar_clrsetbits32(offset, clear, 0) -+ -+/* All values stored in here (except the bool) are specified in MiB */ -+struct memory_map_data { -+ uint32_t dpr_size; -+ uint32_t tseg_size; -+ uint32_t gtt_size; -+ uint32_t gms_size; -+ uint32_t me_stolen_size; -+ uint32_t mmio_size; -+ uint32_t touud; -+ uint32_t remaplimit; -+ uint32_t remapbase; -+ uint32_t tom; -+ uint32_t tom_minus_me; -+ uint32_t tolud; -+ uint32_t bdsm_base; -+ uint32_t gtt_base; -+ uint32_t tseg_base; -+ bool reclaim_possible; -+}; -+ -+static void compute_memory_map(struct memory_map_data *map) -+{ -+ map->tom_minus_me = map->tom - map->me_stolen_size; -+ -+ /* -+ * MMIO size will actually be slightly smaller than computed, -+ * but matches what MRC does and is more MTRR-friendly given -+ * that TSEG is treated as WB, but SMRR makes TSEG UC anyway. -+ */ -+ const uint32_t mmio_size = MIN(map->tom_minus_me, 4096) / 2; -+ map->gtt_base = ALIGN_DOWN(mmio_size, map->tseg_size); -+ map->tseg_base = map->gtt_base - map->tseg_size; -+ map->bdsm_base = map->gtt_base + map->gtt_size; -+ map->tolud = map->bdsm_base + map->gms_size; -+ map->reclaim_possible = map->tom_minus_me > map->tolud; -+ -+ if (map->reclaim_possible) { -+ map->remapbase = MAX(4096, map->tom_minus_me); -+ map->touud = MIN(4096, map->tom_minus_me) + map->remapbase - map->tolud; -+ map->remaplimit = map->touud - 1; -+ } else { -+ map->remapbase = 0; -+ map->remaplimit = 0; -+ map->touud = map->tom_minus_me; -+ } -+} -+ -+static void display_memory_map(const struct memory_map_data *map) -+{ -+ if (!CONFIG(DEBUG_RAM_SETUP)) -+ return; -+ -+ printk(BIOS_DEBUG, "============ MEMORY MAP ============\n"); -+ printk(BIOS_DEBUG, "\n"); -+ printk(BIOS_DEBUG, "dpr_size = %u MiB\n", map->dpr_size); -+ printk(BIOS_DEBUG, "tseg_size = %u MiB\n", map->tseg_size); -+ printk(BIOS_DEBUG, "gtt_size = %u MiB\n", map->gtt_size); -+ printk(BIOS_DEBUG, "gms_size = %u MiB\n", map->gms_size); -+ printk(BIOS_DEBUG, "me_stolen_size = %u MiB\n", map->me_stolen_size); -+ printk(BIOS_DEBUG, "\n"); -+ printk(BIOS_DEBUG, "touud = %u MiB\n", map->touud); -+ printk(BIOS_DEBUG, "remaplimit = %u MiB\n", map->remaplimit); -+ printk(BIOS_DEBUG, "remapbase = %u MiB\n", map->remapbase); -+ printk(BIOS_DEBUG, "tom = %u MiB\n", map->tom); -+ printk(BIOS_DEBUG, "tom_minus_me = %u MiB\n", map->tom_minus_me); -+ printk(BIOS_DEBUG, "tolud = %u MiB\n", map->tolud); -+ printk(BIOS_DEBUG, "bdsm_base = %u MiB\n", map->bdsm_base); -+ printk(BIOS_DEBUG, "gtt_base = %u MiB\n", map->gtt_base); -+ printk(BIOS_DEBUG, "tseg_base = %u MiB\n", map->tseg_base); -+ printk(BIOS_DEBUG, "\n"); -+ printk(BIOS_DEBUG, "reclaim_possible = %s\n", map->reclaim_possible ? "Yes" : "No"); -+} -+ -+static void map_write_reg64(const uint16_t reg, const uint64_t size) -+{ -+ const uint64_t value = size << 20; -+ pci_write_config32(HOST_BRIDGE, reg + 4, value >> 32); -+ pci_write_config32(HOST_BRIDGE, reg + 0, value >> 0); -+} -+ -+static void map_write_reg32(const uint16_t reg, const uint32_t size) -+{ -+ const uint32_t value = size << 20; -+ pci_write_config32(HOST_BRIDGE, reg, value); -+} -+ -+static void program_memory_map(const struct memory_map_data *map) -+{ -+ map_write_reg64(TOUUD, map->touud); -+ map_write_reg64(TOM, map->tom); -+ if (map->reclaim_possible) { -+ map_write_reg64(REMAPBASE, map->remapbase); -+ map_write_reg64(REMAPLIMIT, map->remaplimit); -+ } -+ if (map->me_stolen_size) { -+ map_write_reg64(MESEG_LIMIT, 0x80000 - map->me_stolen_size); -+ map_write_reg64(MESEG_BASE, map->tom_minus_me); -+ pci_or_config32(HOST_BRIDGE, MESEG_LIMIT, ME_STLEN_EN); -+ } -+ map_write_reg32(TOLUD, map->tolud); -+ map_write_reg32(BDSM, map->bdsm_base); -+ map_write_reg32(BGSM, map->gtt_base); -+ map_write_reg32(TSEG, map->tseg_base); -+ -+ const uint32_t dpr_reg = map->tseg_base << 20 | map->dpr_size << 4; -+ pci_write_config32(HOST_BRIDGE, DPR, dpr_reg); -+ -+ const uint16_t gfx_stolen_size = GGC_IGD_MEM_IN_32MB_UNITS(map->gms_size / 32); -+ const uint16_t ggc = map->gtt_size << 8 | gfx_stolen_size; -+ pci_write_config16(HOST_BRIDGE, GGC, ggc); -+ -+ /** TODO: Do not hardcode these? GDXC has weird alignment requirements, though. **/ -+ gdxcbar_write32(MPCOHTRK_GDXC_MOT_ADDRESS_LO, 0); -+ gdxcbar_write32(MPCOHTRK_GDXC_MOT_ADDRESS_HI, 0); -+ gdxcbar_write32(MPCOHTRK_GDXC_MOT_REGION, 0); -+ -+ gdxcbar_write32(MPCOHTRK_GDXC_OCLA_ADDRESS_LO, 0); -+ gdxcbar_write32(MPCOHTRK_GDXC_OCLA_ADDRESS_HI, 0); -+ gdxcbar_write32(MPCOHTRK_GDXC_OCLA_REGION, 0); -+ -+ gdxcbar_setbits32(MPCOHTRK_GDXC_OCLA_ADDRESS_HI, MPCOHTRK_GDXC_OCLA_ADDRESS_HI_LOCK); -+} -+ -+enum raminit_status configure_memory_map(struct sysinfo *ctrl) -+{ -+ struct memory_map_data memory_map = { -+ .tom = ctrl->channel_size_mb[0] + ctrl->channel_size_mb[1], -+ .dpr_size = CONFIG_INTEL_TXT_DPR_SIZE, -+ .tseg_size = CONFIG_SMM_TSEG_SIZE >> 20, -+ .me_stolen_size = intel_early_me_uma_size(), -+ }; -+ /** FIXME: MRC hardcodes iGPU parameters, but we should not **/ -+ const bool igpu_on = pci_read_config32(HOST_BRIDGE, DEVEN) & DEVEN_D2EN; -+ if (CONFIG(ONBOARD_VGA_IS_PRIMARY) || igpu_on) { -+ memory_map.gtt_size = 2; -+ memory_map.gms_size = 64; -+ pci_or_config32(HOST_BRIDGE, DEVEN, DEVEN_D2EN); -+ } -+ compute_memory_map(&memory_map); -+ display_memory_map(&memory_map); -+ program_memory_map(&memory_map); -+ return 0; -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index fcc981ad04..559dfc3a4e 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -23,6 +23,7 @@ static const struct task_entry cold_boot[] = { - { initialise_mpll, true, "INITMPLL", }, - { convert_timings, true, "CONVTIM", }, - { configure_mc, true, "CONFMC", }, -+ { configure_memory_map, true, "MEMMAP", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 5915a2bab0..8f937c4ccd 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -203,6 +203,7 @@ enum raminit_status collect_spd_info(struct sysinfo *ctrl); - enum raminit_status initialise_mpll(struct sysinfo *ctrl); - enum raminit_status convert_timings(struct sysinfo *ctrl); - enum raminit_status configure_mc(struct sysinfo *ctrl); -+enum raminit_status configure_memory_map(struct sysinfo *ctrl); - - void configure_timings(struct sysinfo *ctrl); - void configure_refresh(struct sysinfo *ctrl); -diff --git a/src/northbridge/intel/haswell/registers/host_bridge.h b/src/northbridge/intel/haswell/registers/host_bridge.h -index 1ee0ab2890..0228cf6bb9 100644 ---- a/src/northbridge/intel/haswell/registers/host_bridge.h -+++ b/src/northbridge/intel/haswell/registers/host_bridge.h -@@ -34,6 +34,8 @@ - - #define MESEG_BASE 0x70 /* Management Engine Base */ - #define MESEG_LIMIT 0x78 /* Management Engine Limit */ -+#define MELCK (1 << 10) /* ME Range Lock */ -+#define ME_STLEN_EN (1 << 11) /* ME Stolen Memory Enable */ - - #define PAM0 0x80 - #define PAM1 0x81 --- -2.39.5 - diff --git a/config/coreboot/default/patches/0034-soc-intel-pmc-Hardcoded-poweroff-after-power-fail.patch b/config/coreboot/default/patches/0034-soc-intel-pmc-Hardcoded-poweroff-after-power-fail.patch new file mode 100644 index 00000000..ceee75c4 --- /dev/null +++ b/config/coreboot/default/patches/0034-soc-intel-pmc-Hardcoded-poweroff-after-power-fail.patch @@ -0,0 +1,82 @@ +From 09740dc9d43a8dc24b7416b70476796515af6581 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <info@minifree.org> +Date: Tue, 31 Dec 2024 01:40:42 +0000 +Subject: [PATCH 34/37] soc/intel/pmc: Hardcoded poweroff after power fail + +Coreboot can set the power state for power on after previous +power failure, based on the option table. On the ThinkPad T480, +we have no nvram and, due to coreboot's design, we therefore +have no option table, so the default setting is enabled. + +In my testing, this seems to be that the system will turn on +after a power failure. If your ThinkPad was previously in a state +where it wouldn't turn on when plugging in the power, it'd be fine. + +If your battery ran out later on, this would be triggered and +your ThinkPad would permanently turn on, when plugging in a charger, +and there is currently no way to configure this behaviour. + +We currently only use the common SoC PMC code on the ThinkPad +T480, T480s and the Dell OptiPlex 3050 Micro, at the time of +this patch, and it is desirable that the system be set to power +off after power fail anyway. + +In some cases, you might want the opposite, for example if you're +running a server. This will be documented on the website, for that +reason. + +Signed-off-by: Leah Rowe <info@minifree.org> +--- + src/soc/intel/common/block/pmc/pmclib.c | 36 +++---------------------- + 1 file changed, 4 insertions(+), 32 deletions(-) + +diff --git a/src/soc/intel/common/block/pmc/pmclib.c b/src/soc/intel/common/block/pmc/pmclib.c +index 64b9bb997c..7823775bcb 100644 +--- a/src/soc/intel/common/block/pmc/pmclib.c ++++ b/src/soc/intel/common/block/pmc/pmclib.c +@@ -776,38 +776,10 @@ void pmc_clear_pmcon_sts(void) + + void pmc_set_power_failure_state(const bool target_on) + { +- const unsigned int state = get_uint_option("power_on_after_fail", +- CONFIG_MAINBOARD_POWER_FAILURE_STATE); +- +- /* +- * On the shutdown path (target_on == false), we only need to +- * update the register for MAINBOARD_POWER_STATE_PREVIOUS. For +- * all other cases, we don't write the register to avoid clob- +- * bering the value set on the boot path. This is necessary, +- * for instance, when we can't access the option backend in SMM. +- */ +- +- switch (state) { +- case MAINBOARD_POWER_STATE_OFF: +- if (!target_on) +- break; +- printk(BIOS_INFO, "Set power off after power failure.\n"); +- pmc_soc_set_afterg3_en(false); +- break; +- case MAINBOARD_POWER_STATE_ON: +- if (!target_on) +- break; +- printk(BIOS_INFO, "Set power on after power failure.\n"); +- pmc_soc_set_afterg3_en(true); +- break; +- case MAINBOARD_POWER_STATE_PREVIOUS: +- printk(BIOS_INFO, "Keep power state after power failure.\n"); +- pmc_soc_set_afterg3_en(target_on); +- break; +- default: +- printk(BIOS_WARNING, "Unknown power-failure state: %d\n", state); +- break; +- } ++ if (!target_on) ++ return; ++ printk(BIOS_INFO, "Set power off after power failure.\n"); ++ pmc_soc_set_afterg3_en(false); + } + + /* This function returns the highest assertion duration of the SLP_Sx assertion widths */ +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0035-haswell-NRI-Add-DDR3-JEDEC-reset-and-init.patch b/config/coreboot/default/patches/0035-haswell-NRI-Add-DDR3-JEDEC-reset-and-init.patch deleted file mode 100644 index 29bdec9f..00000000 --- a/config/coreboot/default/patches/0035-haswell-NRI-Add-DDR3-JEDEC-reset-and-init.patch +++ /dev/null @@ -1,1036 +0,0 @@ -From db2b383a8ee5a4fc45c9ce0003ae45f25ed51f86 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sat, 7 May 2022 21:49:40 +0200 -Subject: [PATCH 35/51] haswell NRI: Add DDR3 JEDEC reset and init - -Implement JEDEC reset and init sequence for DDR3. The MRS commands are -issued through the REUT (Robust Electrical Unified Testing) hardware. - -Change-Id: I2a0c066537021b587599228086727cb1e041bff5 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 3 + - .../intel/haswell/native_raminit/ddr3.c | 217 ++++++++++++++++++ - .../haswell/native_raminit/io_comp_control.c | 19 ++ - .../haswell/native_raminit/jedec_reset.c | 120 ++++++++++ - .../haswell/native_raminit/raminit_main.c | 2 + - .../haswell/native_raminit/raminit_native.h | 99 ++++++++ - .../haswell/native_raminit/reg_structs.h | 154 +++++++++++++ - .../intel/haswell/native_raminit/reut.c | 196 ++++++++++++++++ - .../intel/haswell/registers/mchbar.h | 21 ++ - src/southbridge/intel/lynxpoint/pch.h | 2 + - 10 files changed, 833 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/ddr3.c - create mode 100644 src/northbridge/intel/haswell/native_raminit/jedec_reset.c - create mode 100644 src/northbridge/intel/haswell/native_raminit/reut.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index 37d527e972..e9212df9e6 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -1,11 +1,14 @@ - ## SPDX-License-Identifier: GPL-2.0-or-later - - romstage-y += configure_mc.c -+romstage-y += ddr3.c -+romstage-y += jedec_reset.c - romstage-y += lookup_timings.c - romstage-y += init_mpll.c - romstage-y += io_comp_control.c - romstage-y += memory_map.c - romstage-y += raminit_main.c - romstage-y += raminit_native.c -+romstage-y += reut.c - romstage-y += spd_bitmunching.c - romstage-y += timings_refresh.c -diff --git a/src/northbridge/intel/haswell/native_raminit/ddr3.c b/src/northbridge/intel/haswell/native_raminit/ddr3.c -new file mode 100644 -index 0000000000..6ddb11488b ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/ddr3.c -@@ -0,0 +1,217 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <assert.h> -+#include <console/console.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+#define DDR3_RTTNOM(a, b, c) (((a) << 9) | ((b) << 6) | ((c) << 2)) -+ -+uint16_t encode_ddr3_rttnom(const uint32_t rttnom) -+{ -+ switch (rttnom) { -+ case 0: return DDR3_RTTNOM(0, 0, 0); /* RttNom is disabled */ -+ case 20: return DDR3_RTTNOM(1, 0, 0); /* RZQ/12 */ -+ case 30: return DDR3_RTTNOM(1, 0, 1); /* RZQ/8 */ -+ case 40: return DDR3_RTTNOM(0, 1, 1); /* RZQ/6 */ -+ case 60: return DDR3_RTTNOM(0, 0, 1); /* RZQ/4 */ -+ case 120: return DDR3_RTTNOM(0, 1, 0); /* RZQ/2 */ -+ } -+ printk(BIOS_ERR, "%s: Invalid rtt_nom value %u\n", __func__, rttnom); -+ return 0; -+} -+ -+static const uint8_t jedec_wr_t[12] = { 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0 }; -+ -+static void ddr3_program_mr0(struct sysinfo *ctrl, const uint8_t dll_reset) -+{ -+ assert(ctrl->tWR >= 5 && ctrl->tWR <= 16); -+ assert(ctrl->tAA >= 4); -+ const uint8_t jedec_cas = ctrl->tAA - 4; -+ const union { -+ struct __packed { -+ uint16_t burst_length : 2; // Bits 1:0 -+ uint16_t cas_latency_msb : 1; // Bits 2:2 -+ uint16_t read_burst_type : 1; // Bits 3:3 -+ uint16_t cas_latency_low : 3; // Bits 6:4 -+ uint16_t test_mode : 1; // Bits 7:7 -+ uint16_t dll_reset : 1; // Bits 8:8 -+ uint16_t write_recovery : 3; // Bits 11:9 -+ uint16_t precharge_pd_dll : 1; // Bits 12:12 -+ uint16_t : 3; // Bits 15:13 -+ }; -+ uint16_t raw; -+ } mr0reg = { -+ .burst_length = 0, -+ .cas_latency_msb = !!(jedec_cas & BIT(3)), -+ .read_burst_type = 0, -+ .cas_latency_low = jedec_cas & 0x7, -+ .dll_reset = 1, -+ .write_recovery = jedec_wr_t[ctrl->tWR - 5], -+ .precharge_pd_dll = 0, -+ }; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) { -+ if (!rank_in_ch(ctrl, slot + slot, channel)) -+ continue; -+ -+ if (!ctrl->restore_mrs) -+ ctrl->mr0[channel][slot] = mr0reg.raw; -+ } -+ reut_issue_mrs_all(ctrl, channel, 0, ctrl->mr0[channel]); -+ } -+} -+ -+void ddr3_program_mr1(struct sysinfo *ctrl, const uint8_t wl_mode, const uint8_t q_off) -+{ -+ /* -+ * JESD79-3F (JEDEC DDR3 spec) refers to bit 0 of MR1 as 'DLL Enable'. -+ * However, its encoding is weird, and 'DLL Disable' makes more sense. -+ * -+ * Moreover, bit 5 is part of ODIC (Output Driver Impedance Control), -+ * but all encodings where MR1 bit 5 is 1 are reserved. Thus, omit it. -+ */ -+ union { -+ struct __packed { -+ uint16_t dll_disable : 1; // Bits 0:0 -+ uint16_t od_impedance_ctl : 1; // Bits 1:1 -+ uint16_t odt_rtt_nom_low : 1; // Bits 2:2 -+ uint16_t additive_latency : 2; // Bits 4:3 -+ uint16_t : 1; // Bits 5:5 -+ uint16_t odt_rtt_nom_mid : 1; // Bits 6:6 -+ uint16_t write_level_mode : 1; // Bits 7:7 -+ uint16_t : 1; // Bits 8:8 -+ uint16_t odt_rtt_nom_high : 1; // Bits 9:9 -+ uint16_t : 1; // Bits 10:10 -+ uint16_t t_dqs : 1; // Bits 11:11 -+ uint16_t q_off : 1; // Bits 12:12 -+ uint16_t : 3; // Bits 15:13 -+ }; -+ uint16_t raw; -+ } mr1reg = { -+ .dll_disable = 0, -+ .od_impedance_ctl = 1, /* RZQ/7 */ -+ .additive_latency = 0, -+ .write_level_mode = wl_mode, -+ .t_dqs = 0, -+ .q_off = q_off, -+ }; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ mr1reg.raw &= ~RTTNOM_MASK; -+ mr1reg.raw |= encode_ddr3_rttnom(ctrl->dpc[channel] == 2 ? 60 : 0); -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) { -+ if (!rank_in_ch(ctrl, slot + slot, channel)) -+ continue; -+ -+ if (!ctrl->restore_mrs) -+ ctrl->mr1[channel][slot] = mr1reg.raw; -+ } -+ reut_issue_mrs_all(ctrl, channel, 1, ctrl->mr1[channel]); -+ } -+} -+ -+enum { -+ RTT_WR_OFF = 0, -+ RTT_WR_60 = 1, -+ RTT_WR_120 = 2, -+}; -+ -+static void ddr3_program_mr2(struct sysinfo *ctrl) -+{ -+ assert(ctrl->tCWL >= 5); -+ const bool dimm_srt = ctrl->flags.ext_temp_refresh && !ctrl->flags.asr; -+ -+ const union { -+ struct __packed { -+ uint16_t partial_array_sr : 3; // Bits 0:2 -+ uint16_t cas_write_latency : 3; // Bits 5:3 -+ uint16_t auto_self_refresh : 1; // Bits 6:6 -+ uint16_t self_refresh_temp : 1; // Bits 7:7 -+ uint16_t : 1; // Bits 8:8 -+ uint16_t odt_rtt_wr : 2; // Bits 10:9 -+ uint16_t : 5; // Bits 15:11 -+ }; -+ uint16_t raw; -+ } mr2reg = { -+ .partial_array_sr = 0, -+ .cas_write_latency = ctrl->tCWL - 5, -+ .auto_self_refresh = ctrl->flags.asr, -+ .self_refresh_temp = dimm_srt, -+ .odt_rtt_wr = is_hsw_ult() ? RTT_WR_120 : RTT_WR_60, -+ }; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) { -+ if (!rank_in_ch(ctrl, slot + slot, channel)) -+ continue; -+ -+ if (!ctrl->restore_mrs) -+ ctrl->mr2[channel][slot] = mr2reg.raw; -+ } -+ /* MR2 shadow register is similar but not identical to MR2 */ -+ if (!ctrl->restore_mrs) { -+ union tc_mr2_shadow_reg tc_mr2_shadow = { -+ .raw = mr2reg.raw & 0x073f, -+ }; -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) { -+ if (!rank_in_ch(ctrl, slot + slot, channel)) -+ continue; -+ -+ if (dimm_srt) -+ tc_mr2_shadow.srt_available |= BIT(slot); -+ -+ if (ctrl->rank_mirrored[channel] & BIT(slot + slot + 1)) -+ tc_mr2_shadow.addr_bit_swizzle |= BIT(slot); -+ } -+ mchbar_write32(TC_MR2_SHADOW_ch(channel), tc_mr2_shadow.raw); -+ } -+ reut_issue_mrs_all(ctrl, channel, 2, ctrl->mr2[channel]); -+ } -+} -+ -+static void ddr3_program_mr3(struct sysinfo *ctrl, const uint8_t mpr_mode) -+{ -+ const union { -+ struct __packed { -+ uint16_t mpr_loc : 2; // Bits 1:0 -+ uint16_t mpr_mode : 1; // Bits 2:2 -+ uint16_t : 13; // Bits 15:3 -+ }; -+ uint16_t raw; -+ } mr3reg = { -+ .mpr_loc = 0, -+ .mpr_mode = mpr_mode, -+ }; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) { -+ if (!rank_in_ch(ctrl, slot + slot, channel)) -+ continue; -+ -+ if (!ctrl->restore_mrs) -+ ctrl->mr3[channel][slot] = mr3reg.raw; -+ } -+ reut_issue_mrs_all(ctrl, channel, 3, ctrl->mr3[channel]); -+ } -+} -+ -+enum raminit_status ddr3_jedec_init(struct sysinfo *ctrl) -+{ -+ ddr3_program_mr2(ctrl); -+ ddr3_program_mr3(ctrl, 0); -+ ddr3_program_mr1(ctrl, 0, 0); -+ ddr3_program_mr0(ctrl, 1); -+ return reut_issue_zq(ctrl, ctrl->chanmap, ZQ_INIT); -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/io_comp_control.c b/src/northbridge/intel/haswell/native_raminit/io_comp_control.c -index d45b608dd3..8a55fd81b2 100644 ---- a/src/northbridge/intel/haswell/native_raminit/io_comp_control.c -+++ b/src/northbridge/intel/haswell/native_raminit/io_comp_control.c -@@ -8,6 +8,25 @@ - - #include "raminit_native.h" - -+enum raminit_status io_reset(void) -+{ -+ union mc_init_state_g_reg mc_init_state_g = { -+ .raw = mchbar_read32(MC_INIT_STATE_G), -+ }; -+ mc_init_state_g.reset_io = 1; -+ mchbar_write32(MC_INIT_STATE_G, mc_init_state_g.raw); -+ struct stopwatch timer; -+ stopwatch_init_msecs_expire(&timer, 2000); -+ do { -+ mc_init_state_g.raw = mchbar_read32(MC_INIT_STATE_G); -+ if (mc_init_state_g.reset_io == 0) -+ return RAMINIT_STATUS_SUCCESS; -+ -+ } while (!stopwatch_expired(&timer)); -+ printk(BIOS_ERR, "Timed out waiting for DDR I/O reset to complete\n"); -+ return RAMINIT_STATUS_POLL_TIMEOUT; -+} -+ - enum raminit_status wait_for_first_rcomp(void) - { - struct stopwatch timer; -diff --git a/src/northbridge/intel/haswell/native_raminit/jedec_reset.c b/src/northbridge/intel/haswell/native_raminit/jedec_reset.c -new file mode 100644 -index 0000000000..de0f676758 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/jedec_reset.c -@@ -0,0 +1,120 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <console/console.h> -+#include <delay.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <southbridge/intel/lynxpoint/pch.h> -+#include <types.h> -+#include <timer.h> -+ -+#include "raminit_native.h" -+ -+static void assert_reset(const bool do_reset) -+{ -+ if (is_hsw_ult()) { -+ uint32_t pm_cfg2 = RCBA32(PM_CFG2); -+ if (do_reset) -+ pm_cfg2 &= ~PM_CFG2_DRAM_RESET_CTL; -+ else -+ pm_cfg2 |= PM_CFG2_DRAM_RESET_CTL; -+ RCBA32(PM_CFG2) = pm_cfg2; -+ } else { -+ union mc_init_state_g_reg mc_init_state_g = { -+ .raw = mchbar_read32(MC_INIT_STATE_G), -+ }; -+ mc_init_state_g.ddr_not_reset = !do_reset; -+ mchbar_write32(MC_INIT_STATE_G, mc_init_state_g.raw); -+ } -+} -+ -+/* -+ * Perform JEDEC reset. -+ * -+ * If RTT_NOM is to be enabled in MR1, the ODT input signal must be -+ * statically held low in our system since RTT_NOM is always enabled. -+ */ -+static void jedec_reset(struct sysinfo *ctrl) -+{ -+ if (is_hsw_ult()) -+ assert_reset(false); -+ -+ union mc_init_state_g_reg mc_init_state_g = { -+ .ddr_not_reset = 1, -+ .safe_self_refresh = 1, -+ }; -+ mchbar_write32(MC_INIT_STATE_G, mc_init_state_g.raw); -+ -+ union reut_misc_cke_ctrl_reg reut_misc_cke_ctrl = { -+ .cke_override = 0xf, -+ .cke_on = 0, -+ }; -+ mchbar_write32(REUT_MISC_CKE_CTRL, reut_misc_cke_ctrl.raw); -+ -+ assert_reset(true); -+ -+ /** TODO: check and switch DDR3 voltage here (mainboard-specific) **/ -+ -+ udelay(200); -+ -+ assert_reset(false); -+ -+ udelay(500); -+ -+ mc_init_state_g.dclk_enable = 1; -+ mchbar_write32(MC_INIT_STATE_G, mc_init_state_g.raw); -+ -+ /* Delay at least 20 nanoseconds for tCKSRX */ -+ tick_delay(1); -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ reut_misc_cke_ctrl.cke_on = ctrl->rankmap[channel]; -+ mchbar_write32(REUT_ch_MISC_CKE_CTRL(channel), reut_misc_cke_ctrl.raw); -+ } -+ -+ /* -+ * Wait minimum of reset CKE exit time, tXPR. -+ * Spec says MAX(tXS, 5 tCK). 5 tCK is 10 ns. -+ */ -+ tick_delay(1); -+} -+ -+enum raminit_status do_jedec_init(struct sysinfo *ctrl) -+{ -+ /* Never do a JEDEC reset in S3 resume */ -+ if (ctrl->bootmode == BOOTMODE_S3) -+ return RAMINIT_STATUS_SUCCESS; -+ -+ enum raminit_status status = io_reset(); -+ if (status) -+ return status; -+ -+ status = wait_for_first_rcomp(); -+ if (status) -+ return status; -+ -+ /* Force ODT low (JEDEC spec) */ -+ const union reut_misc_odt_ctrl_reg reut_misc_odt_ctrl = { -+ .odt_override = 0xf, -+ .odt_on = 0, -+ }; -+ mchbar_write32(REUT_MISC_ODT_CTRL, reut_misc_odt_ctrl.raw); -+ -+ /* -+ * Note: Haswell MRC does not clear ODT override for LPDDR3. However, -+ * Broadwell MRC does. Hell suspects this difference is important, as -+ * there is an erratum in the specification update for Broadwell: -+ * -+ * Erratum BDM74: LPDDR3 Memory Training May Cause Platform Boot Failure -+ */ -+ if (ctrl->lpddr) -+ die("%s: LPDDR-specific JEDEC init not implemented\n", __func__); -+ -+ jedec_reset(ctrl); -+ status = ddr3_jedec_init(ctrl); -+ if (!status) -+ ctrl->restore_mrs = true; -+ -+ /* Release ODT override */ -+ mchbar_write32(REUT_MISC_ODT_CTRL, 0); -+ return status; -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 559dfc3a4e..94b268468c 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -24,6 +24,7 @@ static const struct task_entry cold_boot[] = { - { convert_timings, true, "CONVTIM", }, - { configure_mc, true, "CONFMC", }, - { configure_memory_map, true, "MEMMAP", }, -+ { do_jedec_init, true, "JEDECINIT", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -@@ -57,6 +58,7 @@ static void initialize_ctrl(struct sysinfo *ctrl) - ctrl->stepping = get_stepping(ctrl->cpu); - ctrl->vdd_mv = is_hsw_ult() ? 1350 : 1500; /** FIXME: Hardcoded, does it matter? **/ - ctrl->dq_pins_interleaved = cfg->dq_pins_interleaved; -+ ctrl->restore_mrs = false; - ctrl->bootmode = bootmode; - } - -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 8f937c4ccd..759d755d6d 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -28,6 +28,30 @@ - /* Always use 12 legs for emphasis (not trained) */ - #define TXEQFULLDRV (3 << 4) - -+/* DDR3 mode register bits */ -+#define MR0_DLL_RESET BIT(8) -+ -+#define MR1_WL_ENABLE BIT(7) -+#define MR1_QOFF_ENABLE BIT(12) /* If set, output buffers disabled */ -+ -+#define RTTNOM_MASK (BIT(9) | BIT(6) | BIT(2)) -+ -+/* ZQ calibration types */ -+enum { -+ ZQ_INIT, /* DDR3: ZQCL with tZQinit, LPDDR3: ZQ Init with tZQinit */ -+ ZQ_LONG, /* DDR3: ZQCL with tZQoper, LPDDR3: ZQ Long with tZQCL */ -+ ZQ_SHORT, /* DDR3: ZQCS with tZQCS, LPDDR3: ZQ Short with tZQCS */ -+ ZQ_RESET, /* DDR3: not used, LPDDR3: ZQ Reset with tZQreset */ -+}; -+ -+/* REUT initialisation modes */ -+enum { -+ REUT_MODE_IDLE = 0, -+ REUT_MODE_TEST = 1, -+ REUT_MODE_MRS = 2, -+ REUT_MODE_NOP = 3, /* Normal operation mode */ -+}; -+ - enum command_training_iteration { - CT_ITERATION_CLOCK = 0, - CT_ITERATION_CMD_NORTH, -@@ -51,6 +75,7 @@ enum raminit_status { - RAMINIT_STATUS_UNSUPPORTED_MEMORY, - RAMINIT_STATUS_MPLL_INIT_FAILURE, - RAMINIT_STATUS_POLL_TIMEOUT, -+ RAMINIT_STATUS_REUT_ERROR, - RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/ - }; - -@@ -73,6 +98,7 @@ struct sysinfo { - uint32_t cpu; /* CPUID value */ - - bool dq_pins_interleaved; -+ bool restore_mrs; - - /** TODO: ECC support untested **/ - bool is_ecc; -@@ -162,6 +188,11 @@ struct sysinfo { - union tc_bank_rank_b_reg tc_bankrank_b[NUM_CHANNELS]; - union tc_bank_rank_c_reg tc_bankrank_c[NUM_CHANNELS]; - union tc_bank_rank_d_reg tc_bankrank_d[NUM_CHANNELS]; -+ -+ uint16_t mr0[NUM_CHANNELS][NUM_SLOTS]; -+ uint16_t mr1[NUM_CHANNELS][NUM_SLOTS]; -+ uint16_t mr2[NUM_CHANNELS][NUM_SLOTS]; -+ uint16_t mr3[NUM_CHANNELS][NUM_SLOTS]; - }; - - static inline bool is_hsw_ult(void) -@@ -197,6 +228,53 @@ static inline void clear_data_offset_train_all(struct sysinfo *ctrl) - memset(ctrl->data_offset_train, 0, sizeof(ctrl->data_offset_train)); - } - -+/* Number of ticks to wait in units of 69.841279 ns (citation needed) */ -+static inline void tick_delay(const uint32_t delay) -+{ -+ /* Just perform reads to a random register */ -+ for (uint32_t start = 0; start <= delay; start++) -+ mchbar_read32(REUT_ERR_DATA_STATUS); -+} -+ -+/* -+ * 64-bit MCHBAR registers need to be accessed atomically. If one uses -+ * two 32-bit ops instead, there will be problems with the REUT's CADB -+ * (Command Address Data Buffer): hardware automatically advances the -+ * pointer into the register file after a write to the input register. -+ */ -+static inline uint64_t mchbar_read64(const uintptr_t x) -+{ -+ const uint64_t *offset = (uint64_t *)(CONFIG_FIXED_MCHBAR_MMIO_BASE + x); -+ uint64_t mmxsave, v; -+ asm volatile ( -+ "\n\t movq %%mm0, %0" -+ "\n\t movq %2, %%mm0" -+ "\n\t movq %%mm0, %1" -+ "\n\t movq %3, %%mm0" -+ "\n\t emms" -+ : "=m"(mmxsave), -+ "=m"(v) -+ : "m"(offset[0]), -+ "m"(mmxsave)); -+ return v; -+} -+ -+static inline void mchbar_write64(const uintptr_t x, const uint64_t v) -+{ -+ const uint64_t *offset = (uint64_t *)(CONFIG_FIXED_MCHBAR_MMIO_BASE + x); -+ uint64_t mmxsave; -+ asm volatile ( -+ "\n\t movq %%mm0, %0" -+ "\n\t movq %2, %%mm0" -+ "\n\t movq %%mm0, %1" -+ "\n\t movq %3, %%mm0" -+ "\n\t emms" -+ : "=m"(mmxsave) -+ : "m"(offset[0]), -+ "m"(v), -+ "m"(mmxsave)); -+} -+ - void raminit_main(enum raminit_boot_mode bootmode); - - enum raminit_status collect_spd_info(struct sysinfo *ctrl); -@@ -204,6 +282,7 @@ enum raminit_status initialise_mpll(struct sysinfo *ctrl); - enum raminit_status convert_timings(struct sysinfo *ctrl); - enum raminit_status configure_mc(struct sysinfo *ctrl); - enum raminit_status configure_memory_map(struct sysinfo *ctrl); -+enum raminit_status do_jedec_init(struct sysinfo *ctrl); - - void configure_timings(struct sysinfo *ctrl); - void configure_refresh(struct sysinfo *ctrl); -@@ -216,8 +295,28 @@ uint32_t get_tXS_offset(uint32_t mem_clock_mhz); - uint32_t get_tZQOPER(uint32_t mem_clock_mhz, bool lpddr); - uint32_t get_tZQCS(uint32_t mem_clock_mhz, bool lpddr); - -+enum raminit_status io_reset(void); - enum raminit_status wait_for_first_rcomp(void); - -+uint16_t encode_ddr3_rttnom(uint32_t rttnom); -+void ddr3_program_mr1(struct sysinfo *ctrl, uint8_t wl_mode, uint8_t q_off); -+enum raminit_status ddr3_jedec_init(struct sysinfo *ctrl); -+ -+void reut_issue_mrs( -+ struct sysinfo *ctrl, -+ uint8_t channel, -+ uint8_t rankmask, -+ uint8_t mr, -+ uint16_t val); -+ -+void reut_issue_mrs_all( -+ struct sysinfo *ctrl, -+ uint8_t channel, -+ uint8_t mr, -+ const uint16_t val[NUM_SLOTS]); -+ -+enum raminit_status reut_issue_zq(struct sysinfo *ctrl, uint8_t chanmask, uint8_t zq_type); -+ - uint8_t get_rx_bias(const struct sysinfo *ctrl); - - uint8_t get_tCWL(uint32_t mem_clock_mhz); -diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -index 70487e1640..9929f617fe 100644 ---- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h -+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -@@ -335,6 +335,127 @@ union mcscheds_cbit_reg { - uint32_t raw; - }; - -+union reut_pat_cadb_prog_reg { -+ struct __packed { -+ uint32_t addr : 16; // Bits 15:0 -+ uint32_t : 8; // Bits 23:16 -+ uint32_t bank : 3; // Bits 26:24 -+ uint32_t : 5; // Bits 31:27 -+ uint32_t cs : 4; // Bits 35:32 -+ uint32_t : 4; // Bits 39:36 -+ uint32_t cmd : 3; // Bits 42:40 -+ uint32_t : 5; // Bits 47:43 -+ uint32_t odt : 4; // Bits 51:48 -+ uint32_t : 4; // Bits 55:52 -+ uint32_t cke : 4; // Bits 59:56 -+ uint32_t : 4; // Bits 63:60 -+ }; -+ uint64_t raw; -+ uint32_t raw32[2]; -+}; -+ -+union reut_pat_cadb_mrs_reg { -+ struct __packed { -+ uint32_t delay_gap : 3; // Bits 2:0 -+ uint32_t : 5; // Bits 7:3 -+ uint32_t start_ptr : 3; // Bits 10:8 -+ uint32_t : 5; // Bits 15:11 -+ uint32_t end_ptr : 3; // Bits 18:16 -+ uint32_t : 5; // Bits 23:19 -+ uint32_t curr_ptr : 3; // Bits 26:24 -+ uint32_t : 5; // Bits 31:27 -+ }; -+ uint32_t raw; -+}; -+ -+union reut_seq_cfg_reg { -+ struct __packed { -+ uint32_t : 3; // Bits 2:0 -+ uint32_t stop_base_seq_on_wrap_trigger : 1; // Bits 3:3 -+ uint32_t : 1; // Bits 4:4 -+ uint32_t address_update_rate_mode : 1; // Bits 5:5 -+ uint32_t : 1; // Bits 6:6 -+ uint32_t enable_dummy_reads : 1; // Bits 7:7 -+ uint32_t : 2; // Bits 9:8 -+ uint32_t enable_constant_write_strobe : 1; // Bits 10:10 -+ uint32_t global_control : 1; // Bits 11:11 -+ uint32_t initialization_mode : 2; // Bits 13:12 -+ uint32_t : 2; // Bits 15:14 -+ uint32_t early_steppings_loop_count : 5; // Bits 20:16 *** Not on C0 *** -+ uint32_t : 3; // Bits 23:21 -+ uint32_t subsequence_start_pointer : 3; // Bits 26:24 -+ uint32_t : 1; // Bits 27:27 -+ uint32_t subsequence_end_pointer : 3; // Bits 30:28 -+ uint32_t : 1; // Bits 31:31 -+ uint32_t start_test_delay : 10; // Bits 41:32 -+ uint32_t : 22; // Bits 63:42 -+ }; -+ uint64_t raw; -+ uint32_t raw32[2]; -+}; -+ -+union reut_seq_ctl_reg { -+ struct __packed { -+ uint32_t start_test : 1; // Bits 0:0 -+ uint32_t stop_test : 1; // Bits 1:1 -+ uint32_t clear_errors : 1; // Bits 2:2 -+ uint32_t : 1; // Bits 3:3 -+ uint32_t stop_on_error : 1; // Bits 4:4 -+ uint32_t : 27; // Bits 31:5 -+ }; -+ uint32_t raw; -+}; -+ -+union reut_global_err_reg { -+ struct __packed { -+ uint32_t ch_error : 2; // Bits 1:0 -+ uint32_t : 14; // Bits 15:2 -+ uint32_t ch_test_done : 2; // Bits 17:16 -+ uint32_t : 14; // Bits 31:18 -+ }; -+ uint32_t raw; -+}; -+ -+union reut_misc_cke_ctrl_reg { -+ struct __packed { -+ uint32_t cke_override : 4; // Bits 3:0 -+ uint32_t : 4; // Bits 7:4 -+ uint32_t cke_en_start_test_sync : 1; // Bits 8:8 -+ uint32_t : 7; // Bits 15:9 -+ uint32_t cke_on : 4; // Bits 19:16 -+ uint32_t : 12; // Bits 31:20 -+ }; -+ uint32_t raw; -+}; -+ -+union reut_misc_odt_ctrl_reg { -+ struct __packed { -+ uint32_t odt_override : 4; // Bits 3:0 -+ uint32_t : 12; // Bits 15:4 -+ uint32_t odt_on : 4; // Bits 19:16 -+ uint32_t : 11; // Bits 30:20 -+ uint32_t mpr_train_ddr_on : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union mcscheds_dft_misc_reg { -+ struct __packed { -+ uint32_t wdar : 1; // Bits 0:0 -+ uint32_t safe_mask_sel : 3; // Bits 3:1 -+ uint32_t force_rcv_en : 1; // Bits 4:4 -+ uint32_t : 3; // Bits 7:5 -+ uint32_t ddr_qualifier : 2; // Bits 9:8 -+ uint32_t qualifier_length : 2; // Bits 11:10 -+ uint32_t wdb_block_en : 1; // Bits 12:12 -+ uint32_t rt_dft_read_ptr : 4; // Bits 16:13 -+ uint32_t rt_dft_read_enable : 1; // Bits 17:17 -+ uint32_t rt_dft_read_sel_addr : 1; // Bits 18:18 -+ uint32_t : 13; // Bits 31:19 -+ }; -+ uint32_t raw; -+}; -+ - union tc_bank_reg { - struct __packed { - uint32_t tRCD : 5; // Bits 4:0 -@@ -428,6 +549,18 @@ union tc_srftp_reg { - uint32_t raw; - }; - -+union tc_mr2_shadow_reg { -+ struct __packed { -+ uint32_t mr2_shadow_low : 6; // Bits 5:0 -+ uint32_t srt_available : 2; // Bits 7:6 -+ uint32_t mr2_shadow_high : 3; // Bits 10:8 -+ uint32_t : 3; // Bits 13:11 -+ uint32_t addr_bit_swizzle : 2; // Bits 15:14 -+ uint32_t : 16; // Bits 31:16 -+ }; -+ uint32_t raw; -+}; -+ - union mcmain_command_rate_limit_reg { - struct __packed { - uint32_t enable_cmd_limit : 1; // Bits 0:0 -@@ -483,6 +616,27 @@ union mad_zr_reg { - uint32_t raw; - }; - -+union mc_init_state_g_reg { -+ struct __packed { -+ uint32_t pu_mrc_done : 1; // Bits 0:0 -+ uint32_t ddr_not_reset : 1; // Bits 1:1 -+ uint32_t : 1; // Bits 2:2 -+ uint32_t refresh_enable : 1; // Bits 3:3 -+ uint32_t : 1; // Bits 4:4 -+ uint32_t mc_init_done_ack : 1; // Bits 5:5 -+ uint32_t : 1; // Bits 6:6 -+ uint32_t mrc_done : 1; // Bits 7:7 -+ uint32_t safe_self_refresh : 1; // Bits 8:8 -+ uint32_t : 1; // Bits 9:9 -+ uint32_t hvm_gate_ddr_reset : 1; // Bits 10:10 -+ uint32_t : 11; // Bits 21:11 -+ uint32_t dclk_enable : 1; // Bits 22:22 -+ uint32_t reset_io : 1; // Bits 23:23 -+ uint32_t : 8; // Bits 31:24 -+ }; -+ uint32_t raw; -+}; -+ - /* Same definition for P_COMP, M_COMP, D_COMP */ - union pcu_comp_reg { - struct __packed { -diff --git a/src/northbridge/intel/haswell/native_raminit/reut.c b/src/northbridge/intel/haswell/native_raminit/reut.c -new file mode 100644 -index 0000000000..31019f74a1 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/reut.c -@@ -0,0 +1,196 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <console/console.h> -+#include <delay.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <timer.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+enum { -+ CADB_CMD_MRS = 0, -+ CADB_CMD_REF = 1, -+ CADB_CMD_PRE = 2, -+ CADB_CMD_ACT = 3, -+ CADB_CMD_WR = 4, -+ CADB_CMD_RD = 5, -+ CADB_CMD_ZQ = 6, -+ CADB_CMD_NOP = 7, -+}; -+ -+/* -+ * DDR3 rank mirror swaps the following pins: A3<->A4, A5<->A6, A7<->A8, BA0<->BA1 -+ * -+ * Note that the swapped bits are contiguous. We can use some XOR magic to swap the bits. -+ * Address lanes are at bits 0..15 and bank selects are at bits 24..26 on the REUT register. -+ */ -+#define MIRROR_BITS (BIT(24) | BIT(7) | BIT(5) | BIT(3)) -+static uint64_t cadb_prog_rank_mirror(const uint64_t cadb_prog) -+{ -+ /* First XOR: find which pairs of bits are different (need swapping) */ -+ const uint64_t tmp64 = (cadb_prog ^ (cadb_prog >> 1)) & MIRROR_BITS; -+ -+ /* Second XOR: invert the pairs of bits that have different values */ -+ return cadb_prog ^ (tmp64 | tmp64 << 1); -+} -+ -+static enum raminit_status reut_write_cadb_cmd( -+ struct sysinfo *ctrl, -+ const uint8_t channel, -+ const uint8_t rankmask, -+ const uint8_t cmd, -+ const uint8_t bank, -+ const uint16_t valarr[NUM_SLOTRANKS], -+ const uint8_t delay) -+{ -+ union mcscheds_dft_misc_reg dft_misc = { -+ .raw = mchbar_read32(MCSCHEDS_DFT_MISC), -+ }; -+ dft_misc.ddr_qualifier = 0; -+ mchbar_write32(MCSCHEDS_DFT_MISC, dft_misc.raw); -+ -+ /* Pointer will be dynamically incremented after a write to CADB_PROG register */ -+ mchbar_write8(REUT_ch_PAT_CADB_WRITE_PTR(channel), 0); -+ -+ uint8_t count = 0; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!(ctrl->rankmap[channel] & BIT(rank) & rankmask)) -+ continue; -+ -+ union reut_pat_cadb_prog_reg reut_cadb_prog = { -+ .addr = valarr[rank], -+ .bank = bank, -+ .cs = ~BIT(rank), /* CS is active low */ -+ .cmd = cmd, -+ .cke = 0xf, -+ }; -+ if (ctrl->rank_mirrored[channel] & BIT(rank)) -+ reut_cadb_prog.raw = cadb_prog_rank_mirror(reut_cadb_prog.raw); -+ -+ mchbar_write64(REUT_ch_PAT_CADB_PROG(channel), reut_cadb_prog.raw); -+ count++; -+ } -+ if (!count) { -+ printk(BIOS_ERR, "%s: rankmask is invalid\n", __func__); -+ return RAMINIT_STATUS_UNSPECIFIED_ERROR; /** FIXME: Is this needed? **/ -+ } -+ const union reut_pat_cadb_mrs_reg reut_cadb_mrs = { -+ .delay_gap = delay ? delay : 3, -+ .end_ptr = count - 1, -+ }; -+ mchbar_write32(REUT_ch_PAT_CADB_MRS(channel), reut_cadb_mrs.raw); -+ -+ const uint32_t reut_seq_cfg_save = mchbar_read32(REUT_ch_SEQ_CFG(channel)); -+ union reut_seq_cfg_reg reut_seq_cfg = { -+ .raw = reut_seq_cfg_save, -+ }; -+ reut_seq_cfg.global_control = 0; -+ reut_seq_cfg.initialization_mode = REUT_MODE_MRS; -+ mchbar_write32(REUT_ch_SEQ_CFG(channel), reut_seq_cfg.raw); -+ mchbar_write32(REUT_ch_SEQ_CTL(channel), (union reut_seq_ctl_reg) { -+ .start_test = 1, -+ .clear_errors = 1, -+ }.raw); -+ enum raminit_status status = RAMINIT_STATUS_SUCCESS; -+ union reut_global_err_reg reut_global_err; -+ struct stopwatch timer; -+ stopwatch_init_msecs_expire(&timer, 100); -+ do { -+ reut_global_err.raw = mchbar_read32(REUT_GLOBAL_ERR); -+ if (reut_global_err.ch_error & BIT(channel)) { -+ printk(BIOS_ERR, "Unexpected REUT error for channel %u\n", channel); -+ status = RAMINIT_STATUS_REUT_ERROR; -+ break; -+ } -+ if (stopwatch_expired(&timer)) { -+ printk(BIOS_ERR, "%s: REUT timed out!\n", __func__); -+ status = RAMINIT_STATUS_POLL_TIMEOUT; -+ break; -+ } -+ } while (!(reut_global_err.ch_test_done & BIT(channel))); -+ mchbar_write32(REUT_ch_SEQ_CTL(channel), (union reut_seq_ctl_reg) { -+ .clear_errors = 1, -+ }.raw); -+ mchbar_write32(REUT_ch_SEQ_CFG(channel), reut_seq_cfg_save); -+ return status; -+} -+ -+static enum raminit_status reut_write_cadb_cmd_all( -+ struct sysinfo *ctrl, -+ const uint8_t channel, -+ const uint8_t rankmask, -+ const uint8_t cmd, -+ const uint8_t bank, -+ const uint16_t val, -+ const uint8_t delay) -+{ -+ const uint16_t valarr[NUM_SLOTRANKS] = { val, val, val, val }; -+ return reut_write_cadb_cmd(ctrl, channel, rankmask, cmd, bank, valarr, delay); -+} -+ -+void reut_issue_mrs( -+ struct sysinfo *ctrl, -+ const uint8_t channel, -+ const uint8_t rankmask, -+ const uint8_t mr, -+ const uint16_t val) -+{ -+ reut_write_cadb_cmd_all(ctrl, channel, rankmask, CADB_CMD_MRS, mr, val, 0); -+} -+ -+void reut_issue_mrs_all( -+ struct sysinfo *ctrl, -+ const uint8_t channel, -+ const uint8_t mr, -+ const uint16_t val[NUM_SLOTS]) -+{ -+ const uint16_t valarr[NUM_SLOTRANKS] = { val[0], val[0], val[1], val[1] }; -+ reut_write_cadb_cmd(ctrl, channel, 0xf, CADB_CMD_MRS, mr, valarr, 0); -+} -+ -+enum raminit_status reut_issue_zq(struct sysinfo *ctrl, uint8_t chanmask, uint8_t zq_type) -+{ -+ /** TODO: Issuing ZQ commands differs for LPDDR **/ -+ if (ctrl->lpddr) -+ die("%s: LPDDR not yet supported in ZQ calibration\n", __func__); -+ -+ __maybe_unused uint8_t opcode; /* NOTE: Only used for LPDDR */ -+ uint16_t zq = 0; -+ switch (zq_type) { -+ case ZQ_INIT: -+ zq = BIT(10); -+ opcode = 0xff; -+ break; -+ case ZQ_LONG: -+ zq = BIT(10); -+ opcode = 0xab; -+ break; -+ case ZQ_SHORT: -+ opcode = 0x56; -+ break; -+ case ZQ_RESET: -+ opcode = 0xc3; -+ break; -+ default: -+ die("%s: ZQ type %u is invalid\n", __func__, zq_type); -+ } -+ -+ /* ZQCS on single-channel needs a longer delay */ -+ const uint8_t delay = zq_type == ZQ_SHORT && (!ctrl->dpc[0] || !ctrl->dpc[1]) ? 7 : 1; -+ enum raminit_status status = RAMINIT_STATUS_SUCCESS; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!(BIT(channel) & chanmask) || !does_ch_exist(ctrl, channel)) -+ continue; -+ -+ status = reut_write_cadb_cmd_all(ctrl, channel, 0xf, CADB_CMD_ZQ, 0, zq, delay); -+ if (status) -+ break; -+ } -+ -+ /* Wait a bit after ZQ INIT and ZQCL commands */ -+ if (zq) -+ udelay(1); -+ -+ return status; -+} -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 2acc5cbbc8..4fc78a7f43 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -96,15 +96,36 @@ - - #define SC_WR_ADD_DELAY_ch(ch) _MCMAIN_C(0x40d0, ch) - -+#define REUT_ch_MISC_CKE_CTRL(ch) _MCMAIN_C(0x4190, ch) -+ -+#define REUT_ch_PAT_CADB_MRS(ch) _MCMAIN_C(0x419c, ch) -+ -+#define REUT_ch_PAT_CADB_WRITE_PTR(ch) _MCMAIN_C(0x41bc, ch) -+#define REUT_ch_PAT_CADB_PROG(ch) _MCMAIN_C(0x41c0, ch) -+ - #define TC_ZQCAL_ch(ch) _MCMAIN_C(0x4290, ch) - #define TC_RFP_ch(ch) _MCMAIN_C(0x4294, ch) - #define TC_RFTP_ch(ch) _MCMAIN_C(0x4298, ch) -+#define TC_MR2_SHADOW_ch(ch) _MCMAIN_C(0x429c, ch) - #define MC_INIT_STATE_ch(ch) _MCMAIN_C(0x42a0, ch) - #define TC_SRFTP_ch(ch) _MCMAIN_C(0x42a4, ch) - -+#define REUT_GLOBAL_ERR 0x4804 -+ -+#define REUT_ch_SEQ_CFG(ch) (0x48a8 + 8 * (ch)) -+ -+#define REUT_ch_SEQ_CTL(ch) (0x48b8 + 4 * (ch)) -+ - /* MCMAIN broadcast */ - #define MCSCHEDS_CBIT 0x4c20 - -+#define MCSCHEDS_DFT_MISC 0x4c30 -+ -+#define REUT_ERR_DATA_STATUS 0x4ce0 -+ -+#define REUT_MISC_CKE_CTRL 0x4d90 -+#define REUT_MISC_ODT_CTRL 0x4d94 -+ - #define MCMNTS_SC_WDBWM 0x4f8c - - /* MCDECS */ -diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h -index 07f4b9dc16..5b3696347c 100644 ---- a/src/southbridge/intel/lynxpoint/pch.h -+++ b/src/southbridge/intel/lynxpoint/pch.h -@@ -586,6 +586,8 @@ void mainboard_config_rcba(void); - #define ACPIIRQEN 0x31e0 /* 32bit */ - #define OIC 0x31fe /* 16bit */ - #define PRSTS 0x3310 /* 32bit */ -+#define PM_CFG2 0x333c /* 32bit */ -+#define PM_CFG2_DRAM_RESET_CTL (1 << 26) /* ULT only */ - #define PMSYNC_CONFIG 0x33c4 /* 32bit */ - #define PMSYNC_CONFIG2 0x33cc /* 32bit */ - #define SOFT_RESET_CTRL 0x38f4 --- -2.39.5 - diff --git a/config/coreboot/default/patches/0035-src-intel-skylake-Disable-stack-overflow-debug-optio.patch b/config/coreboot/default/patches/0035-src-intel-skylake-Disable-stack-overflow-debug-optio.patch new file mode 100644 index 00000000..eb5f0028 --- /dev/null +++ b/config/coreboot/default/patches/0035-src-intel-skylake-Disable-stack-overflow-debug-optio.patch @@ -0,0 +1,61 @@ +From 18f4e970ebda43dd538f74398aea463a67040dd3 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <leah@libreboot.org> +Date: Mon, 6 Jan 2025 01:36:23 +0000 +Subject: [PATCH 35/37] src/intel/skylake: Disable stack overflow debug options + +The option was appearing in T480/3050micro configs of lbmk, +after updating on the coreboot/next uprev for 20241206 rev8: + +CONFIG_DEBUG_STACK_OVERFLOW_BREAKPOINTS=y + +I did some digging. See coreboot commit: + +commit 51cc2bacb6b07279b97e9934d079060475481fb6 +Author: Subrata Banik <subratabanik@google.com> +Date: Fri Dec 13 13:07:28 2024 +0530 + + soc/intel/pantherlake: Disable stack overflow debug options + +Well now: + +I'm disabling this behaviour on Skylake, for the same +behaviour, because I want as few behaviour changes in general, +as possible, for the rev8 release. + +According to Subrata's patch, which was for Pantherlake, +without this change, stack corruption can occur on verstage +and romstage early on. Please look at that coreboot patch, +referenced above, for clarity. + +I see no harm in disabling this option for Skylake, since +the behaviour that it otherwise enables was not present +before. + +Signed-off-by: Leah Rowe <leah@libreboot.org> +--- + src/soc/intel/skylake/Kconfig | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig +index d51ffaef7b..42af82a5d8 100644 +--- a/src/soc/intel/skylake/Kconfig ++++ b/src/soc/intel/skylake/Kconfig +@@ -129,6 +129,15 @@ config DCACHE_RAM_SIZE + The size of the cache-as-ram region required during bootblock + and/or romstage. + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + config DCACHE_BSP_STACK_SIZE + hex + default 0x20400 if FSP_USES_CB_STACK +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0036-haswell-NRI-Add-pre-training-steps.patch b/config/coreboot/default/patches/0036-haswell-NRI-Add-pre-training-steps.patch deleted file mode 100644 index 1b58a1f1..00000000 --- a/config/coreboot/default/patches/0036-haswell-NRI-Add-pre-training-steps.patch +++ /dev/null @@ -1,392 +0,0 @@ -From 19bc8d27c8f52b205df218d5917ae67ac4646024 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sat, 7 May 2022 23:12:18 +0200 -Subject: [PATCH 36/51] haswell NRI: Add pre-training steps - -Implement pre-training steps, which consist of enabling ECC I/O and -filling the WDB (Write Data Buffer, stores test patterns) through a -magic LDAT port. - -Change-Id: Ie2e09e3b218c4569ed8de5c5e1b05d491032e0f1 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/raminit_main.c | 35 ++++ - .../haswell/native_raminit/raminit_native.h | 24 +++ - .../haswell/native_raminit/reg_structs.h | 45 +++++ - .../intel/haswell/native_raminit/setup_wdb.c | 159 ++++++++++++++++++ - .../intel/haswell/registers/mchbar.h | 9 + - 6 files changed, 273 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/setup_wdb.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index e9212df9e6..8d7d4e4db0 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -10,5 +10,6 @@ romstage-y += memory_map.c - romstage-y += raminit_main.c - romstage-y += raminit_native.c - romstage-y += reut.c -+romstage-y += setup_wdb.c - romstage-y += spd_bitmunching.c - romstage-y += timings_refresh.c -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 94b268468c..5e4674957d 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -3,6 +3,7 @@ - #include <assert.h> - #include <console/console.h> - #include <cpu/intel/haswell/haswell.h> -+#include <delay.h> - #include <device/pci_ops.h> - #include <northbridge/intel/haswell/chip.h> - #include <northbridge/intel/haswell/haswell.h> -@@ -12,6 +13,39 @@ - - #include "raminit_native.h" - -+static enum raminit_status pre_training(struct sysinfo *ctrl) -+{ -+ /* Skip on S3 resume */ -+ if (ctrl->bootmode == BOOTMODE_S3) -+ return RAMINIT_STATUS_SUCCESS; -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) { -+ if (!rank_in_ch(ctrl, slot + slot, channel)) -+ continue; -+ -+ printk(RAM_DEBUG, "C%uS%u:\n", channel, slot); -+ printk(RAM_DEBUG, "\tMR0: 0x%04x\n", ctrl->mr0[channel][slot]); -+ printk(RAM_DEBUG, "\tMR1: 0x%04x\n", ctrl->mr1[channel][slot]); -+ printk(RAM_DEBUG, "\tMR2: 0x%04x\n", ctrl->mr2[channel][slot]); -+ printk(RAM_DEBUG, "\tMR3: 0x%04x\n", ctrl->mr3[channel][slot]); -+ printk(RAM_DEBUG, "\n"); -+ } -+ if (ctrl->is_ecc) { -+ union mad_dimm_reg mad_dimm = { -+ .raw = mchbar_read32(MAD_DIMM(channel)), -+ }; -+ /* Enable ECC I/O */ -+ mad_dimm.ecc_mode = 1; -+ mchbar_write32(MAD_DIMM(channel), mad_dimm.raw); -+ /* Wait 4 usec after enabling the ECC I/O, needed by HW */ -+ udelay(4); -+ } -+ } -+ setup_wdb(ctrl); -+ return RAMINIT_STATUS_SUCCESS; -+} -+ - struct task_entry { - enum raminit_status (*task)(struct sysinfo *); - bool is_enabled; -@@ -25,6 +59,7 @@ static const struct task_entry cold_boot[] = { - { configure_mc, true, "CONFMC", }, - { configure_memory_map, true, "MEMMAP", }, - { do_jedec_init, true, "JEDECINIT", }, -+ { pre_training, true, "PRETRAIN", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 759d755d6d..4d9487d79c 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -36,6 +36,13 @@ - - #define RTTNOM_MASK (BIT(9) | BIT(6) | BIT(2)) - -+#define BASIC_VA_PAT_SPREAD_8 0x01010101 -+ -+#define WDB_CACHE_LINE_SIZE 8 -+ -+#define NUM_WDB_CL_MUX_SEEDS 3 -+#define NUM_CADB_MUX_SEEDS 3 -+ - /* ZQ calibration types */ - enum { - ZQ_INIT, /* DDR3: ZQCL with tZQinit, LPDDR3: ZQ Init with tZQinit */ -@@ -317,6 +324,23 @@ void reut_issue_mrs_all( - - enum raminit_status reut_issue_zq(struct sysinfo *ctrl, uint8_t chanmask, uint8_t zq_type); - -+void write_wdb_fixed_pat( -+ const struct sysinfo *ctrl, -+ const uint8_t patterns[], -+ const uint8_t pat_mask[], -+ uint8_t spread, -+ uint16_t start); -+ -+void write_wdb_va_pat( -+ const struct sysinfo *ctrl, -+ uint32_t agg_mask, -+ uint32_t vic_mask, -+ uint8_t vic_rot, -+ uint16_t start); -+ -+void program_wdb_lfsr(const struct sysinfo *ctrl, bool cleanup); -+void setup_wdb(const struct sysinfo *ctrl); -+ - uint8_t get_rx_bias(const struct sysinfo *ctrl); - - uint8_t get_tCWL(uint32_t mem_clock_mhz); -diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -index 9929f617fe..7aa8d8c8b2 100644 ---- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h -+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -@@ -335,6 +335,18 @@ union mcscheds_cbit_reg { - uint32_t raw; - }; - -+union reut_pat_cl_mux_lmn_reg { -+ struct __packed { -+ uint32_t l_data_select : 1; // Bits 0:0 -+ uint32_t en_sweep_freq : 1; // Bits 1:1 -+ uint32_t : 6; // Bits 7:2 -+ uint32_t l_counter : 8; // Bits 15:8 -+ uint32_t m_counter : 8; // Bits 23:16 -+ uint32_t n_counter : 8; // Bits 31:24 -+ }; -+ uint32_t raw; -+}; -+ - union reut_pat_cadb_prog_reg { - struct __packed { - uint32_t addr : 16; // Bits 15:0 -@@ -439,6 +451,39 @@ union reut_misc_odt_ctrl_reg { - uint32_t raw; - }; - -+union ldat_pdat_reg { -+ struct __packed { -+ uint32_t fast_addr : 12; // Bits 11:0 -+ uint32_t : 4; // Bits 15:12 -+ uint32_t addr_en : 1; // Bits 16:16 -+ uint32_t seq_en : 1; // Bits 17:17 -+ uint32_t pol_0 : 1; // Bits 18:18 -+ uint32_t pol_1 : 1; // Bits 19:19 -+ uint32_t cmd_a : 4; // Bits 23:20 -+ uint32_t cmd_b : 4; // Bits 27:24 -+ uint32_t cmd_c : 4; // Bits 31:28 -+ }; -+ uint32_t raw; -+}; -+ -+union ldat_sdat_reg { -+ struct __packed { -+ uint32_t bank_sel : 4; // Bits 3:0 -+ uint32_t : 1; // Bits 4:4 -+ uint32_t array_sel : 5; // Bits 9:5 -+ uint32_t cmp : 1; // Bits 10:10 -+ uint32_t replicate : 1; // Bits 11:11 -+ uint32_t dword : 4; // Bits 15:12 -+ uint32_t mode : 2; // Bits 17:16 -+ uint32_t mpmap : 6; // Bits 23:18 -+ uint32_t mpb_offset : 4; // Bits 27:24 -+ uint32_t stage_en : 1; // Bits 28:28 -+ uint32_t shadow : 2; // Bits 30:29 -+ uint32_t : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ - union mcscheds_dft_misc_reg { - struct __packed { - uint32_t wdar : 1; // Bits 0:0 -diff --git a/src/northbridge/intel/haswell/native_raminit/setup_wdb.c b/src/northbridge/intel/haswell/native_raminit/setup_wdb.c -new file mode 100644 -index 0000000000..ec37c48415 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/setup_wdb.c -@@ -0,0 +1,159 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <northbridge/intel/haswell/haswell.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+static void ldat_write_cacheline( -+ const struct sysinfo *const ctrl, -+ const uint8_t chunk, -+ const uint16_t start, -+ const uint64_t data) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ /* -+ * Do not do a 64-bit write here. The register is not aligned -+ * to a 64-bit boundary, which could potentially cause issues. -+ */ -+ mchbar_write32(QCLK_ch_LDAT_DATA_IN_x(channel, 0), data & UINT32_MAX); -+ mchbar_write32(QCLK_ch_LDAT_DATA_IN_x(channel, 1), data >> 32); -+ /* -+ * Set REPLICATE = 0 as you don't want to replicate the data. -+ * Set BANK_SEL to the chunk you want to write the 64 bits to. -+ * Set ARRAY_SEL = 0 (the MC WDB) and MODE = 1. -+ */ -+ const union ldat_sdat_reg ldat_sdat = { -+ .bank_sel = chunk, -+ .mode = 1, -+ }; -+ mchbar_write32(QCLK_ch_LDAT_SDAT(channel), ldat_sdat.raw); -+ /* -+ * Finally, write the PDAT register indicating which cacheline -+ * of the WDB you want to write to by setting FAST_ADDR field -+ * to one of the 64 cache lines. Also set CMD_B in the PDAT -+ * register to 4'b1000, indicating that this is a LDAT write. -+ */ -+ const union ldat_pdat_reg ldat_pdat = { -+ .fast_addr = MIN(start, 0xfff), -+ .cmd_b = 8, -+ }; -+ mchbar_write32(QCLK_ch_LDAT_PDAT(channel), ldat_pdat.raw); -+ } -+} -+ -+static void clear_ldat_mode(const struct sysinfo *const ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) -+ mchbar_write32(QCLK_ch_LDAT_SDAT(channel), 0); -+} -+ -+void write_wdb_fixed_pat( -+ const struct sysinfo *const ctrl, -+ const uint8_t patterns[], -+ const uint8_t pat_mask[], -+ const uint8_t spread, -+ const uint16_t start) -+{ -+ for (uint8_t chunk = 0; chunk < WDB_CACHE_LINE_SIZE; chunk++) { -+ uint64_t data = 0; -+ for (uint8_t b = 0; b < 64; b++) { -+ const uint8_t beff = b % spread; -+ const uint8_t burst = patterns[pat_mask[beff]]; -+ if (burst & BIT(chunk)) -+ data |= 1ULL << b; -+ } -+ ldat_write_cacheline(ctrl, chunk, start, data); -+ } -+ clear_ldat_mode(ctrl); -+} -+ -+static inline uint32_t rol_u32(const uint32_t val) -+{ -+ return (val << 1) | ((val >> 31) & 1); -+} -+ -+void write_wdb_va_pat( -+ const struct sysinfo *const ctrl, -+ const uint32_t agg_mask, -+ const uint32_t vic_mask, -+ const uint8_t vic_rot, -+ const uint16_t start) -+{ -+ static const uint8_t va_mask_to_compressed[4] = {0xaa, 0xc0, 0xcc, 0xf0}; -+ uint32_t v_mask = vic_mask; -+ uint32_t a_mask = agg_mask; -+ for (uint8_t v = 0; v < vic_rot; v++) { -+ uint8_t compressed[32] = {0}; -+ /* Iterate through all 32 bits and create a compressed version of cacheline */ -+ for (uint8_t b = 0; b < ARRAY_SIZE(compressed); b++) { -+ const uint8_t vic = !!(v_mask & BIT(b)); -+ const uint8_t agg = !!(a_mask & BIT(b)); -+ const uint8_t index = !vic << 1 | agg << 0; -+ compressed[b] = va_mask_to_compressed[index]; -+ } -+ for (uint8_t chunk = 0; chunk < WDB_CACHE_LINE_SIZE; chunk++) { -+ uint32_t data = 0; -+ for (uint8_t b = 0; b < ARRAY_SIZE(compressed); b++) -+ data |= !!(compressed[b] & BIT(chunk)) << b; -+ -+ const uint64_t data64 = (uint64_t)data << 32 | data; -+ ldat_write_cacheline(ctrl, chunk, start + v, data64); -+ } -+ v_mask = rol_u32(v_mask); -+ a_mask = rol_u32(a_mask); -+ } -+ clear_ldat_mode(ctrl); -+} -+ -+void program_wdb_lfsr(const struct sysinfo *ctrl, const bool cleanup) -+{ -+ /* Cleanup LFSR seeds are sequential */ -+ const uint32_t cleanup_seeds[NUM_WDB_CL_MUX_SEEDS] = { 0xaaaaaa, 0xcccccc, 0xf0f0f0 }; -+ const uint32_t regular_seeds[NUM_WDB_CL_MUX_SEEDS] = { 0xa10ca1, 0xef0d08, 0xad0a1e }; -+ const uint32_t *seeds = cleanup ? cleanup_seeds : regular_seeds; -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t i = 0; i < NUM_WDB_CL_MUX_SEEDS; i++) { -+ mchbar_write32(REUT_ch_PAT_WDB_CL_MUX_RD_x(channel, i), seeds[i]); -+ mchbar_write32(REUT_ch_PAT_WDB_CL_MUX_WR_x(channel, i), seeds[i]); -+ } -+ } -+} -+ -+void setup_wdb(const struct sysinfo *ctrl) -+{ -+ const uint32_t amask[9] = { -+ 0x86186186, 0x18618618, 0x30c30c30, -+ 0xa28a28a2, 0x8a28a28a, 0x14514514, -+ 0x28a28a28, 0x92492492, 0x24924924, -+ }; -+ const uint32_t vmask = 0x41041041; -+ -+ /* Fill first 8 entries with simple 2-LFSR VA pattern */ -+ write_wdb_va_pat(ctrl, 0, BASIC_VA_PAT_SPREAD_8, 8, 0); -+ -+ /* Fill next 54 entries with 3-LFSR VA pattern */ -+ for (uint8_t a = 0; a < ARRAY_SIZE(amask); a++) -+ write_wdb_va_pat(ctrl, amask[a], vmask, 6, 8 + a * 6); -+ -+ program_wdb_lfsr(ctrl, false); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ const union reut_pat_cl_mux_lmn_reg wdb_cl_mux_lmn = { -+ .en_sweep_freq = 1, -+ .l_counter = 1, -+ .m_counter = 1, -+ .n_counter = 10, -+ }; -+ mchbar_write32(REUT_ch_PAT_WDB_CL_MUX_LMN(channel), wdb_cl_mux_lmn.raw); -+ } -+} -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 4fc78a7f43..f8408e51a0 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -94,6 +94,11 @@ - #define TC_BANK_RANK_D_ch(ch) _MCMAIN_C(0x4014, ch) - #define SC_ROUNDT_LAT_ch(ch) _MCMAIN_C(0x4024, ch) - -+#define REUT_ch_PAT_WDB_CL_MUX_WR_x(ch, x) _MCMAIN_C_X(0x4048, ch, x) /* x in 0 .. 2 */ -+#define REUT_ch_PAT_WDB_CL_MUX_RD_x(ch, x) _MCMAIN_C_X(0x4054, ch, x) /* x in 0 .. 2 */ -+ -+#define REUT_ch_PAT_WDB_CL_MUX_LMN(ch) _MCMAIN_C(0x4078, ch) -+ - #define SC_WR_ADD_DELAY_ch(ch) _MCMAIN_C(0x40d0, ch) - - #define REUT_ch_MISC_CKE_CTRL(ch) _MCMAIN_C(0x4190, ch) -@@ -110,6 +115,10 @@ - #define MC_INIT_STATE_ch(ch) _MCMAIN_C(0x42a0, ch) - #define TC_SRFTP_ch(ch) _MCMAIN_C(0x42a4, ch) - -+#define QCLK_ch_LDAT_PDAT(ch) _MCMAIN_C(0x42d0, ch) -+#define QCLK_ch_LDAT_SDAT(ch) _MCMAIN_C(0x42d4, ch) -+#define QCLK_ch_LDAT_DATA_IN_x(ch, x) _MCMAIN_C_X(0x42dc, ch, x) /* x in 0 .. 1 */ -+ - #define REUT_GLOBAL_ERR 0x4804 - - #define REUT_ch_SEQ_CFG(ch) (0x48a8 + 8 * (ch)) --- -2.39.5 - diff --git a/config/coreboot/default/patches/0036-src-intel-x4x-Disable-stack-overflow-debug.patch b/config/coreboot/default/patches/0036-src-intel-x4x-Disable-stack-overflow-debug.patch new file mode 100644 index 00000000..2e06ad79 --- /dev/null +++ b/config/coreboot/default/patches/0036-src-intel-x4x-Disable-stack-overflow-debug.patch @@ -0,0 +1,33 @@ +From 8dcd86c34d92b9b17bcfe4c7c61793042dc97268 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <leah@libreboot.org> +Date: Mon, 6 Jan 2025 01:53:53 +0000 +Subject: [PATCH 36/37] src/intel/x4x: Disable stack overflow debug + +Signed-off-by: Leah Rowe <leah@libreboot.org> +--- + src/northbridge/intel/x4x/Kconfig | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/northbridge/intel/x4x/Kconfig b/src/northbridge/intel/x4x/Kconfig +index 1803ef5733..7129aabf72 100644 +--- a/src/northbridge/intel/x4x/Kconfig ++++ b/src/northbridge/intel/x4x/Kconfig +@@ -32,6 +32,15 @@ config ECAM_MMCONF_BUS_NUMBER + int + default 256 + ++# Override DEBUG Kconfig to avoid false alarm about stack overflow. ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS ++ bool ++ default n ++ ++config DEBUG_STACK_OVERFLOW_BREAKPOINTS_IN_ALL_STAGES ++ bool ++ default n ++ + # This number must be equal or lower than what's reported in ACPI PCI _CRS + config DOMAIN_RESOURCE_32BIT_LIMIT + default 0xfec00000 +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0037-Conditional-TBFW-setting-for-T480-T480S.patch b/config/coreboot/default/patches/0037-Conditional-TBFW-setting-for-T480-T480S.patch new file mode 100644 index 00000000..7bca06a7 --- /dev/null +++ b/config/coreboot/default/patches/0037-Conditional-TBFW-setting-for-T480-T480S.patch @@ -0,0 +1,37 @@ +From 9b547c2029611793f895117a807fa2d2c22a5332 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <leah@libreboot.org> +Date: Mon, 21 Apr 2025 05:14:45 +0100 +Subject: [PATCH 37/37] Conditional TBFW setting for T480/T480S + +Otherwise, other boards will define it, which +might trigger the vendor download script, and +lead to a non-zero exit. + +Signed-off-by: Leah Rowe <leah@libreboot.org> +--- + src/mainboard/lenovo/Kconfig | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/mainboard/lenovo/Kconfig b/src/mainboard/lenovo/Kconfig +index 512b326381..3d3490b35d 100644 +--- a/src/mainboard/lenovo/Kconfig ++++ b/src/mainboard/lenovo/Kconfig +@@ -18,6 +18,8 @@ config MAINBOARD_FAMILY + string + default MAINBOARD_PART_NUMBER + ++if BOARD_LENOVO_T480 || BOARD_LENOVO_T480S ++ + config LENOVO_TBFW_BIN + string "Lenovo ThunderBolt firmware bin file" + default "" +@@ -44,4 +46,6 @@ config LENOVO_TBFW_BIN + Just leave this blank if you don't care about this option. It's not + useful for every ThinkPad, only certain models. + ++endif # BOARD LENOVO_T480 || BOARD_LENOVO_T480S ++ + endif # VENDOR_LENOVO +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0037-haswell-NRI-Add-REUT-I-O-test-library.patch b/config/coreboot/default/patches/0037-haswell-NRI-Add-REUT-I-O-test-library.patch deleted file mode 100644 index eaafcde3..00000000 --- a/config/coreboot/default/patches/0037-haswell-NRI-Add-REUT-I-O-test-library.patch +++ /dev/null @@ -1,1130 +0,0 @@ -From 460a092b22c9800c5ee9d8c4198e8b241664693f Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sun, 8 May 2022 00:11:29 +0200 -Subject: [PATCH 37/51] haswell NRI: Add REUT I/O test library - -Implement a library to run I/O tests using the REUT hardware. - -Change-Id: Id7b207cd0a3989ddd23c88c6b1f0cfa79d2c861f -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/raminit_native.h | 110 +++ - .../haswell/native_raminit/reg_structs.h | 121 +++ - .../intel/haswell/native_raminit/testing_io.c | 744 ++++++++++++++++++ - .../intel/haswell/registers/mchbar.h | 30 + - 5 files changed, 1006 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/testing_io.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index 8d7d4e4db0..6e1b365602 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -12,4 +12,5 @@ romstage-y += raminit_native.c - romstage-y += reut.c - romstage-y += setup_wdb.c - romstage-y += spd_bitmunching.c -+romstage-y += testing_io.c - romstage-y += timings_refresh.c -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 4d9487d79c..f029e7f076 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -59,6 +59,88 @@ enum { - REUT_MODE_NOP = 3, /* Normal operation mode */ - }; - -+/* REUT error counter control */ -+enum { -+ COUNT_ERRORS_PER_CHANNEL = 0, -+ COUNT_ERRORS_PER_LANE = 1, -+ COUNT_ERRORS_PER_BYTE_GROUP = 2, -+ COUNT_ERRORS_PER_CHUNK = 3, -+}; -+ -+enum wdb_dq_pattern { -+ BASIC_VA = 0, -+ SEGMENT_WDB, -+ CADB, -+ TURN_AROUND, -+ LMN_VA, -+ TURN_AROUND_WR, -+ TURN_AROUND_ODT, -+ RD_RD_TA, -+ RD_RD_TA_ALL, -+}; -+ -+enum reut_cmd_pat { -+ PAT_WR_RD, -+ PAT_WR, -+ PAT_RD, -+ PAT_RD_WR_TA, -+ PAT_WR_RD_TA, -+ PAT_ODT_TA, -+}; -+ -+/* REUT subsequence types (B = Base, O = Offset) */ -+enum { -+ SUBSEQ_B_RD = 0 << 22, -+ SUBSEQ_B_WR = 1 << 22, -+ SUBSEQ_B_RD_WR = 2 << 22, -+ SUBSEQ_B_WR_RD = 3 << 22, -+ SUBSEQ_O_RD = 4 << 22, -+ SUBSEQ_O_WR = 5 << 22, -+}; -+ -+/* REUT mux control */ -+enum { -+ REUT_MUX_LMN = 0, -+ REUT_MUX_BTBUFFER = 1, -+ REUT_MUX_LFSR = 2, -+}; -+ -+/* Increment scale */ -+enum { -+ SCALE_LOGARITHM = 0, -+ SCALE_LINEAR = 1, -+}; -+ -+enum test_stop { -+ NSOE = 0, /* Never stop on error */ -+ NTHSOE = 1, /* Stop on the nth error (we use n = 1) */ -+ ABGSOE = 2, /* Stop on all byte groups error */ -+ ALSOE = 3, /* Stop on all lanes error */ -+}; -+ -+struct wdb_pat { -+ uint32_t start_ptr; /* Starting pointer in WDB */ -+ uint32_t stop_ptr; /* Stopping pointer in WDB */ -+ uint16_t inc_rate; /* How quickly the WDB walks through cachelines */ -+ uint8_t dq_pattern; /* DQ pattern to use (see enum wdb_dq_pattern above) */ -+}; -+ -+struct reut_pole { -+ uint16_t start; -+ uint16_t stop; -+ uint16_t order; -+ uint32_t inc_rate; -+ uint16_t inc_val; -+ bool wrap_trigger; -+}; -+ -+struct reut_box { -+ struct reut_pole rank; -+ struct reut_pole bank; -+ struct reut_pole row; -+ struct reut_pole col; -+}; -+ - enum command_training_iteration { - CT_ITERATION_CLOCK = 0, - CT_ITERATION_CMD_NORTH, -@@ -200,6 +282,10 @@ struct sysinfo { - uint16_t mr1[NUM_CHANNELS][NUM_SLOTS]; - uint16_t mr2[NUM_CHANNELS][NUM_SLOTS]; - uint16_t mr3[NUM_CHANNELS][NUM_SLOTS]; -+ -+ uint8_t dq_pat; -+ -+ uint8_t dq_pat_lc; - }; - - static inline bool is_hsw_ult(void) -@@ -341,6 +427,30 @@ void write_wdb_va_pat( - void program_wdb_lfsr(const struct sysinfo *ctrl, bool cleanup); - void setup_wdb(const struct sysinfo *ctrl); - -+void program_seq_addr(uint8_t channel, const struct reut_box *reut_addr, bool log_seq_addr); -+void program_loop_count(const struct sysinfo *ctrl, uint8_t channel, uint8_t lc_exp); -+ -+void setup_io_test( -+ struct sysinfo *ctrl, -+ uint8_t chanmask, -+ enum reut_cmd_pat cmd_pat, -+ uint16_t num_cl, -+ uint8_t lc, -+ const struct reut_box *reut_addr, -+ enum test_stop soe, -+ const struct wdb_pat *pat, -+ uint8_t en_cadb, -+ uint8_t subseq_wait); -+ -+void setup_io_test_cadb(struct sysinfo *ctrl, uint8_t chanmask, uint8_t lc, enum test_stop soe); -+void setup_io_test_basic_va(struct sysinfo *ctrl, uint8_t chm, uint8_t lc, enum test_stop soe); -+void setup_io_test_mpr(struct sysinfo *ctrl, uint8_t chanmask, uint8_t lc, enum test_stop soe); -+ -+uint8_t select_reut_ranks(struct sysinfo *ctrl, uint8_t channel, uint8_t rankmask); -+ -+void run_mpr_io_test(bool clear_errors); -+uint8_t run_io_test(struct sysinfo *ctrl, uint8_t chanmask, uint8_t dq_pat, bool clear_errors); -+ - uint8_t get_rx_bias(const struct sysinfo *ctrl); - - uint8_t get_tCWL(uint32_t mem_clock_mhz); -diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -index 7aa8d8c8b2..b943259b91 100644 ---- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h -+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -@@ -347,6 +347,54 @@ union reut_pat_cl_mux_lmn_reg { - uint32_t raw; - }; - -+union reut_err_ctl_reg { -+ struct __packed { -+ uint32_t stop_on_nth_error : 6; // Bits 5:0 -+ uint32_t : 6; // Bits 11:6 -+ uint32_t stop_on_error_control : 2; // Bits 13:12 -+ uint32_t : 2; // Bits 15:14 -+ uint32_t selective_err_enable_chunk : 8; // Bits 23:16 -+ uint32_t selective_err_enable_cacheline : 8; // Bits 31:24 -+ }; -+ uint32_t raw; -+}; -+ -+union reut_pat_cadb_mux_ctrl_reg { -+ struct __packed { -+ uint32_t mux_0_ctrl : 2; // Bits 1:0 -+ uint32_t : 2; // Bits 3:2 -+ uint32_t mux_1_ctrl : 2; // Bits 5:4 -+ uint32_t : 2; // Bits 7:6 -+ uint32_t mux_2_ctrl : 2; // Bits 9:8 -+ uint32_t : 6; // Bits 15:10 -+ uint32_t sel_mux_0_ctrl : 2; // Bits 17:16 -+ uint32_t : 2; // Bits 19:18 -+ uint32_t sel_mux_1_ctrl : 2; // Bits 21:20 -+ uint32_t : 2; // Bits 23:22 -+ uint32_t sel_mux_2_ctrl : 2; // Bits 25:24 -+ uint32_t : 6; // Bits 31:26 -+ }; -+ uint32_t raw; -+}; -+ -+union reut_pat_wdb_cl_mux_cfg_reg { -+ struct __packed { -+ uint32_t mux_0_control : 2; // Bits 1:0 -+ uint32_t : 1; // Bits 2:2 -+ uint32_t mux_1_control : 2; // Bits 4:3 -+ uint32_t : 1; // Bits 5:5 -+ uint32_t mux_2_control : 2; // Bits 7:6 -+ uint32_t : 6; // Bits 13:8 -+ uint32_t ecc_replace_byte_ctl : 1; // Bits 14:14 -+ uint32_t ecc_data_source_sel : 1; // Bits 15:15 -+ uint32_t save_lfsr_seed_rate : 6; // Bits 21:16 -+ uint32_t : 2; // Bits 23:22 -+ uint32_t reload_lfsr_seed_rate : 3; // Bits 26:24 -+ uint32_t : 5; // Bits 31:27 -+ }; -+ uint32_t raw; -+}; -+ - union reut_pat_cadb_prog_reg { - struct __packed { - uint32_t addr : 16; // Bits 15:0 -@@ -366,6 +414,19 @@ union reut_pat_cadb_prog_reg { - uint32_t raw32[2]; - }; - -+union reut_pat_wdb_cl_ctrl_reg { -+ struct __packed { -+ uint32_t inc_rate : 5; // Bits 4:0 -+ uint32_t inc_scale : 1; // Bits 5:5 -+ uint32_t : 2; // Bits 7:6 -+ uint32_t start_ptr : 6; // Bits 13:8 -+ uint32_t : 2; // Bits 15:14 -+ uint32_t end_ptr : 6; // Bits 21:16 -+ uint32_t : 10; // Bits 31:22 -+ }; -+ uint32_t raw; -+}; -+ - union reut_pat_cadb_mrs_reg { - struct __packed { - uint32_t delay_gap : 3; // Bits 2:0 -@@ -406,6 +467,66 @@ union reut_seq_cfg_reg { - uint32_t raw32[2]; - }; - -+union reut_seq_base_addr_reg { -+ struct __packed { -+ uint32_t : 3; // Bits 2:0 -+ uint32_t col_addr : 8; // Bits 10:3 -+ uint32_t : 13; // Bits 23:11 -+ uint32_t row_addr : 16; // Bits 39:24 -+ uint32_t : 8; // Bits 47:40 -+ uint32_t bank_addr : 3; // Bits 50:48 -+ uint32_t : 5; // Bits 55:51 -+ uint32_t rank_addr : 3; // Bits 58:56 -+ uint32_t : 5; // Bits 63:59 -+ }; -+ uint32_t raw32[2]; -+ uint64_t raw; -+}; -+ -+union reut_seq_misc_ctl_reg { -+ struct __packed { -+ uint32_t col_addr_order : 2; // Bits 1:0 -+ uint32_t row_addr_order : 2; // Bits 3:2 -+ uint32_t bank_addr_order : 2; // Bits 5:4 -+ uint32_t rank_addr_order : 2; // Bits 7:6 -+ uint32_t : 5; // Bits 12:8 -+ uint32_t addr_invert_rate : 3; // Bits 15:13 -+ uint32_t : 4; // Bits 19:16 -+ uint32_t col_addr_invert_en : 1; // Bits 20:20 -+ uint32_t row_addr_invert_en : 1; // Bits 21:21 -+ uint32_t bank_addr_invert_en : 1; // Bits 22:22 -+ uint32_t rank_addr_invert_en : 1; // Bits 23:23 -+ uint32_t col_wrap_trigger_en : 1; // Bits 24:24 -+ uint32_t row_wrap_trigger_en : 1; // Bits 25:25 -+ uint32_t bank_wrap_trigger_en : 1; // Bits 26:26 -+ uint32_t rank_wrap_trigger_en : 1; // Bits 27:27 -+ uint32_t col_wrap_carry_en : 1; // Bits 28:28 -+ uint32_t row_wrap_carry_en : 1; // Bits 29:29 -+ uint32_t bank_wrap_carry_en : 1; // Bits 30:30 -+ uint32_t rank_wrap_carry_en : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ -+union reut_seq_addr_inc_ctl_reg { -+ struct __packed { -+ uint32_t : 3; // Bits 2:0 -+ uint32_t col_addr_increment : 8; // Bits 10:3 -+ uint32_t : 1; // Bits 11:11 -+ uint32_t col_addr_update : 8; // Bits 19:12 -+ uint32_t row_addr_increment : 12; // Bits 31:20 -+ uint32_t row_addr_update : 6; // Bits 37:32 -+ uint32_t bank_addr_increment : 3; // Bits 40:38 -+ uint32_t : 3; // Bits 43:41 -+ uint32_t bank_addr_update : 8; // Bits 53:44 -+ uint32_t rank_addr_increment : 3; // Bits 54:52 -+ uint32_t : 1; // Bits 55:55 -+ uint32_t rank_addr_update : 8; // Bits 63:56 -+ }; -+ uint64_t raw; -+ uint32_t raw32[2]; -+}; -+ - union reut_seq_ctl_reg { - struct __packed { - uint32_t start_test : 1; // Bits 0:0 -diff --git a/src/northbridge/intel/haswell/native_raminit/testing_io.c b/src/northbridge/intel/haswell/native_raminit/testing_io.c -new file mode 100644 -index 0000000000..2632c238f8 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/testing_io.c -@@ -0,0 +1,744 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <console/console.h> -+#include <delay.h> -+#include <lib.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <timer.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+static void set_cadb_patterns(const uint8_t channel, const uint16_t seeds[NUM_CADB_MUX_SEEDS]) -+{ -+ for (uint8_t i = 0; i < NUM_CADB_MUX_SEEDS; i++) -+ mchbar_write32(REUT_ch_PAT_CADB_MUX_x(channel, i), seeds[i]); -+} -+ -+static void setup_cadb( -+ struct sysinfo *ctrl, -+ const uint8_t channel, -+ const uint8_t vic_spread, -+ const uint8_t vic_bit) -+{ -+ const bool lmn_en = false; -+ -+ /* -+ * Currently, always start writing at CADB row 0. -+ * Could add a start point parameter in the future. -+ */ -+ mchbar_write8(REUT_ch_PAT_CADB_WRITE_PTR(channel), 0); -+ const uint8_t num_cadb_rows = 8; -+ for (uint8_t row = 0; row < num_cadb_rows; row++) { -+ const uint8_t lfsr0 = (row >> 0) & 1; -+ const uint8_t lfsr1 = (row >> 1) & 1; -+ uint64_t reg64 = 0; -+ for (uint8_t bit = 0; bit < 22; bit++) { -+ uint8_t bremap; -+ if (bit >= 19) { -+ /* (bremap in 40 .. 42) => CADB data control */ -+ bremap = bit + 21; -+ } else if (bit >= 16) { -+ /* (bremap in 24 .. 26) => CADB data bank */ -+ bremap = bit + 8; -+ } else { -+ /* (bremap in 0 .. 15) => CADB data address */ -+ bremap = bit; -+ } -+ const uint8_t fine = bit % vic_spread; -+ reg64 |= ((uint64_t)(fine == vic_bit ? lfsr0 : lfsr1)) << bremap; -+ } -+ /* -+ * Write row. CADB pointer is auto incremented after every write. This must be -+ * a single 64-bit write, otherwise the CADB pointer will auto-increment twice. -+ */ -+ mchbar_write64(REUT_ch_PAT_CADB_PROG(channel), reg64); -+ } -+ const union reut_pat_cadb_mux_ctrl_reg cadb_mux_ctrl = { -+ .mux_0_ctrl = lmn_en ? REUT_MUX_LMN : REUT_MUX_LFSR, -+ .mux_1_ctrl = REUT_MUX_LFSR, -+ .mux_2_ctrl = REUT_MUX_LFSR, -+ }; -+ mchbar_write32(REUT_ch_PAT_CADB_MUX_CTRL(channel), cadb_mux_ctrl.raw); -+ const union reut_pat_cl_mux_lmn_reg cadb_cl_mux_lmn = { -+ .en_sweep_freq = 1, -+ .l_counter = 1, -+ .m_counter = 1, -+ .n_counter = 6, -+ }; -+ mchbar_write32(REUT_ch_PAT_CADB_CL_MUX_LMN(channel), cadb_cl_mux_lmn.raw); -+ const uint16_t cadb_mux_seeds[NUM_CADB_MUX_SEEDS] = { 0x0ea1, 0xbeef, 0xdead }; -+ set_cadb_patterns(channel, cadb_mux_seeds); -+} -+ -+static uint32_t calc_rate(const uint32_t rate, const uint32_t lim, const uint8_t scale_bit) -+{ -+ return rate > lim ? log2_ceil(rate - 1) : BIT(scale_bit) | rate; -+} -+ -+void program_seq_addr( -+ const uint8_t channel, -+ const struct reut_box *reut_addr, -+ const bool log_seq_addr) -+{ -+ const int loglevel = log_seq_addr ? BIOS_ERR : BIOS_NEVER; -+ const uint32_t div = 8; -+ union reut_seq_base_addr_reg reut_seq_addr_start = { -+ .col_addr = reut_addr->col.start / div, -+ .row_addr = reut_addr->row.start, -+ .bank_addr = reut_addr->bank.start, -+ .rank_addr = reut_addr->rank.start, -+ }; -+ mchbar_write64(REUT_ch_SEQ_ADDR_START(channel), reut_seq_addr_start.raw); -+ reut_seq_addr_start.raw = mchbar_read64(REUT_ch_SEQ_ADDR_START(channel)); -+ printk(loglevel, "\tStart column: %u\n", reut_seq_addr_start.col_addr); -+ printk(loglevel, "\tStart row: %u\n", reut_seq_addr_start.row_addr); -+ printk(loglevel, "\tStart bank: %u\n", reut_seq_addr_start.bank_addr); -+ printk(loglevel, "\tStart rank: %u\n", reut_seq_addr_start.rank_addr); -+ printk(loglevel, "\n"); -+ -+ union reut_seq_base_addr_reg reut_seq_addr_stop = { -+ .col_addr = reut_addr->col.stop / div, -+ .row_addr = reut_addr->row.stop, -+ .bank_addr = reut_addr->bank.stop, -+ .rank_addr = reut_addr->rank.stop, -+ }; -+ mchbar_write64(REUT_ch_SEQ_ADDR_WRAP(channel), reut_seq_addr_stop.raw); -+ reut_seq_addr_stop.raw = mchbar_read64(REUT_ch_SEQ_ADDR_WRAP(channel)); -+ printk(loglevel, "\tStop column: %u\n", reut_seq_addr_stop.col_addr); -+ printk(loglevel, "\tStop row: %u\n", reut_seq_addr_stop.row_addr); -+ printk(loglevel, "\tStop bank: %u\n", reut_seq_addr_stop.bank_addr); -+ printk(loglevel, "\tStop rank: %u\n", reut_seq_addr_stop.rank_addr); -+ printk(loglevel, "\n"); -+ -+ union reut_seq_misc_ctl_reg reut_seq_misc_ctl = { -+ .col_wrap_trigger_en = reut_addr->col.wrap_trigger, -+ .row_wrap_trigger_en = reut_addr->row.wrap_trigger, -+ .bank_wrap_trigger_en = reut_addr->bank.wrap_trigger, -+ .rank_wrap_trigger_en = reut_addr->rank.wrap_trigger, -+ }; -+ mchbar_write32(REUT_ch_SEQ_MISC_CTL(channel), reut_seq_misc_ctl.raw); -+ printk(loglevel, "\tWrap column: %u\n", reut_addr->col.wrap_trigger); -+ printk(loglevel, "\tWrap row: %u\n", reut_addr->row.wrap_trigger); -+ printk(loglevel, "\tWrap bank: %u\n", reut_addr->bank.wrap_trigger); -+ printk(loglevel, "\tWrap rank: %u\n", reut_addr->rank.wrap_trigger); -+ printk(loglevel, "\n"); -+ -+ union reut_seq_addr_inc_ctl_reg reut_seq_addr_inc_ctl = { -+ .col_addr_update = calc_rate(reut_addr->col.inc_rate, 31, 7), -+ .row_addr_update = calc_rate(reut_addr->row.inc_rate, 15, 5), -+ .bank_addr_update = calc_rate(reut_addr->bank.inc_rate, 31, 7), -+ .rank_addr_update = calc_rate(reut_addr->rank.inc_rate, 31, 7), -+ .col_addr_increment = reut_addr->col.inc_val, -+ .row_addr_increment = reut_addr->row.inc_val, -+ .bank_addr_increment = reut_addr->bank.inc_val, -+ .rank_addr_increment = reut_addr->rank.inc_val, -+ }; -+ printk(loglevel, "\tUpdRate column: %u\n", reut_addr->col.inc_rate); -+ printk(loglevel, "\tUpdRate row: %u\n", reut_addr->row.inc_rate); -+ printk(loglevel, "\tUpdRate bank: %u\n", reut_addr->bank.inc_rate); -+ printk(loglevel, "\tUpdRate rank: %u\n", reut_addr->rank.inc_rate); -+ printk(loglevel, "\n"); -+ printk(loglevel, "\tUpdRateCR column: %u\n", reut_seq_addr_inc_ctl.col_addr_update); -+ printk(loglevel, "\tUpdRateCR row: %u\n", reut_seq_addr_inc_ctl.row_addr_update); -+ printk(loglevel, "\tUpdRateCR bank: %u\n", reut_seq_addr_inc_ctl.bank_addr_update); -+ printk(loglevel, "\tUpdRateCR rank: %u\n", reut_seq_addr_inc_ctl.rank_addr_update); -+ printk(loglevel, "\n"); -+ printk(loglevel, "\tUpdInc column: %u\n", reut_seq_addr_inc_ctl.col_addr_increment); -+ printk(loglevel, "\tUpdInc row: %u\n", reut_seq_addr_inc_ctl.row_addr_increment); -+ printk(loglevel, "\tUpdInc bank: %u\n", reut_seq_addr_inc_ctl.bank_addr_increment); -+ printk(loglevel, "\tUpdInc rank: %u\n", reut_seq_addr_inc_ctl.rank_addr_increment); -+ printk(loglevel, "\n"); -+ mchbar_write64(REUT_ch_SEQ_ADDR_INC_CTL(channel), reut_seq_addr_inc_ctl.raw); -+} -+ -+/* -+ * Early steppings take exponential (base 2) loopcount values, -+ * but later steppings take linear loopcount values elsewhere. -+ * Address the differences in register offset and format here. -+ */ -+void program_loop_count(const struct sysinfo *ctrl, const uint8_t channel, const uint8_t lc_exp) -+{ -+ if (ctrl->stepping >= STEPPING_C0) { -+ const uint32_t loopcount = lc_exp >= 32 ? 0 : BIT(lc_exp); -+ mchbar_write32(HSW_REUT_ch_SEQ_LOOP_COUNT(channel), loopcount); -+ } else { -+ const uint8_t loopcount = lc_exp >= 32 ? 0 : lc_exp + 1; -+ union reut_seq_cfg_reg reut_seq_cfg = { -+ .raw = mchbar_read64(REUT_ch_SEQ_CFG(channel)), -+ }; -+ reut_seq_cfg.early_steppings_loop_count = loopcount; -+ mchbar_write64(REUT_ch_SEQ_CFG(channel), reut_seq_cfg.raw); -+ } -+} -+ -+static inline void write_subseq(const uint8_t channel, const uint8_t idx, const uint32_t ssq) -+{ -+ mchbar_write32(REUT_ch_SUBSEQ_x_CTL(channel, idx), ssq); -+} -+ -+static void program_subseq( -+ struct sysinfo *const ctrl, -+ const uint8_t channel, -+ const enum reut_cmd_pat cmd_pat, -+ const uint32_t ss_a, -+ const uint32_t ss_b) -+{ -+ switch (cmd_pat) { -+ case PAT_WR_RD_TA: -+ write_subseq(channel, 0, ss_a | SUBSEQ_B_WR); -+ for (uint8_t i = 1; i < 7; i++) -+ write_subseq(channel, i, ss_b | SUBSEQ_B_RD_WR); -+ -+ write_subseq(channel, 7, ss_a | SUBSEQ_B_RD); -+ break; -+ case PAT_RD_WR_TA: -+ write_subseq(channel, 0, ss_b | SUBSEQ_B_WR_RD); -+ break; -+ case PAT_ODT_TA: -+ write_subseq(channel, 0, ss_a | SUBSEQ_B_WR); -+ write_subseq(channel, 1, ss_b | SUBSEQ_B_RD_WR); -+ write_subseq(channel, 2, ss_a | SUBSEQ_B_RD); -+ write_subseq(channel, 3, ss_b | SUBSEQ_B_WR_RD); -+ break; -+ default: -+ write_subseq(channel, 0, ss_a | SUBSEQ_B_WR); -+ write_subseq(channel, 1, ss_a | SUBSEQ_B_RD); -+ break; -+ } -+} -+ -+void setup_io_test( -+ struct sysinfo *ctrl, -+ const uint8_t chanmask, -+ const enum reut_cmd_pat cmd_pat, -+ const uint16_t num_cl, -+ const uint8_t lc, -+ const struct reut_box *const reut_addr, -+ const enum test_stop soe, -+ const struct wdb_pat *const pat, -+ const uint8_t en_cadb, -+ const uint8_t subseq_wait) -+{ -+ if (!chanmask) { -+ printk(BIOS_ERR, "\n%s: chanmask is invalid\n", __func__); -+ return; -+ } -+ -+ /* -+ * Prepare variables needed for both channels. -+ * Check for the cases where this MUST be 1: when -+ * we manually walk through subseq ODT and TA Wr. -+ */ -+ uint8_t lc_exp = MAX(lc - log2_ceil(num_cl), 0); -+ if (cmd_pat == PAT_WR_RD_TA || cmd_pat == PAT_ODT_TA) -+ lc_exp = 0; -+ -+ uint8_t num_clcr; -+ if (num_cl > 127) { -+ /* Assume exponential number */ -+ num_clcr = log2_ceil(num_cl); -+ } else { -+ /* Set number of cache lines as linear number */ -+ num_clcr = num_cl | BIT(7); -+ } -+ -+ const uint16_t num_cl2 = 2 * num_cl; -+ uint8_t num_cl2cr; -+ if (num_cl2 > 127) { -+ /* Assume exponential number */ -+ num_cl2cr = log2_ceil(num_cl2); -+ } else { -+ /* Set number of cache lines as linear number */ -+ num_cl2cr = num_cl2 | BIT(7); -+ } -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!(chanmask & BIT(channel))) { -+ union reut_seq_cfg_reg reut_seq_cfg = { -+ .raw = mchbar_read64(REUT_ch_SEQ_CFG(channel)), -+ }; -+ reut_seq_cfg.global_control = 0; -+ mchbar_write64(REUT_ch_SEQ_CFG(channel), reut_seq_cfg.raw); -+ continue; -+ } -+ -+ /* -+ * Program CADB -+ */ -+ mchbar_write8(REUT_ch_MISC_PAT_CADB_CTRL(channel), !!en_cadb); -+ if (en_cadb) -+ setup_cadb(ctrl, channel, 7, 8); -+ -+ /* -+ * Program sequence -+ */ -+ uint8_t subseq_start = 0; -+ uint8_t subseq_end = 0; -+ switch (cmd_pat) { -+ case PAT_WR_RD: -+ subseq_end = 1; -+ break; -+ case PAT_WR: -+ break; -+ case PAT_RD: -+ subseq_start = 1; -+ subseq_end = 1; -+ break; -+ case PAT_RD_WR_TA: -+ break; -+ case PAT_WR_RD_TA: -+ subseq_end = 7; -+ break; -+ case PAT_ODT_TA: -+ subseq_end = 3; -+ break; -+ default: -+ die("\n%s: Pattern type %u is invalid\n", __func__, cmd_pat); -+ } -+ const union reut_seq_cfg_reg reut_seq_cfg = { -+ .global_control = 1, -+ .initialization_mode = REUT_MODE_TEST, -+ .subsequence_start_pointer = subseq_start, -+ .subsequence_end_pointer = subseq_end, -+ .start_test_delay = 2, -+ }; -+ mchbar_write64(REUT_ch_SEQ_CFG(channel), reut_seq_cfg.raw); -+ program_loop_count(ctrl, channel, lc_exp); -+ mchbar_write32(REUT_ch_SEQ_CTL(channel), (union reut_seq_ctl_reg) { -+ .clear_errors = 1, -+ }.raw); -+ -+ /* -+ * Program subsequences -+ */ -+ uint32_t subseq_a = 0; -+ -+ /* Number of cachelines and scale */ -+ subseq_a |= (num_clcr & 0x00ff) << 0; -+ subseq_a |= (subseq_wait & 0x3fff) << 8; -+ -+ /* Reset current base address to start */ -+ subseq_a |= BIT(27); -+ -+ uint32_t subseq_b = 0; -+ -+ /* Number of cachelines and scale */ -+ subseq_b |= (num_cl2cr & 0x00ff) << 0; -+ subseq_b |= (subseq_wait & 0x3fff) << 8; -+ -+ /* Reset current base address to start */ -+ subseq_b |= BIT(27); -+ -+ program_subseq(ctrl, channel, cmd_pat, subseq_a, subseq_b); -+ -+ /* Program sequence address */ -+ program_seq_addr(channel, reut_addr, false); -+ -+ /* Program WDB */ -+ const bool is_linear = pat->inc_rate < 32; -+ mchbar_write32(REUT_ch_WDB_CL_CTRL(channel), (union reut_pat_wdb_cl_ctrl_reg) { -+ .start_ptr = pat->start_ptr, -+ .end_ptr = pat->stop_ptr, -+ .inc_rate = is_linear ? pat->inc_rate : log2_ceil(pat->inc_rate), -+ .inc_scale = is_linear, -+ }.raw); -+ -+ /* Enable LMN in LMN or CADB modes, used to create lots of supply noise */ -+ const bool use_lmn = pat->dq_pattern == LMN_VA || pat->dq_pattern == CADB; -+ union reut_pat_wdb_cl_mux_cfg_reg pat_wdb_cl_mux_cfg = { -+ .mux_0_control = use_lmn ? REUT_MUX_LMN : REUT_MUX_LFSR, -+ .mux_1_control = REUT_MUX_LFSR, -+ .mux_2_control = REUT_MUX_LFSR, -+ .ecc_data_source_sel = 1, -+ }; -+ -+ /* Program LFSR save/restore, too complex unless everything is power of 2 */ -+ if (cmd_pat == PAT_ODT_TA || cmd_pat == PAT_WR_RD_TA) { -+ pat_wdb_cl_mux_cfg.reload_lfsr_seed_rate = log2_ceil(num_cl) + 1; -+ pat_wdb_cl_mux_cfg.save_lfsr_seed_rate = 1; -+ } -+ mchbar_write32(REUT_ch_PAT_WDB_CL_MUX_CFG(channel), pat_wdb_cl_mux_cfg.raw); -+ -+ /* Inversion mask is not used */ -+ mchbar_write32(REUT_ch_PAT_WDB_INV(channel), 0); -+ -+ /* Program error checking */ -+ const union reut_err_ctl_reg reut_err_ctl = { -+ .selective_err_enable_cacheline = 0xff, -+ .selective_err_enable_chunk = 0xff, -+ .stop_on_error_control = soe, -+ .stop_on_nth_error = 1, -+ }; -+ mchbar_write32(REUT_ch_ERR_CONTROL(channel), reut_err_ctl.raw); -+ mchbar_write64(REUT_ch_ERR_DATA_MASK(channel), 0); -+ mchbar_write8(REUT_ch_ERR_ECC_MASK(channel), 0); -+ } -+ -+ /* Always do a ZQ short before the beginning of a test */ -+ reut_issue_zq(ctrl, chanmask, ZQ_SHORT); -+} -+ -+void setup_io_test_cadb( -+ struct sysinfo *ctrl, -+ const uint8_t chanmask, -+ const uint8_t lc, -+ const enum test_stop soe) -+{ -+ const struct reut_box reut_addr = { -+ .rank = { -+ .start = 0, -+ .stop = 0, -+ .inc_rate = 32, -+ .inc_val = 1, -+ }, -+ .bank = { -+ .start = 0, -+ .stop = 7, -+ .inc_rate = 3, -+ .inc_val = 1, -+ }, -+ .row = { -+ .start = 0, -+ .stop = 2047, -+ .inc_rate = 3, -+ .inc_val = 73, -+ }, -+ .col = { -+ .start = 0, -+ .stop = 1023, -+ .inc_rate = 0, -+ .inc_val = 53, -+ }, -+ }; -+ const struct wdb_pat pattern = { -+ .start_ptr = 0, -+ .stop_ptr = 9, -+ .inc_rate = 4, -+ .dq_pattern = CADB, -+ }; -+ setup_io_test( -+ ctrl, -+ chanmask, -+ PAT_WR_RD, -+ 128, -+ lc, -+ &reut_addr, -+ soe, -+ &pattern, -+ 1, -+ 0); -+ -+ ctrl->dq_pat_lc = MAX(lc - 2 - 3, 0) + 1; -+ ctrl->dq_pat = CADB; -+} -+ -+void setup_io_test_basic_va( -+ struct sysinfo *ctrl, -+ const uint8_t chanmask, -+ const uint8_t lc, -+ const enum test_stop soe) -+{ -+ const uint32_t spread = 8; -+ const struct reut_box reut_addr = { -+ .rank = { -+ .start = 0, -+ .stop = 0, -+ .inc_rate = 32, -+ .inc_val = 1, -+ }, -+ .col = { -+ .start = 0, -+ .stop = 1023, -+ .inc_rate = 0, -+ .inc_val = 1, -+ }, -+ }; -+ const struct wdb_pat pattern = { -+ .start_ptr = 0, -+ .stop_ptr = spread - 1, -+ .inc_rate = 4, -+ .dq_pattern = BASIC_VA, -+ }; -+ setup_io_test( -+ ctrl, -+ chanmask, -+ PAT_WR_RD, -+ 128, -+ lc, -+ &reut_addr, -+ soe, -+ &pattern, -+ 0, -+ 0); -+ -+ ctrl->dq_pat_lc = MAX(lc - 8, 0) + 1; -+ ctrl->dq_pat = BASIC_VA; -+} -+ -+void setup_io_test_mpr( -+ struct sysinfo *ctrl, -+ const uint8_t chanmask, -+ const uint8_t lc, -+ const enum test_stop soe) -+{ -+ const struct reut_box reut_addr_ddr = { -+ .rank = { -+ .start = 0, -+ .stop = 0, -+ .inc_rate = 32, -+ .inc_val = 1, -+ }, -+ .col = { -+ .start = 0, -+ .stop = 1023, -+ .inc_rate = 0, -+ .inc_val = 1, -+ }, -+ }; -+ const struct reut_box reut_addr_lpddr = { -+ .bank = { -+ .start = 4, -+ .stop = 4, -+ .inc_rate = 0, -+ .inc_val = 0, -+ }, -+ }; -+ const struct wdb_pat pattern = { -+ .start_ptr = 0, -+ .stop_ptr = 9, -+ .inc_rate = 4, -+ .dq_pattern = BASIC_VA, -+ }; -+ setup_io_test( -+ ctrl, -+ chanmask, -+ PAT_RD, -+ 128, -+ lc, -+ ctrl->lpddr ? &reut_addr_lpddr : &reut_addr_ddr, -+ soe, -+ &pattern, -+ 0, -+ 0); -+ -+ ctrl->dq_pat_lc = 1; -+ ctrl->dq_pat = BASIC_VA; -+} -+ -+uint8_t select_reut_ranks(struct sysinfo *ctrl, const uint8_t channel, uint8_t rankmask) -+{ -+ rankmask &= ctrl->rankmap[channel]; -+ -+ uint8_t rank_count = 0; -+ uint32_t rank_log_to_phys = 0; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_mask(rank, rankmask)) -+ continue; -+ -+ rank_log_to_phys |= rank << (4 * rank_count); -+ rank_count++; -+ } -+ mchbar_write32(REUT_ch_RANK_LOG_TO_PHYS(channel), rank_log_to_phys); -+ -+ union reut_seq_cfg_reg reut_seq_cfg = { -+ .raw = mchbar_read64(REUT_ch_SEQ_CFG(channel)), -+ }; -+ if (!rank_count) { -+ reut_seq_cfg.global_control = 0; -+ mchbar_write64(REUT_ch_SEQ_CFG(channel), reut_seq_cfg.raw); -+ return 0; -+ } -+ union reut_seq_base_addr_reg reut_seq_addr_stop = { -+ .raw = mchbar_read64(REUT_ch_SEQ_ADDR_WRAP(channel)), -+ }; -+ reut_seq_addr_stop.rank_addr = rank_count - 1; -+ mchbar_write64(REUT_ch_SEQ_ADDR_WRAP(channel), reut_seq_addr_stop.raw); -+ -+ reut_seq_cfg.global_control = 1; -+ mchbar_write64(REUT_ch_SEQ_CFG(channel), reut_seq_cfg.raw); -+ return BIT(channel); -+} -+ -+void run_mpr_io_test(const bool clear_errors) -+{ -+ io_reset(); -+ mchbar_write32(REUT_GLOBAL_CTL, (union reut_seq_ctl_reg) { -+ .start_test = 1, -+ .clear_errors = clear_errors, -+ }.raw); -+ tick_delay(2); -+ io_reset(); -+ tick_delay(2); -+ mchbar_write32(REUT_GLOBAL_CTL, (union reut_seq_ctl_reg) { -+ .stop_test = 1, -+ }.raw); -+} -+ -+static uint8_t get_num_tests(const uint8_t dq_pat) -+{ -+ switch (dq_pat) { -+ case SEGMENT_WDB: return 4; -+ case CADB: return 7; -+ case TURN_AROUND_WR: return 8; -+ case TURN_AROUND_ODT: return 4; -+ case RD_RD_TA: return 2; -+ case RD_RD_TA_ALL: return 8; -+ default: return 1; -+ } -+} -+ -+uint8_t run_io_test( -+ struct sysinfo *const ctrl, -+ const uint8_t chanmask, -+ const uint8_t dq_pat, -+ const bool clear_errors) -+{ -+ /* SEGMENT_WDB only runs 4 tests */ -+ const uint8_t segment_wdb_lc[4] = { 0, 0, 4, 2 }; -+ const union reut_pat_wdb_cl_ctrl_reg pat_wdb_cl[4] = { -+ [0] = { -+ .start_ptr = 0, -+ .end_ptr = 9, -+ .inc_rate = 25, -+ .inc_scale = SCALE_LINEAR, -+ }, -+ [1] = { -+ .start_ptr = 0, -+ .end_ptr = 9, -+ .inc_rate = 25, -+ .inc_scale = SCALE_LINEAR, -+ }, -+ [2] = { -+ .start_ptr = 10, -+ .end_ptr = 63, -+ .inc_rate = 19, -+ .inc_scale = SCALE_LINEAR, -+ }, -+ [3] = { -+ .start_ptr = 10, -+ .end_ptr = 63, -+ .inc_rate = 10, -+ .inc_scale = SCALE_LINEAR, -+ }, -+ }; -+ const bool is_turnaround = dq_pat == RD_RD_TA || dq_pat == RD_RD_TA_ALL; -+ const uint8_t num_tests = get_num_tests(dq_pat); -+ union tc_bank_rank_a_reg tc_bank_rank_a[NUM_CHANNELS] = { 0 }; -+ if (is_turnaround) { -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!(chanmask & BIT(channel))) -+ continue; -+ -+ tc_bank_rank_a[channel].raw = ctrl->tc_bankrank_a[channel].raw; -+ } -+ } -+ for (uint8_t t = 0; t < num_tests; t++) { -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!(chanmask & BIT(channel))) -+ continue; -+ -+ if (dq_pat == SEGMENT_WDB) { -+ mchbar_write32(REUT_ch_WDB_CL_CTRL(channel), pat_wdb_cl[t].raw); -+ /* -+ * Skip programming LFSR save/restore. Too complex -+ * unless power of 2. Program desired loopcount. -+ */ -+ const uint8_t pat_lc = ctrl->dq_pat_lc + segment_wdb_lc[t]; -+ program_loop_count(ctrl, channel, pat_lc); -+ } else if (dq_pat == CADB) { -+ setup_cadb(ctrl, channel, num_tests, t); -+ } else if (dq_pat == TURN_AROUND_WR || dq_pat == TURN_AROUND_ODT) { -+ union reut_seq_cfg_reg reut_seq_cfg = { -+ .raw = mchbar_read64(REUT_ch_SEQ_CFG(channel)), -+ }; -+ reut_seq_cfg.subsequence_start_pointer = t; -+ reut_seq_cfg.subsequence_end_pointer = t; -+ mchbar_write64(REUT_ch_SEQ_CFG(channel), reut_seq_cfg.raw); -+ union reut_seq_addr_inc_ctl_reg addr_inc_ctl = { -+ .raw = mchbar_read64(REUT_ch_SEQ_ADDR_INC_CTL(channel)), -+ }; -+ uint8_t ta_inc_rate = 1; -+ if (dq_pat == TURN_AROUND_WR && (t == 0 || t == 7)) -+ ta_inc_rate = 0; -+ else if (dq_pat == TURN_AROUND_ODT && (t == 0 || t == 2)) -+ ta_inc_rate = 0; -+ -+ /* Program increment rate as linear value */ -+ addr_inc_ctl.rank_addr_update = BIT(7) | ta_inc_rate; -+ addr_inc_ctl.col_addr_update = BIT(7) | ta_inc_rate; -+ mchbar_write64(REUT_ch_SEQ_ADDR_INC_CTL(channel), -+ addr_inc_ctl.raw); -+ } else if (dq_pat == RD_RD_TA) { -+ tc_bank_rank_a[channel].tRDRD_sr = (t == 0) ? 4 : 5; -+ mchbar_write32(TC_BANK_RANK_A_ch(channel), -+ tc_bank_rank_a[channel].raw); -+ } else if (dq_pat == RD_RD_TA_ALL) { -+ /* -+ * Program tRDRD for SR and DR. Run 8 tests, covering -+ * tRDRD_sr = 4, 5, 6, 7 and tRDRD_dr = min, +1, +2, +3 -+ */ -+ const uint32_t tRDRD_dr = ctrl->tc_bankrank_a[channel].tRDRD_dr; -+ tc_bank_rank_a[channel].tRDRD_sr = (t % 4) + 4; -+ tc_bank_rank_a[channel].tRDRD_dr = (t % 4) + tRDRD_dr; -+ mchbar_write32(TC_BANK_RANK_A_ch(channel), -+ tc_bank_rank_a[channel].raw); -+ -+ /* Program linear rank increment rate */ -+ union reut_seq_addr_inc_ctl_reg addr_inc_ctl = { -+ .raw = mchbar_read64(REUT_ch_SEQ_ADDR_INC_CTL(channel)), -+ }; -+ addr_inc_ctl.rank_addr_update = BIT(7) | (t / 4) ? 0 : 31; -+ mchbar_write64(REUT_ch_SEQ_ADDR_INC_CTL(channel), -+ addr_inc_ctl.raw); -+ } -+ } -+ bool test_soe = false; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!(chanmask & BIT(channel))) -+ continue; -+ -+ const union reut_err_ctl_reg reut_err_ctl = { -+ .raw = mchbar_read32(REUT_ch_ERR_CONTROL(channel)), -+ }; -+ const uint8_t soe = reut_err_ctl.stop_on_error_control; -+ if (soe != NSOE) { -+ test_soe = true; -+ break; -+ } -+ } -+ io_reset(); -+ mchbar_write32(REUT_GLOBAL_CTL, (union reut_seq_ctl_reg) { -+ .start_test = 1, -+ .clear_errors = clear_errors && t == 0, -+ }.raw); -+ struct mono_time prev, curr; -+ timer_monotonic_get(&prev); -+ union reut_global_err_reg global_err; -+ do { -+ global_err.raw = mchbar_read32(REUT_GLOBAL_ERR); -+ /** TODO: Clean up this mess **/ -+ timer_monotonic_get(&curr); -+ if (mono_time_diff_microseconds(&prev, &curr) > 1000 * 1000) { -+ mchbar_write32(REUT_GLOBAL_CTL, (union reut_seq_ctl_reg) { -+ .stop_test = 1, -+ }.raw); -+ printk(BIOS_ERR, "REUT timed out, ch_done: %x\n", -+ global_err.ch_test_done); -+ break; -+ } -+ } while ((global_err.ch_test_done & chanmask) != chanmask); -+ if (test_soe && global_err.ch_error & chanmask) -+ break; -+ } -+ if (is_turnaround) { -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!(chanmask & BIT(channel))) -+ continue; -+ -+ mchbar_write32(TC_BANK_RANK_A_ch(channel), -+ ctrl->tc_bankrank_a[channel].raw); -+ } -+ } -+ return ((union reut_global_err_reg)mchbar_read32(REUT_GLOBAL_ERR)).ch_error; -+} -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index f8408e51a0..817a9f8bf8 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -94,20 +94,35 @@ - #define TC_BANK_RANK_D_ch(ch) _MCMAIN_C(0x4014, ch) - #define SC_ROUNDT_LAT_ch(ch) _MCMAIN_C(0x4024, ch) - -+#define REUT_ch_PAT_WDB_CL_MUX_CFG(ch) _MCMAIN_C(0x4040, ch) -+ - #define REUT_ch_PAT_WDB_CL_MUX_WR_x(ch, x) _MCMAIN_C_X(0x4048, ch, x) /* x in 0 .. 2 */ - #define REUT_ch_PAT_WDB_CL_MUX_RD_x(ch, x) _MCMAIN_C_X(0x4054, ch, x) /* x in 0 .. 2 */ - - #define REUT_ch_PAT_WDB_CL_MUX_LMN(ch) _MCMAIN_C(0x4078, ch) - -+#define REUT_ch_PAT_WDB_INV(ch) _MCMAIN_C(0x4084, ch) -+ -+#define REUT_ch_ERR_CONTROL(ch) _MCMAIN_C(0x4098, ch) -+#define REUT_ch_ERR_ECC_MASK(ch) _MCMAIN_C(0x409c, ch) -+ - #define SC_WR_ADD_DELAY_ch(ch) _MCMAIN_C(0x40d0, ch) - -+#define REUT_ch_ERR_DATA_MASK(ch) _MCMAIN_C(0x40d8, ch) -+ - #define REUT_ch_MISC_CKE_CTRL(ch) _MCMAIN_C(0x4190, ch) - -+#define REUT_ch_MISC_PAT_CADB_CTRL(ch) _MCMAIN_C(0x4198, ch) - #define REUT_ch_PAT_CADB_MRS(ch) _MCMAIN_C(0x419c, ch) -+#define REUT_ch_PAT_CADB_MUX_CTRL(ch) _MCMAIN_C(0x41a0, ch) -+#define REUT_ch_PAT_CADB_MUX_x(ch, x) _MCMAIN_C_X(0x41a4, ch, x) /* x in 0 .. 2 */ - -+#define REUT_ch_PAT_CADB_CL_MUX_LMN(ch) _MCMAIN_C(0x41b0, ch) - #define REUT_ch_PAT_CADB_WRITE_PTR(ch) _MCMAIN_C(0x41bc, ch) - #define REUT_ch_PAT_CADB_PROG(ch) _MCMAIN_C(0x41c0, ch) - -+#define REUT_ch_WDB_CL_CTRL(ch) _MCMAIN_C(0x4200, ch) -+ - #define TC_ZQCAL_ch(ch) _MCMAIN_C(0x4290, ch) - #define TC_RFP_ch(ch) _MCMAIN_C(0x4294, ch) - #define TC_RFTP_ch(ch) _MCMAIN_C(0x4298, ch) -@@ -119,12 +134,27 @@ - #define QCLK_ch_LDAT_SDAT(ch) _MCMAIN_C(0x42d4, ch) - #define QCLK_ch_LDAT_DATA_IN_x(ch, x) _MCMAIN_C_X(0x42dc, ch, x) /* x in 0 .. 1 */ - -+#define REUT_GLOBAL_CTL 0x4800 - #define REUT_GLOBAL_ERR 0x4804 - -+#define REUT_ch_SUBSEQ_x_CTL(ch, x) (0x4808 + 40 * (ch) + 4 * (x)) -+ - #define REUT_ch_SEQ_CFG(ch) (0x48a8 + 8 * (ch)) - - #define REUT_ch_SEQ_CTL(ch) (0x48b8 + 4 * (ch)) - -+#define REUT_ch_SEQ_ADDR_START(ch) (0x48d8 + 8 * (ch)) -+ -+#define REUT_ch_SEQ_ADDR_WRAP(ch) (0x48e8 + 8 * (ch)) -+ -+#define REUT_ch_SEQ_MISC_CTL(ch) (0x4908 + 4 * (ch)) -+ -+#define REUT_ch_SEQ_ADDR_INC_CTL(ch) (0x4910 + 8 * (ch)) -+ -+#define REUT_ch_RANK_LOG_TO_PHYS(ch) (0x4930 + 4 * (ch)) /* 4 bits per rank */ -+ -+#define HSW_REUT_ch_SEQ_LOOP_COUNT(ch) (0x4980 + 4 * (ch)) /* *** only on C0 *** */ -+ - /* MCMAIN broadcast */ - #define MCSCHEDS_CBIT 0x4c20 - --- -2.39.5 - diff --git a/config/coreboot/default/patches/0038-do-not-break-building-other-thinkpads-with-the-hacks.patch b/config/coreboot/default/patches/0038-do-not-break-building-other-thinkpads-with-the-hacks.patch new file mode 100644 index 00000000..87cde056 --- /dev/null +++ b/config/coreboot/default/patches/0038-do-not-break-building-other-thinkpads-with-the-hacks.patch @@ -0,0 +1,153 @@ +From 49204919e885dca2be45ffbaf2f5af62109ec3a7 Mon Sep 17 00:00:00 2001 +From: gaspar-ilom <gasparilom@riseup.net> +Date: Thu, 6 Mar 2025 23:00:00 +0000 +Subject: [PATCH 1/1] do not break building other thinkpads with the hacks for + the t480/s made Mate Kukri + +still not fixing things properly but at least it should now be possible to build older thinkpads without regressions. +prior, some code was just commented or unreachable. now we make this explicit with preprocessor directives. +heads should build all boards on this coreboot version from the same coreboot tree. + +Signed-off-by: gaspar-ilom <gasparilom@riseup.net> +--- + src/device/pci_rom.c | 9 ++++++--- + src/ec/lenovo/h8/acpi/ec.asl | 4 +++- + src/ec/lenovo/h8/bluetooth.c | 14 ++++++++++---- + src/ec/lenovo/h8/wwan.c | 14 ++++++++++---- + 4 files changed, 29 insertions(+), 12 deletions(-) + +diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c +index bba98d9dea..db3dbbe2ce 100644 +--- a/src/device/pci_rom.c ++++ b/src/device/pci_rom.c +@@ -396,16 +396,19 @@ void pci_rom_ssdt(const struct device *device) + rom = cbrom; + } + +-#if 0 ++ ++ #if CONFIG(BOARD_LENOVO_SKLKBL_THINKPAD_COMMON) ++ const char *scope = "\\_SB.PCI0.RP01.PEGP"; ++ #else + const char *scope = acpi_device_path(device); ++ #endif + if (!scope) { + printk(BIOS_ERR, "%s: Missing ACPI scope\n", dev_path(device)); + return; + } +-#endif + + /* write _ROM method */ +- acpigen_write_scope("\\_SB.PCI0.RP01.PEGP"); ++ acpigen_write_scope(scope); + acpigen_write_rom((void *)rom, rom->size * 512); + acpigen_pop_len(); /* pop scope */ + } +diff --git a/src/ec/lenovo/h8/acpi/ec.asl b/src/ec/lenovo/h8/acpi/ec.asl +index 8f4a8e1986..f80c15106c 100644 +--- a/src/ec/lenovo/h8/acpi/ec.asl ++++ b/src/ec/lenovo/h8/acpi/ec.asl +@@ -331,7 +331,9 @@ Device(EC) + #include "sleepbutton.asl" + #include "lid.asl" + #include "beep.asl" +-//#include "thermal.asl" ++#if !CONFIG(BOARD_LENOVO_SKLKBL_THINKPAD_COMMON) ++#include "thermal.asl" ++#endif + #include "systemstatus.asl" + #include "thinkpad.asl" + } +diff --git a/src/ec/lenovo/h8/bluetooth.c b/src/ec/lenovo/h8/bluetooth.c +index be71a24ced..e60b6c088c 100644 +--- a/src/ec/lenovo/h8/bluetooth.c ++++ b/src/ec/lenovo/h8/bluetooth.c +@@ -1,6 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + +-// #include <southbridge/intel/common/gpio.h> ++#if !CONFIG(BOARD_LENOVO_SKLKBL_THINKPAD_COMMON) ++#include <southbridge/intel/common/gpio.h> ++#endif + #include <console/console.h> + #include <device/device.h> + #include <ec/acpi/ec.h> +@@ -26,23 +28,27 @@ void h8_bluetooth_enable(int on) + */ + bool h8_has_bdc(const struct device *dev) + { ++ #if CONFIG(BOARD_LENOVO_SKLKBL_THINKPAD_COMMON) ++ printk(BIOS_INFO, "H8: BDC detection not implemented. " ++ "Assuming BDC installed\n"); ++ return true; ++ #else + struct ec_lenovo_h8_config *conf = dev->chip_info; + +- if (1 || !conf->has_bdc_detection) { ++ if (!conf->has_bdc_detection) { + printk(BIOS_INFO, "H8: BDC detection not implemented. " + "Assuming BDC installed\n"); + return true; + } + +-#if 0 + if (get_gpio(conf->bdc_gpio_num) == conf->bdc_gpio_lvl) { + printk(BIOS_INFO, "H8: BDC installed\n"); + return true; + } +-#endif + + printk(BIOS_INFO, "H8: BDC not installed\n"); + return false; ++ #endif + } + + /* +diff --git a/src/ec/lenovo/h8/wwan.c b/src/ec/lenovo/h8/wwan.c +index 5cdcf77406..b4f5787e01 100644 +--- a/src/ec/lenovo/h8/wwan.c ++++ b/src/ec/lenovo/h8/wwan.c +@@ -1,6 +1,8 @@ + /* SPDX-License-Identifier: GPL-2.0-only */ + +-// #include <southbridge/intel/common/gpio.h> ++#if !CONFIG(BOARD_LENOVO_SKLKBL_THINKPAD_COMMON) ++#include <southbridge/intel/common/gpio.h> ++#endif + #include <console/console.h> + #include <device/device.h> + #include <ec/acpi/ec.h> +@@ -24,23 +26,27 @@ void h8_wwan_enable(int on) + */ + bool h8_has_wwan(const struct device *dev) + { ++ #if CONFIG(BOARD_LENOVO_SKLKBL_THINKPAD_COMMON) ++ printk(BIOS_INFO, "H8: WWAN detection not implemented. " ++ "Assuming WWAN installed\n"); ++ return true; ++ #else + struct ec_lenovo_h8_config *conf = dev->chip_info; + +- if (1 || !conf->has_wwan_detection) { ++ if (!conf->has_wwan_detection) { + printk(BIOS_INFO, "H8: WWAN detection not implemented. " + "Assuming WWAN installed\n"); + return true; + } + +-#if 0 + if (get_gpio(conf->wwan_gpio_num) == conf->wwan_gpio_lvl) { + printk(BIOS_INFO, "H8: WWAN installed\n"); + return true; + } +-#endif + + printk(BIOS_INFO, "H8: WWAN not installed\n"); + return false; ++ #endif + } + + /* +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0038-haswell-NRI-Add-range-tracking-library.patch b/config/coreboot/default/patches/0038-haswell-NRI-Add-range-tracking-library.patch deleted file mode 100644 index 45fdc951..00000000 --- a/config/coreboot/default/patches/0038-haswell-NRI-Add-range-tracking-library.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 36b206a88281796458e6ebc30fe34a7c51c86548 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sun, 8 May 2022 00:56:00 +0200 -Subject: [PATCH 38/51] haswell NRI: Add range tracking library - -Implement a small library used to keep track of passing ranges. This -will be used by 1D training algorithms when margining some parameter. - -Change-Id: I8718e85165160afd7c0c8e730b5ce6c9c00f8a60 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../intel/haswell/native_raminit/ranges.c | 109 ++++++++++++++++++ - .../intel/haswell/native_raminit/ranges.h | 68 +++++++++++ - 3 files changed, 178 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/ranges.c - create mode 100644 src/northbridge/intel/haswell/native_raminit/ranges.h - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index 6e1b365602..2da950771d 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -9,6 +9,7 @@ romstage-y += io_comp_control.c - romstage-y += memory_map.c - romstage-y += raminit_main.c - romstage-y += raminit_native.c -+romstage-y += ranges.c - romstage-y += reut.c - romstage-y += setup_wdb.c - romstage-y += spd_bitmunching.c -diff --git a/src/northbridge/intel/haswell/native_raminit/ranges.c b/src/northbridge/intel/haswell/native_raminit/ranges.c -new file mode 100644 -index 0000000000..cdebc1fa66 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/ranges.c -@@ -0,0 +1,109 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <types.h> -+ -+#include "ranges.h" -+ -+void linear_record_pass( -+ struct linear_train_data *const data, -+ const bool pass, -+ const int32_t value, -+ const int32_t start, -+ const int32_t step) -+{ -+ /* If this is the first time, initialize all values */ -+ if (value == start) { -+ /* -+ * If value passed, create a zero-length region for the current value, -+ * which may be extended as long as the successive values are passing. -+ * -+ * Otherwise, create a zero-length range for the preceding value. This -+ * range cannot be extended by other passing values, which is desired. -+ */ -+ data->current.start = start - (pass ? 0 : step); -+ data->current.end = data->current.start; -+ data->largest = data->current; -+ } else if (pass) { -+ /* If this pass is not contiguous, it belongs to a new region */ -+ if (data->current.end != (value - step)) -+ data->current.start = value; -+ -+ /* Update end of current region */ -+ data->current.end = value; -+ -+ /* Update largest region */ -+ if (range_width(data->current) > range_width(data->largest)) -+ data->largest = data->current; -+ } -+} -+ -+void phase_record_pass( -+ struct phase_train_data *const data, -+ const bool pass, -+ const int32_t value, -+ const int32_t start, -+ const int32_t step) -+{ -+ /* If this is the first time, initialize all values */ -+ if (value == start) { -+ /* -+ * If value passed, create a zero-length region for the current value, -+ * which may be extended as long as the successive values are passing. -+ * -+ * Otherwise, create a zero-length range for the preceding value. This -+ * range cannot be extended by other passing values, which is desired. -+ */ -+ data->current.start = start - (pass ? 0 : step); -+ data->current.end = data->current.start; -+ data->largest = data->current; -+ data->initial = data->current; -+ return; -+ } -+ if (!pass) -+ return; -+ -+ /* Update initial region */ -+ if (data->initial.end == (value - step)) -+ data->initial.end = value; -+ -+ /* If this pass is not contiguous, it belongs to a new region */ -+ if (data->current.end != (value - step)) -+ data->current.start = value; -+ -+ /* Update end of current region */ -+ data->current.end = value; -+ -+ /* Update largest region */ -+ if (range_width(data->current) > range_width(data->largest)) -+ data->largest = data->current; -+} -+ -+void phase_append_initial_to_current( -+ struct phase_train_data *const data, -+ const int32_t start, -+ const int32_t step) -+{ -+ /* If initial region is valid and does not overlap, append it */ -+ if (data->initial.start == start && data->initial.end != data->current.end) -+ data->current.end += step + range_width(data->initial); -+ -+ /* Update largest region */ -+ if (range_width(data->current) > range_width(data->largest)) -+ data->largest = data->current; -+} -+ -+void phase_append_current_to_initial( -+ struct phase_train_data *const data, -+ const int32_t start, -+ const int32_t step) -+{ -+ /* If initial region is valid and does not overlap, append it */ -+ if (data->initial.start == start && data->initial.end != data->current.end) { -+ data->initial.start -= (step + range_width(data->current)); -+ data->current = data->initial; -+ } -+ -+ /* Update largest region */ -+ if (range_width(data->current) > range_width(data->largest)) -+ data->largest = data->current; -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/ranges.h b/src/northbridge/intel/haswell/native_raminit/ranges.h -new file mode 100644 -index 0000000000..235392df96 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/ranges.h -@@ -0,0 +1,68 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#ifndef HASWELL_RAMINIT_RANGES_H -+#define HASWELL_RAMINIT_RANGES_H -+ -+#include <types.h> -+ -+/* -+ * Many algorithms shmoo some parameter to determine the largest passing -+ * range. Provide a common implementation to avoid redundant boilerplate. -+ */ -+struct passing_range { -+ int32_t start; -+ int32_t end; -+}; -+ -+/* Structure for linear parameters, such as roundtrip delays */ -+struct linear_train_data { -+ struct passing_range current; -+ struct passing_range largest; -+}; -+ -+/* -+ * Phase ranges are "circular": the first and last indices are contiguous. -+ * To correctly determine the largest passing range, one has to combine -+ * the initial range and the current range when processing the last index. -+ */ -+struct phase_train_data { -+ struct passing_range initial; -+ struct passing_range current; -+ struct passing_range largest; -+}; -+ -+static inline int32_t range_width(const struct passing_range range) -+{ -+ return range.end - range.start; -+} -+ -+static inline int32_t range_center(const struct passing_range range) -+{ -+ return range.start + range_width(range) / 2; -+} -+ -+void linear_record_pass( -+ struct linear_train_data *data, -+ bool pass, -+ int32_t value, -+ int32_t start, -+ int32_t step); -+ -+void phase_record_pass( -+ struct phase_train_data *data, -+ bool pass, -+ int32_t value, -+ int32_t start, -+ int32_t step); -+ -+void phase_append_initial_to_current( -+ struct phase_train_data *data, -+ int32_t start, -+ int32_t step); -+ -+void phase_append_current_to_initial( -+ struct phase_train_data *data, -+ int32_t start, -+ int32_t step); -+ -+#endif --- -2.39.5 - diff --git a/config/coreboot/default/patches/0039-haswell-NRI-Add-library-to-change-margins.patch b/config/coreboot/default/patches/0039-haswell-NRI-Add-library-to-change-margins.patch deleted file mode 100644 index 401433ac..00000000 --- a/config/coreboot/default/patches/0039-haswell-NRI-Add-library-to-change-margins.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 926b1af1033c26ad231587fd3a4506efb4b0d8a3 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sun, 8 May 2022 01:11:03 +0200 -Subject: [PATCH 39/51] haswell NRI: Add library to change margins - -Implement a library to change Rx/Tx margins. It will be expanded later. - -Change-Id: I0b55aba428d8b4d4e16d2fbdec57235ce3ce8adf -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/change_margin.c | 154 ++++++++++++++++++ - .../haswell/native_raminit/raminit_native.h | 50 ++++++ - .../intel/haswell/registers/mchbar.h | 9 + - 4 files changed, 214 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/change_margin.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index 2da950771d..ebe9e9b762 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -1,5 +1,6 @@ - ## SPDX-License-Identifier: GPL-2.0-or-later - -+romstage-y += change_margin.c - romstage-y += configure_mc.c - romstage-y += ddr3.c - romstage-y += jedec_reset.c -diff --git a/src/northbridge/intel/haswell/native_raminit/change_margin.c b/src/northbridge/intel/haswell/native_raminit/change_margin.c -new file mode 100644 -index 0000000000..055c666eee ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/change_margin.c -@@ -0,0 +1,154 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <delay.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <timer.h> -+ -+#include "raminit_native.h" -+ -+void update_rxt( -+ struct sysinfo *ctrl, -+ const uint8_t channel, -+ const uint8_t rank, -+ const uint8_t byte, -+ const enum rxt_subfield subfield, -+ const int32_t value) -+{ -+ union ddr_data_rx_train_rank_reg rxt = { -+ .rcven = ctrl->rcven[channel][rank][byte], -+ .dqs_p = ctrl->rxdqsp[channel][rank][byte], -+ .rx_eq = ctrl->rx_eq[channel][rank][byte], -+ .dqs_n = ctrl->rxdqsn[channel][rank][byte], -+ .vref = ctrl->rxvref[channel][rank][byte], -+ }; -+ int32_t new_value; -+ switch (subfield) { -+ case RXT_RCVEN: -+ new_value = clamp_s32(0, value, 511); -+ rxt.rcven = new_value; -+ break; -+ case RXT_RXDQS_P: -+ new_value = clamp_s32(0, value, 63); -+ rxt.dqs_p = new_value; -+ break; -+ case RXT_RX_EQ: -+ new_value = clamp_s32(0, value, 31); -+ rxt.rx_eq = new_value; -+ break; -+ case RXT_RXDQS_N: -+ new_value = clamp_s32(0, value, 63); -+ rxt.dqs_n = new_value; -+ break; -+ case RXT_RX_VREF: -+ new_value = clamp_s32(-32, value, 31); -+ rxt.vref = new_value; -+ break; -+ case RXT_RXDQS_BOTH: -+ new_value = clamp_s32(0, value, 63); -+ rxt.dqs_p = new_value; -+ rxt.dqs_n = new_value; -+ break; -+ case RXT_RESTORE: -+ new_value = value; -+ break; -+ default: -+ die("%s: Unhandled subfield index %u\n", __func__, subfield); -+ } -+ -+ if (new_value != value) { -+ printk(BIOS_ERR, "%s: Overflow for subfield %u: %d ---> %d\n", -+ __func__, subfield, value, new_value); -+ } -+ mchbar_write32(RX_TRAIN_ch_r_b(channel, rank, byte), rxt.raw); -+ download_regfile(ctrl, channel, false, rank, REG_FILE_USE_RANK, byte, true, false); -+} -+ -+void update_txt( -+ struct sysinfo *ctrl, -+ const uint8_t channel, -+ const uint8_t rank, -+ const uint8_t byte, -+ const enum txt_subfield subfield, -+ const int32_t value) -+{ -+ union ddr_data_tx_train_rank_reg txt = { -+ .dq_delay = ctrl->tx_dq[channel][rank][byte], -+ .dqs_delay = ctrl->txdqs[channel][rank][byte], -+ .tx_eq = ctrl->tx_eq[channel][rank][byte], -+ }; -+ int32_t new_value; -+ switch (subfield) { -+ case TXT_TX_DQ: -+ new_value = clamp_s32(0, value, 511); -+ txt.dq_delay = new_value; -+ break; -+ case TXT_TXDQS: -+ new_value = clamp_s32(0, value, 511); -+ txt.dqs_delay = new_value; -+ break; -+ case TXT_TX_EQ: -+ new_value = clamp_s32(0, value, 63); -+ txt.tx_eq = new_value; -+ break; -+ case TXT_DQDQS_OFF: -+ new_value = value; -+ txt.dqs_delay += new_value; -+ txt.dq_delay += new_value; -+ break; -+ case TXT_RESTORE: -+ new_value = value; -+ break; -+ default: -+ die("%s: Unhandled subfield index %u\n", __func__, subfield); -+ } -+ if (new_value != value) { -+ printk(BIOS_ERR, "%s: Overflow for subfield %u: %d ---> %d\n", -+ __func__, subfield, value, new_value); -+ } -+ mchbar_write32(TX_TRAIN_ch_r_b(channel, rank, byte), txt.raw); -+ download_regfile(ctrl, channel, false, rank, REG_FILE_USE_RANK, byte, false, true); -+} -+ -+void download_regfile( -+ struct sysinfo *ctrl, -+ const uint8_t channel, -+ const bool multicast, -+ const uint8_t rank, -+ const enum regfile_mode regfile, -+ const uint8_t byte, -+ const bool read_rf_rd, -+ const bool read_rf_wr) -+{ -+ union reut_seq_base_addr_reg reut_seq_base_addr; -+ switch (regfile) { -+ case REG_FILE_USE_START: -+ reut_seq_base_addr.raw = mchbar_read64(REUT_ch_SEQ_ADDR_START(channel)); -+ break; -+ case REG_FILE_USE_CURRENT: -+ reut_seq_base_addr.raw = mchbar_read64(REUT_ch_SEQ_ADDR_CURRENT(channel)); -+ break; -+ case REG_FILE_USE_RANK: -+ reut_seq_base_addr.raw = 0; -+ if (rank >= NUM_SLOTRANKS) -+ die("%s: bad rank %u\n", __func__, rank); -+ break; -+ default: -+ die("%s: Invalid regfile param %u\n", __func__, regfile); -+ } -+ uint8_t phys_rank = rank; -+ if (reut_seq_base_addr.raw != 0) { -+ /* Map REUT logical rank to physical rank */ -+ const uint32_t log_to_phys = mchbar_read32(REUT_ch_RANK_LOG_TO_PHYS(channel)); -+ phys_rank = log_to_phys >> (reut_seq_base_addr.rank_addr * 4) & 0x3; -+ } -+ uint32_t reg = multicast ? DDR_DATA_ch_CONTROL_0(channel) : DQ_CONTROL_0(channel, byte); -+ union ddr_data_control_0_reg ddr_data_control_0 = { -+ .raw = mchbar_read32(reg), -+ }; -+ ddr_data_control_0.read_rf_rd = read_rf_rd; -+ ddr_data_control_0.read_rf_wr = read_rf_wr; -+ ddr_data_control_0.read_rf_rank = phys_rank; -+ mchbar_write32(reg, ddr_data_control_0.raw); -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index f029e7f076..8707257b27 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -118,6 +118,30 @@ enum test_stop { - ALSOE = 3, /* Stop on all lanes error */ - }; - -+enum rxt_subfield { -+ RXT_RCVEN = 0, -+ RXT_RXDQS_P = 1, -+ RXT_RX_EQ = 2, -+ RXT_RXDQS_N = 3, -+ RXT_RX_VREF = 4, -+ RXT_RXDQS_BOTH = 5, -+ RXT_RESTORE = 255, -+}; -+ -+enum txt_subfield { -+ TXT_TX_DQ = 0, -+ TXT_TXDQS = 1, -+ TXT_TX_EQ = 2, -+ TXT_DQDQS_OFF = 3, -+ TXT_RESTORE = 255, -+}; -+ -+enum regfile_mode { -+ REG_FILE_USE_RANK, /* Used when changing parameters for each rank */ -+ REG_FILE_USE_START, /* Used when changing parameters before the test */ -+ REG_FILE_USE_CURRENT, /* Used when changing parameters after the test */ -+}; -+ - struct wdb_pat { - uint32_t start_ptr; /* Starting pointer in WDB */ - uint32_t stop_ptr; /* Stopping pointer in WDB */ -@@ -451,6 +475,32 @@ uint8_t select_reut_ranks(struct sysinfo *ctrl, uint8_t channel, uint8_t rankmas - void run_mpr_io_test(bool clear_errors); - uint8_t run_io_test(struct sysinfo *ctrl, uint8_t chanmask, uint8_t dq_pat, bool clear_errors); - -+void update_rxt( -+ struct sysinfo *ctrl, -+ uint8_t channel, -+ uint8_t rank, -+ uint8_t byte, -+ enum rxt_subfield subfield, -+ int32_t value); -+ -+void update_txt( -+ struct sysinfo *ctrl, -+ uint8_t channel, -+ uint8_t rank, -+ uint8_t byte, -+ enum txt_subfield subfield, -+ int32_t value); -+ -+void download_regfile( -+ struct sysinfo *ctrl, -+ uint8_t channel, -+ bool multicast, -+ uint8_t rank, -+ enum regfile_mode regfile, -+ uint8_t byte, -+ bool read_rf_rd, -+ bool read_rf_wr); -+ - uint8_t get_rx_bias(const struct sysinfo *ctrl); - - uint8_t get_tCWL(uint32_t mem_clock_mhz); -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 817a9f8bf8..a81559bb1e 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -15,7 +15,11 @@ - /* Register definitions */ - - /* DDR DATA per-channel per-bytelane */ -+#define RX_TRAIN_ch_r_b(ch, rank, byte) _DDRIO_C_R_B(0x0000, ch, rank, byte) -+#define TX_TRAIN_ch_r_b(ch, rank, byte) _DDRIO_C_R_B(0x0020, ch, rank, byte) -+ - #define DQ_CONTROL_2(ch, byte) _DDRIO_C_R_B(0x0064, ch, 0, byte) -+#define DQ_CONTROL_0(ch, byte) _DDRIO_C_R_B(0x0074, ch, 0, byte) - - /* DDR CKE per-channel */ - #define DDR_CKE_ch_CMD_COMP_OFFSET(ch) _DDRIO_C_R_B(0x1204, ch, 0, 0) -@@ -38,6 +42,9 @@ - #define DDR_SCRAMBLE_ch(ch) (0x2000 + 4 * (ch)) - #define DDR_SCRAM_MISC_CONTROL 0x2008 - -+/* DDR DATA per-channel multicast */ -+#define DDR_DATA_ch_CONTROL_0(ch) _DDRIO_C_R_B(0x3074, ch, 0, 0) -+ - /* DDR CMDN/CMDS per-channel (writes go to both CMDN and CMDS fubs) */ - #define DDR_CMD_ch_COMP_OFFSET(ch) _DDRIO_C_R_B(0x3204, ch, 0, 0) - #define DDR_CMD_ch_PI_CODING(ch) _DDRIO_C_R_B(0x3208, ch, 0, 0) -@@ -147,6 +154,8 @@ - - #define REUT_ch_SEQ_ADDR_WRAP(ch) (0x48e8 + 8 * (ch)) - -+#define REUT_ch_SEQ_ADDR_CURRENT(ch) (0x48f8 + 8 * (ch)) -+ - #define REUT_ch_SEQ_MISC_CTL(ch) (0x4908 + 4 * (ch)) - - #define REUT_ch_SEQ_ADDR_INC_CTL(ch) (0x4910 + 8 * (ch)) --- -2.39.5 - diff --git a/config/coreboot/default/patches/0040-haswell-NRI-Add-RcvEn-training.patch b/config/coreboot/default/patches/0040-haswell-NRI-Add-RcvEn-training.patch deleted file mode 100644 index a40ffa69..00000000 --- a/config/coreboot/default/patches/0040-haswell-NRI-Add-RcvEn-training.patch +++ /dev/null @@ -1,708 +0,0 @@ -From 61435822eb1d65b919bec45076737ce4ea91e1b1 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sun, 8 May 2022 00:05:41 +0200 -Subject: [PATCH 40/51] haswell NRI: Add RcvEn training - -Implement the RcvEn (Receive Enable) calibration procedure. - -Change-Id: Ifbfa520f3e0486c56d0988ce67af2ddb9cf29888 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/raminit_main.c | 1 + - .../haswell/native_raminit/raminit_native.h | 14 + - .../haswell/native_raminit/reg_structs.h | 13 + - .../native_raminit/train_receive_enable.c | 561 ++++++++++++++++++ - .../intel/haswell/registers/mchbar.h | 3 + - 6 files changed, 593 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/train_receive_enable.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index ebe9e9b762..e2fbfb4211 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -16,3 +16,4 @@ romstage-y += setup_wdb.c - romstage-y += spd_bitmunching.c - romstage-y += testing_io.c - romstage-y += timings_refresh.c -+romstage-y += train_receive_enable.c -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 5e4674957d..7d444659c3 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -60,6 +60,7 @@ static const struct task_entry cold_boot[] = { - { configure_memory_map, true, "MEMMAP", }, - { do_jedec_init, true, "JEDECINIT", }, - { pre_training, true, "PRETRAIN", }, -+ { train_receive_enable, true, "RCVET", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 8707257b27..eaaaedad1e 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -43,6 +43,9 @@ - #define NUM_WDB_CL_MUX_SEEDS 3 - #define NUM_CADB_MUX_SEEDS 3 - -+/* Specified in PI ticks. 64 PI ticks == 1 qclk */ -+#define tDQSCK_DRIFT 64 -+ - /* ZQ calibration types */ - enum { - ZQ_INIT, /* DDR3: ZQCL with tZQinit, LPDDR3: ZQ Init with tZQinit */ -@@ -189,6 +192,7 @@ enum raminit_status { - RAMINIT_STATUS_MPLL_INIT_FAILURE, - RAMINIT_STATUS_POLL_TIMEOUT, - RAMINIT_STATUS_REUT_ERROR, -+ RAMINIT_STATUS_RCVEN_FAILURE, - RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/ - }; - -@@ -271,6 +275,10 @@ struct sysinfo { - - union ddr_data_vref_adjust_reg dimm_vref; - -+ uint8_t io_latency[NUM_CHANNELS][NUM_SLOTRANKS]; -+ uint8_t rt_latency[NUM_CHANNELS][NUM_SLOTRANKS]; -+ uint32_t rt_io_comp[NUM_CHANNELS]; -+ - uint32_t data_offset_train[NUM_CHANNELS][NUM_LANES]; - uint32_t data_offset_comp[NUM_CHANNELS][NUM_LANES]; - -@@ -345,6 +353,11 @@ static inline void clear_data_offset_train_all(struct sysinfo *ctrl) - memset(ctrl->data_offset_train, 0, sizeof(ctrl->data_offset_train)); - } - -+static inline uint32_t get_data_train_feedback(const uint8_t channel, const uint8_t byte) -+{ -+ return mchbar_read32(DDR_DATA_TRAIN_FEEDBACK(channel, byte)); -+} -+ - /* Number of ticks to wait in units of 69.841279 ns (citation needed) */ - static inline void tick_delay(const uint32_t delay) - { -@@ -400,6 +413,7 @@ enum raminit_status convert_timings(struct sysinfo *ctrl); - enum raminit_status configure_mc(struct sysinfo *ctrl); - enum raminit_status configure_memory_map(struct sysinfo *ctrl); - enum raminit_status do_jedec_init(struct sysinfo *ctrl); -+enum raminit_status train_receive_enable(struct sysinfo *ctrl); - - void configure_timings(struct sysinfo *ctrl); - void configure_refresh(struct sysinfo *ctrl); -diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -index b943259b91..b099f4bb82 100644 ---- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h -+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -@@ -297,6 +297,19 @@ union ddr_scram_misc_control_reg { - uint32_t raw; - }; - -+union sc_io_latency_reg { -+ struct __packed { -+ uint32_t iolat_rank0 : 4; // Bits 3:0 -+ uint32_t iolat_rank1 : 4; // Bits 7:4 -+ uint32_t iolat_rank2 : 4; // Bits 11:8 -+ uint32_t iolat_rank3 : 4; // Bits 15:12 -+ uint32_t rt_iocomp : 6; // Bits 21:16 -+ uint32_t : 9; // Bits 30:22 -+ uint32_t dis_rt_clk_gate : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ - union mcscheds_cbit_reg { - struct __packed { - uint32_t dis_opp_cas : 1; // Bits 0:0 -diff --git a/src/northbridge/intel/haswell/native_raminit/train_receive_enable.c b/src/northbridge/intel/haswell/native_raminit/train_receive_enable.c -new file mode 100644 -index 0000000000..576c6bc21e ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/train_receive_enable.c -@@ -0,0 +1,561 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <console/console.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+#include "ranges.h" -+ -+#define RCVEN_PLOT RAM_DEBUG -+ -+static enum raminit_status change_rcven_timing(struct sysinfo *ctrl, const uint8_t channel) -+{ -+ int16_t max_rcven = -4096; -+ int16_t min_rcven = 4096; -+ int16_t max_rcven_rank[NUM_SLOTRANKS]; -+ int16_t min_rcven_rank[NUM_SLOTRANKS]; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ max_rcven_rank[rank] = max_rcven; -+ min_rcven_rank[rank] = min_rcven; -+ } -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ int16_t new_rcven = ctrl->rcven[channel][rank][byte]; -+ new_rcven -= ctrl->io_latency[channel][rank] * 64; -+ if (max_rcven_rank[rank] < new_rcven) -+ max_rcven_rank[rank] = new_rcven; -+ -+ if (min_rcven_rank[rank] > new_rcven) -+ min_rcven_rank[rank] = new_rcven; -+ } -+ if (max_rcven < max_rcven_rank[rank]) -+ max_rcven = max_rcven_rank[rank]; -+ -+ if (min_rcven > min_rcven_rank[rank]) -+ min_rcven = min_rcven_rank[rank]; -+ } -+ -+ /* -+ * Determine how far we are from the ideal center point for RcvEn timing. -+ * (PiIdeal - AveRcvEn) / 64 is the ideal number of cycles we should have -+ * for IO latency. command training will reduce this by 64, so plan for -+ * that now in the ideal value. Round to closest integer. -+ */ -+ const int16_t rre_pi_ideal = 256 + 64; -+ const int16_t pi_reserve = 64; -+ const int16_t rcven_center = (max_rcven + min_rcven) / 2; -+ const int8_t iolat_target = DIV_ROUND_CLOSEST(rre_pi_ideal - rcven_center, 64); -+ -+ int8_t io_g_offset = 0; -+ int8_t io_lat[NUM_SLOTRANKS] = { 0 }; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ io_lat[rank] = iolat_target; -+ -+ /* Check for RcvEn underflow/overflow */ -+ const int16_t rcven_lower = 64 * io_lat[rank] + min_rcven_rank[rank]; -+ if (rcven_lower < pi_reserve) -+ io_lat[rank] += DIV_ROUND_UP(pi_reserve - rcven_lower, 64); -+ -+ const int16_t rcven_upper = 64 * io_lat[rank] + max_rcven_rank[rank]; -+ if (rcven_upper > 511 - pi_reserve) -+ io_lat[rank] -= DIV_ROUND_UP(rcven_upper - (511 - pi_reserve), 64); -+ -+ /* Check for IO latency over/underflow */ -+ if (io_lat[rank] - io_g_offset > 14) -+ io_g_offset = io_lat[rank] - 14; -+ -+ if (io_lat[rank] - io_g_offset < 1) -+ io_g_offset = io_lat[rank] - 1; -+ -+ const int8_t cycle_offset = io_lat[rank] - ctrl->io_latency[channel][rank]; -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ ctrl->rcven[channel][rank][byte] += 64 * cycle_offset; -+ update_rxt(ctrl, channel, rank, byte, RXT_RESTORE, 0); -+ } -+ } -+ -+ /* Calculate new IO comp latency */ -+ union sc_io_latency_reg sc_io_lat = { -+ .raw = mchbar_read32(SC_IO_LATENCY_ch(channel)), -+ }; -+ -+ /* Check if we are underflowing or overflowing this field */ -+ if (io_g_offset < 0 && sc_io_lat.rt_iocomp < -io_g_offset) { -+ printk(BIOS_ERR, "%s: IO COMP underflow\n", __func__); -+ printk(BIOS_ERR, "io_g_offset: %d\n", io_g_offset); -+ printk(BIOS_ERR, "rt_iocomp: %u\n", sc_io_lat.rt_iocomp); -+ return RAMINIT_STATUS_RCVEN_FAILURE; -+ } -+ if (io_g_offset > 0 && io_g_offset > 0x3f - sc_io_lat.rt_iocomp) { -+ printk(BIOS_ERR, "%s: IO COMP overflow\n", __func__); -+ printk(BIOS_ERR, "io_g_offset: %d\n", io_g_offset); -+ printk(BIOS_ERR, "rt_iocomp: %u\n", sc_io_lat.rt_iocomp); -+ return RAMINIT_STATUS_RCVEN_FAILURE; -+ } -+ sc_io_lat.rt_iocomp += io_g_offset; -+ ctrl->rt_io_comp[channel] = sc_io_lat.rt_iocomp; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (ctrl->rankmap[channel] & BIT(rank)) -+ ctrl->io_latency[channel][rank] = io_lat[rank] - io_g_offset; -+ -+ const uint8_t shift = rank * 4; -+ sc_io_lat.raw &= ~(0xf << shift); -+ sc_io_lat.raw |= ctrl->io_latency[channel][rank] << shift; -+ } -+ mchbar_write32(SC_IO_LATENCY_ch(channel), sc_io_lat.raw); -+ return RAMINIT_STATUS_SUCCESS; -+} -+ -+#define RL_START (256 + 24) -+#define RL_STOP (384 + 24) -+#define RL_STEP 8 -+ -+#define RE_NUM_SAMPLES 6 -+ -+static enum raminit_status verify_high_region(const int32_t center, const int32_t lwidth) -+{ -+ if (center > RL_STOP) { -+ /* Check if center of high was found where it should be */ -+ printk(BIOS_ERR, "RcvEn: Center of high (%d) higher than expected\n", center); -+ return RAMINIT_STATUS_RCVEN_FAILURE; -+ } -+ if (lwidth <= 32) { -+ /* Check if width is large enough */ -+ printk(BIOS_ERR, "RcvEn: Width of high region (%d) too small\n", lwidth); -+ return RAMINIT_STATUS_RCVEN_FAILURE; -+ } -+ if (lwidth >= 96) { -+ /* Since we're calibrating a phase, a too large region is a problem */ -+ printk(BIOS_ERR, "RcvEn: Width of high region (%d) too large\n", lwidth); -+ return RAMINIT_STATUS_RCVEN_FAILURE; -+ } -+ return RAMINIT_STATUS_SUCCESS; -+} -+ -+static void program_io_latency(struct sysinfo *ctrl, const uint8_t channel, const uint8_t rank) -+{ -+ const uint8_t shift = rank * 4; -+ const uint8_t iolat = ctrl->io_latency[channel][rank]; -+ mchbar_clrsetbits32(SC_IO_LATENCY_ch(channel), 0xf << shift, iolat << shift); -+} -+ -+static void program_rl_delays(struct sysinfo *ctrl, const uint8_t rank, const uint16_t rl_delay) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ update_rxt(ctrl, channel, rank, byte, RXT_RCVEN, rl_delay); -+ } -+} -+ -+static bool sample_dqs(const uint8_t channel, const uint8_t byte) -+{ -+ return (get_data_train_feedback(channel, byte) & 0x1ff) >= BIT(RE_NUM_SAMPLES - 1); -+} -+ -+enum raminit_status train_receive_enable(struct sysinfo *ctrl) -+{ -+ const struct reut_box reut_addr = { -+ .col = { -+ .start = 0, -+ .stop = 1023, -+ .inc_rate = 0, -+ .inc_val = 1, -+ }, -+ }; -+ const struct wdb_pat wdb_pattern = { -+ .start_ptr = 0, -+ .stop_ptr = 9, -+ .inc_rate = 32, -+ .dq_pattern = BASIC_VA, -+ }; -+ -+ const uint16_t bytemask = BIT(ctrl->lanes) - 1; -+ const uint8_t fine_step = 1; -+ -+ const uint8_t rt_delta = is_hsw_ult() ? 4 : 2; -+ const uint8_t rt_io_comp = 21 + rt_delta; -+ const uint8_t rt_latency = 16 + rt_delta; -+ setup_io_test( -+ ctrl, -+ ctrl->chanmap, -+ PAT_RD, -+ 2, -+ RE_NUM_SAMPLES + 1, -+ &reut_addr, -+ 0, -+ &wdb_pattern, -+ 0, -+ 8); -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ union ddr_data_control_2_reg data_control_2 = { -+ .raw = ctrl->dq_control_2[channel][byte], -+ }; -+ data_control_2.force_rx_on = 1; -+ mchbar_write32(DQ_CONTROL_2(channel, byte), data_control_2.raw); -+ } -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ if (ctrl->lpddr) { -+ /** -+ * W/A for b4618574 - @todo: remove for HSW ULT C0 -+ * Can't have force_odt_on together with leaker, disable LPDDR -+ * mode during this training step. lpddr_mode is restored -+ * at the end of this function from the host structure. -+ */ -+ data_control_0.lpddr_mode = 0; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ } -+ data_control_0.force_odt_on = 1; -+ data_control_0.rl_training_mode = 1; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ mchbar_write32(SC_IO_LATENCY_ch(channel), (union sc_io_latency_reg) { -+ .rt_iocomp = rt_io_comp, -+ }.raw); -+ } -+ enum raminit_status status = RAMINIT_STATUS_SUCCESS; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!does_rank_exist(ctrl, rank)) -+ continue; -+ -+ /* -+ * Set initial roundtrip latency values. Assume -4 QCLK for worst board -+ * layout. This is calculated as HW_ROUNDT_LAT_DEFAULT_VALUE plus: -+ * -+ * DDR3: Default + (2 * tAA) + 4 QCLK + PI_CLK + N-mode value * 2 -+ * LPDDR3: Default + (2 * tAA) + 4 QCLK + PI_CLK + tDQSCK_max -+ * -+ * N-mode is 3 during training mode. Both channels use the same timings. -+ */ -+ /** TODO: differs for LPDDR **/ -+ const uint32_t tmp = MAX(ctrl->multiplier, 4) + 5 + 2 * ctrl->tAA; -+ const uint32_t initial_rt_latency = MIN(rt_latency + tmp, 0x3f); -+ -+ uint8_t chanmask = 0; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ chanmask |= select_reut_ranks(ctrl, channel, BIT(rank)); -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ ctrl->io_latency[channel][rank] = 0; -+ mchbar_write8(SC_ROUNDT_LAT_ch(channel) + rank, initial_rt_latency); -+ ctrl->rt_latency[channel][rank] = initial_rt_latency; -+ } -+ -+ printk(BIOS_DEBUG, "Rank %u\n", rank); -+ printk(BIOS_DEBUG, "Steps 1 and 2: Find middle of high region\n"); -+ printk(RCVEN_PLOT, "Byte"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(RCVEN_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(RCVEN_PLOT, "%u ", byte); -+ } -+ printk(RCVEN_PLOT, "\nRcvEn\n"); -+ struct phase_train_data region_data[NUM_CHANNELS][NUM_LANES] = { 0 }; -+ for (uint16_t rl_delay = RL_START; rl_delay < RL_STOP; rl_delay += RL_STEP) { -+ printk(RCVEN_PLOT, " % 3d", rl_delay); -+ program_rl_delays(ctrl, rank, rl_delay); -+ run_io_test(ctrl, chanmask, BASIC_VA, true); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(RCVEN_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const bool high = sample_dqs(channel, byte); -+ printk(RCVEN_PLOT, high ? ". " : "# "); -+ phase_record_pass( -+ ®ion_data[channel][byte], -+ high, -+ rl_delay, -+ RL_START, -+ RL_STEP); -+ } -+ } -+ printk(RCVEN_PLOT, "\n"); -+ } -+ printk(RCVEN_PLOT, "\n"); -+ printk(BIOS_DEBUG, "Update RcvEn timing to be in the center of high region\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(BIOS_DEBUG, "C%u.R%u: \tLeft\tRight\tWidth\tCenter\n", -+ channel, rank); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ struct phase_train_data *const curr_data = -+ ®ion_data[channel][byte]; -+ phase_append_current_to_initial(curr_data, RL_START, RL_STEP); -+ const int32_t lwidth = range_width(curr_data->largest); -+ const int32_t center = range_center(curr_data->largest); -+ printk(BIOS_DEBUG, " B%u: \t%d\t%d\t%d\t%d\n", -+ byte, -+ curr_data->largest.start, -+ curr_data->largest.end, -+ lwidth, -+ center); -+ -+ status = verify_high_region(center, lwidth); -+ if (status) { -+ printk(BIOS_ERR, -+ "RcvEn problems on channel %u, byte %u\n", -+ channel, byte); -+ goto clean_up; -+ } -+ ctrl->rcven[channel][rank][byte] = center; -+ update_rxt(ctrl, channel, rank, byte, RXT_RESTORE, 0); -+ } -+ printk(BIOS_DEBUG, "\n"); -+ } -+ -+ printk(BIOS_DEBUG, "Step 3: Quarter preamble - Walk backwards\n"); -+ printk(RCVEN_PLOT, "Byte"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(RCVEN_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(RCVEN_PLOT, "%u ", byte); -+ } -+ printk(RCVEN_PLOT, "\nIOLAT\n"); -+ bool done = false; -+ while (!done) { -+ run_io_test(ctrl, chanmask, BASIC_VA, true); -+ done = true; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(RCVEN_PLOT, " %2u\t", ctrl->io_latency[channel][rank]); -+ uint16_t highs = 0; -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const bool high = sample_dqs(channel, byte); -+ printk(RCVEN_PLOT, high ? "H " : "L "); -+ if (high) -+ highs |= BIT(byte); -+ } -+ if (!highs) -+ continue; -+ -+ done = false; -+ -+ /* If all bytes sample high, adjust timing globally */ -+ if (highs == bytemask && ctrl->io_latency[channel][rank] < 14) { -+ ctrl->io_latency[channel][rank] += 2; -+ ctrl->io_latency[channel][rank] %= 16; -+ program_io_latency(ctrl, channel, rank); -+ continue; -+ } -+ -+ /* Otherwise, adjust individual bytes */ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ if (!(highs & BIT(byte))) -+ continue; -+ -+ if (ctrl->rcven[channel][rank][byte] < 128) { -+ printk(BIOS_ERR, -+ "RcvEn underflow: walking backwards\n"); -+ printk(BIOS_ERR, -+ "For channel %u, rank %u, byte %u\n", -+ channel, rank, byte); -+ status = RAMINIT_STATUS_RCVEN_FAILURE; -+ goto clean_up; -+ } -+ ctrl->rcven[channel][rank][byte] -= 128; -+ update_rxt(ctrl, channel, rank, byte, RXT_RESTORE, 0); -+ } -+ } -+ printk(RCVEN_PLOT, "\n"); -+ } -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(BIOS_DEBUG, "\nC%u: Preamble\n", channel); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ printk(BIOS_DEBUG, -+ " B%u: %u\n", byte, ctrl->rcven[channel][rank][byte]); -+ } -+ } -+ printk(BIOS_DEBUG, "\n"); -+ -+ printk(BIOS_DEBUG, "Step 4: Add 1 qclk\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ ctrl->rcven[channel][rank][byte] += 64; -+ update_rxt(ctrl, channel, rank, byte, RXT_RESTORE, 0); -+ } -+ } -+ printk(BIOS_DEBUG, "\n"); -+ -+ printk(BIOS_DEBUG, "Step 5: Walk forward to find rising edge\n"); -+ printk(RCVEN_PLOT, "Byte"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(RCVEN_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(RCVEN_PLOT, "%u ", byte); -+ } -+ printk(RCVEN_PLOT, "\n inc\n"); -+ uint16_t ch_result[NUM_CHANNELS] = { 0 }; -+ uint8_t inc_preamble[NUM_CHANNELS][NUM_LANES] = { 0 }; -+ for (uint8_t inc = 0; inc < 64; inc += fine_step) { -+ printk(RCVEN_PLOT, " %2u\t", inc); -+ run_io_test(ctrl, chanmask, BASIC_VA, true); -+ done = true; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ if (ch_result[channel] & BIT(byte)) { -+ /* Skip bytes that are already done */ -+ printk(RCVEN_PLOT, ". "); -+ continue; -+ } -+ const bool pass = sample_dqs(channel, byte); -+ printk(RCVEN_PLOT, pass ? ". " : "# "); -+ if (pass) { -+ ch_result[channel] |= BIT(byte); -+ continue; -+ } -+ ctrl->rcven[channel][rank][byte] += fine_step; -+ update_rxt(ctrl, channel, rank, byte, RXT_RESTORE, 0); -+ inc_preamble[channel][byte] = inc; -+ } -+ printk(RCVEN_PLOT, "\t"); -+ if (ch_result[channel] != bytemask) -+ done = false; -+ } -+ printk(RCVEN_PLOT, "\n"); -+ if (done) -+ break; -+ } -+ printk(BIOS_DEBUG, "\n"); -+ if (!done) { -+ printk(BIOS_ERR, "Error: Preamble edge not found for all bytes\n"); -+ printk(BIOS_ERR, "The final RcvEn results are as follows:\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(BIOS_ERR, "Channel %u Rank %u: preamble\n", -+ channel, rank); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ printk(BIOS_ERR, " Byte %u: %u%s\n", byte, -+ ctrl->rcven[channel][rank][byte], -+ (ch_result[channel] ^ bytemask) & BIT(byte) -+ ? "" -+ : " *** Check this byte! ***"); -+ } -+ } -+ status = RAMINIT_STATUS_RCVEN_FAILURE; -+ goto clean_up; -+ } -+ -+ printk(BIOS_DEBUG, "Step 6: center on preamble and clean up rank\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(BIOS_DEBUG, "C%u: Preamble increment\n", channel); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ /* -+ * For Traditional, pull in RcvEn by 64. For ULT, take the DQS -+ * drift into account to the specified guardband: tDQSCK_DRIFT. -+ */ -+ ctrl->rcven[channel][rank][byte] -= tDQSCK_DRIFT; -+ update_rxt(ctrl, channel, rank, byte, RXT_RESTORE, 0); -+ printk(BIOS_DEBUG, " B%u: %u %u\n", byte, -+ ctrl->rcven[channel][rank][byte], -+ inc_preamble[channel][byte]); -+ } -+ printk(BIOS_DEBUG, "\n"); -+ } -+ printk(BIOS_DEBUG, "\n"); -+ } -+ -+clean_up: -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ if (ctrl->lpddr) { -+ /** -+ * W/A for b4618574 - @todo: remove for HSW ULT C0 -+ * Can't have force_odt_on together with leaker, disable LPDDR mode for -+ * this training step. This write will disable force_odt_on while still -+ * keeping LPDDR mode disabled. Second write will restore LPDDR mode. -+ */ -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ data_control_0.lpddr_mode = 0; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ } -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), ctrl->dq_control_0[channel]); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ mchbar_write32(DQ_CONTROL_2(channel, byte), -+ ctrl->dq_control_2[channel][byte]); -+ } -+ } -+ io_reset(); -+ if (status) -+ return status; -+ -+ printk(BIOS_DEBUG, "Step 7: Sync IO latency across all ranks\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ status = change_rcven_timing(ctrl, channel); -+ if (status) -+ return status; -+ } -+ printk(BIOS_DEBUG, "\nFinal Receive Enable and IO latency settings:\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ const union sc_io_latency_reg sc_io_latency = { -+ .raw = mchbar_read32(SC_IO_LATENCY_ch(channel)), -+ }; -+ printk(BIOS_DEBUG, " C%u.R%u: IOLAT = %u rt_iocomp = %u\n", channel, -+ rank, ctrl->io_latency[channel][rank], sc_io_latency.rt_iocomp); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ printk(BIOS_DEBUG, " B%u: %u\n", byte, -+ ctrl->rcven[channel][rank][byte]); -+ } -+ printk(BIOS_DEBUG, "\n"); -+ } -+ } -+ return status; -+} -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index a81559bb1e..9172d4f2b0 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -18,6 +18,8 @@ - #define RX_TRAIN_ch_r_b(ch, rank, byte) _DDRIO_C_R_B(0x0000, ch, rank, byte) - #define TX_TRAIN_ch_r_b(ch, rank, byte) _DDRIO_C_R_B(0x0020, ch, rank, byte) - -+#define DDR_DATA_TRAIN_FEEDBACK(ch, byte) _DDRIO_C_R_B(0x0054, ch, 0, byte) -+ - #define DQ_CONTROL_2(ch, byte) _DDRIO_C_R_B(0x0064, ch, 0, byte) - #define DQ_CONTROL_0(ch, byte) _DDRIO_C_R_B(0x0074, ch, 0, byte) - -@@ -100,6 +102,7 @@ - #define COMMAND_RATE_LIMIT_ch(ch) _MCMAIN_C(0x4010, ch) - #define TC_BANK_RANK_D_ch(ch) _MCMAIN_C(0x4014, ch) - #define SC_ROUNDT_LAT_ch(ch) _MCMAIN_C(0x4024, ch) -+#define SC_IO_LATENCY_ch(ch) _MCMAIN_C(0x4028, ch) - - #define REUT_ch_PAT_WDB_CL_MUX_CFG(ch) _MCMAIN_C(0x4040, ch) - --- -2.39.5 - diff --git a/config/coreboot/default/patches/0041-haswell-NRI-Add-function-to-change-margins.patch b/config/coreboot/default/patches/0041-haswell-NRI-Add-function-to-change-margins.patch deleted file mode 100644 index 296dbed6..00000000 --- a/config/coreboot/default/patches/0041-haswell-NRI-Add-function-to-change-margins.patch +++ /dev/null @@ -1,272 +0,0 @@ -From fc6c3edf561dd11eeb2ebe7f4cb93542e664935a Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sun, 8 May 2022 11:58:59 +0200 -Subject: [PATCH 41/51] haswell NRI: Add function to change margins - -Implement a function to change margin parameters. Haswell provides a -register to apply an offset to margin parameters during training, so -make use of it. There are other margin parameters that have not been -implemented yet, as they are not needed for now and special handling -is needed to provide offset training functionality. - -Change-Id: I5392380e13de3c44e77b7bc9f3b819e2661d1e2d -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../haswell/native_raminit/change_margin.c | 136 ++++++++++++++++++ - .../haswell/native_raminit/raminit_native.h | 39 +++++ - .../haswell/native_raminit/reg_structs.h | 12 ++ - .../intel/haswell/registers/mchbar.h | 1 + - 4 files changed, 188 insertions(+) - -diff --git a/src/northbridge/intel/haswell/native_raminit/change_margin.c b/src/northbridge/intel/haswell/native_raminit/change_margin.c -index 055c666eee..299c44a6b0 100644 ---- a/src/northbridge/intel/haswell/native_raminit/change_margin.c -+++ b/src/northbridge/intel/haswell/native_raminit/change_margin.c -@@ -1,5 +1,6 @@ - /* SPDX-License-Identifier: GPL-2.0-or-later */ - -+#include <assert.h> - #include <commonlib/bsd/clamp.h> - #include <console/console.h> - #include <delay.h> -@@ -152,3 +153,138 @@ void download_regfile( - ddr_data_control_0.read_rf_rank = phys_rank; - mchbar_write32(reg, ddr_data_control_0.raw); - } -+ -+static void update_data_offset_train( -+ struct sysinfo *ctrl, -+ const uint8_t param, -+ const uint8_t en_multicast, -+ const uint8_t channel_in, -+ const uint8_t rank, -+ const uint8_t byte_in, -+ const bool update_ctrl, -+ const enum regfile_mode regfile, -+ const uint32_t value) -+{ -+ bool is_rd = false; -+ bool is_wr = false; -+ switch (param) { -+ case RdT: -+ case RdV: -+ case RcvEna: -+ is_rd = true; -+ break; -+ case WrT: -+ case WrDqsT: -+ is_wr = true; -+ break; -+ default: -+ die("%s: Invalid margin parameter %u\n", __func__, param); -+ } -+ if (en_multicast) { -+ mchbar_write32(DDR_DATA_OFFSET_TRAIN, value); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ download_regfile(ctrl, channel, true, rank, regfile, 0, is_rd, is_wr); -+ if (update_ctrl) { -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ ctrl->data_offset_train[channel][byte] = value; -+ } -+ } -+ } else { -+ mchbar_write32(DDR_DATA_OFFSET_TRAIN_ch_b(channel_in, byte_in), value); -+ download_regfile(ctrl, channel_in, false, rank, regfile, byte_in, is_rd, is_wr); -+ if (update_ctrl) -+ ctrl->data_offset_train[channel_in][byte_in] = value; -+ } -+} -+ -+static uint32_t get_max_margin(const enum margin_parameter param) -+{ -+ switch (param) { -+ case RcvEna: -+ case RdT: -+ case WrT: -+ case WrDqsT: -+ return MAX_POSSIBLE_TIME; -+ case RdV: -+ return MAX_POSSIBLE_VREF; -+ default: -+ die("%s: Invalid margin parameter %u\n", __func__, param); -+ } -+} -+ -+void change_margin( -+ struct sysinfo *ctrl, -+ const enum margin_parameter param, -+ const int32_t value0, -+ const bool en_multicast, -+ const uint8_t channel, -+ const uint8_t rank, -+ const uint8_t byte, -+ const bool update_ctrl, -+ const enum regfile_mode regfile) -+{ -+ /** FIXME: Remove this **/ -+ if (rank == 0xff) -+ die("%s: rank is 0xff\n", __func__); -+ -+ if (!en_multicast && !does_ch_exist(ctrl, channel)) -+ die("%s: Tried to change margin of empty channel %u\n", __func__, channel); -+ -+ const uint32_t max_value = get_max_margin(param); -+ const int32_t v0 = clamp_s32(-max_value, value0, max_value); -+ -+ union ddr_data_offset_train_reg ddr_data_offset_train = { -+ .raw = en_multicast ? 0 : ctrl->data_offset_train[channel][byte], -+ }; -+ bool update_offset_train = false; -+ switch (param) { -+ case RcvEna: -+ ddr_data_offset_train.rcven = v0; -+ update_offset_train = true; -+ break; -+ case RdT: -+ ddr_data_offset_train.rx_dqs = v0; -+ update_offset_train = true; -+ break; -+ case WrT: -+ ddr_data_offset_train.tx_dq = v0; -+ update_offset_train = true; -+ break; -+ case WrDqsT: -+ ddr_data_offset_train.tx_dqs = v0; -+ update_offset_train = true; -+ break; -+ case RdV: -+ ddr_data_offset_train.vref = v0; -+ update_offset_train = true; -+ break; -+ default: -+ die("%s: Invalid margin parameter %u\n", __func__, param); -+ } -+ if (update_offset_train) { -+ update_data_offset_train( -+ ctrl, -+ param, -+ en_multicast, -+ channel, -+ rank, -+ byte, -+ update_ctrl, -+ regfile, -+ ddr_data_offset_train.raw); -+ } -+} -+ -+void change_1d_margin_multicast( -+ struct sysinfo *ctrl, -+ const enum margin_parameter param, -+ const int32_t value0, -+ const uint8_t rank, -+ const bool update_ctrl, -+ const enum regfile_mode regfile) -+{ -+ change_margin(ctrl, param, value0, true, 0, rank, 0, update_ctrl, regfile); -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index eaaaedad1e..1c8473056b 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -36,6 +36,18 @@ - - #define RTTNOM_MASK (BIT(9) | BIT(6) | BIT(2)) - -+/* Margin parameter limits */ -+#define MAX_POSSIBLE_TIME 31 -+#define MAX_POSSIBLE_VREF 54 -+ -+#define MAX_POSSIBLE_BOTH MAX_POSSIBLE_VREF -+ -+#define MIN_TIME (-MAX_POSSIBLE_TIME) -+#define MAX_TIME (MAX_POSSIBLE_TIME) -+ -+#define MIN_VREF (-MAX_POSSIBLE_VREF) -+#define MAX_VREF (MAX_POSSIBLE_VREF) -+ - #define BASIC_VA_PAT_SPREAD_8 0x01010101 - - #define WDB_CACHE_LINE_SIZE 8 -@@ -46,6 +58,14 @@ - /* Specified in PI ticks. 64 PI ticks == 1 qclk */ - #define tDQSCK_DRIFT 64 - -+enum margin_parameter { -+ RcvEna, -+ RdT, -+ WrT, -+ WrDqsT, -+ RdV, -+}; -+ - /* ZQ calibration types */ - enum { - ZQ_INIT, /* DDR3: ZQCL with tZQinit, LPDDR3: ZQ Init with tZQinit */ -@@ -515,6 +535,25 @@ void download_regfile( - bool read_rf_rd, - bool read_rf_wr); - -+void change_margin( -+ struct sysinfo *ctrl, -+ const enum margin_parameter param, -+ const int32_t value0, -+ const bool en_multicast, -+ const uint8_t channel, -+ const uint8_t rank, -+ const uint8_t byte, -+ const bool update_ctrl, -+ const enum regfile_mode regfile); -+ -+void change_1d_margin_multicast( -+ struct sysinfo *ctrl, -+ const enum margin_parameter param, -+ const int32_t value0, -+ const uint8_t rank, -+ const bool update_ctrl, -+ const enum regfile_mode regfile); -+ - uint8_t get_rx_bias(const struct sysinfo *ctrl); - - uint8_t get_tCWL(uint32_t mem_clock_mhz); -diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -index b099f4bb82..a0e36ed082 100644 ---- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h -+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -@@ -25,6 +25,18 @@ union ddr_data_tx_train_rank_reg { - uint32_t raw; - }; - -+union ddr_data_offset_train_reg { -+ struct __packed { -+ int32_t rcven : 6; // Bits 5:0 -+ int32_t rx_dqs : 6; // Bits 11:6 -+ int32_t tx_dq : 6; // Bits 17:12 -+ int32_t tx_dqs : 6; // Bits 23:18 -+ int32_t vref : 7; // Bits 30:24 -+ int32_t : 1; // Bits 31:31 -+ }; -+ uint32_t raw; -+}; -+ - union ddr_data_control_0_reg { - struct __packed { - uint32_t rx_training_mode : 1; // Bits 0:0 -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 9172d4f2b0..0acafbc826 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -21,6 +21,7 @@ - #define DDR_DATA_TRAIN_FEEDBACK(ch, byte) _DDRIO_C_R_B(0x0054, ch, 0, byte) - - #define DQ_CONTROL_2(ch, byte) _DDRIO_C_R_B(0x0064, ch, 0, byte) -+#define DDR_DATA_OFFSET_TRAIN_ch_b(ch, byte) _DDRIO_C_R_B(0x0070, ch, 0, byte) - #define DQ_CONTROL_0(ch, byte) _DDRIO_C_R_B(0x0074, ch, 0, byte) - - /* DDR CKE per-channel */ --- -2.39.5 - diff --git a/config/coreboot/default/patches/0042-haswell-NRI-Add-read-MPR-training.patch b/config/coreboot/default/patches/0042-haswell-NRI-Add-read-MPR-training.patch deleted file mode 100644 index f2ccb7ad..00000000 --- a/config/coreboot/default/patches/0042-haswell-NRI-Add-read-MPR-training.patch +++ /dev/null @@ -1,332 +0,0 @@ -From 8f07ea076572dd3371dca7b3dbd5ff9c9b332c55 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sun, 8 May 2022 11:35:49 +0200 -Subject: [PATCH 42/51] haswell NRI: Add read MPR training - -Implement read training using DDR3 MPR (Multi-Purpose Register). - -Change-Id: Id17cb2c4c399ac9bcc937b595b58f863c152461b -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/raminit_main.c | 1 + - .../haswell/native_raminit/raminit_native.h | 4 + - .../haswell/native_raminit/train_read_mpr.c | 241 ++++++++++++++++++ - .../intel/haswell/registers/mchbar.h | 2 +- - 5 files changed, 248 insertions(+), 1 deletion(-) - create mode 100644 src/northbridge/intel/haswell/native_raminit/train_read_mpr.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index e2fbfb4211..c442be0728 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -16,4 +16,5 @@ romstage-y += setup_wdb.c - romstage-y += spd_bitmunching.c - romstage-y += testing_io.c - romstage-y += timings_refresh.c -+romstage-y += train_read_mpr.c - romstage-y += train_receive_enable.c -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 7d444659c3..264d1468f5 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -61,6 +61,7 @@ static const struct task_entry cold_boot[] = { - { do_jedec_init, true, "JEDECINIT", }, - { pre_training, true, "PRETRAIN", }, - { train_receive_enable, true, "RCVET", }, -+ { train_read_mpr, true, "RDMPRT", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 1c8473056b..7a486479ea 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -28,6 +28,8 @@ - /* Always use 12 legs for emphasis (not trained) */ - #define TXEQFULLDRV (3 << 4) - -+#define LOOPCOUNT_INFINITE 0xff -+ - /* DDR3 mode register bits */ - #define MR0_DLL_RESET BIT(8) - -@@ -213,6 +215,7 @@ enum raminit_status { - RAMINIT_STATUS_POLL_TIMEOUT, - RAMINIT_STATUS_REUT_ERROR, - RAMINIT_STATUS_RCVEN_FAILURE, -+ RAMINIT_STATUS_RMPR_FAILURE, - RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/ - }; - -@@ -434,6 +437,7 @@ enum raminit_status configure_mc(struct sysinfo *ctrl); - enum raminit_status configure_memory_map(struct sysinfo *ctrl); - enum raminit_status do_jedec_init(struct sysinfo *ctrl); - enum raminit_status train_receive_enable(struct sysinfo *ctrl); -+enum raminit_status train_read_mpr(struct sysinfo *ctrl); - - void configure_timings(struct sysinfo *ctrl); - void configure_refresh(struct sysinfo *ctrl); -diff --git a/src/northbridge/intel/haswell/native_raminit/train_read_mpr.c b/src/northbridge/intel/haswell/native_raminit/train_read_mpr.c -new file mode 100644 -index 0000000000..ade1e36148 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/train_read_mpr.c -@@ -0,0 +1,241 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <delay.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+#include "ranges.h" -+ -+#define RMPR_START (-32) -+#define RMPR_STOP (32) -+#define RMPR_STEP 1 -+ -+#define RMPR_MIN_WIDTH 12 -+ -+#define RMPR_PLOT RAM_DEBUG -+ -+/* -+ * Clear rx_training_mode. For LPDDR, we first need to disable odt_samp_extend_en, -+ * then disable rx_training_mode, and finally re-enable odt_samp_extend_en. -+ */ -+static void clear_rx_training_mode(struct sysinfo *ctrl, const uint8_t channel) -+{ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ mchbar_write32(DQ_CONTROL_2(channel, byte), ctrl->dq_control_2[channel][byte]); -+ -+ if (ctrl->lpddr) { -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = mchbar_read32(DDR_DATA_ch_CONTROL_0(channel)), -+ }; -+ data_control_0.odt_samp_extend_en = 0; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ tick_delay(1); -+ data_control_0.rx_training_mode = 0; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ tick_delay(1); -+ } -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), ctrl->dq_control_0[channel]); -+} -+ -+static void set_rxdqs_edges_to_midpoint(struct sysinfo *ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ update_rxt(ctrl, channel, rank, byte, RXT_RXDQS_BOTH, 32); -+ } -+ } -+} -+ -+static void enter_mpr_train_ddr_mode(struct sysinfo *ctrl, const uint8_t rank) -+{ -+ /* Program MR3 and mask RAS/WE to prevent scheduler from issuing non-read commands */ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ if (!ctrl->lpddr) -+ reut_issue_mrs(ctrl, channel, BIT(rank), 3, 1 << 2); -+ -+ union reut_misc_odt_ctrl_reg reut_misc_odt_ctrl = { -+ .raw = mchbar_read32(REUT_ch_MISC_ODT_CTRL(channel)), -+ }; -+ reut_misc_odt_ctrl.mpr_train_ddr_on = 1; -+ mchbar_write32(REUT_ch_MISC_ODT_CTRL(channel), reut_misc_odt_ctrl.raw); -+ } -+} -+ -+static void leave_mpr_train_ddr_mode(struct sysinfo *ctrl, const uint8_t rank) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ /* -+ * The mpr_train_ddr_on bit will force a special command. -+ * Therefore, clear it before issuing the MRS command. -+ */ -+ union reut_misc_odt_ctrl_reg reut_misc_odt_ctrl = { -+ .raw = mchbar_read32(REUT_ch_MISC_ODT_CTRL(channel)), -+ }; -+ reut_misc_odt_ctrl.mpr_train_ddr_on = 0; -+ mchbar_write32(REUT_ch_MISC_ODT_CTRL(channel), reut_misc_odt_ctrl.raw); -+ if (!ctrl->lpddr) -+ reut_issue_mrs(ctrl, channel, BIT(rank), 3, 0 << 2); -+ } -+} -+ -+enum raminit_status train_read_mpr(struct sysinfo *ctrl) -+{ -+ set_rxdqs_edges_to_midpoint(ctrl); -+ clear_data_offset_train_all(ctrl); -+ setup_io_test_mpr(ctrl, ctrl->chanmap, LOOPCOUNT_INFINITE, NSOE); -+ enum raminit_status status = RAMINIT_STATUS_SUCCESS; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!does_rank_exist(ctrl, rank)) -+ continue; -+ -+ printk(BIOS_DEBUG, "Rank %u\n", rank); -+ printk(RMPR_PLOT, "Channel"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(RMPR_PLOT, "\t%u\t\t", channel); -+ } -+ printk(RMPR_PLOT, "\nByte"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(RMPR_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(RMPR_PLOT, "%u ", byte); -+ } -+ enter_mpr_train_ddr_mode(ctrl, rank); -+ struct linear_train_data region_data[NUM_CHANNELS][NUM_LANES] = { 0 }; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) -+ select_reut_ranks(ctrl, channel, BIT(rank)); -+ -+ printk(RMPR_PLOT, "\nDqsDelay\n"); -+ int8_t dqs_delay; -+ for (dqs_delay = RMPR_START; dqs_delay < RMPR_STOP; dqs_delay += RMPR_STEP) { -+ printk(RMPR_PLOT, "% 5d", dqs_delay); -+ const enum regfile_mode regfile = REG_FILE_USE_START; -+ /* Looks like MRC uses rank 0 here, but it feels wrong */ -+ change_1d_margin_multicast(ctrl, RdT, dqs_delay, rank, false, regfile); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ union ddr_data_control_2_reg data_control_2 = { -+ .raw = ctrl->dq_control_2[channel][byte], -+ }; -+ data_control_2.force_bias_on = 1; -+ data_control_2.force_rx_on = 1; -+ data_control_2.leaker_comp = 0; -+ mchbar_write32(DQ_CONTROL_2(channel, byte), -+ data_control_2.raw); -+ } -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ data_control_0.rx_training_mode = 1; -+ data_control_0.force_odt_on = !ctrl->lpddr; -+ data_control_0.en_read_preamble = 0; -+ data_control_0.odt_samp_extend_en = ctrl->lpddr; -+ const uint32_t reg_offset = DDR_DATA_ch_CONTROL_0(channel); -+ mchbar_write32(reg_offset, data_control_0.raw); -+ } -+ run_mpr_io_test(false); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(RMPR_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ uint32_t fb = get_data_train_feedback(channel, byte); -+ const bool pass = fb == 1; -+ printk(RMPR_PLOT, pass ? ". " : "# "); -+ linear_record_pass( -+ ®ion_data[channel][byte], -+ pass, -+ dqs_delay, -+ RMPR_START, -+ RMPR_STEP); -+ } -+ } -+ printk(RMPR_PLOT, "\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ clear_rx_training_mode(ctrl, channel); -+ } -+ io_reset(); -+ } -+ printk(RMPR_PLOT, "\n"); -+ leave_mpr_train_ddr_mode(ctrl, rank); -+ clear_data_offset_train_all(ctrl); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(BIOS_DEBUG, "C%u.R%u: \tLeft\tRight\tWidth\tCenter\tRxDqsPN\n", -+ channel, rank); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ struct linear_train_data *data = ®ion_data[channel][byte]; -+ const int32_t lwidth = range_width(data->largest); -+ if (lwidth <= RMPR_MIN_WIDTH) { -+ printk(BIOS_ERR, -+ "Bad eye (lwidth %d <= min %d) for byte %u\n", -+ lwidth, RMPR_MIN_WIDTH, byte); -+ status = RAMINIT_STATUS_RMPR_FAILURE; -+ } -+ /* -+ * The MPR center may not be ideal on certain platforms for -+ * unknown reasons. If so, adjust it with a magical number. -+ * For Haswell, the magical number is zero. Hell knows why. -+ */ -+ const int32_t center = range_center(data->largest); -+ ctrl->rxdqsp[channel][rank][byte] = center - RMPR_START; -+ ctrl->rxdqsn[channel][rank][byte] = center - RMPR_START; -+ printk(BIOS_DEBUG, " B%u: \t%d\t%d\t%d\t%d\t%u\n", byte, -+ data->largest.start, data->largest.end, lwidth, -+ center, ctrl->rxdqsp[channel][rank][byte]); -+ } -+ printk(BIOS_DEBUG, "\n"); -+ } -+ } -+ -+ /* -+ * Now program the DQS center values on populated ranks. data is taken from -+ * the host struct. We need to do it after all ranks are trained, because we -+ * need to keep the same DQS value on all ranks during the training procedure. -+ */ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ update_rxt(ctrl, channel, rank, byte, RXT_RESTORE, 0); -+ } -+ } -+ change_1d_margin_multicast(ctrl, RdT, 0, 0, false, REG_FILE_USE_CURRENT); -+ io_reset(); -+ return status; -+} -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 0acafbc826..6a31d3a32c 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -122,7 +122,7 @@ - #define REUT_ch_ERR_DATA_MASK(ch) _MCMAIN_C(0x40d8, ch) - - #define REUT_ch_MISC_CKE_CTRL(ch) _MCMAIN_C(0x4190, ch) -- -+#define REUT_ch_MISC_ODT_CTRL(ch) _MCMAIN_C(0x4194, ch) - #define REUT_ch_MISC_PAT_CADB_CTRL(ch) _MCMAIN_C(0x4198, ch) - #define REUT_ch_PAT_CADB_MRS(ch) _MCMAIN_C(0x419c, ch) - #define REUT_ch_PAT_CADB_MUX_CTRL(ch) _MCMAIN_C(0x41a0, ch) --- -2.39.5 - diff --git a/config/coreboot/default/patches/0043-haswell-NRI-Add-write-leveling.patch b/config/coreboot/default/patches/0043-haswell-NRI-Add-write-leveling.patch deleted file mode 100644 index 0202ed1b..00000000 --- a/config/coreboot/default/patches/0043-haswell-NRI-Add-write-leveling.patch +++ /dev/null @@ -1,689 +0,0 @@ -From 6df4b7eb0512c24a5f53bc92e81ad6cf42cd28a7 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sun, 8 May 2022 12:56:04 +0200 -Subject: [PATCH 43/51] haswell NRI: Add write leveling - -Implement JEDEC write leveling, which is done in two steps. The first -step uses the JEDEC procedure to do "fine" write leveling, i.e. align -the DQS phase to the clock signal. The second step performs a regular -read-write test to correct "coarse" cycle errors. - -Change-Id: I27678523fe22c38173a688e2a4751c259a20f009 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/raminit_main.c | 1 + - .../haswell/native_raminit/raminit_native.h | 10 + - .../train_jedec_write_leveling.c | 581 ++++++++++++++++++ - .../intel/haswell/registers/mchbar.h | 2 + - 5 files changed, 595 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/train_jedec_write_leveling.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index c442be0728..40c2f5e014 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -16,5 +16,6 @@ romstage-y += setup_wdb.c - romstage-y += spd_bitmunching.c - romstage-y += testing_io.c - romstage-y += timings_refresh.c -+romstage-y += train_jedec_write_leveling.c - romstage-y += train_read_mpr.c - romstage-y += train_receive_enable.c -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 264d1468f5..1ff23be615 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -62,6 +62,7 @@ static const struct task_entry cold_boot[] = { - { pre_training, true, "PRETRAIN", }, - { train_receive_enable, true, "RCVET", }, - { train_read_mpr, true, "RDMPRT", }, -+ { train_jedec_write_leveling, true, "JWRL", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 7a486479ea..d6b11b9d3c 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -60,6 +60,9 @@ - /* Specified in PI ticks. 64 PI ticks == 1 qclk */ - #define tDQSCK_DRIFT 64 - -+/* Maximum additional latency */ -+#define MAX_ADD_DELAY 2 -+ - enum margin_parameter { - RcvEna, - RdT, -@@ -216,6 +219,7 @@ enum raminit_status { - RAMINIT_STATUS_REUT_ERROR, - RAMINIT_STATUS_RCVEN_FAILURE, - RAMINIT_STATUS_RMPR_FAILURE, -+ RAMINIT_STATUS_JWRL_FAILURE, - RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/ - }; - -@@ -381,6 +385,11 @@ static inline uint32_t get_data_train_feedback(const uint8_t channel, const uint - return mchbar_read32(DDR_DATA_TRAIN_FEEDBACK(channel, byte)); - } - -+static inline uint16_t get_byte_group_errors(const uint8_t channel) -+{ -+ return mchbar_read32(4 + REUT_ch_ERR_MISC_STATUS(channel)) & 0x1ff; -+} -+ - /* Number of ticks to wait in units of 69.841279 ns (citation needed) */ - static inline void tick_delay(const uint32_t delay) - { -@@ -438,6 +447,7 @@ enum raminit_status configure_memory_map(struct sysinfo *ctrl); - enum raminit_status do_jedec_init(struct sysinfo *ctrl); - enum raminit_status train_receive_enable(struct sysinfo *ctrl); - enum raminit_status train_read_mpr(struct sysinfo *ctrl); -+enum raminit_status train_jedec_write_leveling(struct sysinfo *ctrl); - - void configure_timings(struct sysinfo *ctrl); - void configure_refresh(struct sysinfo *ctrl); -diff --git a/src/northbridge/intel/haswell/native_raminit/train_jedec_write_leveling.c b/src/northbridge/intel/haswell/native_raminit/train_jedec_write_leveling.c -new file mode 100644 -index 0000000000..ef6483e2bd ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/train_jedec_write_leveling.c -@@ -0,0 +1,581 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <assert.h> -+#include <console/console.h> -+#include <delay.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+#include "ranges.h" -+ -+#define JWLC_PLOT RAM_DEBUG -+#define JWRL_PLOT RAM_DEBUG -+ -+static void reset_dram_dll(struct sysinfo *ctrl, const uint8_t channel, const uint8_t rank) -+{ -+ const uint16_t mr0reg = ctrl->mr0[channel][rank / 2]; -+ reut_issue_mrs(ctrl, channel, BIT(rank), 0, mr0reg | MR0_DLL_RESET); -+} -+ -+static void program_wdb_pattern(struct sysinfo *ctrl, const bool invert) -+{ -+ /* Pattern to keep DQ-DQS simple but detect any failures. Same as NHM/WSM. */ -+ const uint8_t pat[4][2] = { -+ { 0x00, 0xff }, -+ { 0xff, 0x00 }, -+ { 0xc3, 0x3c }, -+ { 0x3c, 0xc3 }, -+ }; -+ const uint8_t pmask[2][8] = { -+ { 0, 0, 1, 1, 1, 1, 0, 0 }, -+ { 1, 1, 0, 0, 0, 0, 1, 1 }, -+ }; -+ for (uint8_t s = 0; s < ARRAY_SIZE(pat); s++) -+ write_wdb_fixed_pat(ctrl, pat[s], pmask[invert], ARRAY_SIZE(pmask[invert]), s); -+} -+ -+static int16_t set_add_delay(uint32_t *add_delay, uint8_t rank, int8_t target_off) -+{ -+ const uint8_t shift = rank * 2; -+ if (target_off > MAX_ADD_DELAY) { -+ *add_delay &= ~(3 << shift); -+ *add_delay |= MAX_ADD_DELAY << shift; -+ return 128 * (target_off - MAX_ADD_DELAY); -+ } else if (target_off < 0) { -+ *add_delay &= ~(3 << shift); -+ *add_delay |= 0 << shift; -+ return 128 * target_off; -+ } else { -+ *add_delay &= ~(3 << shift); -+ *add_delay |= target_off << shift; -+ return 0; -+ } -+} -+ -+static enum raminit_status train_jedec_write_leveling_cleanup(struct sysinfo *ctrl) -+{ -+ const struct reut_box reut_addr = { -+ .col = { -+ .start = 0, -+ .stop = 1023, -+ .inc_val = 1, -+ }, -+ }; -+ const struct wdb_pat wdb_pattern = { -+ .start_ptr = 0, -+ .stop_ptr = 3, -+ .inc_rate = 1, -+ .dq_pattern = BASIC_VA, -+ }; -+ const int8_t offsets[] = { 0, 1, -1, 2, 3 }; -+ const int8_t dq_offsets[] = { 0, -10, 10, -5, 5, -15, 15 }; -+ const uint8_t dq_offset_max = ARRAY_SIZE(dq_offsets); -+ -+ /* Set LFSR seeds to be sequential */ -+ program_wdb_lfsr(ctrl, true); -+ setup_io_test( -+ ctrl, -+ ctrl->chanmap, -+ PAT_WR_RD, -+ 2, -+ 4, -+ &reut_addr, -+ NSOE, -+ &wdb_pattern, -+ 0, -+ 0); -+ -+ const union reut_pat_wdb_cl_mux_cfg_reg reut_wdb_cl_mux_cfg = { -+ .mux_0_control = REUT_MUX_BTBUFFER, -+ .mux_1_control = REUT_MUX_BTBUFFER, -+ .mux_2_control = REUT_MUX_BTBUFFER, -+ .ecc_data_source_sel = 1, -+ }; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ mchbar_write32(REUT_ch_PAT_WDB_CL_MUX_CFG(channel), reut_wdb_cl_mux_cfg.raw); -+ } -+ -+ int8_t byte_off[NUM_CHANNELS][NUM_LANES] = { 0 }; -+ uint32_t add_delay[NUM_CHANNELS] = { 0 }; -+ enum raminit_status status = RAMINIT_STATUS_SUCCESS; -+ bool invert = false; -+ const uint16_t valid_byte_mask = BIT(ctrl->lanes) - 1; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ uint8_t chanmask = 0; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) -+ chanmask |= select_reut_ranks(ctrl, channel, BIT(rank)); -+ -+ if (!chanmask) -+ continue; -+ -+ printk(BIOS_DEBUG, "Rank %u\n", rank); -+ printk(JWLC_PLOT, "Channel"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(JWLC_PLOT, "\t\t%u\t", channel); -+ } -+ printk(JWLC_PLOT, "\nByte\t"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(JWLC_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(JWLC_PLOT, "%u ", byte); -+ } -+ printk(JWLC_PLOT, "\nDelay DqOffset"); -+ bool done = false; -+ int8_t byte_sum[NUM_CHANNELS] = { 0 }; -+ uint16_t byte_pass[NUM_CHANNELS] = { 0 }; -+ for (uint8_t off = 0; off < ARRAY_SIZE(offsets); off++) { -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ const int16_t global_byte_off = -+ set_add_delay(&add_delay[channel], rank, offsets[off]); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ update_txt(ctrl, channel, rank, byte, TXT_DQDQS_OFF, -+ global_byte_off); -+ } -+ mchbar_write32(SC_WR_ADD_DELAY_ch(channel), -+ add_delay[channel]); -+ } -+ /* Reset FIFOs and DRAM DLL (Micron workaround) */ -+ if (!ctrl->lpddr) { -+ io_reset(); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ reset_dram_dll(ctrl, channel, rank); -+ } -+ udelay(1); -+ } -+ for (uint8_t dq_offset = 0; dq_offset < dq_offset_max; dq_offset++) { -+ printk(JWLC_PLOT, "\n% 3d\t% 3d", -+ offsets[off], dq_offsets[dq_offset]); -+ change_1d_margin_multicast( -+ ctrl, -+ WrT, -+ dq_offsets[dq_offset], -+ rank, -+ false, -+ REG_FILE_USE_RANK); -+ -+ /* -+ * Re-program the WDB pattern. Change the pattern -+ * for the next test to avoid false pass issues. -+ */ -+ program_wdb_pattern(ctrl, invert); -+ invert = !invert; -+ run_io_test(ctrl, chanmask, BASIC_VA, true); -+ done = true; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(JWLC_PLOT, "\t"); -+ uint16_t result = get_byte_group_errors(channel); -+ result &= valid_byte_mask; -+ -+ /* Skip bytes that have failed or already passed */ -+ const uint16_t skip_me = result | byte_pass[channel]; -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const bool pass = result & BIT(byte); -+ printk(JWLC_PLOT, pass ? "# " : ". "); -+ if (skip_me & BIT(byte)) -+ continue; -+ -+ byte_pass[channel] |= BIT(byte); -+ byte_off[channel][byte] = offsets[off]; -+ byte_sum[channel] += offsets[off]; -+ } -+ if (byte_pass[channel] != valid_byte_mask) -+ done = false; -+ } -+ if (done) -+ break; -+ } -+ if (done) -+ break; -+ } -+ printk(BIOS_DEBUG, "\n\n"); -+ if (!done) { -+ printk(BIOS_ERR, "JWLC: Could not find a pass for all bytes\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(BIOS_ERR, "Channel %u, rank %u fail:", channel, rank); -+ const uint16_t passing_mask = byte_pass[channel]; -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ if (BIT(byte) & passing_mask) -+ continue; -+ -+ printk(BIOS_ERR, " %u", byte); -+ } -+ printk(BIOS_ERR, "\n"); -+ } -+ status = RAMINIT_STATUS_JWRL_FAILURE; -+ break; -+ } -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ /* Refine target offset to make sure it works for all bytes */ -+ int8_t target_off = DIV_ROUND_CLOSEST(byte_sum[channel], ctrl->lanes); -+ int16_t global_byte_off = 0; -+ uint8_t all_good_loops = 0; -+ bool all_good = 0; -+ while (!all_good) { -+ global_byte_off = -+ set_add_delay(&add_delay[channel], rank, target_off); -+ all_good = true; -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ int16_t local_offset; -+ local_offset = byte_off[channel][byte] - target_off; -+ local_offset = local_offset * 128 + global_byte_off; -+ const uint16_t tx_dq = ctrl->tx_dq[channel][rank][byte]; -+ if (tx_dq + local_offset >= (512 - 64)) { -+ all_good = false; -+ all_good_loops++; -+ target_off++; -+ break; -+ } -+ const uint16_t txdqs = ctrl->tx_dq[channel][rank][byte]; -+ if (txdqs + local_offset < 96) { -+ all_good = false; -+ all_good_loops++; -+ target_off--; -+ break; -+ } -+ } -+ /* Avoid an infinite loop */ -+ if (all_good_loops > 3) -+ break; -+ } -+ if (!all_good) { -+ printk(BIOS_ERR, "JWLC: Target offset refining failed\n"); -+ status = RAMINIT_STATUS_JWRL_FAILURE; -+ break; -+ } -+ printk(BIOS_DEBUG, "C%u.R%u: Offset\tFinalEdge\n", channel, rank); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ int16_t local_offset; -+ local_offset = byte_off[channel][byte] - target_off; -+ local_offset = local_offset * 128 + global_byte_off; -+ ctrl->tx_dq[channel][rank][byte] += local_offset; -+ ctrl->txdqs[channel][rank][byte] += local_offset; -+ update_txt(ctrl, channel, rank, byte, TXT_RESTORE, 0); -+ printk(BIOS_DEBUG, " B%u: %d\t%d\n", byte, local_offset, -+ ctrl->txdqs[channel][rank][byte]); -+ } -+ mchbar_write32(SC_WR_ADD_DELAY_ch(channel), add_delay[channel]); -+ if (!ctrl->lpddr) { -+ reset_dram_dll(ctrl, channel, rank); -+ udelay(1); -+ } -+ printk(BIOS_DEBUG, "\n"); -+ } -+ printk(BIOS_DEBUG, "\n"); -+ } -+ -+ /* Restore WDB after test */ -+ write_wdb_va_pat(ctrl, 0, BASIC_VA_PAT_SPREAD_8, 8, 0); -+ program_wdb_lfsr(ctrl, false); -+ mchbar_write32(DDR_DATA_OFFSET_TRAIN, 0); -+ -+ /** TODO: Do full JEDEC init instead? **/ -+ io_reset(); -+ return status; -+} -+ -+static enum raminit_status verify_wl_width(const int32_t lwidth) -+{ -+ if (lwidth <= 32) { -+ /* Check if width is valid */ -+ printk(BIOS_ERR, "WrLevel: Width region (%d) too small\n", lwidth); -+ return RAMINIT_STATUS_JWRL_FAILURE; -+ } -+ if (lwidth >= 96) { -+ /* Since we're calibrating a phase, a too large region is a problem */ -+ printk(BIOS_ERR, "WrLevel: Width region (%d) too large\n", lwidth); -+ return RAMINIT_STATUS_JWRL_FAILURE; -+ } -+ return 0; -+} -+ -+enum raminit_status train_jedec_write_leveling(struct sysinfo *ctrl) -+{ -+ /* -+ * Enabling WL mode causes DQS to toggle for 1024 QCLK. -+ * Wait for this to stop. Round up to nearest microsecond. -+ */ -+ const bool wl_long_delay = ctrl->lpddr; -+ const uint32_t dqs_toggle_time = wl_long_delay ? 2048 : 1024; -+ const uint32_t wait_time_us = DIV_ROUND_UP(ctrl->qclkps * dqs_toggle_time, 1000 * 1000); -+ -+ const uint16_t wl_start = 192; -+ const uint16_t wl_stop = 192 + 128; -+ const uint16_t wl_step = 2; -+ -+ /* Do not use cached MR values */ -+ const bool save_restore_mrs = ctrl->restore_mrs; -+ ctrl->restore_mrs = 0; -+ -+ /* Propagate delay values (without a write command) */ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ /* Propagate delay values from rank 0 to prevent assertion failures in RTL */ -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ data_control_0.read_rf_rd = 0; -+ data_control_0.read_rf_wr = 1; -+ data_control_0.read_rf_rank = 0; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ union ddr_data_control_2_reg data_control_2 = { -+ .raw = ctrl->dq_control_2[channel][byte], -+ }; -+ data_control_2.force_bias_on = 1; -+ data_control_2.force_rx_on = 0; -+ data_control_2.wl_long_delay = wl_long_delay; -+ mchbar_write32(DQ_CONTROL_2(channel, byte), data_control_2.raw); -+ } -+ } -+ -+ if (ctrl->lpddr) -+ die("%s: Missing LPDDR support\n", __func__); -+ -+ if (!ctrl->lpddr) -+ ddr3_program_mr1(ctrl, 0, 1); -+ -+ enum raminit_status status = RAMINIT_STATUS_SUCCESS; -+ struct phase_train_data region_data[NUM_CHANNELS][NUM_LANES] = { 0 }; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!does_rank_exist(ctrl, rank)) -+ continue; -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ /** TODO: Differs for LPDDR **/ -+ uint16_t mr1reg = ctrl->mr1[channel][rank / 2]; -+ mr1reg &= ~MR1_QOFF_ENABLE; -+ mr1reg |= MR1_WL_ENABLE; -+ if (is_hsw_ult()) { -+ mr1reg &= ~RTTNOM_MASK; -+ mr1reg |= encode_ddr3_rttnom(120); -+ } else if (ctrl->dpc[channel] == 2) { -+ mr1reg &= ~RTTNOM_MASK; -+ mr1reg |= encode_ddr3_rttnom(60); -+ } -+ reut_issue_mrs(ctrl, channel, BIT(rank), 1, mr1reg); -+ -+ /* Assert ODT for myself */ -+ uint8_t odt_matrix = BIT(rank); -+ if (ctrl->dpc[channel] == 2) { -+ /* Assert ODT for non-target DIMM */ -+ const uint8_t other_dimm = ((rank + 2) / 2) & 1; -+ odt_matrix |= BIT(2 * other_dimm); -+ } -+ -+ union reut_misc_odt_ctrl_reg reut_misc_odt_ctrl = { -+ .raw = 0, -+ }; -+ if (ctrl->lpddr) { -+ /* Only one ODT pin for ULT */ -+ reut_misc_odt_ctrl.odt_on = 1; -+ reut_misc_odt_ctrl.odt_override = 1; -+ } else if (!is_hsw_ult()) { -+ reut_misc_odt_ctrl.odt_on = odt_matrix; -+ reut_misc_odt_ctrl.odt_override = 0xf; -+ } -+ mchbar_write32(REUT_ch_MISC_ODT_CTRL(channel), reut_misc_odt_ctrl.raw); -+ } -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ /* -+ * Enable write leveling mode in DDR and propagate delay -+ * values (without a write command). Stay in WL mode. -+ */ -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ data_control_0.wl_training_mode = 1; -+ data_control_0.tx_pi_on = 1; -+ data_control_0.read_rf_rd = 0; -+ data_control_0.read_rf_wr = 1; -+ data_control_0.read_rf_rank = rank; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ } -+ printk(BIOS_DEBUG, "\nRank %u\n", rank); -+ printk(JWRL_PLOT, "Channel\t"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(JWRL_PLOT, "%u", channel); -+ if (channel > 0) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(JWRL_PLOT, "\t"); -+ } -+ printk(JWRL_PLOT, "\nByte"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(JWRL_PLOT, "\t%u", byte); -+ } -+ printk(JWRL_PLOT, "\nWlDelay"); -+ for (uint16_t wl_delay = wl_start; wl_delay < wl_stop; wl_delay += wl_step) { -+ printk(JWRL_PLOT, "\n %3u:", wl_delay); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ update_txt(ctrl, channel, rank, byte, TXT_TXDQS, -+ wl_delay); -+ } -+ } -+ /* Wait for the first burst to finish */ -+ if (wl_delay == wl_start) -+ udelay(wait_time_us); -+ -+ io_reset(); -+ udelay(wait_time_us); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const uint32_t feedback = -+ get_data_train_feedback(channel, byte); -+ const bool pass = (feedback & 0x1ff) >= 16; -+ printk(JWRL_PLOT, "\t%c%u", pass ? '.' : '#', feedback); -+ phase_record_pass( -+ ®ion_data[channel][byte], -+ pass, -+ wl_delay, -+ wl_start, -+ wl_step); -+ } -+ } -+ } -+ printk(JWRL_PLOT, "\n"); -+ printk(BIOS_DEBUG, "\n\tInitSt\tInitEn\tCurrSt\tCurrEn\tLargSt\tLargEn\n"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ printk(BIOS_DEBUG, "C%u\n", channel); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ struct phase_train_data *data = ®ion_data[channel][byte]; -+ -+ phase_append_initial_to_current(data, wl_start, wl_step); -+ printk(BIOS_DEBUG, " B%u:\t%d\t%d\t%d\t%d\t%d\t%d\n", -+ byte, -+ data->initial.start, -+ data->initial.end, -+ data->current.start, -+ data->current.end, -+ data->largest.start, -+ data->largest.end); -+ } -+ } -+ -+ /* -+ * Clean up after test. Very coarsely adjust for -+ * any cycle errors. Program values for TxDQS. -+ */ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ /* Clear ODT before MRS (JEDEC spec) */ -+ mchbar_write32(REUT_ch_MISC_ODT_CTRL(channel), 0); -+ -+ /** TODO: Differs for LPDDR **/ -+ const uint16_t mr1reg = ctrl->mr1[channel][rank / 2] | MR1_QOFF_ENABLE; -+ reut_issue_mrs(ctrl, channel, BIT(rank), 1, mr1reg); -+ -+ printk(BIOS_DEBUG, "\nC%u.R%u: LftEdge Width\n", channel, rank); -+ const bool rank_x16 = ctrl->dimms[channel][rank / 2].data.width == 16; -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ struct phase_train_data *data = ®ion_data[channel][byte]; -+ const int32_t lwidth = range_width(data->largest); -+ int32_t tx_start = data->largest.start; -+ printk(BIOS_DEBUG, " B%u: %d\t%d\n", byte, tx_start, lwidth); -+ status = verify_wl_width(lwidth); -+ if (status) { -+ printk(BIOS_ERR, -+ "WrLevel problems on channel %u, byte %u\n", -+ channel, byte); -+ goto clean_up; -+ } -+ -+ /* Align byte pairs if DIMM is x16 */ -+ if (rank_x16 && (byte & 1)) { -+ const struct phase_train_data *const ref_data = -+ ®ion_data[channel][byte - 1]; -+ -+ if (tx_start > ref_data->largest.start + 64) -+ tx_start -= 128; -+ -+ if (tx_start < ref_data->largest.start - 64) -+ tx_start += 128; -+ } -+ -+ /* Fix for b4618067 - need to add 1 QCLK to DQS PI */ -+ if (is_hsw_ult()) -+ tx_start += 64; -+ -+ assert(tx_start >= 0); -+ ctrl->txdqs[channel][rank][byte] = tx_start; -+ ctrl->tx_dq[channel][rank][byte] = tx_start + 32; -+ update_txt(ctrl, channel, rank, byte, TXT_RESTORE, 0); -+ } -+ } -+ printk(BIOS_DEBUG, "\n"); -+ } -+ -+clean_up: -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), ctrl->dq_control_0[channel]); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ mchbar_write32(DQ_CONTROL_2(channel, byte), -+ ctrl->dq_control_2[channel][byte]); -+ } -+ } -+ if (!ctrl->lpddr) -+ ddr3_program_mr1(ctrl, 0, 0); -+ -+ ctrl->restore_mrs = save_restore_mrs; -+ -+ if (status) -+ return status; -+ -+ /** TODO: If this step fails and dec_wrd is set, clear it and try again **/ -+ return train_jedec_write_leveling_cleanup(ctrl); -+} -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 6a31d3a32c..7c0b5a49de 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -121,6 +121,8 @@ - - #define REUT_ch_ERR_DATA_MASK(ch) _MCMAIN_C(0x40d8, ch) - -+#define REUT_ch_ERR_MISC_STATUS(ch) _MCMAIN_C(0x40e8, ch) -+ - #define REUT_ch_MISC_CKE_CTRL(ch) _MCMAIN_C(0x4190, ch) - #define REUT_ch_MISC_ODT_CTRL(ch) _MCMAIN_C(0x4194, ch) - #define REUT_ch_MISC_PAT_CADB_CTRL(ch) _MCMAIN_C(0x4198, ch) --- -2.39.5 - diff --git a/config/coreboot/default/patches/0044-haswell-NRI-Add-final-raminit-steps.patch b/config/coreboot/default/patches/0044-haswell-NRI-Add-final-raminit-steps.patch deleted file mode 100644 index 62cae936..00000000 --- a/config/coreboot/default/patches/0044-haswell-NRI-Add-final-raminit-steps.patch +++ /dev/null @@ -1,570 +0,0 @@ -From 9d1b945702006db5678c5dc81699699bf6e6741a Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sun, 8 May 2022 14:29:05 +0200 -Subject: [PATCH 44/51] haswell NRI: Add final raminit steps - -Implement the remaining raminit steps. Although many training steps are -missing, this is enough to boot on the Asrock B85M Pro4. - -Change-Id: I94f3b65f0218d4da4fda4d84592dfd91f77f8f21 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - src/northbridge/intel/haswell/Kconfig | 4 +- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/activate_mc.c | 388 ++++++++++++++++++ - .../haswell/native_raminit/raminit_main.c | 5 +- - .../haswell/native_raminit/raminit_native.c | 5 +- - .../haswell/native_raminit/raminit_native.h | 2 + - .../haswell/native_raminit/reg_structs.h | 12 + - .../intel/haswell/registers/mchbar.h | 7 + - 8 files changed, 416 insertions(+), 8 deletions(-) - create mode 100644 src/northbridge/intel/haswell/native_raminit/activate_mc.c - -diff --git a/src/northbridge/intel/haswell/Kconfig b/src/northbridge/intel/haswell/Kconfig -index 4b83a25bc1..c6ab27184e 100644 ---- a/src/northbridge/intel/haswell/Kconfig -+++ b/src/northbridge/intel/haswell/Kconfig -@@ -11,12 +11,12 @@ config NORTHBRIDGE_INTEL_HASWELL - if NORTHBRIDGE_INTEL_HASWELL - - config USE_NATIVE_RAMINIT -- bool "[NOT WORKING] Use native raminit" -+ bool "[NOT COMPLETE] Use native raminit" - default n - select HAVE_DEBUG_RAM_SETUP - help - Select if you want to use coreboot implementation of raminit rather than -- MRC.bin. Currently incomplete and does not boot. -+ MRC.bin. Currently incomplete and does not support S3 resume. - - config HASWELL_VBOOT_IN_BOOTBLOCK - depends on VBOOT -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index 40c2f5e014..d97da72890 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -1,5 +1,6 @@ - ## SPDX-License-Identifier: GPL-2.0-or-later - -+romstage-y += activate_mc.c - romstage-y += change_margin.c - romstage-y += configure_mc.c - romstage-y += ddr3.c -diff --git a/src/northbridge/intel/haswell/native_raminit/activate_mc.c b/src/northbridge/intel/haswell/native_raminit/activate_mc.c -new file mode 100644 -index 0000000000..78a7ad27ef ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/activate_mc.c -@@ -0,0 +1,388 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <console/console.h> -+#include <delay.h> -+#include <device/pci_ops.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <timer.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+static void update_internal_clocks_on(struct sysinfo *ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ bool clocks_on = false; -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const union ddr_data_control_1_reg data_control_1 = { -+ .raw = ctrl->dq_control_1[channel][byte], -+ }; -+ const int8_t o_on = data_control_1.odt_delay; -+ const int8_t s_on = data_control_1.sense_amp_delay; -+ const int8_t o_off = data_control_1.odt_duration; -+ const int8_t s_off = data_control_1.sense_amp_duration; -+ if (o_on + o_off >= 7 || s_on + s_off >= 7) { -+ clocks_on = true; -+ break; -+ } -+ } -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ data_control_0.internal_clocks_on = clocks_on; -+ ctrl->dq_control_0[channel] = data_control_0.raw; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ } -+} -+ -+/* Switch off unused segments of the SDLL to save power */ -+static void update_sdll_length(struct sysinfo *ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ uint8_t max_pi = 0; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ const uint8_t rx_dqs_p = ctrl->rxdqsp[channel][rank][byte]; -+ const uint8_t rx_dqs_n = ctrl->rxdqsn[channel][rank][byte]; -+ max_pi = MAX(max_pi, MAX(rx_dqs_p, rx_dqs_n)); -+ } -+ /* Update SDLL length for power savings */ -+ union ddr_data_control_1_reg data_control_1 = { -+ .raw = ctrl->dq_control_1[channel][byte], -+ }; -+ /* Calculate which segments to turn off */ -+ data_control_1.sdll_segment_disable = (7 - (max_pi >> 3)) & ~1; -+ ctrl->dq_control_1[channel][byte] = data_control_1.raw; -+ mchbar_write32(DQ_CONTROL_1(channel, byte), data_control_1.raw); -+ } -+ } -+} -+ -+static void set_rx_clk_stg_num(struct sysinfo *ctrl, const uint8_t channel) -+{ -+ const uint8_t rcven_drift = ctrl->lpddr ? DIV_ROUND_UP(tDQSCK_DRIFT, ctrl->qclkps) : 1; -+ uint8_t max_rcven = 0; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ max_rcven = MAX(max_rcven, ctrl->rcven[channel][rank][byte] / 64); -+ } -+ const union ddr_data_control_1_reg ddr_data_control_1 = { -+ .raw = ctrl->dq_control_1[channel][0], -+ }; -+ const bool lpddr_long_odt = ddr_data_control_1.lpddr_long_odt_en; -+ const uint8_t rcven_turnoff = max_rcven + 18 + 2 * rcven_drift + lpddr_long_odt; -+ const union ddr_data_control_0_reg ddr_data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ union ddr_data_control_2_reg ddr_data_control_2 = { -+ .raw = ctrl->dq_control_2[channel][byte], -+ }; -+ if (ddr_data_control_0.odt_samp_extend_en) { -+ if (ddr_data_control_2.rx_clk_stg_num < rcven_turnoff) -+ ddr_data_control_2.rx_clk_stg_num = rcven_turnoff; -+ } else { -+ const int8_t o_on = ddr_data_control_1.odt_delay; -+ const int8_t o_off = ddr_data_control_1.odt_duration; -+ ddr_data_control_2.rx_clk_stg_num = MAX(17, o_on + o_off + 14); -+ } -+ ctrl->dq_control_2[channel][byte] = ddr_data_control_2.raw; -+ mchbar_write32(DQ_CONTROL_2(channel, byte), ddr_data_control_2.raw); -+ } -+} -+ -+#define SELF_REFRESH_IDLE_COUNT 0x200 -+ -+static void enter_sr(void) -+{ -+ mchbar_write32(PM_SREF_CONFIG, SELF_REFRESH_IDLE_COUNT | BIT(16)); -+ udelay(1); -+} -+ -+enum power_down_mode { -+ PDM_NO_PD = 0, -+ PDM_APD = 1, -+ PDM_PPD = 2, -+ PDM_PPD_DLL_OFF = 6, -+}; -+ -+static void power_down_config(struct sysinfo *ctrl) -+{ -+ const enum power_down_mode pd_mode = ctrl->lpddr ? PDM_PPD : PDM_PPD_DLL_OFF; -+ mchbar_write32(PM_PDWN_CONFIG, pd_mode << 12 | 0x40); -+} -+ -+static void train_power_modes_post(struct sysinfo *ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ /* Adjust tCPDED and tPRPDEN */ -+ if (ctrl->mem_clock_mhz >= 933) -+ ctrl->tc_bankrank_d[channel].tCPDED = 2; -+ -+ if (ctrl->mem_clock_mhz >= 1066) -+ ctrl->tc_bankrank_d[channel].tPRPDEN = 2; -+ -+ mchbar_write32(TC_BANK_RANK_D_ch(channel), ctrl->tc_bankrank_d[channel].raw); -+ } -+ power_down_config(ctrl); -+ mchbar_write32(MCDECS_CBIT, BIT(30)); /* dis_msg_clk_gate */ -+} -+ -+static uint8_t compute_burst_end_odt_delay(const struct sysinfo *const ctrl) -+{ -+ /* Must be disabled for LPDDR */ -+ if (ctrl->lpddr) -+ return 0; -+ -+ const uint8_t beod = MIN(7, DIV_ROUND_CLOSEST(14300 * 20 / 100, ctrl->qclkps)); -+ if (beod < 3) -+ return 0; -+ -+ if (beod < 4) -+ return 4; -+ -+ return beod; -+} -+ -+static void program_burst_end_odt_delay(struct sysinfo *ctrl) -+{ -+ /* Program burst_end_odt_delay - it should be zero during training steps */ -+ const uint8_t beod = compute_burst_end_odt_delay(ctrl); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ union ddr_data_control_1_reg ddr_data_control_1 = { -+ .raw = ctrl->dq_control_1[channel][byte], -+ }; -+ ddr_data_control_1.burst_end_odt_delay = beod; -+ ctrl->dq_control_1[channel][byte] = ddr_data_control_1.raw; -+ mchbar_write32(DQ_CONTROL_1(channel, byte), ddr_data_control_1.raw); -+ } -+ } -+} -+ -+/* -+ * Return a random value to use for scrambler seeds. Try to use RDRAND -+ * first and fall back to hardcoded values if RDRAND does not succeed. -+ */ -+static uint16_t get_random_number(const uint8_t channel) -+{ -+ /* The RDRAND instruction is only available 100k cycles after reset */ -+ for (size_t i = 0; i < 100000; i++) { -+ uint32_t status; -+ uint32_t random; -+ /** TODO: Clean up asm **/ -+ __asm__ __volatile__( -+ "\n\t .byte 0x0F, 0xC7, 0xF0" -+ "\n\t movl %%eax, %0" -+ "\n\t pushf" -+ "\n\t pop %%eax" -+ "\n\t movl %%eax, %1" -+ : "=m"(random), -+ "=m"(status) -+ : /* No inputs */ -+ : "eax", "cc"); -+ -+ /* Only consider non-zero random values as valid */ -+ if (status & 1 && random) -+ return random; -+ } -+ -+ /* https://xkcd.com/221 */ -+ if (channel) -+ return 0x28f4; -+ else -+ return 0x893e; -+} -+ -+/* Work around "error: 'typeof' applied to a bit-field" */ -+static inline uint32_t max(const uint32_t a, const uint32_t b) -+{ -+ return MAX(a, b); -+} -+ -+enum raminit_status activate_mc(struct sysinfo *ctrl) -+{ -+ const bool enable_scrambling = true; -+ const bool enable_cmd_tristate = true; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ if (enable_scrambling && ctrl->stepping < STEPPING_C0) { -+ /* Make sure tRDRD_(sr, dr, dd) are at least 6 for scrambler W/A */ -+ union tc_bank_rank_a_reg tc_bank_rank_a = { -+ .raw = mchbar_read32(TC_BANK_RANK_A_ch(channel)), -+ }; -+ tc_bank_rank_a.tRDRD_sr = max(tc_bank_rank_a.tRDRD_sr, 6); -+ tc_bank_rank_a.tRDRD_dr = max(tc_bank_rank_a.tRDRD_dr, 6); -+ tc_bank_rank_a.tRDRD_dd = max(tc_bank_rank_a.tRDRD_dd, 6); -+ mchbar_write32(TC_BANK_RANK_A_ch(channel), tc_bank_rank_a.raw); -+ } -+ if (enable_scrambling) { -+ const union ddr_scramble_reg ddr_scramble = { -+ .scram_key = get_random_number(channel), -+ .scram_en = 1, -+ }; -+ mchbar_write32(DDR_SCRAMBLE_ch(channel), ddr_scramble.raw); -+ } -+ if (ctrl->tCMD == 1) { -+ /* If we are in 1N mode, enable and set command rate limit to 3 */ -+ union mcmain_command_rate_limit_reg cmd_rate_limit = { -+ .raw = mchbar_read32(COMMAND_RATE_LIMIT_ch(channel)), -+ }; -+ cmd_rate_limit.enable_cmd_limit = 1; -+ cmd_rate_limit.cmd_rate_limit = 3; -+ mchbar_write32(COMMAND_RATE_LIMIT_ch(channel), cmd_rate_limit.raw); -+ } -+ if (enable_cmd_tristate) { -+ /* Enable command tri-state at the end of training */ -+ union tc_bank_rank_a_reg tc_bank_rank_a = { -+ .raw = mchbar_read32(TC_BANK_RANK_A_ch(channel)), -+ }; -+ tc_bank_rank_a.cmd_3st_dis = 0; -+ mchbar_write32(TC_BANK_RANK_A_ch(channel), tc_bank_rank_a.raw); -+ } -+ /* Set MC to normal mode and clean the ODT and CKE */ -+ mchbar_write32(REUT_ch_SEQ_CFG(channel), REUT_MODE_NOP << 12); -+ /* Set again the rank occupancy */ -+ mchbar_write8(MC_INIT_STATE_ch(channel), ctrl->rankmap[channel]); -+ if (ctrl->is_ecc) { -+ /* Enable ECC I/O and logic */ -+ union mad_dimm_reg mad_dimm = { -+ .raw = mchbar_read32(MAD_DIMM(channel)), -+ }; -+ mad_dimm.ecc_mode = 3; -+ mchbar_write32(MAD_DIMM(channel), mad_dimm.raw); -+ } -+ } -+ -+ if (!is_hsw_ult()) -+ update_internal_clocks_on(ctrl); -+ -+ update_sdll_length(ctrl); -+ -+ program_burst_end_odt_delay(ctrl); -+ -+ if (is_hsw_ult()) { -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ set_rx_clk_stg_num(ctrl, channel); -+ } -+ /** TODO: Program DDRPL_CR_DDR_TX_DELAY if Memory Trace is enabled **/ -+ } -+ -+ /* Enable periodic COMP */ -+ mchbar_write32(M_COMP, (union pcu_comp_reg) { -+ .comp_interval = COMP_INT, -+ }.raw); -+ -+ /* Enable the power mode before PCU starts working */ -+ train_power_modes_post(ctrl); -+ -+ /* Set idle timer and self refresh enable bits */ -+ enter_sr(); -+ -+ /** FIXME: Do not hardcode power weights and RAPL settings **/ -+ mchbar_write32(0x5888, 0x00000d0d); -+ mchbar_write32(0x5884, 0x00000004); /* 58.2 pJ */ -+ -+ mchbar_write32(0x58e0, 0); -+ mchbar_write32(0x58e4, 0); -+ -+ mchbar_write32(0x5890, 0xffff); -+ mchbar_write32(0x5894, 0xffff); -+ mchbar_write32(0x5898, 0xffff); -+ mchbar_write32(0x589c, 0xffff); -+ mchbar_write32(0x58d0, 0xffff); -+ mchbar_write32(0x58d4, 0xffff); -+ mchbar_write32(0x58d8, 0xffff); -+ mchbar_write32(0x58dc, 0xffff); -+ -+ /* Overwrite thermal parameters */ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ mchbar_write32(_MCMAIN_C(0x42ec, channel), 0x0000000f); -+ mchbar_write32(_MCMAIN_C(0x42f0, channel), 0x00000009); -+ mchbar_write32(_MCMAIN_C(0x42f4, channel), 0x00000093); -+ mchbar_write32(_MCMAIN_C(0x42f8, channel), 0x00000087); -+ mchbar_write32(_MCMAIN_C(0x42fc, channel), 0x000000de); -+ -+ /** TODO: Differs for LPDDR **/ -+ mchbar_write32(PM_THRT_CKE_MIN_ch(channel), 0x30); -+ } -+ mchbar_write32(PCU_DDR_PTM_CTL, 0x40); -+ return RAMINIT_STATUS_SUCCESS; -+} -+ -+static void mc_lockdown(void) -+{ -+ /* Lock memory controller registers */ -+ mchbar_write32(MC_LOCK, 0x8f); -+ -+ /* MPCOHTRK_GDXC_OCLA_ADDRESS_HI_LOCK is set when programming the memory map */ -+ -+ /* Lock memory map registers */ -+ pci_or_config16(HOST_BRIDGE, GGC, 1 << 0); -+ pci_or_config32(HOST_BRIDGE, DPR, 1 << 0); -+ pci_or_config32(HOST_BRIDGE, MESEG_LIMIT, 1 << 10); -+ pci_or_config32(HOST_BRIDGE, REMAPBASE, 1 << 0); -+ pci_or_config32(HOST_BRIDGE, REMAPLIMIT, 1 << 0); -+ pci_or_config32(HOST_BRIDGE, TOM, 1 << 0); -+ pci_or_config32(HOST_BRIDGE, TOUUD, 1 << 0); -+ pci_or_config32(HOST_BRIDGE, BDSM, 1 << 0); -+ pci_or_config32(HOST_BRIDGE, BGSM, 1 << 0); -+ pci_or_config32(HOST_BRIDGE, TOLUD, 1 << 0); -+} -+ -+enum raminit_status raminit_done(struct sysinfo *ctrl) -+{ -+ union mc_init_state_g_reg mc_init_state_g = { -+ .raw = mchbar_read32(MC_INIT_STATE_G), -+ }; -+ mc_init_state_g.refresh_enable = 1; -+ mc_init_state_g.pu_mrc_done = 1; -+ mc_init_state_g.mrc_done = 1; -+ mchbar_write32(MC_INIT_STATE_G, mc_init_state_g.raw); -+ -+ /* Lock the memory controller to enable normal operation */ -+ mc_lockdown(); -+ -+ /* Poll for mc_init_done_ack to make sure memory initialization is complete */ -+ printk(BIOS_DEBUG, "Waiting for mc_init_done acknowledgement... "); -+ -+ struct stopwatch timer; -+ stopwatch_init_msecs_expire(&timer, 2000); -+ do { -+ mc_init_state_g.raw = mchbar_read32(MC_INIT_STATE_G); -+ -+ /* DRAM will NOT work without the acknowledgement. There is no hope. */ -+ if (stopwatch_expired(&timer)) -+ die("\nTimed out waiting for mc_init_done acknowledgement\n"); -+ -+ } while (mc_init_state_g.mc_init_done_ack == 0); -+ printk(BIOS_DEBUG, "DONE!\n"); -+ -+ /* Provide some data for the graphics driver. Yes, it's hardcoded. */ -+ mchbar_write32(SSKPD + 0, 0x05a2404f); -+ mchbar_write32(SSKPD + 4, 0x140000a0); -+ return RAMINIT_STATUS_SUCCESS; -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 1ff23be615..3a65fb01fb 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -63,6 +63,8 @@ static const struct task_entry cold_boot[] = { - { train_receive_enable, true, "RCVET", }, - { train_read_mpr, true, "RDMPRT", }, - { train_jedec_write_leveling, true, "JWRL", }, -+ { activate_mc, true, "ACTIVATE", }, -+ { raminit_done, true, "RAMINITEND", }, - }; - - /* Return a generic stepping value to make stepping checks simpler */ -@@ -143,7 +145,4 @@ void raminit_main(const enum raminit_boot_mode bootmode) - - if (status != RAMINIT_STATUS_SUCCESS) - die("Memory initialization was met with utmost failure and misery\n"); -- -- /** TODO: Implement the required magic **/ -- die("NATIVE RAMINIT: More Magic (tm) required.\n"); - } -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.c b/src/northbridge/intel/haswell/native_raminit/raminit_native.c -index 2fed93de5b..5f7ceec222 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.c -@@ -199,8 +199,6 @@ void perform_raminit(const int s3resume) - else - me_status = ME_INIT_STATUS_SUCCESS; - -- /** TODO: Remove this once raminit is implemented **/ -- me_status = ME_INIT_STATUS_ERROR; - intel_early_me_init_done(me_status); - } - -@@ -214,7 +212,8 @@ void perform_raminit(const int s3resume) - } - - /* Save training data on non-S3 resumes */ -- if (!s3resume) -+ /** TODO: Enable this once training data is populated **/ -+ if (0 && !s3resume) - save_mrc_data(&md); - - /** TODO: setup_sdram_meminfo **/ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index d6b11b9d3c..a0a913f926 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -448,6 +448,8 @@ enum raminit_status do_jedec_init(struct sysinfo *ctrl); - enum raminit_status train_receive_enable(struct sysinfo *ctrl); - enum raminit_status train_read_mpr(struct sysinfo *ctrl); - enum raminit_status train_jedec_write_leveling(struct sysinfo *ctrl); -+enum raminit_status activate_mc(struct sysinfo *ctrl); -+enum raminit_status raminit_done(struct sysinfo *ctrl); - - void configure_timings(struct sysinfo *ctrl); - void configure_refresh(struct sysinfo *ctrl); -diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -index a0e36ed082..0d9aaa1f7c 100644 ---- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h -+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h -@@ -294,6 +294,18 @@ union ddr_cke_ctl_controls_reg { - uint32_t raw; - }; - -+union ddr_scramble_reg { -+ struct __packed { -+ uint32_t scram_en : 1; // Bits 0:0 -+ uint32_t scram_key : 16; // Bits 16:1 -+ uint32_t clk_gate_ab : 2; // Bits 18:17 -+ uint32_t clk_gate_c : 2; // Bits 20:19 -+ uint32_t en_dbi_ab : 1; // Bits 21:21 -+ uint32_t : 10; // Bits 31:17 -+ }; -+ uint32_t raw; -+}; -+ - union ddr_scram_misc_control_reg { - struct __packed { - uint32_t wl_wake_cycles : 2; // Bits 1:0 -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 7c0b5a49de..49a215aa71 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -20,6 +20,7 @@ - - #define DDR_DATA_TRAIN_FEEDBACK(ch, byte) _DDRIO_C_R_B(0x0054, ch, 0, byte) - -+#define DQ_CONTROL_1(ch, byte) _DDRIO_C_R_B(0x0060, ch, 0, byte) - #define DQ_CONTROL_2(ch, byte) _DDRIO_C_R_B(0x0064, ch, 0, byte) - #define DDR_DATA_OFFSET_TRAIN_ch_b(ch, byte) _DDRIO_C_R_B(0x0070, ch, 0, byte) - #define DQ_CONTROL_0(ch, byte) _DDRIO_C_R_B(0x0074, ch, 0, byte) -@@ -147,6 +148,8 @@ - #define QCLK_ch_LDAT_SDAT(ch) _MCMAIN_C(0x42d4, ch) - #define QCLK_ch_LDAT_DATA_IN_x(ch, x) _MCMAIN_C_X(0x42dc, ch, x) /* x in 0 .. 1 */ - -+#define PM_THRT_CKE_MIN_ch(ch) _MCMAIN_C(0x4328, ch) -+ - #define REUT_GLOBAL_CTL 0x4800 - #define REUT_GLOBAL_ERR 0x4804 - -@@ -175,6 +178,8 @@ - - #define MCSCHEDS_DFT_MISC 0x4c30 - -+#define PM_PDWN_CONFIG 0x4cb0 -+ - #define REUT_ERR_DATA_STATUS 0x4ce0 - - #define REUT_MISC_CKE_CTRL 0x4d90 -@@ -186,8 +191,10 @@ - #define MAD_CHNL 0x5000 /* Address Decoder Channel Configuration */ - #define MAD_DIMM(ch) (0x5004 + (ch) * 4) - #define MAD_ZR 0x5014 -+#define MCDECS_CBIT 0x501c - #define MC_INIT_STATE_G 0x5030 - #define MRC_REVISION 0x5034 /* MRC Revision */ -+#define PM_SREF_CONFIG 0x5060 - - #define RCOMP_TIMER 0x5084 - --- -2.39.5 - diff --git a/config/coreboot/default/patches/0045-Haswell-NRI-Implement-fast-boot-path.patch b/config/coreboot/default/patches/0045-Haswell-NRI-Implement-fast-boot-path.patch deleted file mode 100644 index af614a5f..00000000 --- a/config/coreboot/default/patches/0045-Haswell-NRI-Implement-fast-boot-path.patch +++ /dev/null @@ -1,722 +0,0 @@ -From b6b89013630d535b68a005cede9e2540f273f4e7 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Sat, 13 Apr 2024 01:16:30 +0200 -Subject: [PATCH 45/51] Haswell NRI: Implement fast boot path - -When the memory configuration hasn't changed, there is no need to do -full memory training. Instead, boot firmware can use saved training -data to reinitialise the memory controller and memory. - -Unlike native RAM init for other platforms, Haswell does not save the -main structure (the "mighty ctrl" struct) to flash. Instead, separate -structures define the data to be saved, which can be smaller than the -main structure. - -This makes S3 suspend and resume work: RAM contents MUST be preserved -for a S3 resume to succeed, but RAM training destroys RAM contents. - -Change-Id: I06f6cd39ceecdca104fae89159f28e85cf7ff4e6 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/activate_mc.c | 17 + - .../intel/haswell/native_raminit/ddr3.c | 41 ++ - .../haswell/native_raminit/raminit_main.c | 34 +- - .../haswell/native_raminit/raminit_native.c | 30 +- - .../haswell/native_raminit/raminit_native.h | 18 + - .../haswell/native_raminit/save_restore.c | 387 ++++++++++++++++++ - 7 files changed, 504 insertions(+), 24 deletions(-) - create mode 100644 src/northbridge/intel/haswell/native_raminit/save_restore.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index d97da72890..8fdd17c542 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -13,6 +13,7 @@ romstage-y += raminit_main.c - romstage-y += raminit_native.c - romstage-y += ranges.c - romstage-y += reut.c -+romstage-y += save_restore.c - romstage-y += setup_wdb.c - romstage-y += spd_bitmunching.c - romstage-y += testing_io.c -diff --git a/src/northbridge/intel/haswell/native_raminit/activate_mc.c b/src/northbridge/intel/haswell/native_raminit/activate_mc.c -index 78a7ad27ef..0b3eb917da 100644 ---- a/src/northbridge/intel/haswell/native_raminit/activate_mc.c -+++ b/src/northbridge/intel/haswell/native_raminit/activate_mc.c -@@ -333,6 +333,23 @@ enum raminit_status activate_mc(struct sysinfo *ctrl) - return RAMINIT_STATUS_SUCCESS; - } - -+enum raminit_status normal_state(struct sysinfo *ctrl) -+{ -+ /* Enable periodic COMP */ -+ mchbar_write32(M_COMP, (union pcu_comp_reg) { -+ .comp_interval = COMP_INT, -+ }.raw); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ /* Set MC to normal mode and clean the ODT and CKE */ -+ mchbar_write32(REUT_ch_SEQ_CFG(channel), REUT_MODE_NOP << 12); -+ } -+ power_down_config(ctrl); -+ return RAMINIT_STATUS_SUCCESS; -+} -+ - static void mc_lockdown(void) - { - /* Lock memory controller registers */ -diff --git a/src/northbridge/intel/haswell/native_raminit/ddr3.c b/src/northbridge/intel/haswell/native_raminit/ddr3.c -index 6ddb11488b..9b6368edb1 100644 ---- a/src/northbridge/intel/haswell/native_raminit/ddr3.c -+++ b/src/northbridge/intel/haswell/native_raminit/ddr3.c -@@ -2,6 +2,7 @@ - - #include <assert.h> - #include <console/console.h> -+#include <delay.h> - #include <northbridge/intel/haswell/haswell.h> - #include <types.h> - -@@ -215,3 +216,43 @@ enum raminit_status ddr3_jedec_init(struct sysinfo *ctrl) - ddr3_program_mr0(ctrl, 1); - return reut_issue_zq(ctrl, ctrl->chanmap, ZQ_INIT); - } -+ -+enum raminit_status exit_selfrefresh(struct sysinfo *ctrl) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ /* Fields in ctrl aren't populated on a warm boot */ -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = mchbar_read32(DQ_CONTROL_0(channel, 0)), -+ }; -+ data_control_0.read_rf_rd = 1; -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ data_control_0.read_rf_rank = rank; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ } -+ } -+ -+ /* Time needed to stabilize the DCLK (~6 us) */ -+ udelay(6); -+ -+ /* Pull the DIMMs out of self refresh by asserting CKE high */ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ const union reut_misc_cke_ctrl_reg reut_misc_cke_ctrl = { -+ .cke_on = ctrl->rankmap[channel], -+ }; -+ mchbar_write32(REUT_ch_MISC_CKE_CTRL(channel), reut_misc_cke_ctrl.raw); -+ } -+ mchbar_write32(REUT_MISC_ODT_CTRL, 0); -+ -+ const enum raminit_status status = reut_issue_zq(ctrl, ctrl->chanmap, ZQ_LONG); -+ if (status) { -+ /* ZQCL errors don't seem to be a fatal problem here */ -+ printk(BIOS_ERR, "ZQ Long failed during S3 resume or warm reset flow\n"); -+ } -+ return RAMINIT_STATUS_SUCCESS; -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 3a65fb01fb..056dde1adc 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -64,6 +64,22 @@ static const struct task_entry cold_boot[] = { - { train_read_mpr, true, "RDMPRT", }, - { train_jedec_write_leveling, true, "JWRL", }, - { activate_mc, true, "ACTIVATE", }, -+ { save_training_values, true, "SAVE_TRAIN", }, -+ { save_non_training, true, "SAVE_NONT", }, -+ { raminit_done, true, "RAMINITEND", }, -+}; -+ -+static const struct task_entry fast_boot[] = { -+ { collect_spd_info, true, "PROCSPD", }, -+ { restore_non_training, true, "RST_NONT", }, -+ { initialise_mpll, true, "INITMPLL", }, -+ { configure_mc, true, "CONFMC", }, -+ { configure_memory_map, true, "MEMMAP", }, -+ { do_jedec_init, true, "JEDECINIT", }, -+ { pre_training, true, "PRETRAIN", }, -+ { restore_training_values, true, "RST_TRAIN", }, -+ { exit_selfrefresh, true, "EXIT_SR", }, -+ { normal_state, true, "NORMALMODE", }, - { raminit_done, true, "RAMINITEND", }, - }; - -@@ -102,11 +118,11 @@ static void initialize_ctrl(struct sysinfo *ctrl) - ctrl->bootmode = bootmode; - } - --static enum raminit_status try_raminit(struct sysinfo *ctrl) -+static enum raminit_status try_raminit( -+ struct sysinfo *ctrl, -+ const struct task_entry *const schedule, -+ const size_t length) - { -- const struct task_entry *const schedule = cold_boot; -- const size_t length = ARRAY_SIZE(cold_boot); -- - enum raminit_status status = RAMINIT_STATUS_UNSPECIFIED_ERROR; - - for (size_t i = 0; i < length; i++) { -@@ -140,8 +156,16 @@ void raminit_main(const enum raminit_boot_mode bootmode) - mighty_ctrl.bootmode = bootmode; - initialize_ctrl(&mighty_ctrl); - -+ enum raminit_status status = RAMINIT_STATUS_UNSPECIFIED_ERROR; -+ -+ if (bootmode != BOOTMODE_COLD) { -+ status = try_raminit(&mighty_ctrl, fast_boot, ARRAY_SIZE(fast_boot)); -+ if (status == RAMINIT_STATUS_SUCCESS) -+ return; -+ } -+ - /** TODO: Try more than once **/ -- enum raminit_status status = try_raminit(&mighty_ctrl); -+ status = try_raminit(&mighty_ctrl, cold_boot, ARRAY_SIZE(cold_boot)); - - if (status != RAMINIT_STATUS_SUCCESS) - die("Memory initialization was met with utmost failure and misery\n"); -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.c b/src/northbridge/intel/haswell/native_raminit/raminit_native.c -index 5f7ceec222..3ad8ce29e7 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.c -@@ -54,23 +54,17 @@ static bool early_init_native(enum raminit_boot_mode bootmode) - return cpu_replaced; - } - --#define MRC_CACHE_VERSION 1 -- --struct mrc_data { -- const void *buffer; -- size_t buffer_len; --}; -- --static void save_mrc_data(struct mrc_data *md) -+static void save_mrc_data(void) - { -- mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, md->buffer, md->buffer_len); -+ mrc_cache_stash_data(MRC_TRAINING_DATA, reg_frame_rev(), -+ reg_frame_ptr(), reg_frame_size()); - } - - static struct mrc_data prepare_mrc_cache(void) - { - struct mrc_data md = {0}; - md.buffer = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, -- MRC_CACHE_VERSION, -+ reg_frame_rev(), - &md.buffer_len); - return md; - } -@@ -94,14 +88,15 @@ static void raminit_reset(void) - } - - static enum raminit_boot_mode do_actual_raminit( -- struct mrc_data *md, - const bool s3resume, - const bool cpu_replaced, - const enum raminit_boot_mode orig_bootmode) - { -+ struct mrc_data md = prepare_mrc_cache(); -+ - enum raminit_boot_mode bootmode = orig_bootmode; - -- bool save_data_valid = md->buffer && md->buffer_len == USHRT_MAX; /** TODO: sizeof() **/ -+ bool save_data_valid = md.buffer && md.buffer_len == reg_frame_size(); - - if (s3resume) { - if (bootmode == BOOTMODE_COLD) { -@@ -154,7 +149,7 @@ static enum raminit_boot_mode do_actual_raminit( - assert(save_data_valid != (bootmode == BOOTMODE_COLD)); - if (save_data_valid) { - printk(BIOS_INFO, "Using cached memory parameters\n"); -- die("RAMINIT: Fast boot is not yet implemented\n"); -+ memcpy(reg_frame_ptr(), md.buffer, reg_frame_size()); - } - printk(RAM_DEBUG, "Initial bootmode: %s\n", bm_names[orig_bootmode]); - printk(RAM_DEBUG, "Current bootmode: %s\n", bm_names[bootmode]); -@@ -181,10 +176,8 @@ void perform_raminit(const int s3resume) - wait_txt_clear(); - wrmsr(0x2e6, (msr_t) {.lo = 0, .hi = 0}); - -- struct mrc_data md = prepare_mrc_cache(); -- - const enum raminit_boot_mode bootmode = -- do_actual_raminit(&md, s3resume, cpu_replaced, orig_bootmode); -+ do_actual_raminit(s3resume, cpu_replaced, orig_bootmode); - - /** TODO: report_memory_config **/ - -@@ -212,9 +205,8 @@ void perform_raminit(const int s3resume) - } - - /* Save training data on non-S3 resumes */ -- /** TODO: Enable this once training data is populated **/ -- if (0 && !s3resume) -- save_mrc_data(&md); -+ if (!s3resume) -+ save_mrc_data(); - - /** TODO: setup_sdram_meminfo **/ - } -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index a0a913f926..2ac16eaad3 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -170,6 +170,8 @@ enum regfile_mode { - REG_FILE_USE_CURRENT, /* Used when changing parameters after the test */ - }; - -+struct register_save_frame; -+ - struct wdb_pat { - uint32_t start_ptr; /* Starting pointer in WDB */ - uint32_t stop_ptr; /* Stopping pointer in WDB */ -@@ -220,6 +222,7 @@ enum raminit_status { - RAMINIT_STATUS_RCVEN_FAILURE, - RAMINIT_STATUS_RMPR_FAILURE, - RAMINIT_STATUS_JWRL_FAILURE, -+ RAMINIT_STATUS_INVALID_CACHE, - RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/ - }; - -@@ -229,6 +232,11 @@ enum generic_stepping { - STEPPING_C0 = 3, - }; - -+struct mrc_data { -+ const void *buffer; -+ size_t buffer_len; -+}; -+ - struct raminit_dimm_info { - spd_ddr3_raw_data raw_spd; - struct dimm_attr_ddr3_st data; -@@ -448,12 +456,22 @@ enum raminit_status do_jedec_init(struct sysinfo *ctrl); - enum raminit_status train_receive_enable(struct sysinfo *ctrl); - enum raminit_status train_read_mpr(struct sysinfo *ctrl); - enum raminit_status train_jedec_write_leveling(struct sysinfo *ctrl); -+enum raminit_status save_training_values(struct sysinfo *ctrl); -+enum raminit_status restore_training_values(struct sysinfo *ctrl); -+enum raminit_status save_non_training(struct sysinfo *ctrl); -+enum raminit_status restore_non_training(struct sysinfo *ctrl); -+enum raminit_status exit_selfrefresh(struct sysinfo *ctrl); -+enum raminit_status normal_state(struct sysinfo *ctrl); - enum raminit_status activate_mc(struct sysinfo *ctrl); - enum raminit_status raminit_done(struct sysinfo *ctrl); - - void configure_timings(struct sysinfo *ctrl); - void configure_refresh(struct sysinfo *ctrl); - -+struct register_save_frame *reg_frame_ptr(void); -+size_t reg_frame_size(void); -+uint32_t reg_frame_rev(void); -+ - uint32_t get_tCKE(uint32_t mem_clock_mhz, bool lpddr); - uint32_t get_tXPDLL(uint32_t mem_clock_mhz); - uint32_t get_tAONPD(uint32_t mem_clock_mhz); -diff --git a/src/northbridge/intel/haswell/native_raminit/save_restore.c b/src/northbridge/intel/haswell/native_raminit/save_restore.c -new file mode 100644 -index 0000000000..f1f50e3ff8 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/save_restore.c -@@ -0,0 +1,387 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <assert.h> -+#include <console/console.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+uint32_t reg_frame_rev(void) -+{ -+ /* -+ * Equivalent to MRC_CACHE_REVISION, but hidden via abstraction. -+ * The structures that get saved to flash are contained within -+ * this translation unit, so changes outside this file shouldn't -+ * require invalidating the cache. -+ */ -+ return 1; -+} -+ -+struct register_save { -+ uint16_t lower; -+ uint16_t upper; -+}; -+ -+/** TODO: Haswell DDRIO aliases writes: 0x80 .. 0xff => 0x00 .. 0x7f **/ -+static const struct register_save ddrio_per_byte_list[] = { -+ {0x0000, 0x003c}, /* 16 registers */ -+// {0x0048, 0x0084}, /* 16 registers */ /** TODO: BDW support **/ -+ {0x0048, 0x004c}, /* 2 registers */ -+ {0x005c, 0x0078}, /* 8 registers */ -+}; -+#define DDRIO_PER_BYTE_REGISTER_COUNT (16 + 2 + 8) -+ -+static const struct register_save ddrio_per_ch_list[] = { -+ /* CKE */ -+ {0x1204, 0x1208}, /* 2 registers */ -+ {0x1214, 0x121c}, /* 3 registers */ -+ /* CMD North */ -+ {0x1404, 0x140c}, /* 3 registers */ -+ /* CLK */ -+ {0x1808, 0x1810}, /* 3 registers */ -+ /* CMD South */ -+ {0x1a04, 0x1a0c}, /* 3 registers */ -+ /* CTL */ -+ {0x1c14, 0x1c1c}, /* 3 registers */ -+}; -+#define DDRIO_PER_CH_REGISTER_COUNT (2 + 3 * 5) -+ -+static const struct register_save ddrio_common_list[] = { -+ {0x2000, 0x2008}, /* 3 registers */ -+ {0x3a14, 0x3a1c}, /* 3 registers */ -+ {0x3a24, 0x3a24}, /* 1 registers */ -+}; -+ -+#define DDRIO_COMMON_REGISTER_COUNT (3 + 3 + 1) -+ -+static const struct register_save mcmain_per_ch_list[] = { -+ {0x4000, 0x4014}, /* 6 registers */ -+ {0x4024, 0x4028}, /* 2 registers */ -+ {0x40d0, 0x40d0}, /* 1 registers */ -+ {0x4220, 0x4224}, /* 2 registers */ -+ {0x4294, 0x4294}, /* 1 registers */ -+ {0x429c, 0x42a0}, /* 2 registers */ -+ {0x42ec, 0x42fc}, /* 5 registers */ -+ {0x4328, 0x4328}, /* 1 registers */ -+ {0x438c, 0x4390}, /* 2 registers */ -+}; -+#define MCMAIN_PER_CH_REGISTER_COUNT (6 + 2 + 1 + 2 + 1 + 2 + 5 + 1 + 2) -+ -+static const struct register_save misc_common_list[] = { -+ {0x5884, 0x5888}, /* 2 registers */ -+ {0x5890, 0x589c}, /* 4 registers */ -+ {0x58a4, 0x58a4}, /* 1 registers */ -+ {0x58d0, 0x58e4}, /* 6 registers */ -+ {0x5880, 0x5880}, /* 1 registers */ -+ {0x5000, 0x50dc}, /* 56 registers */ -+ {0x59b8, 0x59b8} /* 1 registers */ -+}; -+#define MISC_COMMON_REGISTER_COUNT (2 + 4 + 1 + 6 + 1 + 56 + 1) -+ -+struct save_params { -+ bool is_initialised; -+ -+ /* Memory base frequency, either 100 or 133 MHz */ -+ uint8_t base_freq; -+ -+ /* Multiplier */ -+ uint32_t multiplier; -+ -+ /* Memory clock in MHz */ -+ uint32_t mem_clock_mhz; -+ -+ /* Memory clock in femtoseconds */ -+ uint32_t mem_clock_fs; -+ -+ /* Quadrature clock in picoseconds */ -+ uint16_t qclkps; -+ -+ /* Bitfield of supported CAS latencies */ -+ uint16_t cas_supported; -+ -+ /* CPUID value */ -+ uint32_t cpu; -+ -+ /* Cached CPU stepping value */ -+ uint8_t stepping; -+ -+ uint16_t vdd_mv; -+ -+ union dimm_flags_ddr3_st flags; -+ -+ /* Except for tCK, everything is stored in DCLKs */ -+ uint32_t tCK; -+ uint32_t tAA; -+ uint32_t tWR; -+ uint32_t tRCD; -+ uint32_t tRRD; -+ uint32_t tRP; -+ uint32_t tRAS; -+ uint32_t tRC; -+ uint32_t tRFC; -+ uint32_t tWTR; -+ uint32_t tRTP; -+ uint32_t tFAW; -+ uint32_t tCWL; -+ uint32_t tCMD; -+ -+ uint32_t tREFI; -+ uint32_t tXP; -+ -+ uint8_t lpddr_cke_rank_map[NUM_CHANNELS]; -+ -+ struct raminit_dimm_info dimms[NUM_CHANNELS][NUM_SLOTS]; -+ -+ uint8_t chanmap; -+ -+ uint32_t channel_size_mb[NUM_CHANNELS]; -+ -+ /* DIMMs per channel */ -+ uint8_t dpc[NUM_CHANNELS]; -+ -+ uint8_t rankmap[NUM_CHANNELS]; -+ -+ /* Whether a rank is mirrored or not (only rank 1 of each DIMM can be) */ -+ uint8_t rank_mirrored[NUM_CHANNELS]; -+ -+ /* -+ * FIXME: LPDDR support is incomplete. The largest chunks are missing, -+ * but some LPDDR-specific variations in algorithms have been handled. -+ * LPDDR-specific functions have stubs which will halt upon execution. -+ */ -+ bool lpddr; -+ -+ uint8_t lanes; -+ -+ /* FIXME: ECC support missing */ -+ bool is_ecc; -+}; -+ -+struct register_save_frame { -+ uint32_t ddrio_per_byte[NUM_CHANNELS][NUM_LANES][DDRIO_PER_BYTE_REGISTER_COUNT]; -+ uint32_t ddrio_per_ch[NUM_CHANNELS][DDRIO_PER_CH_REGISTER_COUNT]; -+ uint32_t ddrio_common[DDRIO_COMMON_REGISTER_COUNT]; -+ uint32_t mcmain_per_ch[NUM_CHANNELS][MCMAIN_PER_CH_REGISTER_COUNT]; -+ uint32_t misc_common[MISC_COMMON_REGISTER_COUNT]; -+ struct save_params params; -+}; -+ -+struct register_save_frame *reg_frame_ptr(void) -+{ -+ /* The chonky register save frame struct, used for fast boot and S3 resume */ -+ static struct register_save_frame register_frame = { 0 }; -+ return ®ister_frame; -+} -+ -+size_t reg_frame_size(void) -+{ -+ return sizeof(struct register_save_frame); -+} -+ -+typedef void (*reg_func_t)(const uint16_t offset, uint32_t *const value); -+ -+static void save_value(const uint16_t offset, uint32_t *const value) -+{ -+ *value = mchbar_read32(offset); -+} -+ -+static void restore_value(const uint16_t offset, uint32_t *const value) -+{ -+ mchbar_write32(offset, *value); -+} -+ -+static void save_restore( -+ uint32_t *reg_frame, -+ const uint16_t g_offset, -+ const struct register_save *reg_save_list, -+ const size_t reg_save_length, -+ reg_func_t handle_reg) -+{ -+ for (size_t i = 0; i < reg_save_length; i++) { -+ const struct register_save *entry = ®_save_list[i]; -+ for (uint16_t offset = entry->lower; offset <= entry->upper; offset += 4) { -+ handle_reg(offset + g_offset, reg_frame++); -+ } -+ } -+} -+ -+static void save_restore_all(struct register_save_frame *reg_frame, reg_func_t handle_reg) -+{ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ for (uint8_t byte = 0; byte < NUM_LANES; byte++) { -+ const uint16_t g_offset = _DDRIO_C_R_B(0, channel, 0, byte); -+ save_restore( -+ reg_frame->ddrio_per_byte[channel][byte], -+ g_offset, -+ ddrio_per_byte_list, -+ ARRAY_SIZE(ddrio_per_byte_list), -+ handle_reg); -+ } -+ } -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ const uint16_t g_offset = _DDRIO_C_R_B(0, channel, 0, 0); -+ save_restore( -+ reg_frame->ddrio_per_ch[channel], -+ g_offset, -+ ddrio_per_ch_list, -+ ARRAY_SIZE(ddrio_per_ch_list), -+ handle_reg); -+ } -+ save_restore( -+ reg_frame->ddrio_common, -+ 0, -+ ddrio_common_list, -+ ARRAY_SIZE(ddrio_common_list), -+ handle_reg); -+ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ const uint16_t g_offset = _MCMAIN_C(0, channel); -+ save_restore( -+ reg_frame->mcmain_per_ch[channel], -+ g_offset, -+ mcmain_per_ch_list, -+ ARRAY_SIZE(mcmain_per_ch_list), -+ handle_reg); -+ } -+ save_restore( -+ reg_frame->misc_common, -+ 0, -+ misc_common_list, -+ ARRAY_SIZE(misc_common_list), -+ handle_reg); -+} -+ -+enum raminit_status save_training_values(struct sysinfo *ctrl) -+{ -+ save_restore_all(reg_frame_ptr(), save_value); -+ return RAMINIT_STATUS_SUCCESS; -+} -+ -+enum raminit_status restore_training_values(struct sysinfo *ctrl) -+{ -+ save_restore_all(reg_frame_ptr(), restore_value); -+ return RAMINIT_STATUS_SUCCESS; -+} -+ -+enum raminit_status save_non_training(struct sysinfo *ctrl) -+{ -+ struct register_save_frame *reg_frame = reg_frame_ptr(); -+ struct save_params *params = ®_frame->params; -+ -+ params->is_initialised = true; -+ -+ params->base_freq = ctrl->base_freq; -+ params->multiplier = ctrl->multiplier; -+ params->mem_clock_mhz = ctrl->mem_clock_mhz; -+ params->mem_clock_fs = ctrl->mem_clock_fs; -+ params->qclkps = ctrl->qclkps; -+ params->cas_supported = ctrl->cas_supported; -+ params->cpu = ctrl->cpu; -+ params->stepping = ctrl->stepping; -+ params->vdd_mv = ctrl->vdd_mv; -+ params->flags = ctrl->flags; -+ -+ params->tCK = ctrl->tCK; -+ params->tAA = ctrl->tAA; -+ params->tWR = ctrl->tWR; -+ params->tRCD = ctrl->tRCD; -+ params->tRRD = ctrl->tRRD; -+ params->tRP = ctrl->tRP; -+ params->tRAS = ctrl->tRAS; -+ params->tRC = ctrl->tRC; -+ params->tRFC = ctrl->tRFC; -+ params->tWTR = ctrl->tWTR; -+ params->tRTP = ctrl->tRTP; -+ params->tFAW = ctrl->tFAW; -+ params->tCWL = ctrl->tCWL; -+ params->tCMD = ctrl->tCMD; -+ params->tREFI = ctrl->tREFI; -+ params->tXP = ctrl->tXP; -+ -+ params->chanmap = ctrl->chanmap; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ params->lpddr_cke_rank_map[channel] = ctrl->lpddr_cke_rank_map[channel]; -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) -+ params->dimms[channel][slot] = ctrl->dimms[channel][slot]; -+ } -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ params->dpc[channel] = ctrl->dpc[channel]; -+ params->rankmap[channel] = ctrl->rankmap[channel]; -+ params->rank_mirrored[channel] = ctrl->rank_mirrored[channel]; -+ params->channel_size_mb[channel] = ctrl->channel_size_mb[channel]; -+ } -+ params->lpddr = ctrl->lpddr; -+ params->lanes = ctrl->lanes; -+ params->is_ecc = ctrl->is_ecc; -+ return RAMINIT_STATUS_SUCCESS; -+} -+ -+#define RAMINIT_COMPARE(_s1, _s2) \ -+ ((sizeof(_s1) == sizeof(_s2)) && !memcmp(_s1, _s2, sizeof(_s1))) -+ -+enum raminit_status restore_non_training(struct sysinfo *ctrl) -+{ -+ struct register_save_frame *reg_frame = reg_frame_ptr(); -+ struct save_params *params = ®_frame->params; -+ -+ if (!params->is_initialised) { -+ printk(BIOS_WARNING, "Cannot fast boot: saved data is invalid\n"); -+ return RAMINIT_STATUS_INVALID_CACHE; -+ } -+ -+ if (!RAMINIT_COMPARE(ctrl->dimms, params->dimms)) { -+ printk(BIOS_WARNING, "Cannot fast boot: DIMMs have changed\n"); -+ return RAMINIT_STATUS_INVALID_CACHE; -+ } -+ -+ if (ctrl->cpu != params->cpu) { -+ printk(BIOS_WARNING, "Cannot fast boot: CPU has changed\n"); -+ return RAMINIT_STATUS_INVALID_CACHE; -+ } -+ -+ ctrl->base_freq = params->base_freq; -+ ctrl->multiplier = params->multiplier; -+ ctrl->mem_clock_mhz = params->mem_clock_mhz; -+ ctrl->mem_clock_fs = params->mem_clock_fs; -+ ctrl->qclkps = params->qclkps; -+ ctrl->cas_supported = params->cas_supported; -+ ctrl->cpu = params->cpu; -+ ctrl->stepping = params->stepping; -+ ctrl->vdd_mv = params->vdd_mv; -+ ctrl->flags = params->flags; -+ -+ ctrl->tCK = params->tCK; -+ ctrl->tAA = params->tAA; -+ ctrl->tWR = params->tWR; -+ ctrl->tRCD = params->tRCD; -+ ctrl->tRRD = params->tRRD; -+ ctrl->tRP = params->tRP; -+ ctrl->tRAS = params->tRAS; -+ ctrl->tRC = params->tRC; -+ ctrl->tRFC = params->tRFC; -+ ctrl->tWTR = params->tWTR; -+ ctrl->tRTP = params->tRTP; -+ ctrl->tFAW = params->tFAW; -+ ctrl->tCWL = params->tCWL; -+ ctrl->tCMD = params->tCMD; -+ ctrl->tREFI = params->tREFI; -+ ctrl->tXP = params->tXP; -+ -+ ctrl->chanmap = params->chanmap; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ ctrl->lpddr_cke_rank_map[channel] = params->lpddr_cke_rank_map[channel]; -+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) -+ ctrl->dimms[channel][slot] = params->dimms[channel][slot]; -+ } -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ ctrl->dpc[channel] = params->dpc[channel]; -+ ctrl->rankmap[channel] = params->rankmap[channel]; -+ ctrl->rank_mirrored[channel] = params->rank_mirrored[channel]; -+ ctrl->channel_size_mb[channel] = params->channel_size_mb[channel]; -+ } -+ ctrl->lpddr = params->lpddr; -+ ctrl->lanes = params->lanes; -+ ctrl->is_ecc = params->is_ecc; -+ return RAMINIT_STATUS_SUCCESS; -+} --- -2.39.5 - diff --git a/config/coreboot/default/patches/0046-haswell-NRI-Do-sense-amplifier-offset-training.patch b/config/coreboot/default/patches/0046-haswell-NRI-Do-sense-amplifier-offset-training.patch deleted file mode 100644 index c0945df9..00000000 --- a/config/coreboot/default/patches/0046-haswell-NRI-Do-sense-amplifier-offset-training.patch +++ /dev/null @@ -1,476 +0,0 @@ -From 02aa0c5612388e35f5dd1ff9c5f7a7b5b48fb9c0 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Wed, 17 Apr 2024 13:20:32 +0200 -Subject: [PATCH 46/51] haswell NRI: Do sense amplifier offset training - -Quoting Wikipedia: - - A sense amplifier is a circuit that is used to amplify and detect - small signals in electronic systems. It is commonly used in memory - circuits, such as dynamic random access memory (DRAM), to read and - amplify the weak signals stored in memory cells. - -In this case, we're calibrating the sense amplifiers in the memory -controller. This training procedure uses a magic "sense amp offset -cancel" mode of the DDRIO to observe the sampled logic levels, and -sweeps Vref to find the low-high transition for each bit lane. The -procedure consists of two stages: the first stage centers per-byte -Vref (to ensure per-bit Vref offsets are as small as possible) and -the second stage centers per-bit Vref. - -Because this procedure uses the "sense amp offset cancel" mode, it -does not rely on DRAM being trained. It is assumed that the memory -controller simply makes sense amp output levels observable via the -`DDR_DATA_TRAIN_FEEDBACK` register and that the memory bus is idle -during this training step (so the lane voltage is Vdd / 2). - -Note: This procedure will need to be adapted for Broadwell because -it has per-rank per-bit RxVref registers, whereas Haswell only has -a single per-bit RxVref register for all ranks. - -Change-Id: Ia07db68763f90e9701c8a376e01279ada8dbbe07 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk | 1 + - .../haswell/native_raminit/raminit_main.c | 1 + - .../haswell/native_raminit/raminit_native.h | 12 + - .../native_raminit/train_sense_amp_offset.c | 341 ++++++++++++++++++ - .../intel/haswell/registers/mchbar.h | 2 + - 5 files changed, 357 insertions(+) - create mode 100644 src/northbridge/intel/haswell/native_raminit/train_sense_amp_offset.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index 8fdd17c542..4bd668a2d6 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -21,3 +21,4 @@ romstage-y += timings_refresh.c - romstage-y += train_jedec_write_leveling.c - romstage-y += train_read_mpr.c - romstage-y += train_receive_enable.c -+romstage-y += train_sense_amp_offset.c -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 056dde1adc..ce637e2d03 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -60,6 +60,7 @@ static const struct task_entry cold_boot[] = { - { configure_memory_map, true, "MEMMAP", }, - { do_jedec_init, true, "JEDECINIT", }, - { pre_training, true, "PRETRAIN", }, -+ { train_sense_amp_offset, true, "SOT", }, - { train_receive_enable, true, "RCVET", }, - { train_read_mpr, true, "RDMPRT", }, - { train_jedec_write_leveling, true, "JWRL", }, -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 2ac16eaad3..07eea98831 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -23,6 +23,8 @@ - #define NUM_LANES 9 - #define NUM_LANES_NO_ECC 8 - -+#define NUM_BITS 8 -+ - #define COMP_INT 10 - - /* Always use 12 legs for emphasis (not trained) */ -@@ -219,6 +221,7 @@ enum raminit_status { - RAMINIT_STATUS_MPLL_INIT_FAILURE, - RAMINIT_STATUS_POLL_TIMEOUT, - RAMINIT_STATUS_REUT_ERROR, -+ RAMINIT_STATUS_SAMP_OFFSET_FAILURE, - RAMINIT_STATUS_RCVEN_FAILURE, - RAMINIT_STATUS_RMPR_FAILURE, - RAMINIT_STATUS_JWRL_FAILURE, -@@ -244,6 +247,12 @@ struct raminit_dimm_info { - bool valid; - }; - -+struct vref_margin { -+ uint8_t low; -+ uint8_t center; -+ uint8_t high; -+}; -+ - struct sysinfo { - enum raminit_boot_mode bootmode; - enum generic_stepping stepping; -@@ -331,6 +340,8 @@ struct sysinfo { - uint8_t rxdqsn[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; - int8_t rxvref[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES]; - -+ struct vref_margin rxdqvrefpb[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES][NUM_BITS]; -+ - uint8_t clk_pi_code[NUM_CHANNELS][NUM_SLOTRANKS]; - uint8_t ctl_pi_code[NUM_CHANNELS][NUM_SLOTRANKS]; - uint8_t cke_pi_code[NUM_CHANNELS][NUM_SLOTRANKS]; -@@ -453,6 +464,7 @@ enum raminit_status convert_timings(struct sysinfo *ctrl); - enum raminit_status configure_mc(struct sysinfo *ctrl); - enum raminit_status configure_memory_map(struct sysinfo *ctrl); - enum raminit_status do_jedec_init(struct sysinfo *ctrl); -+enum raminit_status train_sense_amp_offset(struct sysinfo *ctrl); - enum raminit_status train_receive_enable(struct sysinfo *ctrl); - enum raminit_status train_read_mpr(struct sysinfo *ctrl); - enum raminit_status train_jedec_write_leveling(struct sysinfo *ctrl); -diff --git a/src/northbridge/intel/haswell/native_raminit/train_sense_amp_offset.c b/src/northbridge/intel/haswell/native_raminit/train_sense_amp_offset.c -new file mode 100644 -index 0000000000..d4f199fefb ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/train_sense_amp_offset.c -@@ -0,0 +1,341 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <assert.h> -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <delay.h> -+#include <lib.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+#define VREF_OFFSET_PLOT RAM_DEBUG -+#define SAMP_OFFSET_PLOT RAM_DEBUG -+ -+struct vref_train_data { -+ int8_t best_sum; -+ int8_t best_vref; -+ int8_t sum_bits; -+ uint8_t high_mask; -+ uint8_t low_mask; -+}; -+ -+static enum raminit_status train_vref_offset(struct sysinfo *ctrl) -+{ -+ const int8_t vref_start = -15; -+ const int8_t vref_stop = 15; -+ const struct vref_train_data initial_vref_values = { -+ .best_sum = -NUM_LANES, -+ .best_vref = 0, -+ .high_mask = 0, -+ .low_mask = 0xff, -+ }; -+ struct vref_train_data vref_data[NUM_CHANNELS][NUM_LANES]; -+ -+ printk(VREF_OFFSET_PLOT, "Plot of sum_bits across Vref settings\nChannel"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ printk(VREF_OFFSET_PLOT, "\t%u\t\t", channel); -+ } -+ -+ printk(VREF_OFFSET_PLOT, "\nByte"); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ printk(VREF_OFFSET_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ printk(VREF_OFFSET_PLOT, "%u ", byte); -+ vref_data[channel][byte] = initial_vref_values; -+ union ddr_data_control_2_reg data_control_2 = { -+ .raw = ctrl->dq_control_2[channel][byte], -+ }; -+ data_control_2.force_bias_on = 1; -+ data_control_2.force_rx_on = 1; -+ mchbar_write32(DQ_CONTROL_2(channel, byte), data_control_2.raw); -+ } -+ } -+ -+ /* Sweep through Vref settings and find point SampOffset of +/- 7 passes */ -+ printk(VREF_OFFSET_PLOT, "\n1/2 Vref"); -+ for (int8_t vref = vref_start; vref <= vref_stop; vref++) { -+ printk(VREF_OFFSET_PLOT, "\n% 3d", vref); -+ -+ /* -+ * To perform this test, enable offset cancel mode and enable ODT. -+ * Check results and update variables. Ideal result is all zeroes. -+ * Clear offset cancel mode at end of test to write RX_OFFSET_VDQ. -+ */ -+ change_1d_margin_multicast(ctrl, RdV, vref, 0, false, REG_FILE_USE_RANK); -+ -+ /* Program settings for Vref and SampOffset = 7 (8 + 7) */ -+ mchbar_write32(DDR_DATA_RX_OFFSET_VDQ, 0xffffffff); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ /* Propagate delay values (without a read command) */ -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ data_control_0.read_rf_rd = 1; -+ data_control_0.read_rf_wr = 0; -+ data_control_0.read_rf_rank = 0; -+ data_control_0.force_odt_on = 1; -+ data_control_0.samp_train_mode = 1; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ udelay(1); -+ data_control_0.samp_train_mode = 0; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const uint8_t feedback = get_data_train_feedback(channel, byte); -+ struct vref_train_data *curr_data = &vref_data[channel][byte]; -+ curr_data->low_mask &= feedback; -+ curr_data->sum_bits = -popcnt(feedback); -+ } -+ } -+ -+ /* Program settings for Vref and SampOffset = -7 (8 - 7) */ -+ mchbar_write32(DDR_DATA_RX_OFFSET_VDQ, 0x11111111); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ /* Propagate delay values (without a read command) */ -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ data_control_0.read_rf_rd = 1; -+ data_control_0.read_rf_wr = 0; -+ data_control_0.read_rf_rank = 0; -+ data_control_0.force_odt_on = 1; -+ data_control_0.samp_train_mode = 1; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ udelay(1); -+ data_control_0.samp_train_mode = 0; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ printk(VREF_OFFSET_PLOT, "\t"); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const uint8_t feedback = get_data_train_feedback(channel, byte); -+ struct vref_train_data *curr_data = &vref_data[channel][byte]; -+ curr_data->high_mask |= feedback; -+ curr_data->sum_bits += popcnt(feedback); -+ printk(VREF_OFFSET_PLOT, "%d ", curr_data->sum_bits); -+ if (curr_data->sum_bits > curr_data->best_sum) { -+ curr_data->best_sum = curr_data->sum_bits; -+ curr_data->best_vref = vref; -+ ctrl->rxvref[channel][0][byte] = vref; -+ } else if (curr_data->sum_bits == curr_data->best_sum) { -+ curr_data->best_vref = vref; -+ } -+ } -+ } -+ } -+ printk(BIOS_DEBUG, "\n\nHi-Lo (XOR):"); -+ enum raminit_status status = RAMINIT_STATUS_SUCCESS; -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ printk(BIOS_DEBUG, "\n C%u:", channel); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ struct vref_train_data *const curr_data = &vref_data[channel][byte]; -+ const uint8_t bit_xor = curr_data->high_mask ^ curr_data->low_mask; -+ printk(BIOS_DEBUG, "\t0x%02x", bit_xor); -+ if (bit_xor == 0xff) -+ continue; -+ -+ /* Report an error if any bit did not change */ -+ status = RAMINIT_STATUS_SAMP_OFFSET_FAILURE; -+ } -+ } -+ if (status) -+ printk(BIOS_ERR, "\nUnexpected bit error in Vref offset training\n"); -+ -+ printk(BIOS_DEBUG, "\n\nRdVref:"); -+ change_1d_margin_multicast(ctrl, RdV, 0, 0, false, REG_FILE_USE_RANK); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ printk(BIOS_DEBUG, "\n C%u:", channel); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ struct vref_train_data *const curr_data = &vref_data[channel][byte]; -+ const int8_t vref_width = -+ curr_data->best_vref - ctrl->rxvref[channel][0][byte]; -+ -+ /* -+ * Step size for Rx Vref in DATA_OFFSET_TRAIN is about 3.9 mV -+ * whereas Rx Vref step size in RX_TRAIN_RANK is about 7.8 mV -+ */ -+ int8_t vref = ctrl->rxvref[channel][0][byte] + vref_width / 2; -+ if (vref < 0) -+ vref--; -+ else -+ vref++; -+ -+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) { -+ if (!rank_in_ch(ctrl, rank, channel)) -+ continue; -+ -+ ctrl->rxvref[channel][rank][byte] = vref / 2; -+ update_rxt(ctrl, channel, rank, byte, RXT_RESTORE, 0); -+ } -+ printk(BIOS_DEBUG, "\t% 4d", ctrl->rxvref[channel][0][byte]); -+ } -+ } -+ printk(BIOS_DEBUG, "\n\n"); -+ return status; -+} -+ -+/** -+ * LPDDR has an additional bit for DQS per each byte. -+ * -+ * TODO: The DQS value must be written into Data Control 2. -+ */ -+#define NUM_OFFSET_TRAIN_BITS (NUM_BITS + 1) -+ -+#define PLOT_CH_SPACE " " -+ -+struct samp_train_data { -+ uint8_t first_zero; -+ uint8_t last_one; -+}; -+ -+static void train_samp_offset(struct sysinfo *ctrl) -+{ -+ const uint8_t max_train_bits = ctrl->lpddr ? NUM_OFFSET_TRAIN_BITS : NUM_BITS; -+ -+ struct samp_train_data samp_data[NUM_CHANNELS][NUM_LANES][NUM_OFFSET_TRAIN_BITS] = {0}; -+ -+ printk(BIOS_DEBUG, "Channel "); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ printk(BIOS_DEBUG, "%u ", channel); /* Same length as PLOT_CH_SPACE */ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(BIOS_DEBUG, " %s ", ctrl->lpddr ? " " : ""); -+ } -+ printk(BIOS_DEBUG, "\nByte "); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(BIOS_DEBUG, "%u %s ", byte, ctrl->lpddr ? " " : ""); -+ -+ printk(BIOS_DEBUG, PLOT_CH_SPACE); -+ } -+ printk(SAMP_OFFSET_PLOT, "\nBits "); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ printk(SAMP_OFFSET_PLOT, "01234567%s ", ctrl->lpddr ? "S" : ""); -+ -+ printk(SAMP_OFFSET_PLOT, PLOT_CH_SPACE); -+ } -+ printk(SAMP_OFFSET_PLOT, "\n SAmp\n"); -+ for (uint8_t samp_offset = 1; samp_offset <= 15; samp_offset++) { -+ printk(SAMP_OFFSET_PLOT, "% 5d\t", samp_offset); -+ -+ uint32_t rx_offset_vdq = 0; -+ for (uint8_t bit = 0; bit < NUM_BITS; bit++) { -+ rx_offset_vdq += samp_offset << (4 * bit); -+ } -+ mchbar_write32(DDR_DATA_RX_OFFSET_VDQ, rx_offset_vdq); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ /* Propagate delay values (without a read command) */ -+ union ddr_data_control_0_reg data_control_0 = { -+ .raw = ctrl->dq_control_0[channel], -+ }; -+ data_control_0.read_rf_rd = 1; -+ data_control_0.read_rf_wr = 0; -+ data_control_0.read_rf_rank = 0; -+ data_control_0.force_odt_on = 1; -+ data_control_0.samp_train_mode = 1; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ udelay(1); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ const uint32_t feedback = -+ get_data_train_feedback(channel, byte); -+ -+ for (uint8_t bit = 0; bit < max_train_bits; bit++) { -+ struct samp_train_data *const curr_data = -+ &samp_data[channel][byte][bit]; -+ const bool result = feedback & BIT(bit); -+ if (result) { -+ curr_data->last_one = samp_offset; -+ } else if (curr_data->first_zero == 0) { -+ curr_data->first_zero = samp_offset; -+ } -+ printk(SAMP_OFFSET_PLOT, result ? "." : "#"); -+ } -+ printk(SAMP_OFFSET_PLOT, " "); -+ } -+ printk(SAMP_OFFSET_PLOT, PLOT_CH_SPACE); -+ data_control_0.samp_train_mode = 0; -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw); -+ } -+ printk(SAMP_OFFSET_PLOT, "\n"); -+ } -+ printk(BIOS_DEBUG, "\nBitSAmp "); -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) { -+ uint32_t rx_offset_vdq = 0; -+ for (uint8_t bit = 0; bit < max_train_bits; bit++) { -+ struct samp_train_data *const curr_data = -+ &samp_data[channel][byte][bit]; -+ -+ uint8_t vref = curr_data->first_zero + curr_data->last_one; -+ vref = clamp_u8(0, vref / 2, 15); -+ /* -+ * Check for saturation conditions to make sure -+ * we are as close as possible to Vdd/2 (750 mV). -+ */ -+ if (curr_data->first_zero == 0) -+ vref = 15; -+ if (curr_data->last_one == 0) -+ vref = 0; -+ -+ ctrl->rxdqvrefpb[channel][0][byte][bit].center = vref; -+ rx_offset_vdq += vref & 0xf << (4 * bit); -+ printk(BIOS_DEBUG, "%x", vref); -+ } -+ mchbar_write32(RX_OFFSET_VDQ(channel, byte), rx_offset_vdq); -+ printk(BIOS_DEBUG, " "); -+ download_regfile(ctrl, channel, 1, 0, REG_FILE_USE_RANK, 0, 1, 0); -+ } -+ printk(BIOS_DEBUG, PLOT_CH_SPACE); -+ } -+ printk(BIOS_DEBUG, "\n"); -+} -+ -+enum raminit_status train_sense_amp_offset(struct sysinfo *ctrl) -+{ -+ printk(BIOS_DEBUG, "Stage 1: Vref offset training\n"); -+ const enum raminit_status status = train_vref_offset(ctrl); -+ -+ printk(BIOS_DEBUG, "Stage 2: Samp offset training\n"); -+ train_samp_offset(ctrl); -+ -+ /* Clean up after test */ -+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) { -+ if (!does_ch_exist(ctrl, channel)) -+ continue; -+ -+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), ctrl->dq_control_0[channel]); -+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) -+ mchbar_write32(DQ_CONTROL_2(channel, byte), -+ ctrl->dq_control_2[channel][byte]); -+ } -+ io_reset(); -+ return status; -+} -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 49a215aa71..1a168a3fc8 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -18,6 +18,8 @@ - #define RX_TRAIN_ch_r_b(ch, rank, byte) _DDRIO_C_R_B(0x0000, ch, rank, byte) - #define TX_TRAIN_ch_r_b(ch, rank, byte) _DDRIO_C_R_B(0x0020, ch, rank, byte) - -+#define RX_OFFSET_VDQ(ch, byte) _DDRIO_C_R_B(0x004c, ch, 0, byte) -+ - #define DDR_DATA_TRAIN_FEEDBACK(ch, byte) _DDRIO_C_R_B(0x0054, ch, 0, byte) - - #define DQ_CONTROL_1(ch, byte) _DDRIO_C_R_B(0x0060, ch, 0, byte) --- -2.39.5 - |