diff options
Diffstat (limited to 'config/coreboot/default/patches')
83 files changed, 15921 insertions, 9452 deletions
diff --git a/config/coreboot/default/patches/0001-apple-macbook21-Set-default-VRAM-to-64MiB-instead-of.patch b/config/coreboot/default/patches/0001-apple-macbook21-Set-default-VRAM-to-64MiB-instead-of.patch index d2bae2e4..1876db23 100644 --- a/config/coreboot/default/patches/0001-apple-macbook21-Set-default-VRAM-to-64MiB-instead-of.patch +++ b/config/coreboot/default/patches/0001-apple-macbook21-Set-default-VRAM-to-64MiB-instead-of.patch @@ -1,7 +1,7 @@ -From 1195c954a3b6822e5e843067251c0c80c9520eab Mon Sep 17 00:00:00 2001 +From e8eb37e87abfdf6d2bcf60cb15d35650fcfa6665 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@retroboot.org> Date: Fri, 19 Mar 2021 05:54:58 +0000 -Subject: [PATCH 01/30] apple/macbook21: Set default VRAM to 64MiB instead of +Subject: [PATCH 01/65] apple/macbook21: Set default VRAM to 64MiB instead of 8MiB --- @@ -9,15 +9,15 @@ Subject: [PATCH 01/30] apple/macbook21: Set default VRAM to 64MiB instead of 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/apple/macbook21/cmos.default b/src/mainboard/apple/macbook21/cmos.default -index cf1bc4566e..dc0df3b6d6 100644 +index b744b11cda..9749e26547 100644 --- a/src/mainboard/apple/macbook21/cmos.default +++ b/src/mainboard/apple/macbook21/cmos.default -@@ -5,4 +5,4 @@ boot_devices='' +@@ -7,4 +7,4 @@ boot_devices='' boot_default=0x40 cmos_defaults_loaded=Yes lpt=Enable -gfx_uma_size=8M +gfx_uma_size=64M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0002-add-c3-and-clockgen-to-apple-macbook21.patch b/config/coreboot/default/patches/0002-add-c3-and-clockgen-to-apple-macbook21.patch index 8cd272ec..b4ffe7fc 100644 --- a/config/coreboot/default/patches/0002-add-c3-and-clockgen-to-apple-macbook21.patch +++ b/config/coreboot/default/patches/0002-add-c3-and-clockgen-to-apple-macbook21.patch @@ -1,7 +1,7 @@ -From 50a52cea2b43e6e407b456c082e908c7d29e090b Mon Sep 17 00:00:00 2001 +From 2533ed49003c470a8dbfbf17f6c6a5ef0672c2e2 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 02/30] add c3 and clockgen to apple/macbook21 +Subject: [PATCH 02/65] add c3 and clockgen to apple/macbook21 --- src/mainboard/apple/macbook21/Kconfig | 1 + @@ -10,10 +10,10 @@ Subject: [PATCH 02/30] add c3 and clockgen to apple/macbook21 3 files changed, 20 insertions(+) diff --git a/src/mainboard/apple/macbook21/Kconfig b/src/mainboard/apple/macbook21/Kconfig -index 5f5ffde588..27377b737c 100644 +index 330d8efae2..cf10343554 100644 --- a/src/mainboard/apple/macbook21/Kconfig +++ b/src/mainboard/apple/macbook21/Kconfig -@@ -16,6 +16,7 @@ config BOARD_SPECIFIC_OPTIONS +@@ -18,6 +18,7 @@ config BOARD_SPECIFIC_OPTIONS select HAVE_ACPI_TABLES select HAVE_ACPI_RESUME select I945_LVDS @@ -64,5 +64,5 @@ index fd86e939b9..263fbabcd1 100644 end end -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0003-lenovo-x60-64MiB-Video-RAM-changed-to-default-previo.patch b/config/coreboot/default/patches/0003-lenovo-x60-64MiB-Video-RAM-changed-to-default-previo.patch index 34e12a6b..db064a9d 100644 --- a/config/coreboot/default/patches/0003-lenovo-x60-64MiB-Video-RAM-changed-to-default-previo.patch +++ b/config/coreboot/default/patches/0003-lenovo-x60-64MiB-Video-RAM-changed-to-default-previo.patch @@ -1,7 +1,7 @@ -From ca4cd66f411247395a323e5ea1abf09e83057827 Mon Sep 17 00:00:00 2001 +From 14920409e51a9a0997d488b166d90bfad56f61f1 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@osboot.org> Date: Sun, 3 Jan 2021 03:34:01 +0000 -Subject: [PATCH 03/30] lenovo/x60: 64MiB Video RAM changed to default +Subject: [PATCH 03/65] lenovo/x60: 64MiB Video RAM changed to default (previously it was 8MiB) --- @@ -9,15 +9,15 @@ Subject: [PATCH 03/30] lenovo/x60: 64MiB Video RAM changed to default 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/x60/cmos.default b/src/mainboard/lenovo/x60/cmos.default -index 5c3576d1f3..88170a1aab 100644 +index 58825c8a36..8e0aaf427d 100644 --- a/src/mainboard/lenovo/x60/cmos.default +++ b/src/mainboard/lenovo/x60/cmos.default -@@ -15,4 +15,4 @@ trackpoint=Enable +@@ -17,4 +17,4 @@ trackpoint=Enable sticky_fn=Disable power_management_beeps=Enable low_battery_beep=Enable -gfx_uma_size=8M +gfx_uma_size=64M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0004-lenovo-t60-make-64MiB-VRAM-the-default-in-cmos.defau.patch b/config/coreboot/default/patches/0004-lenovo-t60-make-64MiB-VRAM-the-default-in-cmos.defau.patch index ee90dd63..738d486e 100644 --- a/config/coreboot/default/patches/0004-lenovo-t60-make-64MiB-VRAM-the-default-in-cmos.defau.patch +++ b/config/coreboot/default/patches/0004-lenovo-t60-make-64MiB-VRAM-the-default-in-cmos.defau.patch @@ -1,22 +1,22 @@ -From eca0f4a3a4d6907e92b948547a362ca0ac3fc382 Mon Sep 17 00:00:00 2001 +From 92b009babd1e4a63dd34638924b9559727713369 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@osboot.org> Date: Mon, 22 Feb 2021 22:16:59 +0000 -Subject: [PATCH 04/30] lenovo/t60: make 64MiB VRAM the default in cmos.default +Subject: [PATCH 04/65] lenovo/t60: make 64MiB VRAM the default in cmos.default --- src/mainboard/lenovo/t60/cmos.default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/t60/cmos.default b/src/mainboard/lenovo/t60/cmos.default -index af865f16da..7f03157df7 100644 +index 283a5747ee..91f6c0e6e2 100644 --- a/src/mainboard/lenovo/t60/cmos.default +++ b/src/mainboard/lenovo/t60/cmos.default -@@ -15,4 +15,4 @@ trackpoint=Enable +@@ -17,4 +17,4 @@ trackpoint=Enable sticky_fn=Disable power_management_beeps=Enable low_battery_beep=Enable -gfx_uma_size=8M +gfx_uma_size=64M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0005-lenovo-t400-set-VRAM-to-256MiB-VRAM-by-default.patch b/config/coreboot/default/patches/0005-lenovo-t400-set-VRAM-to-256MiB-VRAM-by-default.patch index 35d74c75..439679e2 100644 --- a/config/coreboot/default/patches/0005-lenovo-t400-set-VRAM-to-256MiB-VRAM-by-default.patch +++ b/config/coreboot/default/patches/0005-lenovo-t400-set-VRAM-to-256MiB-VRAM-by-default.patch @@ -1,7 +1,7 @@ -From 2eae87815675aebd472b6042777fe51279be4550 Mon Sep 17 00:00:00 2001 +From c7ad2407a7f515d487332382bb55025873c3d987 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Fri, 14 May 2021 13:10:33 +0100 -Subject: [PATCH 05/30] lenovo/t400: set VRAM to 256MiB VRAM by default +Subject: [PATCH 05/65] lenovo/t400: set VRAM to 256MiB VRAM by default Signed-off-by: Leah Rowe <leah@libreboot.org> --- @@ -9,15 +9,15 @@ Signed-off-by: Leah Rowe <leah@libreboot.org> 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/t400/cmos.default b/src/mainboard/lenovo/t400/cmos.default -index a326e315b1..b907a3e2df 100644 +index a16d386dd1..e7bb32306c 100644 --- a/src/mainboard/lenovo/t400/cmos.default +++ b/src/mainboard/lenovo/t400/cmos.default -@@ -13,4 +13,4 @@ power_management_beeps=Enable +@@ -15,4 +15,4 @@ power_management_beeps=Enable low_battery_beep=Enable sata_mode=AHCI hybrid_graphics_mode=Integrated Only -gfx_uma_size=32M +gfx_uma_size=256M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0006-lenovo-x200-set-VRAM-to-256MiB-by-default.patch b/config/coreboot/default/patches/0006-lenovo-x200-set-VRAM-to-256MiB-by-default.patch index cc6abb00..477c1724 100644 --- a/config/coreboot/default/patches/0006-lenovo-x200-set-VRAM-to-256MiB-by-default.patch +++ b/config/coreboot/default/patches/0006-lenovo-x200-set-VRAM-to-256MiB-by-default.patch @@ -1,7 +1,7 @@ -From f6b4913a5eca619b745d5ccea9af022a54fb185b Mon Sep 17 00:00:00 2001 +From 79f686dae47d2ef934b5c95979195f9d3c1978e6 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Fri, 14 May 2021 13:11:59 +0100 -Subject: [PATCH 06/30] lenovo/x200: set VRAM to 256MiB by default +Subject: [PATCH 06/65] lenovo/x200: set VRAM to 256MiB by default Signed-off-by: Leah Rowe <leah@libreboot.org> --- @@ -9,15 +9,15 @@ Signed-off-by: Leah Rowe <leah@libreboot.org> 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/x200/cmos.default b/src/mainboard/lenovo/x200/cmos.default -index bb4323836e..458b3f19c5 100644 +index 434af5d227..443ef54e41 100644 --- a/src/mainboard/lenovo/x200/cmos.default +++ b/src/mainboard/lenovo/x200/cmos.default -@@ -12,4 +12,4 @@ sticky_fn=Disable +@@ -14,4 +14,4 @@ sticky_fn=Disable power_management_beeps=Enable low_battery_beep=Enable sata_mode=AHCI -gfx_uma_size=32M +gfx_uma_size=256M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0007-gigabyte-ga-g41m-es2l-set-VRAM-to-256MiB-by-default.patch b/config/coreboot/default/patches/0007-gigabyte-ga-g41m-es2l-set-VRAM-to-256MiB-by-default.patch index c4840ecc..e435726d 100644 --- a/config/coreboot/default/patches/0007-gigabyte-ga-g41m-es2l-set-VRAM-to-256MiB-by-default.patch +++ b/config/coreboot/default/patches/0007-gigabyte-ga-g41m-es2l-set-VRAM-to-256MiB-by-default.patch @@ -1,7 +1,7 @@ -From a3a0969075163be413f968b03671aa5d8662672a Mon Sep 17 00:00:00 2001 +From a79498ab8a7eac809d99db2fad5b0f8c63870e43 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Fri, 14 May 2021 13:18:26 +0100 -Subject: [PATCH 07/30] gigabyte/ga-g41m-es2l: set VRAM to 256MiB by default +Subject: [PATCH 07/65] gigabyte/ga-g41m-es2l: set VRAM to 256MiB by default Signed-off-by: Leah Rowe <leah@libreboot.org> --- @@ -9,15 +9,15 @@ Signed-off-by: Leah Rowe <leah@libreboot.org> 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/gigabyte/ga-g41m-es2l/cmos.default b/src/mainboard/gigabyte/ga-g41m-es2l/cmos.default -index 8372032119..bedad54d2a 100644 +index fe79c83570..4a1f97a9d8 100644 --- a/src/mainboard/gigabyte/ga-g41m-es2l/cmos.default +++ b/src/mainboard/gigabyte/ga-g41m-es2l/cmos.default -@@ -2,4 +2,4 @@ boot_option=Fallback +@@ -4,4 +4,4 @@ boot_option=Fallback debug_level=Debug power_on_after_fail=Enable nmi=Enable -gfx_uma_size=64M +gfx_uma_size=256M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0008-acer-g43t-am3-set-VRAM-to-256MiB-by-default.patch b/config/coreboot/default/patches/0008-acer-g43t-am3-set-VRAM-to-256MiB-by-default.patch index 19977870..9aa1b1cb 100644 --- a/config/coreboot/default/patches/0008-acer-g43t-am3-set-VRAM-to-256MiB-by-default.patch +++ b/config/coreboot/default/patches/0008-acer-g43t-am3-set-VRAM-to-256MiB-by-default.patch @@ -1,7 +1,7 @@ -From 223ac17617b3a0c08925abbbe42d0d003e144a28 Mon Sep 17 00:00:00 2001 +From 5fbdbb11b215e3aa4256dfaa468224fd0c2a1fb0 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Fri, 14 May 2021 13:21:39 +0100 -Subject: [PATCH 08/30] acer/g43t-am3: set VRAM to 256MiB by default +Subject: [PATCH 08/65] acer/g43t-am3: set VRAM to 256MiB by default Signed-off-by: Leah Rowe <leah@libreboot.org> --- @@ -9,15 +9,15 @@ Signed-off-by: Leah Rowe <leah@libreboot.org> 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/acer/g43t-am3/cmos.default b/src/mainboard/acer/g43t-am3/cmos.default -index 706f5dd551..e8b45ea22c 100644 +index 23f0e55f3e..8d6c4db1ce 100644 --- a/src/mainboard/acer/g43t-am3/cmos.default +++ b/src/mainboard/acer/g43t-am3/cmos.default -@@ -3,4 +3,4 @@ debug_level=Debug +@@ -5,4 +5,4 @@ debug_level=Debug power_on_after_fail=Disable nmi=Enable sata_mode=AHCI -gfx_uma_size=64M +gfx_uma_size=256M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0009-lenovo-t400-Enable-all-SATA-ports.patch b/config/coreboot/default/patches/0009-lenovo-t400-Enable-all-SATA-ports.patch index 332b870e..7dead180 100644 --- a/config/coreboot/default/patches/0009-lenovo-t400-Enable-all-SATA-ports.patch +++ b/config/coreboot/default/patches/0009-lenovo-t400-Enable-all-SATA-ports.patch @@ -1,7 +1,7 @@ -From 80ebbfef42454ea0911e5fc3858103d905987ed8 Mon Sep 17 00:00:00 2001 +From 15003992f57b62ce59dc282cd089987306126cc9 Mon Sep 17 00:00:00 2001 From: persmule <persmule@gmail.com> Date: Sun, 31 Oct 2021 23:33:26 +0000 -Subject: [PATCH 09/30] lenovo/t400: Enable all SATA ports +Subject: [PATCH 09/65] 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 @@ -30,5 +30,5 @@ index 259c3e1b21..3d007533a4 100644 register "sata_traffic_monitor" = "0" -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0010-coreboot-Add-Lenovo-X230-patch-gfx_uma_size-224M-by-.patch b/config/coreboot/default/patches/0010-coreboot-Add-Lenovo-X230-patch-gfx_uma_size-224M-by-.patch index 12917ed8..e5cac363 100644 --- a/config/coreboot/default/patches/0010-coreboot-Add-Lenovo-X230-patch-gfx_uma_size-224M-by-.patch +++ b/config/coreboot/default/patches/0010-coreboot-Add-Lenovo-X230-patch-gfx_uma_size-224M-by-.patch @@ -1,7 +1,7 @@ -From 318a97c284f8d5030100476a32516ddc9e51603d Mon Sep 17 00:00:00 2001 +From f8ea06883762c906a7f3ad7d286b628bca3443ab Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Mon, 20 Dec 2021 01:29:31 +0000 -Subject: [PATCH 10/30] coreboot: Add Lenovo X230 patch: gfx_uma_size 224M by +Subject: [PATCH 10/65] coreboot: Add Lenovo X230 patch: gfx_uma_size 224M by default --- @@ -9,14 +9,14 @@ Subject: [PATCH 10/30] coreboot: Add Lenovo X230 patch: gfx_uma_size 224M by 1 file changed, 1 insertion(+) diff --git a/src/mainboard/lenovo/x230/cmos.default b/src/mainboard/lenovo/x230/cmos.default -index 7314066c2b..2e315d4521 100644 +index 732e214b32..3bb78960b9 100644 --- a/src/mainboard/lenovo/x230/cmos.default +++ b/src/mainboard/lenovo/x230/cmos.default -@@ -16,3 +16,4 @@ backlight=Both +@@ -18,3 +18,4 @@ backlight=Both usb_always_on=Disable f1_to_f12_as_primary=Enable me_state=Normal +gfx_uma_size=224M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0011-lenovo-x230-set-me_state-Disabled-in-cmos.default.patch b/config/coreboot/default/patches/0011-lenovo-x230-set-me_state-Disabled-in-cmos.default.patch index dc3a33ca..375c14fc 100644 --- a/config/coreboot/default/patches/0011-lenovo-x230-set-me_state-Disabled-in-cmos.default.patch +++ b/config/coreboot/default/patches/0011-lenovo-x230-set-me_state-Disabled-in-cmos.default.patch @@ -1,7 +1,7 @@ -From 47afbe8b94edd1ff58c1daf0bda020e6afac35f4 Mon Sep 17 00:00:00 2001 +From 47483865af46a3d1f8732d1bd97f4a7155cc24d6 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Mon, 3 Jan 2022 19:06:22 +0000 -Subject: [PATCH 11/30] lenovo/x230: set me_state=Disabled in cmos.default +Subject: [PATCH 11/65] 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 @@ -23,10 +23,10 @@ Date: Thu Nov 21 21:47:31 2019 +0300 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/x230/cmos.default b/src/mainboard/lenovo/x230/cmos.default -index 2e315d4521..3585cbd58b 100644 +index 3bb78960b9..ae47202aac 100644 --- a/src/mainboard/lenovo/x230/cmos.default +++ b/src/mainboard/lenovo/x230/cmos.default -@@ -15,5 +15,5 @@ trackpoint=Enable +@@ -17,5 +17,5 @@ trackpoint=Enable backlight=Both usb_always_on=Disable f1_to_f12_as_primary=Enable @@ -34,5 +34,5 @@ index 2e315d4521..3585cbd58b 100644 +me_state=Disabled gfx_uma_size=224M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0012-set-me_state-Disabled-on-all-cmos.default-files.patch b/config/coreboot/default/patches/0012-set-me_state-Disabled-on-all-cmos.default-files.patch index 49f4db9b..28a4a6a4 100644 --- a/config/coreboot/default/patches/0012-set-me_state-Disabled-on-all-cmos.default-files.patch +++ b/config/coreboot/default/patches/0012-set-me_state-Disabled-on-all-cmos.default-files.patch @@ -1,7 +1,7 @@ -From 531ef34ece796f38cb8a13a54856e46e79842e29 Mon Sep 17 00:00:00 2001 +From 84f7622ea0c3a78742f129d2ec9f437e6c424839 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Wed, 2 Mar 2022 21:50:01 +0000 -Subject: [PATCH 12/30] set me_state=Disabled on all cmos.default files! +Subject: [PATCH 12/65] set me_state=Disabled on all cmos.default files! yeah. why the hell isn't this the default @@ -20,103 +20,105 @@ Signed-off-by: Leah Rowe <leah@libreboot.org> 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mainboard/lenovo/l520/cmos.default b/src/mainboard/lenovo/l520/cmos.default -index 681c40e78b..57cdcf9162 100644 +index be08e0a342..b8970efa46 100644 --- a/src/mainboard/lenovo/l520/cmos.default +++ b/src/mainboard/lenovo/l520/cmos.default -@@ -14,4 +14,4 @@ sticky_fn=Disable +@@ -16,4 +16,4 @@ sticky_fn=Disable trackpoint=Enable backlight=Both usb_always_on=Disable -me_state=Normal +me_state=Disabled diff --git a/src/mainboard/lenovo/t420/cmos.default b/src/mainboard/lenovo/t420/cmos.default -index 8244071b8a..c011867916 100644 +index 6fd26c5fe3..27a62d07b3 100644 --- a/src/mainboard/lenovo/t420/cmos.default +++ b/src/mainboard/lenovo/t420/cmos.default -@@ -14,4 +14,4 @@ sticky_fn=Disable +@@ -16,4 +16,4 @@ sticky_fn=Disable trackpoint=Enable hybrid_graphics_mode=Integrated Only usb_always_on=Disable -me_state=Normal +me_state=Disabled diff --git a/src/mainboard/lenovo/t420s/cmos.default b/src/mainboard/lenovo/t420s/cmos.default -index 8244071b8a..c011867916 100644 +index 6fd26c5fe3..27a62d07b3 100644 --- a/src/mainboard/lenovo/t420s/cmos.default +++ b/src/mainboard/lenovo/t420s/cmos.default -@@ -14,4 +14,4 @@ sticky_fn=Disable +@@ -16,4 +16,4 @@ sticky_fn=Disable trackpoint=Enable hybrid_graphics_mode=Integrated Only usb_always_on=Disable -me_state=Normal +me_state=Disabled diff --git a/src/mainboard/lenovo/t430/cmos.default b/src/mainboard/lenovo/t430/cmos.default -index 26795fe5cf..55e1e6c04e 100644 +index c896eadec1..6d1e172056 100644 --- a/src/mainboard/lenovo/t430/cmos.default +++ b/src/mainboard/lenovo/t430/cmos.default -@@ -15,4 +15,4 @@ trackpoint=Enable +@@ -17,4 +17,4 @@ trackpoint=Enable backlight=Both usb_always_on=Disable hybrid_graphics_mode=Integrated Only -me_state=Normal +me_state=Disabled diff --git a/src/mainboard/lenovo/t430s/cmos.default b/src/mainboard/lenovo/t430s/cmos.default -index 52dbf70377..b16800ca9e 100644 +index 286fb0ae8c..5a05c73721 100644 --- a/src/mainboard/lenovo/t430s/cmos.default +++ b/src/mainboard/lenovo/t430s/cmos.default -@@ -16,4 +16,4 @@ backlight=Both +@@ -18,4 +18,4 @@ backlight=Both enable_dual_graphics=Disable usb_always_on=Disable f1_to_f12_as_primary=Enable -me_state=Normal +me_state=Disabled diff --git a/src/mainboard/lenovo/t520/cmos.default b/src/mainboard/lenovo/t520/cmos.default -index cf79b391e2..b66f7034dc 100644 +index 4857f92f67..ab1be1a678 100644 --- a/src/mainboard/lenovo/t520/cmos.default +++ b/src/mainboard/lenovo/t520/cmos.default -@@ -15,4 +15,4 @@ trackpoint=Enable +@@ -17,4 +17,4 @@ trackpoint=Enable backlight=Both hybrid_graphics_mode=Integrated Only usb_always_on=Disable -me_state=Normal +me_state=Disabled diff --git a/src/mainboard/lenovo/t530/cmos.default b/src/mainboard/lenovo/t530/cmos.default -index cf79b391e2..b66f7034dc 100644 +index 4857f92f67..ab1be1a678 100644 --- a/src/mainboard/lenovo/t530/cmos.default +++ b/src/mainboard/lenovo/t530/cmos.default -@@ -15,4 +15,4 @@ trackpoint=Enable +@@ -17,4 +17,4 @@ trackpoint=Enable backlight=Both hybrid_graphics_mode=Integrated Only usb_always_on=Disable -me_state=Normal +me_state=Disabled diff --git a/src/mainboard/lenovo/x220/cmos.default b/src/mainboard/lenovo/x220/cmos.default -index 6d1d57a795..52f303dfdb 100644 +index ef706c1303..b318ab9772 100644 --- a/src/mainboard/lenovo/x220/cmos.default +++ b/src/mainboard/lenovo/x220/cmos.default -@@ -13,4 +13,4 @@ usb_always_on=Disable +@@ -15,4 +15,4 @@ usb_always_on=Disable fn_ctrl_swap=Disable sticky_fn=Disable trackpoint=Enable -me_state=Normal +me_state=Disabled diff --git a/src/mainboard/protectli/vault_cml/cmos.default b/src/mainboard/protectli/vault_cml/cmos.default -index 62715bc6ba..129b5fd121 100644 +index d61046df6b..8c793fd1c3 100644 --- a/src/mainboard/protectli/vault_cml/cmos.default +++ b/src/mainboard/protectli/vault_cml/cmos.default -@@ -1,3 +1,3 @@ +@@ -2,4 +2,4 @@ + boot_option=Fallback debug_level=Debug -me_state=Enable +me_state=Disabled diff --git a/src/mainboard/system76/tgl-u/cmos.default b/src/mainboard/system76/tgl-u/cmos.default -index 62715bc6ba..129b5fd121 100644 +index d61046df6b..8c793fd1c3 100644 --- a/src/mainboard/system76/tgl-u/cmos.default +++ b/src/mainboard/system76/tgl-u/cmos.default -@@ -1,3 +1,3 @@ +@@ -2,4 +2,4 @@ + boot_option=Fallback debug_level=Debug -me_state=Enable +me_state=Disabled -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0015-util-ifdtool-add-nuke-flag-all-0xFF-on-region.patch b/config/coreboot/default/patches/0013-util-ifdtool-add-nuke-flag-all-0xFF-on-region.patch index a71324db..a39d14bd 100644 --- a/config/coreboot/default/patches/0015-util-ifdtool-add-nuke-flag-all-0xFF-on-region.patch +++ b/config/coreboot/default/patches/0013-util-ifdtool-add-nuke-flag-all-0xFF-on-region.patch @@ -1,7 +1,7 @@ -From 158b79e6057e071d039619f617c112d31fb13f64 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> +From 851aa297808a4776634df5817cae54c226b4d750 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <info@minifree.org> Date: Sun, 19 Feb 2023 18:21:43 +0000 -Subject: [PATCH 15/30] util/ifdtool: add --nuke flag (all 0xFF on region) +Subject: [PATCH 13/65] util/ifdtool: add --nuke flag (all 0xFF on region) When this option is used, the region's contents are overwritten with all ones (0xFF). @@ -16,14 +16,14 @@ Rebased since the last revision update in lbmk. Signed-off-by: Leah Rowe <leah@libreboot.org> --- - util/ifdtool/ifdtool.c | 112 +++++++++++++++++++++++++++++------------ - 1 file changed, 81 insertions(+), 31 deletions(-) + util/ifdtool/ifdtool.c | 114 ++++++++++++++++++++++++++++++----------- + 1 file changed, 83 insertions(+), 31 deletions(-) diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c -index 191b3216de..38132b4a28 100644 +index 32b2081d93..1473cf058b 100644 --- a/util/ifdtool/ifdtool.c +++ b/util/ifdtool/ifdtool.c -@@ -1942,6 +1942,7 @@ static void print_usage(const char *name) +@@ -2204,6 +2204,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 191b3216de..38132b4a28 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" -@@ -1950,6 +1951,60 @@ static void print_usage(const char *name) +@@ -2212,6 +2213,60 @@ static void print_usage(const char *name) "\n"); } @@ -92,15 +92,15 @@ index 191b3216de..38132b4a28 100644 int main(int argc, char *argv[]) { int opt, option_index = 0; -@@ -1957,6 +2012,7 @@ int main(int argc, char *argv[]) +@@ -2219,6 +2274,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; + 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; -@@ -1990,6 +2046,7 @@ int main(int argc, char *argv[]) +@@ -2254,6 +2310,7 @@ int main(int argc, char *argv[]) {"validate", 0, NULL, 't'}, {"setpchstrap", 1, NULL, 'S'}, {"newvalue", 1, NULL, 'V'}, @@ -108,7 +108,7 @@ index 191b3216de..38132b4a28 100644 {0, 0, 0, 0} }; -@@ -2039,35 +2096,8 @@ int main(int argc, char *argv[]) +@@ -2303,35 +2360,8 @@ int main(int argc, char *argv[]) region_fname++; // Descriptor, BIOS, ME, GbE, Platform // valid type? @@ -141,12 +141,12 @@ index 191b3216de..38132b4a28 100644 - else if (!strcasecmp("PTT", region_type_string)) - region_type = 15; - if (region_type == -1) { -+ if ((region_type = -+ get_region_type_string(region_type_string)) == -1) { ++ if ((region_type = ++ get_region_type_string(region_type_string)) == -1) { fprintf(stderr, "No such region type: '%s'\n\n", region_type_string); fprintf(stderr, "run '%s -h' for usage\n", argv[0]); -@@ -2236,6 +2266,22 @@ int main(int argc, char *argv[]) +@@ -2508,6 +2538,22 @@ int main(int argc, char *argv[]) case 't': mode_validate = 1; break; @@ -169,35 +169,37 @@ index 191b3216de..38132b4a28 100644 case 'v': print_version(); exit(EXIT_SUCCESS); -@@ -2252,7 +2298,7 @@ int main(int argc, char *argv[]) +@@ -2524,7 +2570,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 + -- mode_gpr0_disable) > 1) { -+ mode_gpr0_disable + mode_nuke) > 1) { +- (mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status) > 1) { ++ (mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status + ++ mode_nuke) > 1) { 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); -@@ -2261,7 +2307,7 @@ int main(int argc, char *argv[]) +@@ -2533,7 +2580,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 + -- mode_validate + mode_gpr0_disable) == 0) { -+ mode_validate + mode_gpr0_disable + mode_nuke) == 0) { +- mode_validate + (mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status) == 0) { ++ mode_validate + (mode_gpr0_disable | mode_gpr0_enable) + mode_gpr0_status + ++ mode_nuke) == 0) { fprintf(stderr, "You need to specify a mode.\n\n"); fprintf(stderr, "run '%s -h' for usage\n", argv[0]); exit(EXIT_FAILURE); -@@ -2368,6 +2414,10 @@ int main(int argc, char *argv[]) +@@ -2646,6 +2694,10 @@ int main(int argc, char *argv[]) write_image(new_filename, image, size); } -+ if (mode_nuke) { -+ nuke(new_filename, image, size, region_type); -+ } ++ if (mode_nuke) { ++ nuke(new_filename, image, size, region_type); ++ } + if (mode_altmedisable) { struct fpsba *fpsba = find_fpsba(image, size); struct fmsba *fmsba = find_fmsba(image, size); -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0016-fix-speedstep-on-x200-t400-Revert-cpu-intel-model_10.patch b/config/coreboot/default/patches/0014-fix-speedstep-on-x200-t400-Revert-cpu-intel-model_10.patch index 279fdad1..23677556 100644 --- a/config/coreboot/default/patches/0016-fix-speedstep-on-x200-t400-Revert-cpu-intel-model_10.patch +++ b/config/coreboot/default/patches/0014-fix-speedstep-on-x200-t400-Revert-cpu-intel-model_10.patch @@ -1,7 +1,7 @@ -From bb83e857a2e7b6ecb7cb476ba65019b14e68dc34 Mon Sep 17 00:00:00 2001 +From a1a4312c9bea5b7fb5170174dbd14f914c11637c Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Wed, 1 Dec 2021 02:53:00 +0000 -Subject: [PATCH 16/30] fix speedstep on x200/t400: Revert +Subject: [PATCH 14/65] fix speedstep on x200/t400: Revert "cpu/intel/model_1067x: enable PECI" This reverts commit 70fea013c7ebd6d85a7806748233fcfd76802f5f. @@ -16,7 +16,7 @@ maintain this revert patch in Libreboot, from now on. 1 file changed, 9 deletions(-) diff --git a/src/cpu/intel/model_1067x/model_1067x_init.c b/src/cpu/intel/model_1067x/model_1067x_init.c -index 315e7c36fc..1423fd72bc 100644 +index d051e8915b..30ba2bf0c6 100644 --- a/src/cpu/intel/model_1067x/model_1067x_init.c +++ b/src/cpu/intel/model_1067x/model_1067x_init.c @@ -141,8 +141,6 @@ static void configure_emttm_tables(void) @@ -43,5 +43,5 @@ index 315e7c36fc..1423fd72bc 100644 #define PIC_SENS_CFG 0x1aa -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0017-GM45-type-CPUs-don-t-enable-alternative-SMRR.patch b/config/coreboot/default/patches/0015-GM45-type-CPUs-don-t-enable-alternative-SMRR.patch index 4e5f5089..731742d3 100644 --- a/config/coreboot/default/patches/0017-GM45-type-CPUs-don-t-enable-alternative-SMRR.patch +++ b/config/coreboot/default/patches/0015-GM45-type-CPUs-don-t-enable-alternative-SMRR.patch @@ -1,7 +1,7 @@ -From 8a94f38398b8fa554fa4ae53ecb88a372df634fd Mon Sep 17 00:00:00 2001 +From 7e366e5d4d56aade1cb8de8433eb2b02cc9aceef Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Mon, 17 Apr 2023 15:49:57 +0100 -Subject: [PATCH 17/30] GM45-type CPUs: don't enable alternative SMRR +Subject: [PATCH 15/65] GM45-type CPUs: don't enable alternative SMRR This reverts the changes in coreboot revision: df7aecd92643d207feaf7fd840f8835097346644 @@ -42,7 +42,7 @@ Pragmatism is a good thing. I recommend it. 5 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/cpu/intel/model_1067x/model_1067x_init.c b/src/cpu/intel/model_1067x/model_1067x_init.c -index 1423fd72bc..d1f98ca43a 100644 +index 30ba2bf0c6..312046901a 100644 --- a/src/cpu/intel/model_1067x/model_1067x_init.c +++ b/src/cpu/intel/model_1067x/model_1067x_init.c @@ -8,6 +8,7 @@ @@ -169,5 +169,5 @@ index 535fb8fae7..f7b05facd2 100644 configure_c_states(); -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0018-mb-dell-e6400-Enable-01.0-device-in-devicetree-for-d.patch b/config/coreboot/default/patches/0016-mb-dell-e6400-Enable-01.0-device-in-devicetree-for-d.patch index bfc9231a..040834db 100644 --- a/config/coreboot/default/patches/0018-mb-dell-e6400-Enable-01.0-device-in-devicetree-for-d.patch +++ b/config/coreboot/default/patches/0016-mb-dell-e6400-Enable-01.0-device-in-devicetree-for-d.patch @@ -1,7 +1,7 @@ -From 2b899f40ce5d728faa7c1da23c3348435b7ac9cb Mon Sep 17 00:00:00 2001 +From b925e95cc9d750c56fdbfbd1838b77339c124139 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 18/30] mb/dell/e6400: Enable 01.0 device in devicetree for +Subject: [PATCH 16/65] mb/dell/e6400: Enable 01.0 device in devicetree for dGPU models Change-Id: I9b8e5d3cd1e1f64dc87b682b1e045b6342924aed @@ -24,5 +24,5 @@ index bb954cbd7b..e9f3915d17 100644 device pci 02.1 on end # Display device pci 03.0 on end # ME -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0019-Remove-warning-for-coreboot-images-built-without-a-p.patch b/config/coreboot/default/patches/0017-Remove-warning-for-coreboot-images-built-without-a-p.patch index 090f2629..eb76118f 100644 --- a/config/coreboot/default/patches/0019-Remove-warning-for-coreboot-images-built-without-a-p.patch +++ b/config/coreboot/default/patches/0017-Remove-warning-for-coreboot-images-built-without-a-p.patch @@ -1,7 +1,7 @@ -From 2ccd3e71730004c3ffbed178087cb778c170079e Mon Sep 17 00:00:00 2001 +From f440b426378314bfbc0f397fdd9bd5bd68d81483 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 19/30] Remove warning for coreboot images built without a +Subject: [PATCH 17/65] Remove warning for coreboot images built without a payload I added this in upstream to prevent people from accidentally flashing @@ -13,10 +13,10 @@ up. This has caused confusion and concern so just patch it out. 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/payloads/Makefile.mk b/payloads/Makefile.mk -index a2336aa876..4f1692a873 100644 +index 5f988dac1b..516133880f 100644 --- a/payloads/Makefile.mk +++ b/payloads/Makefile.mk -@@ -49,16 +49,5 @@ distclean-payloads: +@@ -50,16 +50,5 @@ distclean-payloads: print-repo-info-payloads: -$(foreach payload, $(PAYLOADS_LIST), $(MAKE) -C $(payload) print-repo-info 2>/dev/null; ) @@ -35,5 +35,5 @@ index a2336aa876..4f1692a873 100644 -.PHONY: clean-payloads distclean-payloads print-repo-info-payloads warn_no_payload +.PHONY: clean-payloads distclean-payloads print-repo-info-payloads -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0018-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch b/config/coreboot/default/patches/0018-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch new file mode 100644 index 00000000..4d8f0c21 --- /dev/null +++ b/config/coreboot/default/patches/0018-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch @@ -0,0 +1,430 @@ +From e4509a2d3204d8798cc48be37f33e43d07ff5e3b 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 18/65] 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 +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 + +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-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch b/config/coreboot/default/patches/0019-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch new file mode 100644 index 00000000..23eef96f --- /dev/null +++ b/config/coreboot/default/patches/0019-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch @@ -0,0 +1,430 @@ +From cfac9aa347e13065c2e24d62091636cc4d0e56be 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 19/65] 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 +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 +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/0020-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch b/config/coreboot/default/patches/0020-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch new file mode 100644 index 00000000..e42b7c9a --- /dev/null +++ b/config/coreboot/default/patches/0020-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch @@ -0,0 +1,435 @@ +From e5ed7361d41b89ee38b572beb921924b33cc174d 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 20/65] 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 +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 + +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-dell-Add-Latitude-E6430-Ivy-Bridge.patch b/config/coreboot/default/patches/0020-mb-dell-Add-Latitude-E6430-Ivy-Bridge.patch deleted file mode 100644 index fecaf88a..00000000 --- a/config/coreboot/default/patches/0020-mb-dell-Add-Latitude-E6430-Ivy-Bridge.patch +++ /dev/null @@ -1,826 +0,0 @@ -From a49df0307455d6d8b7a9efb9f4639b72be1b64d4 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 20/30] mb/dell: Add Latitude E6430 (Ivy Bridge) - -Mainboard is QAL80/LA-7781P (UMA). The dGPU model was not tested. This -is based on the autoport output with some manual tweaks. The flash is -8MiB + 4MiB, and is fairly easily accessed by removing the keyboard. It -can also 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. - -Working: -- Libgfxinit -- USB EHCI debug (left side usb port is HCD index 2, middle port on the - right side is HCD index 1) -- Keyboard -- Touchpad/trackpoint -- ExpressCard -- Audio -- Ethernet -- SD card reader -- mPCIe WiFi -- SeaBIOS 1.16.2 -- edk2 (MrChromebox' fork, uefipayload_202306) -- Internal flashing using dell-flash-unlock - -Not working: -- S3 suspend: Possibly EC related -- Physical wireless switch - this triggers an SMI handler in the vendor - firmware which sends commands to the EC to enable/disable wireless - devices -- Battery reporting - needs ACPI code for the EC -- Brightness hotkeys - probably EC related - -Unknown/untested: -- Dock -- eSATA -- TPM -- dGPU on non-UMA model -- Bluetooth module (not included on my system) - -[1] https://gitlab.com/nic3-14159/dell-flash-unlock - -Change-Id: I93c6622fc5da1d0d61a5b2c197ac7227d9525908 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/e6430/Kconfig | 44 +++++ - src/mainboard/dell/e6430/Kconfig.name | 2 + - src/mainboard/dell/e6430/Makefile.inc | 6 + - src/mainboard/dell/e6430/acpi/ec.asl | 9 + - src/mainboard/dell/e6430/acpi/platform.asl | 12 ++ - src/mainboard/dell/e6430/acpi/superio.asl | 3 + - src/mainboard/dell/e6430/acpi_tables.c | 16 ++ - src/mainboard/dell/e6430/board_info.txt | 6 + - src/mainboard/dell/e6430/cmos.default | 9 + - src/mainboard/dell/e6430/cmos.layout | 88 ++++++++++ - src/mainboard/dell/e6430/data.vbt | Bin 0 -> 6144 bytes - src/mainboard/dell/e6430/devicetree.cb | 70 ++++++++ - src/mainboard/dell/e6430/dsdt.asl | 30 ++++ - src/mainboard/dell/e6430/early_init.c | 32 ++++ - src/mainboard/dell/e6430/gma-mainboard.ads | 20 +++ - src/mainboard/dell/e6430/gpio.c | 192 +++++++++++++++++++++ - src/mainboard/dell/e6430/hda_verb.c | 33 ++++ - src/mainboard/dell/e6430/mainboard.c | 21 +++ - 18 files changed, 593 insertions(+) - create mode 100644 src/mainboard/dell/e6430/Kconfig - create mode 100644 src/mainboard/dell/e6430/Kconfig.name - create mode 100644 src/mainboard/dell/e6430/Makefile.inc - create mode 100644 src/mainboard/dell/e6430/acpi/ec.asl - create mode 100644 src/mainboard/dell/e6430/acpi/platform.asl - create mode 100644 src/mainboard/dell/e6430/acpi/superio.asl - create mode 100644 src/mainboard/dell/e6430/acpi_tables.c - create mode 100644 src/mainboard/dell/e6430/board_info.txt - create mode 100644 src/mainboard/dell/e6430/cmos.default - create mode 100644 src/mainboard/dell/e6430/cmos.layout - create mode 100644 src/mainboard/dell/e6430/data.vbt - create mode 100644 src/mainboard/dell/e6430/devicetree.cb - create mode 100644 src/mainboard/dell/e6430/dsdt.asl - create mode 100644 src/mainboard/dell/e6430/early_init.c - create mode 100644 src/mainboard/dell/e6430/gma-mainboard.ads - create mode 100644 src/mainboard/dell/e6430/gpio.c - create mode 100644 src/mainboard/dell/e6430/hda_verb.c - create mode 100644 src/mainboard/dell/e6430/mainboard.c - -diff --git a/src/mainboard/dell/e6430/Kconfig b/src/mainboard/dell/e6430/Kconfig -new file mode 100644 -index 0000000000..e4c799803e ---- /dev/null -+++ b/src/mainboard/dell/e6430/Kconfig -@@ -0,0 +1,44 @@ -+if BOARD_DELL_LATITUDE_E6430 -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ select BOARD_ROMSIZE_KB_12288 -+ select EC_ACPI -+ select EC_DELL_MEC5035 -+ select GFX_GMA_PANEL_1_ON_LVDS -+ select HAVE_ACPI_RESUME -+ select HAVE_ACPI_TABLES -+ select HAVE_CMOS_DEFAULT -+ select HAVE_OPTION_TABLE -+ select INTEL_GMA_HAVE_VBT -+ select INTEL_INT15 -+ select MAINBOARD_HAS_LIBGFXINIT -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select NORTHBRIDGE_INTEL_SANDYBRIDGE -+ select SERIRQ_CONTINUOUS_MODE -+ select SOUTHBRIDGE_INTEL_C216 -+ select SYSTEM_TYPE_LAPTOP -+ select USE_NATIVE_RAMINIT -+ -+config DRAM_RESET_GATE_GPIO -+ default 60 -+ -+config MAINBOARD_DIR -+ default "dell/e6430" -+ -+config MAINBOARD_PART_NUMBER -+ default "Latitude E6430" -+ -+config PS2K_EISAID -+ default "PNP0303" -+ -+config PS2M_EISAID -+ default "PNP0F13" -+ -+config USBDEBUG_HCD_INDEX -+ default 2 -+ -+config VGA_BIOS_ID -+ default "8086,0166" -+ -+endif -diff --git a/src/mainboard/dell/e6430/Kconfig.name b/src/mainboard/dell/e6430/Kconfig.name -new file mode 100644 -index 0000000000..f866b03585 ---- /dev/null -+++ b/src/mainboard/dell/e6430/Kconfig.name -@@ -0,0 +1,2 @@ -+config BOARD_DELL_LATITUDE_E6430 -+ bool "Latitude E6430" -diff --git a/src/mainboard/dell/e6430/Makefile.inc b/src/mainboard/dell/e6430/Makefile.inc -new file mode 100644 -index 0000000000..ba64e93eb8 ---- /dev/null -+++ b/src/mainboard/dell/e6430/Makefile.inc -@@ -0,0 +1,6 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+bootblock-y += early_init.c -+bootblock-y += gpio.c -+romstage-y += early_init.c -+romstage-y += gpio.c -+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads -diff --git a/src/mainboard/dell/e6430/acpi/ec.asl b/src/mainboard/dell/e6430/acpi/ec.asl -new file mode 100644 -index 0000000000..0d429410a9 ---- /dev/null -+++ b/src/mainboard/dell/e6430/acpi/ec.asl -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Device(EC) -+{ -+ Name (_HID, EISAID("PNP0C09")) -+ Name (_UID, 0) -+ Name (_GPE, 16) -+/* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e6430/acpi/platform.asl b/src/mainboard/dell/e6430/acpi/platform.asl -new file mode 100644 -index 0000000000..2d24bbd9b9 ---- /dev/null -+++ b/src/mainboard/dell/e6430/acpi/platform.asl -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Method(_WAK, 1) -+{ -+ /* FIXME: EC support */ -+ Return(Package() {0, 0}) -+} -+ -+Method(_PTS,1) -+{ -+ /* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e6430/acpi/superio.asl b/src/mainboard/dell/e6430/acpi/superio.asl -new file mode 100644 -index 0000000000..55b1db5b11 ---- /dev/null -+++ b/src/mainboard/dell/e6430/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/dell/e6430/acpi_tables.c b/src/mainboard/dell/e6430/acpi_tables.c -new file mode 100644 -index 0000000000..e2759659bf ---- /dev/null -+++ b/src/mainboard/dell/e6430/acpi_tables.c -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <acpi/acpi_gnvs.h> -+#include <soc/nvs.h> -+ -+/* FIXME: check this function. */ -+void mainboard_fill_gnvs(struct global_nvs *gnvs) -+{ -+ /* The lid is open by default. */ -+ gnvs->lids = 1; -+ -+ /* Temperature at which OS will shutdown */ -+ gnvs->tcrt = 100; -+ /* Temperature at which OS will throttle CPU */ -+ gnvs->tpsv = 90; -+} -diff --git a/src/mainboard/dell/e6430/board_info.txt b/src/mainboard/dell/e6430/board_info.txt -new file mode 100644 -index 0000000000..4601a4aaba ---- /dev/null -+++ b/src/mainboard/dell/e6430/board_info.txt -@@ -0,0 +1,6 @@ -+Category: laptop -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -+Release year: 2012 -diff --git a/src/mainboard/dell/e6430/cmos.default b/src/mainboard/dell/e6430/cmos.default -new file mode 100644 -index 0000000000..2a5b30f2b7 ---- /dev/null -+++ b/src/mainboard/dell/e6430/cmos.default -@@ -0,0 +1,9 @@ -+boot_option=Fallback -+debug_level=Debug -+power_on_after_fail=Disable -+nmi=Enable -+bluetooth=Enable -+wwan=Enable -+wlan=Enable -+sata_mode=AHCI -+me_state=Normal -diff --git a/src/mainboard/dell/e6430/cmos.layout b/src/mainboard/dell/e6430/cmos.layout -new file mode 100644 -index 0000000000..1aa7e77bce ---- /dev/null -+++ b/src/mainboard/dell/e6430/cmos.layout -@@ -0,0 +1,88 @@ -+## 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 -+ -+#400 8 r 0 reserved for century byte -+ -+# coreboot config options: southbridge -+408 1 e 1 nmi -+409 2 e 7 power_on_after_fail -+411 1 e 9 sata_mode -+ -+# coreboot config options: EC -+412 1 e 1 bluetooth -+413 1 e 1 wwan -+414 1 e 1 wlan -+ -+# coreboot config options: ME -+424 1 e 14 me_state -+425 2 h 0 me_state_prev -+ -+# coreboot config options: northbridge -+432 3 e 11 gfx_uma_size -+435 2 e 12 hybrid_graphics_mode -+440 8 h 0 volume -+ -+# VBOOT -+448 128 r 0 vbnv -+ -+# SandyBridge MRC Scrambler Seed values -+896 32 r 0 mrc_scrambler_seed -+928 32 r 0 mrc_scrambler_seed_s3 -+960 16 r 0 mrc_scrambler_seed_chk -+ -+# 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 -+9 0 AHCI -+9 1 Compatible -+11 0 32M -+11 1 64M -+11 2 96M -+11 3 128M -+11 4 160M -+11 5 192M -+11 6 224M -+14 0 Normal -+14 1 Disabled -+ -+# ----------------------------------------------------------------- -+checksums -+ -+checksum 392 447 984 -diff --git a/src/mainboard/dell/e6430/data.vbt b/src/mainboard/dell/e6430/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..08952c26ab82933ebb5cc5b9c7e2265963a87b2d -GIT binary patch -literal 6144 -zcmeHKU2Gdw7XHRFw#VZc+nI!tq)j-qG$b@>#vu)%WW~fb!7ZV6LkJc^+qlG~(WXgp -zLU)l?#Jhyj)dGqHf<6H13kV^8g;enZDm*~=5kd&@Cn1Fu52*0a2hgri!F%q^IFQ;) -zjkMh#DR=zcpL5Use9xJ4?#x^=mKdcQb|t!Zj3v6R-<{Yod<{*&!ppI%xUMXT9lLMX -zn;IM)+?yEQoxF~o#5x>}{dfwPkR;RSiC=!jj_JAlRQpJWpd}$VY+XtFX9|?cO&y#m -z<SE`uGt*OdcG7S%MVsQ5GkI`wn)VeYZ#ytIou8d0Yb)J)AUAzmo)Vpuq&7;?RQ_;& -zie?W??w`vSW@&DQ`Yr3=;cjcIHNi^L`QOvN$?05SGCy0nZ	>IdrG<AJm@gpdQPz -zx_Yd5oSZFFa;9)-D-BLf(TLc`ERE!6^M%9tiLHiaXuwHXRU|<2BX~C?>4zSq6a*B6 -zRA?%66|w}s0z*YuMNq*73a(KQQ8A>TT}4_&3_e5hDZs@lHpaYN60rOh%jBQN+*9zu -zIASsRL<3j>pYk93g@PXvaUZbpk)yEWDA4C2Ai!cNXi4M~3gjt#<|(LxR49-{<^K|T -zqL5SnLUq0r*kw>Q!0PGk>)$?LCsIS{ox_=t(Xs5!w-o>M=erl0apv_Z`-(^w_5@pz -z)}lBfx8o(*hgal&<dh}67_jhVpb;fTbFdMn7Q<$~Ll)yIMvJN<r<#~$+{1W;@r<hB -z1mh&*ZN|rpFBo4lzGDPK8tNG98Jij1j4K&Q#`TPw7&*r87<Vw{8Gm6s$astqxC3WO -zz9NE-Ek(&|>)aMG1rKzf_^2m;)RTu!i#rBrUK{pWM_5BuDg}f1vGgAMqNM&t?7(IQ -zcDa=Dn9^Q5?6k6+@y4UvvL3SDxKs*_^RS1n^H*!{fYZz^rPBX<FZ?DhF0v6`u90ic -zA-5^lMeh7u!RIful;@oGY=u>mV(=eO(Cd-pvqPqVBRYz~7nA{nO7|Kv{w^;?LXb8F -zZpK}KE=2zd4)ya^Le2qLGkt7<&s%Z6*Z`k>QW26OPC!Y8WP|wUI8Rlea-W3+oBO=P -z7W#bDD=HM*SuTlWaHmLu%9{LBg+7xrp>y^-%p_)+nfZB&dFmKmF?B(+QtAm&-^!?J -zr{Qq~n%$Y;KvfME{x@gVUB~vz&MBs@*k&z6fZ?Ic-b`*fKea1&Fkj=~!ZaqDU=O0r -zYCPKK+S_PdhGTnR+18<YSJL`a_aBz`G`HE=V`WMDYTMfPLXT~qEK3^O(Kj!<{?_~E -z{ct?ZJ!#R&H|_;QGyr;2JDTu4Urkt)#LW}e65l@e>g0GR_nHOE`gieuP-A>69j*W0 -z><PPSE2YwgK714^F4A&KOda3ou4=7C($dQbCP^XH=U4QVf8#_di>h~9>kwTD6>nL4 -zBSLUr+fHA!LgjQi9)hfgsV8iv!rHDd&4tY)VQn!?C&K1ZSo<JM{|K9!t~KbiT{nky -zZA_;>>gEHwc1)*Nb@P2)`%EVorfFy!3`!X0sG<GVpasKx*wBs}^oC)6VrYLeNR61y -z5$%!)?TnbWM6~@8x-Vir9?_nP(0dVcIij74P%LV0jB1@x<FeCA(YGuW>p0XopwxoS -z0g?6TPW!DC<JKR&l%Knmp5z$x;*#X7@7xT>ql9>N1GN_$T-UVr&HErC5juykd~Sxy -zq!PK|<^jJ^DuQ9)7p<sFLXlH${*3wEJ(L;FsEd;DgJ^{x0*)Wd^<xJzFfF2O*!)Bc -zXtuum#xVj7H8Tulu*qs$*N1J-3WmV*15LsWQhjX<ZR^LFq0OSkUSwZ$8NS&h7|>t` -z7FKz(x)t4R_RHf7I)6EA!d)M`R($wttvJgMee=p9zrFL_EL#DYA0wUzD?Ryj%h>lB -ztg|e-5!;@t?uT+rR=1)e9yp?8gwNW88`Zyt!8rx=+B{i(4~DY`_-WO>sGeD;nsGcs -z7h1ZN6srJX#Uke;d$JhpccQxNhw2Qz?Zw91`@8IHm-n!7{19~*_}LvecV2YZ7%!rJ -zJQk}HtK2>CvB*WQ@u9a$Eq*zF2M=FM=@c`>dwDQ;<8EgZ-}dvt6=k(8Kqfa=nDJJ{ -z`Qth}G~%sFr{ZEKZb_%aySrD?sV%fJw`vFfda&ho1a>X)H^I}D_0A<|*{8kwEBU8> -qS<b6g={WLAp3+&R^8(yo-t$_!=7BX2ta)I~18W{w^T5By1OEis_@J`@ - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/e6430/devicetree.cb b/src/mainboard/dell/e6430/devicetree.cb -new file mode 100644 -index 0000000000..054b01c5ac ---- /dev/null -+++ b/src/mainboard/dell/e6430/devicetree.cb -@@ -0,0 +1,70 @@ -+chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. -+ register "gfx" = "GMA_STATIC_DISPLAYS(1)" -+ register "gpu_cpu_backlight" = "0x00001312" -+ register "gpu_dp_b_hotplug" = "4" -+ register "gpu_dp_c_hotplug" = "4" -+ register "gpu_dp_d_hotplug" = "4" -+ register "gpu_panel_port_select" = "0" -+ register "gpu_panel_power_backlight_off_delay" = "2300" -+ register "gpu_panel_power_backlight_on_delay" = "2300" -+ register "gpu_panel_power_cycle_delay" = "6" -+ register "gpu_panel_power_down_delay" = "400" -+ register "gpu_panel_power_up_delay" = "400" -+ register "gpu_pch_backlight" = "0x13121312" -+ -+ register "spd_addresses" = "{0x50, 0, 0x52, 0}" -+ -+ device domain 0x0 on -+ subsystemid 0x1028 0x0534 inherit -+ -+ device ref host_bridge on end -+ device ref peg10 off end -+ device ref igd on end -+ -+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH -+ register "docking_supported" = "1" -+ register "gen1_dec" = "0x007c0681" -+ register "gen2_dec" = "0x005c0921" -+ register "gen3_dec" = "0x003c07e1" -+ register "gen4_dec" = "0x00000911" # Ports 0x910/0x911 for EC -+ register "gpi0_routing" = "2" -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 1, 0, 0, 0, 0 }" -+ register "pcie_port_coalesce" = "1" -+ register "sata_interface_speed_support" = "0x3" -+ register "sata_port_map" = "0x33" -+ register "spi_lvscc" = "0x2005" -+ register "spi_uvscc" = "0x2005" -+ register "superspeed_capable_ports" = "0x0000000f" -+ register "xhci_overcurrent_mapping" = "0x00000c03" -+ register "xhci_switchable_ports" = "0x0000000f" -+ -+ device ref xhci on end -+ device ref mei1 on end -+ device ref mei2 off end -+ device ref me_ide_r off end -+ device ref me_kt on end -+ device ref gbe on end -+ device ref ehci2 on end -+ device ref hda on end -+ device ref pcie_rp1 on end # WWAN Slot -+ device ref pcie_rp2 on end # SLAN Slot -+ device ref pcie_rp3 on end # ExpressCard -+ device ref pcie_rp4 on end # E-Module (optical bay) -+ device ref pcie_rp5 on end # Extra Half Mini PCIe slot -+ device ref pcie_rp6 on end # SD/MMC Card Reader -+ device ref pcie_rp7 off end -+ device ref pcie_rp8 off end -+ device ref ehci1 on end -+ device ref pci_bridge off end -+ device ref lpc on -+ chip ec/dell/mec5035 -+ device pnp ff.0 on end -+ end -+ end -+ device ref sata1 on end -+ device ref smbus on end -+ device ref sata2 off end -+ device ref thermal off end -+ end -+ end -+end -diff --git a/src/mainboard/dell/e6430/dsdt.asl b/src/mainboard/dell/e6430/dsdt.asl -new file mode 100644 -index 0000000000..7d13c55b08 ---- /dev/null -+++ b/src/mainboard/dell/e6430/dsdt.asl -@@ -0,0 +1,30 @@ -+#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB -+#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+ -+#include <acpi/acpi.h> -+ -+DefinitionBlock( -+ "dsdt.aml", -+ "DSDT", -+ ACPI_DSDT_REV_2, -+ OEM_ID, -+ ACPI_TABLE_CREATOR, -+ 0x20141018 /* OEM revision */ -+) -+{ -+ #include <acpi/dsdt_top.asl> -+ #include "acpi/platform.asl" -+ #include <cpu/intel/common/acpi/cpu.asl> -+ #include <southbridge/intel/common/acpi/platform.asl> -+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl> -+ #include <southbridge/intel/common/acpi/sleepstates.asl> -+ -+ Device (\_SB.PCI0) -+ { -+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl> -+ #include <drivers/intel/gma/acpi/default_brightness_levels.asl> -+ #include <southbridge/intel/bd82x6x/acpi/pch.asl> -+ } -+} -diff --git a/src/mainboard/dell/e6430/early_init.c b/src/mainboard/dell/e6430/early_init.c -new file mode 100644 -index 0000000000..d882c3d78b ---- /dev/null -+++ b/src/mainboard/dell/e6430/early_init.c -@@ -0,0 +1,32 @@ -+/* 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, 1, 3 }, -+ { 1, 1, 3 }, -+ { 1, 1, 4 }, -+ { 1, 1, 4 }, -+ { 1, 1, 5 }, -+ { 1, 1, 5 }, -+ { 1, 2, 6 }, -+ { 1, 2, 6 }, -+}; -+ -+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/e6430/gma-mainboard.ads b/src/mainboard/dell/e6430/gma-mainboard.ads -new file mode 100644 -index 0000000000..1310830c8e ---- /dev/null -+++ b/src/mainboard/dell/e6430/gma-mainboard.ads -@@ -0,0 +1,20 @@ -+-- 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 := -+ ( -+ HDMI1, -- mainboard HDMI -+ DP2, -- dock DP -+ DP3, -- dock DP -+ Analog, --mainboard VGA -+ LVDS, -+ others => Disabled); -+ -+end GMA.Mainboard; -diff --git a/src/mainboard/dell/e6430/gpio.c b/src/mainboard/dell/e6430/gpio.c -new file mode 100644 -index 0000000000..777570765a ---- /dev/null -+++ b/src/mainboard/dell/e6430/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/e6430/hda_verb.c b/src/mainboard/dell/e6430/hda_verb.c -new file mode 100644 -index 0000000000..56ada95c58 ---- /dev/null -+++ b/src/mainboard/dell/e6430/hda_verb.c -@@ -0,0 +1,33 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d76df, /* Codec Vendor / Device ID: IDT */ -+ 0x10280534, /* Subsystem ID */ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x10280534), -+ 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/e6430/mainboard.c b/src/mainboard/dell/e6430/mainboard.c -new file mode 100644 -index 0000000000..31e49802fc ---- /dev/null -+++ b/src/mainboard/dell/e6430/mainboard.c -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/device.h> -+#include <drivers/intel/gma/int15.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+#include <ec/acpi/ec.h> -+#include <console/console.h> -+#include <pc80/keyboard.h> -+ -+static void mainboard_enable(struct device *dev) -+{ -+ -+ /* FIXME: fix these values. */ -+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, -+ GMA_INT15_PANEL_FIT_DEFAULT, -+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); -+} -+ -+struct chip_operations mainboard_ops = { -+ .enable_dev = mainboard_enable, -+}; --- -2.39.2 - diff --git a/config/coreboot/default/patches/0021-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch b/config/coreboot/default/patches/0021-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch new file mode 100644 index 00000000..9c210c8c --- /dev/null +++ b/config/coreboot/default/patches/0021-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch @@ -0,0 +1,449 @@ +From 73313e682ba8808f8db6259ac7d93f54c11cb884 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 21/65] 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 +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 +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/0022-don-t-use-github-for-the-acpica-download.patch b/config/coreboot/default/patches/0022-don-t-use-github-for-the-acpica-download.patch deleted file mode 100644 index f66909c6..00000000 --- a/config/coreboot/default/patches/0022-don-t-use-github-for-the-acpica-download.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 536a1dd349f590cbefccac7e7364cafcdaec9600 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <leah@libreboot.org> -Date: Sun, 22 Oct 2023 15:02:25 +0100 -Subject: [PATCH 22/30] don't use github for the acpica download - -i have the tarball from a previous download, and i placed -it on libreboot rsync, which then got mirrored to princeton. - -today, github's ssl cert was b0rking the hell out and i really -really wanted to finish a build, and didn't want to wait for -github to fix their httpd. - -so i'm now hosting this specific acpica tarball on rsync. - -this patch makes that URL be used, instead of the github one. - -that's the 2nd time i've had to patch coreboot's acpica download! - -Signed-off-by: Leah Rowe <leah@libreboot.org> ---- - util/crossgcc/buildgcc | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc -index 23a5caf2bb..36565a906c 100755 ---- a/util/crossgcc/buildgcc -+++ b/util/crossgcc/buildgcc -@@ -72,7 +72,7 @@ MPFR_BASE_URL="https://ftpmirror.gnu.org/mpfr" - MPC_BASE_URL="https://ftpmirror.gnu.org/mpc" - GCC_BASE_URL="https://ftpmirror.gnu.org/gcc/gcc-${GCC_VERSION}" - BINUTILS_BASE_URL="https://ftpmirror.gnu.org/binutils" --IASL_BASE_URL="https://github.com/acpica/acpica/archive/refs/tags" -+IASL_BASE_URL="https://www.mirrorservice.org/sites/libreboot.org/release/misc/acpica" - # CLANG toolchain archive locations - LLVM_BASE_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}" - CLANG_BASE_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}" --- -2.39.2 - diff --git a/config/coreboot/default/patches/0022-mb-dell-Add-Latitude-E5520-Sandy-Bridge.patch b/config/coreboot/default/patches/0022-mb-dell-Add-Latitude-E5520-Sandy-Bridge.patch new file mode 100644 index 00000000..3a580662 --- /dev/null +++ b/config/coreboot/default/patches/0022-mb-dell-Add-Latitude-E5520-Sandy-Bridge.patch @@ -0,0 +1,442 @@ +From a7e2fde426280a944916c341586361f3ac9fa9a8 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 22/65] 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 +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 +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/0023-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch b/config/coreboot/default/patches/0023-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch new file mode 100644 index 00000000..4a7a6bf9 --- /dev/null +++ b/config/coreboot/default/patches/0023-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch @@ -0,0 +1,442 @@ +From f781a8bac250d4902ec3e7caa0628c77836a8ae3 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 23/65] 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 +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 +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/0024-mb-dell-Add-Latitude-E6320-Sandy-Bridge.patch b/config/coreboot/default/patches/0024-mb-dell-Add-Latitude-E6320-Sandy-Bridge.patch new file mode 100644 index 00000000..9ae5ce64 --- /dev/null +++ b/config/coreboot/default/patches/0024-mb-dell-Add-Latitude-E6320-Sandy-Bridge.patch @@ -0,0 +1,435 @@ +From 85a0905b600c1f532c462047941da6e7c2bb47c2 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 24/65] 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 +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 +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/0025-mb-dell-Add-Latitude-E6220-Sandy-Bridge.patch b/config/coreboot/default/patches/0025-mb-dell-Add-Latitude-E6220-Sandy-Bridge.patch new file mode 100644 index 00000000..668c0063 --- /dev/null +++ b/config/coreboot/default/patches/0025-mb-dell-Add-Latitude-E6220-Sandy-Bridge.patch @@ -0,0 +1,438 @@ +From 817b0d543444e52ddfde536ded52509456dcbbf2 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 25/65] 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 +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 + +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-mb-dell-Add-Latitude-E6330-Ivy-Bridge.patch b/config/coreboot/default/patches/0026-mb-dell-Add-Latitude-E6330-Ivy-Bridge.patch new file mode 100644 index 00000000..d88e97b3 --- /dev/null +++ b/config/coreboot/default/patches/0026-mb-dell-Add-Latitude-E6330-Ivy-Bridge.patch @@ -0,0 +1,436 @@ +From 48347cf8bc52db7a454a7be8cbc6f9d9eb67b8b0 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 26/65] 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 +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 + +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/0026-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch b/config/coreboot/default/patches/0026-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch deleted file mode 100644 index 33d743f1..00000000 --- a/config/coreboot/default/patches/0026-mb-dell-Add-Latitude-E6530-Ivy-Bridge.patch +++ /dev/null @@ -1,792 +0,0 @@ -From 973783a989cdcb7b77029e369156c81eefe8cc67 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 26/30] mb/dell: Add Latitude E6530 (Ivy Bridge) - -Mainboard is QALA0/LA-7761P (UMA). The dGPU model was not tested. This -is based on the autoport output with some manual tweaks. The flash is -8MiB + 4MiB. It 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: I93c6622fc5da1d0d61a5b2c197ac7227d9525908 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/e6530/Kconfig | 37 ++++ - src/mainboard/dell/e6530/Kconfig.name | 2 + - src/mainboard/dell/e6530/Makefile.inc | 6 + - src/mainboard/dell/e6530/acpi/ec.asl | 9 + - src/mainboard/dell/e6530/acpi/platform.asl | 12 ++ - src/mainboard/dell/e6530/acpi/superio.asl | 3 + - src/mainboard/dell/e6530/acpi_tables.c | 16 ++ - src/mainboard/dell/e6530/board_info.txt | 6 + - src/mainboard/dell/e6530/cmos.default | 9 + - src/mainboard/dell/e6530/cmos.layout | 88 ++++++++++ - src/mainboard/dell/e6530/data.vbt | Bin 0 -> 4280 bytes - src/mainboard/dell/e6530/devicetree.cb | 68 ++++++++ - src/mainboard/dell/e6530/dsdt.asl | 30 ++++ - src/mainboard/dell/e6530/early_init.c | 38 ++++ - src/mainboard/dell/e6530/gma-mainboard.ads | 20 +++ - src/mainboard/dell/e6530/gpio.c | 192 +++++++++++++++++++++ - src/mainboard/dell/e6530/hda_verb.c | 33 ++++ - src/mainboard/dell/e6530/mainboard.c | 21 +++ - 18 files changed, 590 insertions(+) - create mode 100644 src/mainboard/dell/e6530/Kconfig - create mode 100644 src/mainboard/dell/e6530/Kconfig.name - create mode 100644 src/mainboard/dell/e6530/Makefile.inc - create mode 100644 src/mainboard/dell/e6530/acpi/ec.asl - create mode 100644 src/mainboard/dell/e6530/acpi/platform.asl - create mode 100644 src/mainboard/dell/e6530/acpi/superio.asl - create mode 100644 src/mainboard/dell/e6530/acpi_tables.c - create mode 100644 src/mainboard/dell/e6530/board_info.txt - create mode 100644 src/mainboard/dell/e6530/cmos.default - create mode 100644 src/mainboard/dell/e6530/cmos.layout - create mode 100644 src/mainboard/dell/e6530/data.vbt - create mode 100644 src/mainboard/dell/e6530/devicetree.cb - create mode 100644 src/mainboard/dell/e6530/dsdt.asl - create mode 100644 src/mainboard/dell/e6530/early_init.c - create mode 100644 src/mainboard/dell/e6530/gma-mainboard.ads - create mode 100644 src/mainboard/dell/e6530/gpio.c - create mode 100644 src/mainboard/dell/e6530/hda_verb.c - create mode 100644 src/mainboard/dell/e6530/mainboard.c - -diff --git a/src/mainboard/dell/e6530/Kconfig b/src/mainboard/dell/e6530/Kconfig -new file mode 100644 -index 0000000000..582adddbd4 ---- /dev/null -+++ b/src/mainboard/dell/e6530/Kconfig -@@ -0,0 +1,37 @@ -+if BOARD_DELL_LATITUDE_E6530 -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ select BOARD_ROMSIZE_KB_12288 -+ select EC_ACPI -+ select EC_DELL_MEC5035 -+ select GFX_GMA_PANEL_1_ON_LVDS -+ select HAVE_ACPI_RESUME -+ select HAVE_ACPI_TABLES -+ select HAVE_CMOS_DEFAULT -+ select HAVE_OPTION_TABLE -+ select INTEL_GMA_HAVE_VBT -+ select INTEL_INT15 -+ select MAINBOARD_HAS_LIBGFXINIT -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select NORTHBRIDGE_INTEL_SANDYBRIDGE -+ select SERIRQ_CONTINUOUS_MODE -+ select SOUTHBRIDGE_INTEL_C216 -+ select SYSTEM_TYPE_LAPTOP -+ select USE_NATIVE_RAMINIT -+ -+config MAINBOARD_DIR -+ default "dell/e6530" -+ -+config MAINBOARD_PART_NUMBER -+ default "Latitude E6530" -+ -+config VGA_BIOS_ID -+ default "8086,0166" -+ -+config DRAM_RESET_GATE_GPIO -+ default 60 -+ -+config USBDEBUG_HCD_INDEX -+ default 2 -+endif -diff --git a/src/mainboard/dell/e6530/Kconfig.name b/src/mainboard/dell/e6530/Kconfig.name -new file mode 100644 -index 0000000000..01ed76d107 ---- /dev/null -+++ b/src/mainboard/dell/e6530/Kconfig.name -@@ -0,0 +1,2 @@ -+config BOARD_DELL_LATITUDE_E6530 -+ bool "Latitude E6530" -diff --git a/src/mainboard/dell/e6530/Makefile.inc b/src/mainboard/dell/e6530/Makefile.inc -new file mode 100644 -index 0000000000..ba64e93eb8 ---- /dev/null -+++ b/src/mainboard/dell/e6530/Makefile.inc -@@ -0,0 +1,6 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+bootblock-y += early_init.c -+bootblock-y += gpio.c -+romstage-y += early_init.c -+romstage-y += gpio.c -+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads -diff --git a/src/mainboard/dell/e6530/acpi/ec.asl b/src/mainboard/dell/e6530/acpi/ec.asl -new file mode 100644 -index 0000000000..0d429410a9 ---- /dev/null -+++ b/src/mainboard/dell/e6530/acpi/ec.asl -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Device(EC) -+{ -+ Name (_HID, EISAID("PNP0C09")) -+ Name (_UID, 0) -+ Name (_GPE, 16) -+/* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e6530/acpi/platform.asl b/src/mainboard/dell/e6530/acpi/platform.asl -new file mode 100644 -index 0000000000..2d24bbd9b9 ---- /dev/null -+++ b/src/mainboard/dell/e6530/acpi/platform.asl -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Method(_WAK, 1) -+{ -+ /* FIXME: EC support */ -+ Return(Package() {0, 0}) -+} -+ -+Method(_PTS,1) -+{ -+ /* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e6530/acpi/superio.asl b/src/mainboard/dell/e6530/acpi/superio.asl -new file mode 100644 -index 0000000000..55b1db5b11 ---- /dev/null -+++ b/src/mainboard/dell/e6530/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/dell/e6530/acpi_tables.c b/src/mainboard/dell/e6530/acpi_tables.c -new file mode 100644 -index 0000000000..e2759659bf ---- /dev/null -+++ b/src/mainboard/dell/e6530/acpi_tables.c -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <acpi/acpi_gnvs.h> -+#include <soc/nvs.h> -+ -+/* FIXME: check this function. */ -+void mainboard_fill_gnvs(struct global_nvs *gnvs) -+{ -+ /* The lid is open by default. */ -+ gnvs->lids = 1; -+ -+ /* Temperature at which OS will shutdown */ -+ gnvs->tcrt = 100; -+ /* Temperature at which OS will throttle CPU */ -+ gnvs->tpsv = 90; -+} -diff --git a/src/mainboard/dell/e6530/board_info.txt b/src/mainboard/dell/e6530/board_info.txt -new file mode 100644 -index 0000000000..4601a4aaba ---- /dev/null -+++ b/src/mainboard/dell/e6530/board_info.txt -@@ -0,0 +1,6 @@ -+Category: laptop -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -+Release year: 2012 -diff --git a/src/mainboard/dell/e6530/cmos.default b/src/mainboard/dell/e6530/cmos.default -new file mode 100644 -index 0000000000..279415dfd1 ---- /dev/null -+++ b/src/mainboard/dell/e6530/cmos.default -@@ -0,0 +1,9 @@ -+boot_option=Fallback -+debug_level=Debug -+power_on_after_fail=Disable -+nmi=Enable -+bluetooth=Enable -+wwan=Enable -+wlan=Enable -+sata_mode=AHCI -+me_state=Disabled -diff --git a/src/mainboard/dell/e6530/cmos.layout b/src/mainboard/dell/e6530/cmos.layout -new file mode 100644 -index 0000000000..e85ea4c661 ---- /dev/null -+++ b/src/mainboard/dell/e6530/cmos.layout -@@ -0,0 +1,88 @@ -+## 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 -+ -+#400 8 r 0 reserved for century byte -+ -+# coreboot config options: southbridge -+408 1 e 1 nmi -+409 2 e 7 power_on_after_fail -+411 1 e 9 sata_mode -+ -+# coreboot config options: EC -+412 1 e 1 bluetooth -+413 1 e 1 wwan -+415 1 e 1 wlan -+ -+# coreboot config options: ME -+424 1 e 14 me_state -+425 2 h 0 me_state_prev -+ -+# coreboot config options: northbridge -+432 3 e 11 gfx_uma_size -+435 2 e 12 hybrid_graphics_mode -+440 8 h 0 volume -+ -+# VBOOT -+448 128 r 0 vbnv -+ -+# SandyBridge MRC Scrambler Seed values -+896 32 r 0 mrc_scrambler_seed -+928 32 r 0 mrc_scrambler_seed_s3 -+960 16 r 0 mrc_scrambler_seed_chk -+ -+# 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 -+9 0 AHCI -+9 1 Compatible -+11 0 32M -+11 1 64M -+11 2 96M -+11 3 128M -+11 4 160M -+11 5 192M -+11 6 224M -+14 0 Normal -+14 1 Disabled -+ -+# ----------------------------------------------------------------- -+checksums -+ -+checksum 392 447 984 -diff --git a/src/mainboard/dell/e6530/data.vbt b/src/mainboard/dell/e6530/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..af64a913d521fe240ce30e114e90fe75d3841bbc -GIT binary patch -literal 4280 -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 - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/e6530/devicetree.cb b/src/mainboard/dell/e6530/devicetree.cb -new file mode 100644 -index 0000000000..96eed178c5 ---- /dev/null -+++ b/src/mainboard/dell/e6530/devicetree.cb -@@ -0,0 +1,68 @@ -+chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. -+ register "gfx" = "GMA_STATIC_DISPLAYS(1)" -+ register "gpu_cpu_backlight" = "0x00000251" -+ register "gpu_dp_b_hotplug" = "4" -+ register "gpu_dp_c_hotplug" = "4" -+ register "gpu_dp_d_hotplug" = "4" -+ register "gpu_panel_port_select" = "0" -+ register "gpu_panel_power_backlight_off_delay" = "2300" -+ register "gpu_panel_power_backlight_on_delay" = "2300" -+ register "gpu_panel_power_cycle_delay" = "6" -+ register "gpu_panel_power_down_delay" = "400" -+ register "gpu_panel_power_up_delay" = "400" -+ register "gpu_pch_backlight" = "0x13121312" -+ -+ device domain 0x0 on -+ subsystemid 0x1028 0x0535 inherit -+ -+ device ref host_bridge on end # Host bridge -+ device ref peg10 off end # PEG -+ device ref igd on end # iGPU -+ -+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH -+ register "docking_supported" = "1" -+ register "gen1_dec" = "0x007c0681" -+ register "gen2_dec" = "0x005c0921" -+ register "gen3_dec" = "0x003c07e1" -+ register "gen4_dec" = "0x007c0901" -+ register "gpi0_routing" = "2" -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 1, 0, 0, 0, 0 }" -+ register "pcie_port_coalesce" = "1" -+ register "sata_interface_speed_support" = "0x3" -+ register "sata_port_map" = "0x33" -+ register "spi_lvscc" = "0x2005" -+ register "spi_uvscc" = "0x2005" -+ register "superspeed_capable_ports" = "0x0000000f" -+ register "xhci_overcurrent_mapping" = "0x00000c03" -+ register "xhci_switchable_ports" = "0x0000000f" -+ -+ device ref xhci on end # USB 3.0 Controller -+ device ref mei1 off end # Management Engine Interface 1 -+ device ref mei2 off end # Management Engine Interface 2 -+ device ref me_ide_r off end # Management Engine IDE-R -+ device ref me_kt on end # Management Engine KT -+ device ref gbe on end # Intel Gigabit Ethernet -+ device ref ehci2 on end # USB2 EHCI #2 -+ device ref hda on end # High Definition Audio -+ device ref pcie_rp1 on end # PCIe Port #1 -+ device ref pcie_rp2 on end # PCIe Port #2 -+ device ref pcie_rp3 on end # PCIe Port #3 -+ device ref pcie_rp4 on end # PCIe Port #4 -+ device ref pcie_rp5 off end # PCIe Port #5 -+ device ref pcie_rp6 on end # PCIe Port #6 -+ device ref pcie_rp7 off end # PCIe Port #7 -+ device ref pcie_rp8 off end # PCIe Port #8 -+ device ref ehci1 on end # USB2 EHCI #1 -+ device ref pci_bridge off end # PCI bridge -+ device ref lpc on # LPC bridge -+ chip ec/dell/mec5035 -+ device pnp ff.0 on end -+ end -+ end -+ device ref sata1 on end # SATA Controller 1 -+ device ref smbus on end # SMBus -+ device ref sata2 off end # SATA Controller 2 -+ device ref thermal off end # Thermal -+ end -+ end -+end -diff --git a/src/mainboard/dell/e6530/dsdt.asl b/src/mainboard/dell/e6530/dsdt.asl -new file mode 100644 -index 0000000000..7d13c55b08 ---- /dev/null -+++ b/src/mainboard/dell/e6530/dsdt.asl -@@ -0,0 +1,30 @@ -+#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB -+#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+ -+#include <acpi/acpi.h> -+ -+DefinitionBlock( -+ "dsdt.aml", -+ "DSDT", -+ ACPI_DSDT_REV_2, -+ OEM_ID, -+ ACPI_TABLE_CREATOR, -+ 0x20141018 /* OEM revision */ -+) -+{ -+ #include <acpi/dsdt_top.asl> -+ #include "acpi/platform.asl" -+ #include <cpu/intel/common/acpi/cpu.asl> -+ #include <southbridge/intel/common/acpi/platform.asl> -+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl> -+ #include <southbridge/intel/common/acpi/sleepstates.asl> -+ -+ Device (\_SB.PCI0) -+ { -+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl> -+ #include <drivers/intel/gma/acpi/default_brightness_levels.asl> -+ #include <southbridge/intel/bd82x6x/acpi/pch.asl> -+ } -+} -diff --git a/src/mainboard/dell/e6530/early_init.c b/src/mainboard/dell/e6530/early_init.c -new file mode 100644 -index 0000000000..d57f48e7f1 ---- /dev/null -+++ b/src/mainboard/dell/e6530/early_init.c -@@ -0,0 +1,38 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+ -+#include <bootblock_common.h> -+#include <device/pci_ops.h> -+#include <ec/dell/mec5035/mec5035.h> -+#include <northbridge/intel/sandybridge/raminit_native.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, 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 }, -+}; -+ -+void bootblock_mainboard_early_init(void) -+{ -+ pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1c0f); -+ pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0000); -+ mec5035_early_init(); -+} -+ -+void mainboard_get_spd(spd_raw_data *spd, bool id_only) -+{ -+ read_spd(&spd[0], 0x50, id_only); -+ read_spd(&spd[2], 0x52, id_only); -+} -diff --git a/src/mainboard/dell/e6530/gma-mainboard.ads b/src/mainboard/dell/e6530/gma-mainboard.ads -new file mode 100644 -index 0000000000..1310830c8e ---- /dev/null -+++ b/src/mainboard/dell/e6530/gma-mainboard.ads -@@ -0,0 +1,20 @@ -+-- 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 := -+ ( -+ HDMI1, -- mainboard HDMI -+ DP2, -- dock DP -+ DP3, -- dock DP -+ Analog, --mainboard VGA -+ LVDS, -+ others => Disabled); -+ -+end GMA.Mainboard; -diff --git a/src/mainboard/dell/e6530/gpio.c b/src/mainboard/dell/e6530/gpio.c -new file mode 100644 -index 0000000000..777570765a ---- /dev/null -+++ b/src/mainboard/dell/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/e6530/hda_verb.c b/src/mainboard/dell/e6530/hda_verb.c -new file mode 100644 -index 0000000000..9de7e34311 ---- /dev/null -+++ b/src/mainboard/dell/e6530/hda_verb.c -@@ -0,0 +1,33 @@ -+/* 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/e6530/mainboard.c b/src/mainboard/dell/e6530/mainboard.c -new file mode 100644 -index 0000000000..31e49802fc ---- /dev/null -+++ b/src/mainboard/dell/e6530/mainboard.c -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/device.h> -+#include <drivers/intel/gma/int15.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+#include <ec/acpi/ec.h> -+#include <console/console.h> -+#include <pc80/keyboard.h> -+ -+static void mainboard_enable(struct device *dev) -+{ -+ -+ /* FIXME: fix these values. */ -+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, -+ GMA_INT15_PANEL_FIT_DEFAULT, -+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); -+} -+ -+struct chip_operations mainboard_ops = { -+ .enable_dev = mainboard_enable, -+}; --- -2.39.2 - diff --git a/config/coreboot/default/patches/0027-mb-dell-Add-Latitude-E6230-Ivy-Bridge.patch b/config/coreboot/default/patches/0027-mb-dell-Add-Latitude-E6230-Ivy-Bridge.patch new file mode 100644 index 00000000..bd6f6218 --- /dev/null +++ b/config/coreboot/default/patches/0027-mb-dell-Add-Latitude-E6230-Ivy-Bridge.patch @@ -0,0 +1,440 @@ +From 80af5303da07197a7da5262e82a59b691ffed5a2 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 27/65] 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 +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 +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/0027-rebase-dell-e6530-to-newer-coreboot-code.patch b/config/coreboot/default/patches/0027-rebase-dell-e6530-to-newer-coreboot-code.patch deleted file mode 100644 index 130984fb..00000000 --- a/config/coreboot/default/patches/0027-rebase-dell-e6530-to-newer-coreboot-code.patch +++ /dev/null @@ -1,145 +0,0 @@ -From 88652afd52b0a8e0fc8bb1656e59d8ae4796d847 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <info@minifree.org> -Date: Thu, 25 Jan 2024 14:30:03 +0000 -Subject: [PATCH 27/30] rebase dell/e6530 to newer coreboot code - -i diffed nicholas's current e6430 patch, versus the old one, -prior to this revision update in lbmk, also cross referencing -the original e6430 and e6530 patches, diffing them, and the -result in this patch. most notably, spd data is now defined in -the devicetree, instead of early_init.c as per: - -commit 45e4ab4a660cb7ce312f2d11a153f2d9ef4158da -Author: Keith Hui <buurin@gmail.com> -Date: Sat Jul 22 12:49:05 2023 -0400 - mb/*: Update SPD mapping for sandybridge boards - -This should work fine. Will test after this builds. - -Signed-off-by: Leah Rowe <info@minifree.org> ---- - src/mainboard/dell/e6530/Kconfig | 15 +++++++++++---- - src/mainboard/dell/e6530/cmos.layout | 2 +- - src/mainboard/dell/e6530/devicetree.cb | 8 +++++--- - src/mainboard/dell/e6530/early_init.c | 12 +++--------- - 4 files changed, 20 insertions(+), 17 deletions(-) - -diff --git a/src/mainboard/dell/e6530/Kconfig b/src/mainboard/dell/e6530/Kconfig -index 582adddbd4..a104566890 100644 ---- a/src/mainboard/dell/e6530/Kconfig -+++ b/src/mainboard/dell/e6530/Kconfig -@@ -20,18 +20,25 @@ config BOARD_SPECIFIC_OPTIONS - select SYSTEM_TYPE_LAPTOP - select USE_NATIVE_RAMINIT - -+config DRAM_RESET_GATE_GPIO -+ default 60 -+ - config MAINBOARD_DIR - default "dell/e6530" - - config MAINBOARD_PART_NUMBER - default "Latitude E6530" - --config VGA_BIOS_ID -- default "8086,0166" -+config PS2K_EISAID -+ default "PNP0303" - --config DRAM_RESET_GATE_GPIO -- default 60 -+config PS2M_EISAID -+ default "PNP0F13" - - config USBDEBUG_HCD_INDEX - default 2 -+ -+config VGA_BIOS_ID -+ default "8086,0166" -+ - endif -diff --git a/src/mainboard/dell/e6530/cmos.layout b/src/mainboard/dell/e6530/cmos.layout -index e85ea4c661..1aa7e77bce 100644 ---- a/src/mainboard/dell/e6530/cmos.layout -+++ b/src/mainboard/dell/e6530/cmos.layout -@@ -25,7 +25,7 @@ entries - # coreboot config options: EC - 412 1 e 1 bluetooth - 413 1 e 1 wwan --415 1 e 1 wlan -+414 1 e 1 wlan - - # coreboot config options: ME - 424 1 e 14 me_state -diff --git a/src/mainboard/dell/e6530/devicetree.cb b/src/mainboard/dell/e6530/devicetree.cb -index 96eed178c5..37135bcf0f 100644 ---- a/src/mainboard/dell/e6530/devicetree.cb -+++ b/src/mainboard/dell/e6530/devicetree.cb -@@ -12,6 +12,8 @@ chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. - register "gpu_panel_power_up_delay" = "400" - register "gpu_pch_backlight" = "0x13121312" - -+ register "spd_addresses" = "{0x50, 0, 0x52, 0}" -+ - device domain 0x0 on - subsystemid 0x1028 0x0535 inherit - -@@ -24,7 +26,7 @@ chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. - register "gen1_dec" = "0x007c0681" - register "gen2_dec" = "0x005c0921" - register "gen3_dec" = "0x003c07e1" -- register "gen4_dec" = "0x007c0901" -+ register "gen4_dec" = "0x00000911" # Ports 0x910/0x911 for EC - register "gpi0_routing" = "2" - register "pcie_hotplug_map" = "{ 0, 0, 1, 1, 0, 0, 0, 0 }" - register "pcie_port_coalesce" = "1" -@@ -37,7 +39,7 @@ chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. - register "xhci_switchable_ports" = "0x0000000f" - - device ref xhci on end # USB 3.0 Controller -- device ref mei1 off end # Management Engine Interface 1 -+ device ref mei1 on end # Management Engine Interface 1 - device ref mei2 off end # Management Engine Interface 2 - device ref me_ide_r off end # Management Engine IDE-R - device ref me_kt on end # Management Engine KT -@@ -48,7 +50,7 @@ chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. - device ref pcie_rp2 on end # PCIe Port #2 - device ref pcie_rp3 on end # PCIe Port #3 - device ref pcie_rp4 on end # PCIe Port #4 -- device ref pcie_rp5 off end # PCIe Port #5 -+ device ref pcie_rp5 on end # PCIe Port #5 - device ref pcie_rp6 on end # PCIe Port #6 - device ref pcie_rp7 off end # PCIe Port #7 - device ref pcie_rp8 off end # PCIe Port #8 -diff --git a/src/mainboard/dell/e6530/early_init.c b/src/mainboard/dell/e6530/early_init.c -index d57f48e7f1..2b40f6963f 100644 ---- a/src/mainboard/dell/e6530/early_init.c -+++ b/src/mainboard/dell/e6530/early_init.c -@@ -4,7 +4,6 @@ - #include <bootblock_common.h> - #include <device/pci_ops.h> - #include <ec/dell/mec5035/mec5035.h> --#include <northbridge/intel/sandybridge/raminit_native.h> - #include <southbridge/intel/bd82x6x/pch.h> - - const struct southbridge_usb_port mainboard_usb_ports[] = { -@@ -26,13 +25,8 @@ const struct southbridge_usb_port mainboard_usb_ports[] = { - - void bootblock_mainboard_early_init(void) - { -- pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1c0f); -- pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0000); -+ 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(); - } -- --void mainboard_get_spd(spd_raw_data *spd, bool id_only) --{ -- read_spd(&spd[0], 0x50, id_only); -- read_spd(&spd[2], 0x52, id_only); --} --- -2.39.2 - diff --git a/config/coreboot/default/patches/0021-HACK-Disable-coreboot-related-BL31-features.patch b/config/coreboot/default/patches/0028-HACK-Disable-coreboot-related-BL31-features.patch index 40e1ccee..e6ad26d1 100644 --- a/config/coreboot/default/patches/0021-HACK-Disable-coreboot-related-BL31-features.patch +++ b/config/coreboot/default/patches/0028-HACK-Disable-coreboot-related-BL31-features.patch @@ -1,7 +1,7 @@ -From 70262a5f4bf801814d68f8778ea89b5cd8ef8f9a Mon Sep 17 00:00:00 2001 +From 8fa72bedc6282ba581ede85d62a341917ec5d203 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 21/30] HACK: Disable coreboot related BL31 features +Subject: [PATCH 28/65] 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 538d254ace..18e451d63c 100644 +index cb43897efd..a9e5ff399a 100644 --- a/src/arch/arm64/Makefile.mk +++ b/src/arch/arm64/Makefile.mk -@@ -159,9 +159,6 @@ BL31_MAKEARGS += LOG_LEVEL=40 +@@ -173,9 +173,6 @@ BL31_MAKEARGS += LOG_LEVEL=40 # Always enable crash reporting, even on a release build BL31_MAKEARGS += CRASH_REPORTING=1 @@ -24,5 +24,5 @@ index 538d254ace..18e451d63c 100644 BL31_MAKEARGS += BUILD_PLAT="$(BL31_BUILD)" -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0028-dell-e6-30-disable-the-ME-device-in-devicetree.patch b/config/coreboot/default/patches/0028-dell-e6-30-disable-the-ME-device-in-devicetree.patch deleted file mode 100644 index fa7ab40d..00000000 --- a/config/coreboot/default/patches/0028-dell-e6-30-disable-the-ME-device-in-devicetree.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 8705b719573d2159adde10af9c6a4d8806b7d27b Mon Sep 17 00:00:00 2001 -From: Leah Rowe <info@minifree.org> -Date: Thu, 25 Jan 2024 14:37:30 +0000 -Subject: [PATCH 28/30] dell/e6*30: disable the ME device in devicetree - -we neuter anyway. disabling it in devicetree will prevent linux -from ever trying to use it or load a driver for it, and thus -might prevent benign error messages from appearing in dmesg. - -this change was suggested by nicholas when asked on irc. - -Signed-off-by: Leah Rowe <info@minifree.org> ---- - src/mainboard/dell/e6430/devicetree.cb | 4 ++-- - src/mainboard/dell/e6530/devicetree.cb | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/mainboard/dell/e6430/devicetree.cb b/src/mainboard/dell/e6430/devicetree.cb -index 054b01c5ac..2b8574c984 100644 ---- a/src/mainboard/dell/e6430/devicetree.cb -+++ b/src/mainboard/dell/e6430/devicetree.cb -@@ -39,10 +39,10 @@ chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. - register "xhci_switchable_ports" = "0x0000000f" - - device ref xhci on end -- device ref mei1 on end -+ device ref mei1 off end - device ref mei2 off end - device ref me_ide_r off end -- device ref me_kt on end -+ device ref me_kt off end - device ref gbe on end - device ref ehci2 on end - device ref hda on end -diff --git a/src/mainboard/dell/e6530/devicetree.cb b/src/mainboard/dell/e6530/devicetree.cb -index 37135bcf0f..010200bb6d 100644 ---- a/src/mainboard/dell/e6530/devicetree.cb -+++ b/src/mainboard/dell/e6530/devicetree.cb -@@ -39,10 +39,10 @@ chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. - register "xhci_switchable_ports" = "0x0000000f" - - device ref xhci on end # USB 3.0 Controller -- device ref mei1 on end # Management Engine Interface 1 -+ device ref mei1 off end # Management Engine Interface 1 - device ref mei2 off end # Management Engine Interface 2 - device ref me_ide_r off end # Management Engine IDE-R -- device ref me_kt on end # Management Engine KT -+ device ref me_kt off end # Management Engine KT - device ref gbe on end # Intel Gigabit Ethernet - device ref ehci2 on end # USB2 EHCI #2 - device ref hda on end # High Definition Audio --- -2.39.2 - diff --git a/config/coreboot/default/patches/0029-use-own-mirror-for-acpica-files.patch b/config/coreboot/default/patches/0029-use-own-mirror-for-acpica-files.patch new file mode 100644 index 00000000..97d7def5 --- /dev/null +++ b/config/coreboot/default/patches/0029-use-own-mirror-for-acpica-files.patch @@ -0,0 +1,29 @@ +From 5b425149a2ba0d1c044c32f5e16ba4d4e59796a8 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <info@minifree.org> +Date: Wed, 31 Jul 2024 00:03:02 +0100 +Subject: [PATCH 29/65] use own mirror for acpica files + +intel likes to break links for no reason, +so we host our own backups of acpica. + +Signed-off-by: Leah Rowe <info@minifree.org> +--- + util/crossgcc/buildgcc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc +index ad756652ed..5faff337b4 100755 +--- a/util/crossgcc/buildgcc ++++ b/util/crossgcc/buildgcc +@@ -74,7 +74,7 @@ MPFR_BASE_URL="https://ftpmirror.gnu.org/mpfr" + MPC_BASE_URL="https://ftpmirror.gnu.org/mpc" + GCC_BASE_URL="https://ftpmirror.gnu.org/gcc/gcc-${GCC_VERSION}" + BINUTILS_BASE_URL="https://ftpmirror.gnu.org/binutils" +-IASL_BASE_URL="https://downloadmirror.intel.com/783534" ++IASL_BASE_URL="https://www.mirrorservice.org/sites/libreboot.org/release/misc/acpica" + # CLANG toolchain archive locations + LLVM_BASE_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}" + CLANG_BASE_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}" +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0023-crank-up-vram-allocation-on-more-intel-boards.patch b/config/coreboot/default/patches/0030-crank-up-vram-allocation-on-more-intel-boards.patch index 7701babf..fbf7962d 100644 --- a/config/coreboot/default/patches/0023-crank-up-vram-allocation-on-more-intel-boards.patch +++ b/config/coreboot/default/patches/0030-crank-up-vram-allocation-on-more-intel-boards.patch @@ -1,7 +1,7 @@ -From ad812d008d570c1655bff13a9026f39a9efdcbc9 Mon Sep 17 00:00:00 2001 +From 253f8eeb895e50b3394b58268594acf9e9596bd2 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Tue, 31 Oct 2023 18:24:39 +0000 -Subject: [PATCH 23/30] crank up vram allocation on more intel boards +Subject: [PATCH 30/65] crank up vram allocation on more intel boards these were added to libreboot, and it's a policy of libreboot to max out the vram settings. this was @@ -24,20 +24,20 @@ Signed-off-by: Leah Rowe <leah@libreboot.org> 12 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/mainboard/dell/e6400/cmos.default b/src/mainboard/dell/e6400/cmos.default -index eeb6f47364..25dfa38cb5 100644 +index 744a599708..6b8d478f06 100644 --- a/src/mainboard/dell/e6400/cmos.default +++ b/src/mainboard/dell/e6400/cmos.default -@@ -2,4 +2,4 @@ boot_option=Fallback +@@ -4,4 +4,4 @@ boot_option=Fallback debug_level=Debug power_on_after_fail=Disable sata_mode=AHCI -gfx_uma_size=32M +gfx_uma_size=256M diff --git a/src/mainboard/dell/snb_ivb_workstations/cmos.default b/src/mainboard/dell/snb_ivb_workstations/cmos.default -index ccc7e64625..7c97b84baf 100644 +index 76c16e6a8d..19364aae6e 100644 --- a/src/mainboard/dell/snb_ivb_workstations/cmos.default +++ b/src/mainboard/dell/snb_ivb_workstations/cmos.default -@@ -3,5 +3,5 @@ debug_level=Debug +@@ -5,5 +5,5 @@ debug_level=Debug power_on_after_fail=Disable nmi=Enable sata_mode=AHCI @@ -45,10 +45,10 @@ index ccc7e64625..7c97b84baf 100644 +gfx_uma_size=224M fan_full_speed=Disable diff --git a/src/mainboard/hp/compaq_8200_elite_sff/cmos.default b/src/mainboard/hp/compaq_8200_elite_sff/cmos.default -index 6d27a79c66..4517ffc7c2 100644 +index 497ae92e1f..64d43a07f7 100644 --- a/src/mainboard/hp/compaq_8200_elite_sff/cmos.default +++ b/src/mainboard/hp/compaq_8200_elite_sff/cmos.default -@@ -3,5 +3,5 @@ debug_level=Debug +@@ -5,5 +5,5 @@ debug_level=Debug power_on_after_fail=Enable nmi=Enable sata_mode=AHCI @@ -56,87 +56,87 @@ index 6d27a79c66..4517ffc7c2 100644 +gfx_uma_size=224M psu_fan_lvl=3 diff --git a/src/mainboard/hp/compaq_elite_8300_usdt/cmos.default b/src/mainboard/hp/compaq_elite_8300_usdt/cmos.default -index 6f3cec735e..9fc4db2990 100644 +index f3dad88670..b60f28447b 100644 --- a/src/mainboard/hp/compaq_elite_8300_usdt/cmos.default +++ b/src/mainboard/hp/compaq_elite_8300_usdt/cmos.default -@@ -3,4 +3,4 @@ debug_level=Debug +@@ -5,4 +5,4 @@ debug_level=Debug power_on_after_fail=Enable nmi=Enable sata_mode=AHCI -gfx_uma_size=32M +gfx_uma_size=224M diff --git a/src/mainboard/hp/snb_ivb_laptops/cmos.default b/src/mainboard/hp/snb_ivb_laptops/cmos.default -index ad822d5043..89418a4cfc 100644 +index e6042c0c27..a04026b70c 100644 --- a/src/mainboard/hp/snb_ivb_laptops/cmos.default +++ b/src/mainboard/hp/snb_ivb_laptops/cmos.default -@@ -3,3 +3,4 @@ debug_level=Debug +@@ -5,3 +5,4 @@ debug_level=Debug power_on_after_fail=Disable nmi=Enable sata_mode=AHCI +gfx_uma_size=224M diff --git a/src/mainboard/lenovo/t420/cmos.default b/src/mainboard/lenovo/t420/cmos.default -index c011867916..83f590d39d 100644 +index 27a62d07b3..d1c9fcaaaf 100644 --- a/src/mainboard/lenovo/t420/cmos.default +++ b/src/mainboard/lenovo/t420/cmos.default -@@ -15,3 +15,4 @@ trackpoint=Enable +@@ -17,3 +17,4 @@ trackpoint=Enable hybrid_graphics_mode=Integrated Only usb_always_on=Disable me_state=Disabled +gfx_uma_size=224M diff --git a/src/mainboard/lenovo/t420s/cmos.default b/src/mainboard/lenovo/t420s/cmos.default -index c011867916..83f590d39d 100644 +index 27a62d07b3..d1c9fcaaaf 100644 --- a/src/mainboard/lenovo/t420s/cmos.default +++ b/src/mainboard/lenovo/t420s/cmos.default -@@ -15,3 +15,4 @@ trackpoint=Enable +@@ -17,3 +17,4 @@ trackpoint=Enable hybrid_graphics_mode=Integrated Only usb_always_on=Disable me_state=Disabled +gfx_uma_size=224M diff --git a/src/mainboard/lenovo/t430/cmos.default b/src/mainboard/lenovo/t430/cmos.default -index 55e1e6c04e..a72108f47e 100644 +index 6d1e172056..c00b358314 100644 --- a/src/mainboard/lenovo/t430/cmos.default +++ b/src/mainboard/lenovo/t430/cmos.default -@@ -16,3 +16,4 @@ backlight=Both +@@ -18,3 +18,4 @@ backlight=Both usb_always_on=Disable hybrid_graphics_mode=Integrated Only me_state=Disabled +gfx_uma_size=224M diff --git a/src/mainboard/lenovo/t520/cmos.default b/src/mainboard/lenovo/t520/cmos.default -index b66f7034dc..a73ea6e9ee 100644 +index ab1be1a678..c7ee9564f3 100644 --- a/src/mainboard/lenovo/t520/cmos.default +++ b/src/mainboard/lenovo/t520/cmos.default -@@ -16,3 +16,4 @@ backlight=Both +@@ -18,3 +18,4 @@ backlight=Both hybrid_graphics_mode=Integrated Only usb_always_on=Disable me_state=Disabled +gfx_uma_size=224M diff --git a/src/mainboard/lenovo/t530/cmos.default b/src/mainboard/lenovo/t530/cmos.default -index b66f7034dc..a73ea6e9ee 100644 +index ab1be1a678..c7ee9564f3 100644 --- a/src/mainboard/lenovo/t530/cmos.default +++ b/src/mainboard/lenovo/t530/cmos.default -@@ -16,3 +16,4 @@ backlight=Both +@@ -18,3 +18,4 @@ backlight=Both hybrid_graphics_mode=Integrated Only usb_always_on=Disable me_state=Disabled +gfx_uma_size=224M diff --git a/src/mainboard/lenovo/x201/cmos.default b/src/mainboard/lenovo/x201/cmos.default -index 2cf484fd5a..46294d91ca 100644 +index 94f8e08a75..a1f2eacf11 100644 --- a/src/mainboard/lenovo/x201/cmos.default +++ b/src/mainboard/lenovo/x201/cmos.default -@@ -15,3 +15,4 @@ power_management_beeps=Enable +@@ -17,3 +17,4 @@ power_management_beeps=Enable low_battery_beep=Enable sata_mode=AHCI usb_always_on=Disable +gfx_uma_size=128M diff --git a/src/mainboard/lenovo/x220/cmos.default b/src/mainboard/lenovo/x220/cmos.default -index 52f303dfdb..92a2026542 100644 +index b318ab9772..82292ea5d6 100644 --- a/src/mainboard/lenovo/x220/cmos.default +++ b/src/mainboard/lenovo/x220/cmos.default -@@ -14,3 +14,4 @@ fn_ctrl_swap=Disable +@@ -16,3 +16,4 @@ fn_ctrl_swap=Disable sticky_fn=Disable trackpoint=Enable me_state=Disabled +gfx_uma_size=224M -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0024-dell-e6430-use-ME-Soft-Temporary-Disable.patch b/config/coreboot/default/patches/0031-dell-e6430-use-ME-Soft-Temporary-Disable.patch index 79ee4b6c..ed0a7a08 100644 --- a/config/coreboot/default/patches/0024-dell-e6430-use-ME-Soft-Temporary-Disable.patch +++ b/config/coreboot/default/patches/0031-dell-e6430-use-ME-Soft-Temporary-Disable.patch @@ -1,7 +1,7 @@ -From a9ab864aee1be7a03926443ddc94e4c5012719ba Mon Sep 17 00:00:00 2001 +From 7b1caf7260ab468fa2f0e6d73090c5412bc0254d Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Sun, 5 Nov 2023 11:41:41 +0000 -Subject: [PATCH 24/30] dell/e6430: use ME Soft Temporary Disable +Subject: [PATCH 31/65] dell/e6430: use ME Soft Temporary Disable i overlooked this. it's set on other boards. @@ -12,13 +12,13 @@ disablement, to absolutely ensure Intel ME is not alive Signed-off-by: Leah Rowe <leah@libreboot.org> --- - src/mainboard/dell/e6430/cmos.default | 2 +- + src/mainboard/dell/snb_ivb_latitude/cmos.default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/src/mainboard/dell/e6430/cmos.default b/src/mainboard/dell/e6430/cmos.default +diff --git a/src/mainboard/dell/snb_ivb_latitude/cmos.default b/src/mainboard/dell/snb_ivb_latitude/cmos.default index 2a5b30f2b7..279415dfd1 100644 ---- a/src/mainboard/dell/e6430/cmos.default -+++ b/src/mainboard/dell/e6430/cmos.default +--- a/src/mainboard/dell/snb_ivb_latitude/cmos.default ++++ b/src/mainboard/dell/snb_ivb_latitude/cmos.default @@ -6,4 +6,4 @@ bluetooth=Enable wwan=Enable wlan=Enable @@ -26,5 +26,5 @@ index 2a5b30f2b7..279415dfd1 100644 -me_state=Normal +me_state=Disabled -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0031-mb-dell-Add-OptiPlex-7020-9020-port_cb55232_31.patch b/config/coreboot/default/patches/0031-mb-dell-Add-OptiPlex-7020-9020-port_cb55232_31.patch deleted file mode 100644 index 3b4d8004..00000000 --- a/config/coreboot/default/patches/0031-mb-dell-Add-OptiPlex-7020-9020-port_cb55232_31.patch +++ /dev/null @@ -1,923 +0,0 @@ -From 38a713eb071dd9c1b7d5092ce686537e5d9266f5 Mon Sep 17 00:00:00 2001 -From: Mate Kukri <kukri.mate@gmail.com> -Date: Mon, 4 Dec 2023 21:34:18 +0000 -Subject: [PATCH 1/1] mb/dell: Add OptiPlex 7020/9020 port -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The OptiPlex 7020 and 9020 use physically identical motherboards. - -Each model comes in the following form factors: -- 7020: SFF, MT -- 9020: USFF (not currently supported), SFF, MT - -(7020 SFF) Boots Linux and Windows 10: -- Tested with an i3-4160 and i5-4460 -- DRAM init works using the MRC (4G, 4G+4G) -- iGPU init works using libgfxinit (VGA, 2x DP) -- PCIe 16x: tested, ok -- PCIe 4x: tested, ok -- All USB2 and USB3 ports work -- SMSC SCH5555 Super I/O: serial works, PS/2 untested -- Audio: back and front output works, internal speaker works, - mic inputs untested -- Ethernet: tested, works - -(9020 MT) -- Tested by Michael Büchler (thanks for the overridetree) - -Change-Id: Ie7c7089f443aef9890711c4412209bceb1f1e96a -Signed-off-by: Mate Kukri <kukri.mate@gmail.com> ---- - src/mainboard/dell/optiplex_9020/Kconfig | 34 +++ - src/mainboard/dell/optiplex_9020/Kconfig.name | 11 + - src/mainboard/dell/optiplex_9020/Makefile.inc | 5 + - src/mainboard/dell/optiplex_9020/acpi/ec.asl | 3 + - .../dell/optiplex_9020/acpi/platform.asl | 11 + - .../dell/optiplex_9020/acpi/superio.asl | 3 + - .../dell/optiplex_9020/board_info.txt | 8 + - src/mainboard/dell/optiplex_9020/bootblock.c | 116 ++++++++++ - src/mainboard/dell/optiplex_9020/cmos.default | 4 + - src/mainboard/dell/optiplex_9020/cmos.layout | 58 +++++ - src/mainboard/dell/optiplex_9020/data.vbt | Bin 0 -> 4409 bytes - .../dell/optiplex_9020/devicetree.cb | 80 +++++++ - src/mainboard/dell/optiplex_9020/dsdt.asl | 25 ++ - .../dell/optiplex_9020/gma-mainboard.ads | 18 ++ - src/mainboard/dell/optiplex_9020/gpio.c | 217 ++++++++++++++++++ - src/mainboard/dell/optiplex_9020/hda_verb.c | 27 +++ - src/mainboard/dell/optiplex_9020/mainboard.c | 15 ++ - .../dell/optiplex_9020/overridetree_mt.cb | 10 + - src/mainboard/dell/optiplex_9020/romstage.c | 53 +++++ - 19 files changed, 698 insertions(+) - create mode 100644 src/mainboard/dell/optiplex_9020/Kconfig - create mode 100644 src/mainboard/dell/optiplex_9020/Kconfig.name - create mode 100644 src/mainboard/dell/optiplex_9020/Makefile.inc - create mode 100644 src/mainboard/dell/optiplex_9020/acpi/ec.asl - create mode 100644 src/mainboard/dell/optiplex_9020/acpi/platform.asl - create mode 100644 src/mainboard/dell/optiplex_9020/acpi/superio.asl - create mode 100644 src/mainboard/dell/optiplex_9020/board_info.txt - create mode 100644 src/mainboard/dell/optiplex_9020/bootblock.c - create mode 100644 src/mainboard/dell/optiplex_9020/cmos.default - create mode 100644 src/mainboard/dell/optiplex_9020/cmos.layout - create mode 100644 src/mainboard/dell/optiplex_9020/data.vbt - create mode 100644 src/mainboard/dell/optiplex_9020/devicetree.cb - create mode 100644 src/mainboard/dell/optiplex_9020/dsdt.asl - create mode 100644 src/mainboard/dell/optiplex_9020/gma-mainboard.ads - create mode 100644 src/mainboard/dell/optiplex_9020/gpio.c - create mode 100644 src/mainboard/dell/optiplex_9020/hda_verb.c - create mode 100644 src/mainboard/dell/optiplex_9020/mainboard.c - create mode 100644 src/mainboard/dell/optiplex_9020/overridetree_mt.cb - create mode 100644 src/mainboard/dell/optiplex_9020/romstage.c - -diff --git a/src/mainboard/dell/optiplex_9020/Kconfig b/src/mainboard/dell/optiplex_9020/Kconfig -new file mode 100644 -index 0000000000..774a72f161 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/Kconfig -@@ -0,0 +1,34 @@ -+## SPDX-License-Identifier: GPL-2.0-only -+ -+if BOARD_DELL_OPTIPLEX_9020_SFF || BOARD_DELL_OPTIPLEX_9020_MT -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ select BOARD_ROMSIZE_KB_12288 -+ select HAVE_ACPI_RESUME -+ select HAVE_ACPI_TABLES -+ select HAVE_OPTION_TABLE -+ select HAVE_CMOS_DEFAULT -+ select INTEL_GMA_HAVE_VBT -+ select INTEL_INT15 -+ select MAINBOARD_HAS_LIBGFXINIT -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select NORTHBRIDGE_INTEL_HASWELL -+ select SERIRQ_CONTINUOUS_MODE -+ select SOUTHBRIDGE_INTEL_LYNXPOINT -+ select SUPERIO_SMSC_SCH555x -+ -+config CBFS_SIZE -+ default 0x600000 -+ -+config MAINBOARD_DIR -+ default "dell/optiplex_9020" -+ -+config MAINBOARD_PART_NUMBER -+ default "OptiPlex 7020/9020 SFF" if BOARD_DELL_OPTIPLEX_9020_SFF -+ default "OptiPlex 7020/9020 MT" if BOARD_DELL_OPTIPLEX_9020_MT -+ -+config OVERRIDE_DEVICETREE -+ default "overridetree_mt.cb" if BOARD_DELL_OPTIPLEX_9020_MT -+ -+endif -diff --git a/src/mainboard/dell/optiplex_9020/Kconfig.name b/src/mainboard/dell/optiplex_9020/Kconfig.name -new file mode 100644 -index 0000000000..c25c330a44 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/Kconfig.name -@@ -0,0 +1,11 @@ -+## SPDX-License-Identifier: GPL-2.0-only -+ -+config BOARD_DELL_OPTIPLEX_9020_SFF -+ bool "OptiPlex 7020/9020 SFF" -+ help -+ The 7020 SFF and 9020 SFF mainboards are physically identical. -+ -+config BOARD_DELL_OPTIPLEX_9020_MT -+ bool "OptiPlex 7020/9020 MT" -+ help -+ The 7020 MT and 9020 MT mainboards are physically identical. -diff --git a/src/mainboard/dell/optiplex_9020/Makefile.inc b/src/mainboard/dell/optiplex_9020/Makefile.inc -new file mode 100644 -index 0000000000..6ca2f2afaa ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/Makefile.inc -@@ -0,0 +1,5 @@ -+## SPDX-License-Identifier: GPL-2.0-only -+ -+romstage-y += gpio.c -+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads -+bootblock-y += bootblock.c -diff --git a/src/mainboard/dell/optiplex_9020/acpi/ec.asl b/src/mainboard/dell/optiplex_9020/acpi/ec.asl -new file mode 100644 -index 0000000000..16990d45f4 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/acpi/ec.asl -@@ -0,0 +1,3 @@ -+/* SPDX-License-Identifier: CC-PDDC */ -+ -+/* Please update the license if adding licensable material. */ -diff --git a/src/mainboard/dell/optiplex_9020/acpi/platform.asl b/src/mainboard/dell/optiplex_9020/acpi/platform.asl -new file mode 100644 -index 0000000000..cda7682e3e ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/acpi/platform.asl -@@ -0,0 +1,11 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Method(_WAK, 1) -+{ -+ Return(Package() { 0, 0 }) -+} -+ -+Method(_PTS, 1) -+{ -+ -+} -diff --git a/src/mainboard/dell/optiplex_9020/acpi/superio.asl b/src/mainboard/dell/optiplex_9020/acpi/superio.asl -new file mode 100644 -index 0000000000..16990d45f4 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/acpi/superio.asl -@@ -0,0 +1,3 @@ -+/* SPDX-License-Identifier: CC-PDDC */ -+ -+/* Please update the license if adding licensable material. */ -diff --git a/src/mainboard/dell/optiplex_9020/board_info.txt b/src/mainboard/dell/optiplex_9020/board_info.txt -new file mode 100644 -index 0000000000..e30cf9c41f ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/board_info.txt -@@ -0,0 +1,8 @@ -+Vendor name: Dell Inc. -+Board name: OptiPlex 7020/9020 -+Release year: 2014 -+Category: desktop -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -diff --git a/src/mainboard/dell/optiplex_9020/bootblock.c b/src/mainboard/dell/optiplex_9020/bootblock.c -new file mode 100644 -index 0000000000..2837cf9cf1 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/bootblock.c -@@ -0,0 +1,116 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <arch/io.h> -+#include <device/pnp_ops.h> -+#include <superio/smsc/sch555x/sch555x.h> -+#include <southbridge/intel/lynxpoint/pch.h> -+ -+static void ec_write(uint8_t addr1, uint16_t addr2, uint8_t val) -+{ -+ // Clear EC-to-Host mailbox -+ uint8_t tmp = inb(SCH555x_EMI_IOBASE + 1); -+ outb(tmp, SCH555x_EMI_IOBASE + 1); -+ -+ // Send address and value to the EC -+ sch555x_emi_write16(0, (addr1 * 2) | 0x101); -+ sch555x_emi_write32(4, val | (addr2 << 16)); -+ -+ // Wait for acknowledgement message from EC -+ outb(1, SCH555x_EMI_IOBASE); -+ size_t timeout = 0; -+ do {} while (++timeout < 0xfff && (inb(SCH555x_EMI_IOBASE + 1) & 1) == 0); -+} -+ -+struct ec_init_entry { -+ uint16_t addr; -+ uint8_t val; -+}; -+ -+static void ec_init(void) -+{ -+ /* -+ * Tables from CORE_PEI -+ */ -+ -+ static const struct ec_init_entry init_table1[] = { -+ {0x08cc, 0x11}, {0x08d0, 0x11}, {0x088c, 0x10}, {0x0890, 0x10}, -+ {0x0894, 0x10}, {0x0898, 0x12}, {0x089c, 0x12}, {0x08a0, 0x10}, -+ {0x08a4, 0x12}, {0x08a8, 0x10}, {0x0820, 0x12}, {0x0824, 0x12}, -+ {0x0878, 0x12}, {0x0880, 0x12}, {0x0884, 0x12}, {0x08e0, 0x12}, -+ {0x08e4, 0x12}, {0x083c, 0x10}, {0x0840, 0x10}, {0x0844, 0x10}, -+ {0x0848, 0x10}, {0x084c, 0x10}, {0x0850, 0x10}, {0x0814, 0x11}, -+ }; -+ -+ for (size_t i = 0; i < ARRAY_SIZE(init_table1); ++i) -+ ec_write(2, init_table1[i].addr, init_table1[i].val); -+ -+ static const struct ec_init_entry init_table2[] = { -+ {0x0005, 0x33}, {0x0018, 0x2f}, {0x0019, 0x2f}, {0x001a, 0x2f}, -+ {0x0083, 0xbb}, {0x0085, 0xd9}, {0x0086, 0x2c}, {0x008a, 0x34}, -+ {0x008b, 0x60}, {0x0090, 0x5e}, {0x0091, 0x5e}, {0x0092, 0x86}, -+ {0x0096, 0xa4}, {0x0097, 0xa4}, {0x0098, 0xa4}, {0x009b, 0xa4}, -+ {0x00a0, 0x0a}, {0x00a1, 0x0a}, {0x00ae, 0x7c}, {0x00af, 0x7c}, -+ {0x00b0, 0x9e}, {0x00b3, 0x7c}, {0x00b6, 0x08}, {0x00b7, 0x08}, -+ {0x00ea, 0x64}, {0x00ef, 0xff}, {0x00f8, 0x15}, {0x00f9, 0x00}, -+ {0x00f0, 0x30}, {0x00fd, 0x01}, {0x01a1, 0x00}, {0x01a2, 0x00}, -+ {0x01b1, 0x08}, {0x01be, 0x90}, {0x0280, 0x24}, {0x0281, 0x13}, -+ {0x0282, 0x03}, {0x0283, 0x0a}, {0x0284, 0x80}, {0x0285, 0x03}, -+ {0x0288, 0x80}, {0x0289, 0x0c}, {0x028a, 0x03}, {0x028b, 0x0a}, -+ {0x028c, 0x80}, {0x028d, 0x03}, {0x0040, 0x01}, -+ }; -+ -+ for (size_t i = 0; i < ARRAY_SIZE(init_table2); ++i) -+ ec_write(1, init_table2[i].addr, init_table2[i].val); -+ -+ /* -+ * Table from PeiHwmInit -+ */ -+ -+ static const struct ec_init_entry hwm_init_table[] = { -+ {0x02fc, 0xa0}, {0x02fd, 0x32}, {0x0005, 0x77}, {0x0019, 0x2f}, -+ {0x001a, 0x2f}, {0x008a, 0x33}, {0x008b, 0x33}, {0x008c, 0x33}, -+ {0x00ba, 0x10}, {0x00d1, 0xff}, {0x00d6, 0xff}, {0x00db, 0xff}, -+ {0x0048, 0x00}, {0x0049, 0x00}, {0x007a, 0x00}, {0x007b, 0x00}, -+ {0x007c, 0x00}, {0x0080, 0x00}, {0x0081, 0x00}, {0x0082, 0x00}, -+ {0x0083, 0xbb}, {0x0084, 0xb0}, {0x01a1, 0x88}, {0x01a4, 0x80}, -+ {0x0088, 0x00}, {0x0089, 0x00}, {0x00a0, 0x02}, {0x00a1, 0x02}, -+ {0x00a2, 0x02}, {0x00a4, 0x04}, {0x00a5, 0x04}, {0x00a6, 0x04}, -+ {0x00ab, 0x00}, {0x00ad, 0x3f}, {0x00b7, 0x07}, {0x0062, 0x50}, -+ {0x0000, 0x46}, {0x0000, 0x50}, {0x0000, 0x46}, {0x0000, 0x50}, -+ {0x0000, 0x46}, {0x0000, 0x98}, {0x0059, 0x98}, {0x0061, 0x7c}, -+ {0x01bc, 0x00}, {0x01bd, 0x00}, {0x01bb, 0x00}, {0x0085, 0xdd}, -+ {0x0086, 0xdd}, {0x0087, 0x07}, {0x0090, 0x82}, {0x0091, 0x5e}, -+ {0x0095, 0x5d}, {0x0096, 0xa9}, {0x0097, 0x00}, {0x009b, 0x00}, -+ {0x00ae, 0x86}, {0x00af, 0x86}, {0x00b3, 0x67}, {0x00c4, 0xff}, -+ {0x00c5, 0xff}, {0x00c9, 0xff}, {0x0040, 0x01}, {0x02fc, 0x00}, -+ {0x02b3, 0x9a}, {0x02b4, 0x05}, {0x02cc, 0x01}, {0x02d0, 0x4c}, -+ {0x02d2, 0x01}, {0x02db, 0x01}, {0x006f, 0x01}, {0x0070, 0x02}, -+ {0x0071, 0x03}, {0x018b, 0x03}, {0x018c, 0x03}, -+ }; -+ -+ for (size_t i = 0; i < ARRAY_SIZE(hwm_init_table); ++i) -+ ec_write(1, hwm_init_table[i].addr, hwm_init_table[i].val); -+} -+ -+#define SCH555x_IOBASE 0x2e -+#define GLOBAL_DEV PNP_DEV(SCH555x_IOBASE, SCH555x_LDN_GLOBAL) -+#define SERIAL_DEV PNP_DEV(SCH555x_IOBASE, SCH555x_LDN_UART1) -+ -+void mainboard_config_superio(void) -+{ -+ // Super I/O early init will map Runtime and EMI registers -+ sch555x_early_init(GLOBAL_DEV); -+ -+ // Changes LED color among a few other things (extracted from Dell's FW) -+ outb(0x01, SCH555x_RUNTIME_IOBASE + SCH555x_RUNTIME_PME_STS); -+ outb(0x00, SCH555x_RUNTIME_IOBASE + SCH555x_RUNTIME_PME_EN); -+ outb(0x18, SCH555x_RUNTIME_IOBASE + SCH555x_RUNTIME_PME_EN1); -+ outb(0x01, SCH555x_RUNTIME_IOBASE + SCH555x_RUNTIME_UNK1); -+ outb(0x0f, SCH555x_RUNTIME_IOBASE + SCH555x_RUNTIME_LED); -+ -+ // Magic EC init -+ ec_init(); -+ -+ // Magic EC init is needed for UART1 initialization to work -+ sch555x_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); -+} -diff --git a/src/mainboard/dell/optiplex_9020/cmos.default b/src/mainboard/dell/optiplex_9020/cmos.default -new file mode 100644 -index 0000000000..b159660aa8 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/cmos.default -@@ -0,0 +1,4 @@ -+boot_option=Fallback -+debug_level=Debug -+nmi=Disable -+power_on_after_fail=Disable -diff --git a/src/mainboard/dell/optiplex_9020/cmos.layout b/src/mainboard/dell/optiplex_9020/cmos.layout -new file mode 100644 -index 0000000000..c9ba76c78f ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/cmos.layout -@@ -0,0 +1,58 @@ -+## SPDX-License-Identifier: GPL-2.0-only -+ -+# ----------------------------------------------------------------- -+entries -+ -+# ----------------------------------------------------------------- -+0 120 r 0 reserved_memory -+ -+# ----------------------------------------------------------------- -+# RTC_BOOT_BYTE (coreboot hardcoded) -+384 1 e 3 boot_option -+388 4 h 0 reboot_counter -+ -+# ----------------------------------------------------------------- -+# coreboot config options: console -+395 4 e 4 debug_level -+ -+#400 8 r 0 reserved for century byte -+ -+# coreboot config options: southbridge -+408 1 e 1 nmi -+409 2 e 5 power_on_after_fail -+ -+# 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 -+ -+3 0 Fallback -+3 1 Normal -+ -+4 0 Emergency -+4 1 Alert -+4 2 Critical -+4 3 Error -+4 4 Warning -+4 5 Notice -+4 6 Info -+4 7 Debug -+4 8 Spew -+ -+5 0 Disable -+5 1 Enable -+5 2 Keep -+ -+# ----------------------------------------------------------------- -+checksums -+ -+checksum 392 415 984 -diff --git a/src/mainboard/dell/optiplex_9020/data.vbt b/src/mainboard/dell/optiplex_9020/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..1779f3b8d1018ba0aae480103b145bd7b6dd6187 -GIT binary patch -literal 4409 -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 -PTo#&U0FLJAf1&;f?(g8r - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/optiplex_9020/devicetree.cb b/src/mainboard/dell/optiplex_9020/devicetree.cb -new file mode 100644 -index 0000000000..c0b17a15ff ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/devicetree.cb -@@ -0,0 +1,80 @@ -+## SPDX-License-Identifier: GPL-2.0-only -+ -+chip northbridge/intel/haswell -+ # This mainboard has VGA -+ register "gpu_ddi_e_connected" = "1" -+ -+ chip cpu/intel/haswell -+ device cpu_cluster 0 on ops haswell_cpu_bus_ops end -+ end -+ -+ device domain 0 on -+ ops haswell_pci_domain_ops -+ -+ subsystemid 0x1028 0x05a5 inherit -+ -+ device pci 00.0 on end # Host bridge -+ device pci 01.0 on end # PCIe graphics -+ device pci 02.0 on end # VGA controller -+ device pci 03.0 on end # Mini-HD audio -+ -+ chip southbridge/intel/lynxpoint -+ register "gen1_dec" = "0x007c0a01" -+ register "gen2_dec" = "0x007c0901" -+ register "gen3_dec" = "0x003c07e1" -+ register "gen4_dec" = "0x001c0901" -+ register "sata_port_map" = "0x33" -+ -+ device pci 14.0 on end # xHCI controller -+ device pci 16.0 on end # Management Engine interface 1 -+ device pci 16.1 off end # Management Engine interface 2 -+ device pci 16.2 off end # Management Engine IDE-R -+ device pci 16.3 on end # Management Engine KT -+ device pci 19.0 on # Intel Gigabit Ethernet -+ subsystemid 0x1028 0x05a4 -+ end -+ device pci 1a.0 on end # EHCI controller #2 -+ device pci 1b.0 on end # HD audio controller -+ device pci 1c.0 off end -+ device pci 1c.1 off end -+ device pci 1c.2 off end -+ device pci 1c.3 off end -+ device pci 1c.4 on end # PCIe 4x slot -+ device pci 1c.5 off end -+ device pci 1c.6 off end -+ device pci 1c.7 off end -+ device pci 1d.0 on end # EHCI controller #1 -+ device pci 1f.0 on # LPC bridge -+ chip superio/smsc/sch555x -+ device pnp 2e.0 on # EMI -+ io 0x60 = 0xa00 -+ end -+ device pnp 2e.1 on # 8042 -+ io 0x60 = 0x60 -+ irq 0x0f = 0 -+ irq 0x70 = 1 -+ irq 0x72 = 12 -+ end -+ device pnp 2e.7 on # UART1 -+ io 0x60 = 0x3f8 -+ irq 0x0f = 2 -+ irq 0x70 = 4 -+ end -+ device pnp 2e.8 off end # UART2 -+ device pnp 2e.c on # LPC interface -+ io 0x60 = 0x2e -+ end -+ device pnp 2e.a on # Runtime registers -+ io 0x60 = 0xa40 -+ end -+ device pnp 2e.b off end # Floppy Controller -+ device pnp 2e.11 off end # Parallel Port -+ end -+ end -+ device pci 1f.2 on end # SATA controller 1 -+ device pci 1f.3 on end # SMBus -+ device pci 1f.5 off end # SATA controller 2 -+ device pci 1f.6 off end # Thermal -+ end -+ end -+end -diff --git a/src/mainboard/dell/optiplex_9020/dsdt.asl b/src/mainboard/dell/optiplex_9020/dsdt.asl -new file mode 100644 -index 0000000000..7ec1e9775a ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/dsdt.asl -@@ -0,0 +1,25 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <acpi/acpi.h> -+DefinitionBlock( -+ "dsdt.aml", -+ "DSDT", -+ ACPI_DSDT_REV_2, -+ OEM_ID, -+ ACPI_TABLE_CREATOR, -+ 0x20181031 /* OEM Revision */ -+) -+{ -+ #include <acpi/dsdt_top.asl> -+ #include "acpi/platform.asl" -+ #include <southbridge/intel/common/acpi/platform.asl> -+ #include <southbridge/intel/lynxpoint/acpi/globalnvs.asl> -+ #include <southbridge/intel/common/acpi/sleepstates.asl> -+ #include <cpu/intel/common/acpi/cpu.asl> -+ -+ Device (\_SB.PCI0) -+ { -+ #include <northbridge/intel/haswell/acpi/hostbridge.asl> -+ #include <southbridge/intel/lynxpoint/acpi/pch.asl> -+ } -+} -diff --git a/src/mainboard/dell/optiplex_9020/gma-mainboard.ads b/src/mainboard/dell/optiplex_9020/gma-mainboard.ads -new file mode 100644 -index 0000000000..173f2f1d0d ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/gma-mainboard.ads -@@ -0,0 +1,18 @@ -+-- 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 := -+ (DP1, -+ DP2, -+ DP3, -+ Analog, -+ others => Disabled); -+ -+end GMA.Mainboard; -diff --git a/src/mainboard/dell/optiplex_9020/gpio.c b/src/mainboard/dell/optiplex_9020/gpio.c -new file mode 100644 -index 0000000000..48b7707e2c ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/gpio.c -@@ -0,0 +1,217 @@ -+/* 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_GPIO, -+ .gpio6 = GPIO_MODE_GPIO, -+ .gpio7 = GPIO_MODE_GPIO, -+ .gpio8 = GPIO_MODE_GPIO, -+ .gpio9 = GPIO_MODE_NATIVE, -+ .gpio10 = GPIO_MODE_NATIVE, -+ .gpio11 = GPIO_MODE_GPIO, -+ .gpio12 = GPIO_MODE_NATIVE, -+ .gpio13 = GPIO_MODE_GPIO, -+ .gpio14 = GPIO_MODE_NATIVE, -+ .gpio15 = GPIO_MODE_GPIO, -+ .gpio16 = GPIO_MODE_NATIVE, -+ .gpio17 = GPIO_MODE_GPIO, -+ .gpio18 = GPIO_MODE_NATIVE, -+ .gpio19 = GPIO_MODE_NATIVE, -+ .gpio20 = GPIO_MODE_NATIVE, -+ .gpio21 = GPIO_MODE_GPIO, -+ .gpio22 = GPIO_MODE_GPIO, -+ .gpio23 = GPIO_MODE_GPIO, -+ .gpio24 = GPIO_MODE_GPIO, -+ .gpio25 = GPIO_MODE_GPIO, -+ .gpio26 = GPIO_MODE_GPIO, -+ .gpio27 = GPIO_MODE_GPIO, -+ .gpio28 = GPIO_MODE_GPIO, -+ .gpio29 = GPIO_MODE_NATIVE, -+ .gpio30 = GPIO_MODE_NATIVE, -+ .gpio31 = GPIO_MODE_GPIO, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_direction = { -+ .gpio0 = GPIO_DIR_INPUT, -+ .gpio1 = GPIO_DIR_INPUT, -+ .gpio2 = GPIO_DIR_INPUT, -+ .gpio3 = GPIO_DIR_INPUT, -+ .gpio4 = GPIO_DIR_INPUT, -+ .gpio5 = GPIO_DIR_INPUT, -+ .gpio6 = GPIO_DIR_INPUT, -+ .gpio7 = GPIO_DIR_INPUT, -+ .gpio8 = GPIO_DIR_INPUT, -+ .gpio11 = GPIO_DIR_INPUT, -+ .gpio13 = GPIO_DIR_OUTPUT, -+ .gpio15 = GPIO_DIR_OUTPUT, -+ .gpio17 = GPIO_DIR_INPUT, -+ .gpio21 = GPIO_DIR_INPUT, -+ .gpio22 = GPIO_DIR_OUTPUT, -+ .gpio23 = GPIO_DIR_OUTPUT, -+ .gpio24 = GPIO_DIR_INPUT, -+ .gpio25 = GPIO_DIR_OUTPUT, -+ .gpio26 = GPIO_DIR_OUTPUT, -+ .gpio27 = GPIO_DIR_INPUT, -+ .gpio28 = GPIO_DIR_OUTPUT, -+ .gpio31 = GPIO_DIR_INPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio13 = GPIO_LEVEL_LOW, -+ .gpio15 = GPIO_LEVEL_HIGH, -+ .gpio22 = GPIO_LEVEL_HIGH, -+ .gpio23 = GPIO_LEVEL_HIGH, -+ .gpio25 = GPIO_LEVEL_HIGH, -+ .gpio26 = GPIO_LEVEL_HIGH, -+ .gpio28 = GPIO_LEVEL_HIGH, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_blink = { -+ .gpio18 = GPIO_BLINK, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio8 = GPIO_INVERT, -+ .gpio9 = GPIO_INVERT, -+ .gpio11 = GPIO_INVERT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+ .gpio26 = GPIO_RESET_RSMRST, -+}; -+ -+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_NATIVE, -+ .gpio37 = GPIO_MODE_NATIVE, -+ .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_GPIO, -+ .gpio45 = GPIO_MODE_GPIO, -+ .gpio46 = GPIO_MODE_GPIO, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .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_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 = { -+ .gpio32 = GPIO_DIR_INPUT, -+ .gpio33 = GPIO_DIR_OUTPUT, -+ .gpio34 = GPIO_DIR_OUTPUT, -+ .gpio35 = GPIO_DIR_INPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio44 = GPIO_DIR_INPUT, -+ .gpio45 = GPIO_DIR_OUTPUT, -+ .gpio46 = GPIO_DIR_INPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_INPUT, -+ .gpio50 = GPIO_DIR_OUTPUT, -+ .gpio51 = GPIO_DIR_OUTPUT, -+ .gpio52 = GPIO_DIR_OUTPUT, -+ .gpio53 = GPIO_DIR_OUTPUT, -+ .gpio54 = GPIO_DIR_OUTPUT, -+ .gpio55 = GPIO_DIR_OUTPUT, -+ .gpio57 = GPIO_DIR_OUTPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio33 = GPIO_LEVEL_HIGH, -+ .gpio34 = GPIO_LEVEL_HIGH, -+ .gpio45 = GPIO_LEVEL_LOW, -+ .gpio50 = GPIO_LEVEL_HIGH, -+ .gpio51 = GPIO_LEVEL_HIGH, -+ .gpio52 = GPIO_LEVEL_HIGH, -+ .gpio53 = GPIO_LEVEL_HIGH, -+ .gpio54 = GPIO_LEVEL_HIGH, -+ .gpio55 = GPIO_LEVEL_HIGH, -+ .gpio57 = GPIO_LEVEL_HIGH, -+ .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_GPIO, -+ .gpio65 = GPIO_MODE_NATIVE, -+ .gpio66 = GPIO_MODE_GPIO, -+ .gpio67 = GPIO_MODE_NATIVE, -+ .gpio68 = GPIO_MODE_GPIO, -+ .gpio69 = GPIO_MODE_GPIO, -+ .gpio70 = GPIO_MODE_NATIVE, -+ .gpio71 = GPIO_MODE_NATIVE, -+ .gpio72 = GPIO_MODE_GPIO, -+ .gpio73 = GPIO_MODE_GPIO, -+ .gpio74 = GPIO_MODE_GPIO, -+ .gpio75 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set3 pch_gpio_set3_direction = { -+ .gpio64 = GPIO_DIR_OUTPUT, -+ .gpio66 = GPIO_DIR_OUTPUT, -+ .gpio68 = GPIO_DIR_INPUT, -+ .gpio69 = GPIO_DIR_INPUT, -+ .gpio72 = GPIO_DIR_OUTPUT, -+ .gpio73 = GPIO_DIR_INPUT, -+ .gpio74 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set3 pch_gpio_set3_level = { -+ .gpio64 = GPIO_LEVEL_HIGH, -+ .gpio66 = GPIO_LEVEL_HIGH, -+ .gpio72 = GPIO_LEVEL_HIGH, -+ .gpio74 = GPIO_LEVEL_HIGH, -+}; -+ -+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/optiplex_9020/hda_verb.c b/src/mainboard/dell/optiplex_9020/hda_verb.c -new file mode 100644 -index 0000000000..df43ade3e6 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/hda_verb.c -@@ -0,0 +1,27 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <stdint.h> -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x10ec0280, /* Realtek ALC3220 */ -+ 0x102805a5, /* Subsystem ID */ -+ 13, /* Number of entries */ -+ AZALIA_SUBVENDOR(0, 0x102805a5), -+ AZALIA_PIN_CFG(0, 0x12, 0x4008c000), -+ AZALIA_PIN_CFG(0, 0x13, 0x411111f0), -+ AZALIA_PIN_CFG(0, 0x14, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x15, 0x0221401f), -+ AZALIA_PIN_CFG(0, 0x16, 0x411111f0), -+ AZALIA_PIN_CFG(0, 0x17, 0x411111f0), -+ AZALIA_PIN_CFG(0, 0x18, 0x01a13040), -+ AZALIA_PIN_CFG(0, 0x19, 0x411111f0), -+ AZALIA_PIN_CFG(0, 0x1a, 0x02a19030), -+ AZALIA_PIN_CFG(0, 0x1b, 0x01014020), -+ AZALIA_PIN_CFG(0, 0x1d, 0x40400001), -+ AZALIA_PIN_CFG(0, 0x1e, 0x411111f0), -+}; -+ -+const u32 pc_beep_verbs[] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/dell/optiplex_9020/mainboard.c b/src/mainboard/dell/optiplex_9020/mainboard.c -new file mode 100644 -index 0000000000..c834fea5d3 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/mainboard.c -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/device.h> -+#include <drivers/intel/gma/int15.h> -+ -+static void mainboard_enable(struct device *dev) -+{ -+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_NONE, -+ GMA_INT15_PANEL_FIT_DEFAULT, -+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); -+} -+ -+struct chip_operations mainboard_ops = { -+ .enable_dev = mainboard_enable, -+}; -diff --git a/src/mainboard/dell/optiplex_9020/overridetree_mt.cb b/src/mainboard/dell/optiplex_9020/overridetree_mt.cb -new file mode 100644 -index 0000000000..90205c2d68 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/overridetree_mt.cb -@@ -0,0 +1,10 @@ -+## SPDX-License-Identifier: GPL-2.0-only -+ -+chip northbridge/intel/haswell -+ device domain 0 on -+ chip southbridge/intel/lynxpoint -+ device pci 1c.1 on end # PCI (via XIO2001 bridge) -+ device pci 1c.2 on end # PCIe 1x slot -+ end -+ end -+end -diff --git a/src/mainboard/dell/optiplex_9020/romstage.c b/src/mainboard/dell/optiplex_9020/romstage.c -new file mode 100644 -index 0000000000..2b9cdaa5fd ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/romstage.c -@@ -0,0 +1,53 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <northbridge/intel/haswell/haswell.h> -+#include <northbridge/intel/haswell/raminit.h> -+#include <southbridge/intel/lynxpoint/pch.h> -+ -+void mainboard_config_rcba(void) -+{ -+ RCBA16(D31IR) = DIR_ROUTE(PIRQA, PIRQC, PIRQD, PIRQA); -+ RCBA16(D29IR) = DIR_ROUTE(PIRQC, PIRQA, PIRQD, PIRQH); -+ RCBA16(D28IR) = DIR_ROUTE(PIRQD, PIRQC, PIRQB, PIRQA); -+ RCBA16(D27IR) = DIR_ROUTE(PIRQD, PIRQC, PIRQB, PIRQG); -+ RCBA16(D26IR) = DIR_ROUTE(PIRQD, PIRQC, PIRQF, PIRQA); -+ RCBA16(D25IR) = DIR_ROUTE(PIRQH, PIRQG, PIRQF, PIRQE); -+ RCBA16(D22IR) = DIR_ROUTE(PIRQB, PIRQC, PIRQD, PIRQA); -+ RCBA16(D20IR) = DIR_ROUTE(PIRQD, PIRQC, PIRQB, PIRQA); -+} -+ -+void mb_get_spd_map(struct spd_info *spdi) -+{ -+ spdi->addresses[0] = 0x50; -+ spdi->addresses[1] = 0x51; -+ spdi->addresses[2] = 0x52; -+ spdi->addresses[3] = 0x53; -+} -+ -+const struct usb2_port_config mainboard_usb2_ports[MAX_USB2_PORTS] = { -+ /* Length, Enable, OCn#, Location */ -+ {0x0000, 0, USB_OC_PIN_SKIP, USB_PORT_SKIP}, -+ {0x0000, 0, USB_OC_PIN_SKIP, USB_PORT_SKIP}, -+ {0x0040, 1, 1, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 2, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 3, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 3, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 0, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 0, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 4, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 4, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 5, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 5, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 6, USB_PORT_BACK_PANEL}, -+ {0x0040, 1, 7, USB_PORT_BACK_PANEL}, -+}; -+ -+const struct usb3_port_config mainboard_usb3_ports[MAX_USB3_PORTS] = { -+ /* Enable, OCn# */ -+ {1, 6}, -+ {1, 7}, -+ {0, USB_OC_PIN_SKIP}, -+ {0, USB_OC_PIN_SKIP}, -+ {1, 1}, -+ {1, 2}, -+}; --- -2.39.2 - diff --git a/config/coreboot/default/patches/0032-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch b/config/coreboot/default/patches/0032-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch deleted file mode 100644 index ddfc6571..00000000 --- a/config/coreboot/default/patches/0032-mb-dell-Add-Latitude-E6420-Sandy-Bridge.patch +++ /dev/null @@ -1,774 +0,0 @@ -From 41002e64c92e90903fa591c4a8a1cc0108833743 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] mb/dell: Add Latitude E6420 (Sandy Bridge) - -Change-Id: Ic48d9ea58172a5b13958c8afebcb19c8929c4394 -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/e6420/Kconfig | 38 ++++ - src/mainboard/dell/e6420/Kconfig.name | 2 + - src/mainboard/dell/e6420/Makefile.inc | 6 + - src/mainboard/dell/e6420/acpi/ec.asl | 9 + - src/mainboard/dell/e6420/acpi/platform.asl | 12 ++ - src/mainboard/dell/e6420/acpi/superio.asl | 3 + - src/mainboard/dell/e6420/acpi_tables.c | 16 ++ - src/mainboard/dell/e6420/board_info.txt | 6 + - src/mainboard/dell/e6420/cmos.default | 9 + - src/mainboard/dell/e6420/cmos.layout | 88 ++++++++++ - src/mainboard/dell/e6420/data.vbt | Bin 0 -> 6144 bytes - src/mainboard/dell/e6420/devicetree.cb | 66 +++++++ - src/mainboard/dell/e6420/dsdt.asl | 30 ++++ - src/mainboard/dell/e6420/early_init.c | 32 ++++ - src/mainboard/dell/e6420/gma-mainboard.ads | 20 +++ - src/mainboard/dell/e6420/gpio.c | 191 +++++++++++++++++++++ - src/mainboard/dell/e6420/hda_verb.c | 33 ++++ - src/mainboard/dell/e6420/mainboard.c | 21 +++ - 18 files changed, 582 insertions(+) - create mode 100644 src/mainboard/dell/e6420/Kconfig - create mode 100644 src/mainboard/dell/e6420/Kconfig.name - create mode 100644 src/mainboard/dell/e6420/Makefile.inc - create mode 100644 src/mainboard/dell/e6420/acpi/ec.asl - create mode 100644 src/mainboard/dell/e6420/acpi/platform.asl - create mode 100644 src/mainboard/dell/e6420/acpi/superio.asl - create mode 100644 src/mainboard/dell/e6420/acpi_tables.c - create mode 100644 src/mainboard/dell/e6420/board_info.txt - create mode 100644 src/mainboard/dell/e6420/cmos.default - create mode 100644 src/mainboard/dell/e6420/cmos.layout - create mode 100644 src/mainboard/dell/e6420/data.vbt - create mode 100644 src/mainboard/dell/e6420/devicetree.cb - create mode 100644 src/mainboard/dell/e6420/dsdt.asl - create mode 100644 src/mainboard/dell/e6420/early_init.c - create mode 100644 src/mainboard/dell/e6420/gma-mainboard.ads - create mode 100644 src/mainboard/dell/e6420/gpio.c - create mode 100644 src/mainboard/dell/e6420/hda_verb.c - create mode 100644 src/mainboard/dell/e6420/mainboard.c - -diff --git a/src/mainboard/dell/e6420/Kconfig b/src/mainboard/dell/e6420/Kconfig -new file mode 100644 -index 0000000000..cff62bf70c ---- /dev/null -+++ b/src/mainboard/dell/e6420/Kconfig -@@ -0,0 +1,38 @@ -+if BOARD_DELL_LATITUDE_E6420 -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ select BOARD_ROMSIZE_KB_10240 -+ select EC_ACPI -+ select EC_DELL_MEC5035 -+ select GFX_GMA_PANEL_1_ON_LVDS -+ select HAVE_ACPI_RESUME -+ select HAVE_ACPI_TABLES -+ select HAVE_CMOS_DEFAULT -+ select HAVE_OPTION_TABLE -+ select INTEL_GMA_HAVE_VBT -+ select INTEL_INT15 -+ select MAINBOARD_HAS_LIBGFXINIT -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select NORTHBRIDGE_INTEL_SANDYBRIDGE -+ select SERIRQ_CONTINUOUS_MODE -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ select SYSTEM_TYPE_LAPTOP -+ select USE_NATIVE_RAMINIT -+ -+config DRAM_RESET_GATE_GPIO -+ default 60 -+ -+config MAINBOARD_DIR -+ default "dell/e6420" -+ -+config MAINBOARD_PART_NUMBER -+ default "Latitude E6420" -+ -+config USBDEBUG_HCD_INDEX -+ default 2 -+ -+config VGA_BIOS_ID -+ default "8086,0126" -+ -+endif # BOARD_DELL_LATITUDE_E6420 -diff --git a/src/mainboard/dell/e6420/Kconfig.name b/src/mainboard/dell/e6420/Kconfig.name -new file mode 100644 -index 0000000000..1722891e7b ---- /dev/null -+++ b/src/mainboard/dell/e6420/Kconfig.name -@@ -0,0 +1,2 @@ -+config BOARD_DELL_LATITUDE_E6420 -+ bool "Latitude E6420" -diff --git a/src/mainboard/dell/e6420/Makefile.inc b/src/mainboard/dell/e6420/Makefile.inc -new file mode 100644 -index 0000000000..ba64e93eb8 ---- /dev/null -+++ b/src/mainboard/dell/e6420/Makefile.inc -@@ -0,0 +1,6 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+bootblock-y += early_init.c -+bootblock-y += gpio.c -+romstage-y += early_init.c -+romstage-y += gpio.c -+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads -diff --git a/src/mainboard/dell/e6420/acpi/ec.asl b/src/mainboard/dell/e6420/acpi/ec.asl -new file mode 100644 -index 0000000000..0d429410a9 ---- /dev/null -+++ b/src/mainboard/dell/e6420/acpi/ec.asl -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Device(EC) -+{ -+ Name (_HID, EISAID("PNP0C09")) -+ Name (_UID, 0) -+ Name (_GPE, 16) -+/* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e6420/acpi/platform.asl b/src/mainboard/dell/e6420/acpi/platform.asl -new file mode 100644 -index 0000000000..2d24bbd9b9 ---- /dev/null -+++ b/src/mainboard/dell/e6420/acpi/platform.asl -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Method(_WAK, 1) -+{ -+ /* FIXME: EC support */ -+ Return(Package() {0, 0}) -+} -+ -+Method(_PTS,1) -+{ -+ /* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e6420/acpi/superio.asl b/src/mainboard/dell/e6420/acpi/superio.asl -new file mode 100644 -index 0000000000..55b1db5b11 ---- /dev/null -+++ b/src/mainboard/dell/e6420/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/dell/e6420/acpi_tables.c b/src/mainboard/dell/e6420/acpi_tables.c -new file mode 100644 -index 0000000000..e2759659bf ---- /dev/null -+++ b/src/mainboard/dell/e6420/acpi_tables.c -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <acpi/acpi_gnvs.h> -+#include <soc/nvs.h> -+ -+/* FIXME: check this function. */ -+void mainboard_fill_gnvs(struct global_nvs *gnvs) -+{ -+ /* The lid is open by default. */ -+ gnvs->lids = 1; -+ -+ /* Temperature at which OS will shutdown */ -+ gnvs->tcrt = 100; -+ /* Temperature at which OS will throttle CPU */ -+ gnvs->tpsv = 90; -+} -diff --git a/src/mainboard/dell/e6420/board_info.txt b/src/mainboard/dell/e6420/board_info.txt -new file mode 100644 -index 0000000000..34d5ad9e0b ---- /dev/null -+++ b/src/mainboard/dell/e6420/board_info.txt -@@ -0,0 +1,6 @@ -+Category: laptop -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -+Release year: 2011 -diff --git a/src/mainboard/dell/e6420/cmos.default b/src/mainboard/dell/e6420/cmos.default -new file mode 100644 -index 0000000000..279415dfd1 ---- /dev/null -+++ b/src/mainboard/dell/e6420/cmos.default -@@ -0,0 +1,9 @@ -+boot_option=Fallback -+debug_level=Debug -+power_on_after_fail=Disable -+nmi=Enable -+bluetooth=Enable -+wwan=Enable -+wlan=Enable -+sata_mode=AHCI -+me_state=Disabled -diff --git a/src/mainboard/dell/e6420/cmos.layout b/src/mainboard/dell/e6420/cmos.layout -new file mode 100644 -index 0000000000..1aa7e77bce ---- /dev/null -+++ b/src/mainboard/dell/e6420/cmos.layout -@@ -0,0 +1,88 @@ -+## 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 -+ -+#400 8 r 0 reserved for century byte -+ -+# coreboot config options: southbridge -+408 1 e 1 nmi -+409 2 e 7 power_on_after_fail -+411 1 e 9 sata_mode -+ -+# coreboot config options: EC -+412 1 e 1 bluetooth -+413 1 e 1 wwan -+414 1 e 1 wlan -+ -+# coreboot config options: ME -+424 1 e 14 me_state -+425 2 h 0 me_state_prev -+ -+# coreboot config options: northbridge -+432 3 e 11 gfx_uma_size -+435 2 e 12 hybrid_graphics_mode -+440 8 h 0 volume -+ -+# VBOOT -+448 128 r 0 vbnv -+ -+# SandyBridge MRC Scrambler Seed values -+896 32 r 0 mrc_scrambler_seed -+928 32 r 0 mrc_scrambler_seed_s3 -+960 16 r 0 mrc_scrambler_seed_chk -+ -+# 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 -+9 0 AHCI -+9 1 Compatible -+11 0 32M -+11 1 64M -+11 2 96M -+11 3 128M -+11 4 160M -+11 5 192M -+11 6 224M -+14 0 Normal -+14 1 Disabled -+ -+# ----------------------------------------------------------------- -+checksums -+ -+checksum 392 447 984 -diff --git a/src/mainboard/dell/e6420/data.vbt b/src/mainboard/dell/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/e6420/devicetree.cb b/src/mainboard/dell/e6420/devicetree.cb -new file mode 100644 -index 0000000000..f9259f7175 ---- /dev/null -+++ b/src/mainboard/dell/e6420/devicetree.cb -@@ -0,0 +1,66 @@ -+chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. -+ register "gfx" = "GMA_STATIC_DISPLAYS(1)" -+ register "gpu_cpu_backlight" = "0x0000054f" -+ register "gpu_dp_b_hotplug" = "4" -+ register "gpu_dp_c_hotplug" = "4" -+ register "gpu_dp_d_hotplug" = "4" -+ register "gpu_panel_port_select" = "0" -+ register "gpu_panel_power_backlight_off_delay" = "2300" -+ register "gpu_panel_power_backlight_on_delay" = "2300" -+ register "gpu_panel_power_cycle_delay" = "6" -+ register "gpu_panel_power_down_delay" = "400" -+ register "gpu_panel_power_up_delay" = "400" -+ register "gpu_pch_backlight" = "0x13121312" -+ -+ register "spd_addresses" = "{0x50, 0, 0x52, 0}" -+ -+ device domain 0x0 on -+ subsystemid 0x1028 0x0493 inherit -+ -+ device ref host_bridge on end # Host bridge -+ device ref peg10 on end # PEG -+ device ref igd on end # iGPU -+ -+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH -+ register "docking_supported" = "1" -+ register "gen1_dec" = "0x007c0681" -+ register "gen2_dec" = "0x007c0901" -+ register "gen3_dec" = "0x003c07e1" -+ register "gen4_dec" = "0x001c0901" -+ register "gpi0_routing" = "2" -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 1, 0, 0, 0, 0 }" -+ register "pcie_port_coalesce" = "1" -+ register "sata_interface_speed_support" = "0x3" -+ register "sata_port_map" = "0x3b" -+ register "spi_lvscc" = "0x2005" -+ register "spi_uvscc" = "0x2005" -+ -+ device ref mei1 off end -+ device ref mei2 off end -+ device ref me_ide_r off end -+ device ref me_kt off end -+ device ref gbe on end -+ device ref ehci2 on end -+ device ref hda on end -+ device ref pcie_rp1 on end -+ device ref pcie_rp2 on end -+ device ref pcie_rp3 on end -+ device ref pcie_rp4 on end -+ device ref pcie_rp5 off end -+ device ref pcie_rp6 on end -+ device ref pcie_rp7 off end -+ device ref pcie_rp8 off end -+ device ref ehci1 on end -+ device ref pci_bridge off end -+ device ref lpc on -+ chip ec/dell/mec5035 -+ device pnp ff.0 on end -+ end -+ end -+ device ref sata1 on end -+ device ref smbus on end -+ device ref sata2 off end -+ device ref thermal off end -+ end -+ end -+end -diff --git a/src/mainboard/dell/e6420/dsdt.asl b/src/mainboard/dell/e6420/dsdt.asl -new file mode 100644 -index 0000000000..7d13c55b08 ---- /dev/null -+++ b/src/mainboard/dell/e6420/dsdt.asl -@@ -0,0 +1,30 @@ -+#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB -+#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+ -+#include <acpi/acpi.h> -+ -+DefinitionBlock( -+ "dsdt.aml", -+ "DSDT", -+ ACPI_DSDT_REV_2, -+ OEM_ID, -+ ACPI_TABLE_CREATOR, -+ 0x20141018 /* OEM revision */ -+) -+{ -+ #include <acpi/dsdt_top.asl> -+ #include "acpi/platform.asl" -+ #include <cpu/intel/common/acpi/cpu.asl> -+ #include <southbridge/intel/common/acpi/platform.asl> -+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl> -+ #include <southbridge/intel/common/acpi/sleepstates.asl> -+ -+ Device (\_SB.PCI0) -+ { -+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl> -+ #include <drivers/intel/gma/acpi/default_brightness_levels.asl> -+ #include <southbridge/intel/bd82x6x/acpi/pch.asl> -+ } -+} -diff --git a/src/mainboard/dell/e6420/early_init.c b/src/mainboard/dell/e6420/early_init.c -new file mode 100644 -index 0000000000..0682441ed6 ---- /dev/null -+++ b/src/mainboard/dell/e6420/early_init.c -@@ -0,0 +1,32 @@ -+/* 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, 1, 3 }, -+ { 1, 1, 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/e6420/gma-mainboard.ads b/src/mainboard/dell/e6420/gma-mainboard.ads -new file mode 100644 -index 0000000000..2a16f44360 ---- /dev/null -+++ b/src/mainboard/dell/e6420/gma-mainboard.ads -@@ -0,0 +1,20 @@ -+-- 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 := -+ ( -+ HDMI1, -- mainboard HDMI -+ DP2, -- dock DP -+ DP3, -- dock DP -+ Analog, -- mainboard VGA -+ LVDS, -+ others => Disabled); -+ -+end GMA.Mainboard; -diff --git a/src/mainboard/dell/e6420/gpio.c b/src/mainboard/dell/e6420/gpio.c -new file mode 100644 -index 0000000000..943c743f48 ---- /dev/null -+++ b/src/mainboard/dell/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/e6420/hda_verb.c b/src/mainboard/dell/e6420/hda_verb.c -new file mode 100644 -index 0000000000..b3803b7c65 ---- /dev/null -+++ b/src/mainboard/dell/e6420/hda_verb.c -@@ -0,0 +1,33 @@ -+/* 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/e6420/mainboard.c b/src/mainboard/dell/e6420/mainboard.c -new file mode 100644 -index 0000000000..31e49802fc ---- /dev/null -+++ b/src/mainboard/dell/e6420/mainboard.c -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/device.h> -+#include <drivers/intel/gma/int15.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+#include <ec/acpi/ec.h> -+#include <console/console.h> -+#include <pc80/keyboard.h> -+ -+static void mainboard_enable(struct device *dev) -+{ -+ -+ /* FIXME: fix these values. */ -+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, -+ GMA_INT15_PANEL_FIT_DEFAULT, -+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); -+} -+ -+struct chip_operations mainboard_ops = { -+ .enable_dev = mainboard_enable, -+}; --- -2.43.0 - diff --git a/config/coreboot/default/patches/0025-use-mirrorservice.org-for-gcc-downloads.patch b/config/coreboot/default/patches/0032-use-mirrorservice.org-for-gcc-downloads.patch index 8275d6c5..4fb0f8a0 100644 --- a/config/coreboot/default/patches/0025-use-mirrorservice.org-for-gcc-downloads.patch +++ b/config/coreboot/default/patches/0032-use-mirrorservice.org-for-gcc-downloads.patch @@ -1,7 +1,7 @@ -From 936a8f113772c93d7501e7133159ab4e23436222 Mon Sep 17 00:00:00 2001 +From b769a682016b7d231bb3d004698c8a2059bbf363 Mon Sep 17 00:00:00 2001 From: Leah Rowe <leah@libreboot.org> Date: Sun, 5 Nov 2023 22:57:08 +0000 -Subject: [PATCH 25/30] use mirrorservice.org for gcc downloads +Subject: [PATCH 32/65] use mirrorservice.org for gcc downloads the gnu.org 302 redirect often fails @@ -11,10 +11,10 @@ Signed-off-by: Leah Rowe <leah@libreboot.org> 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc -index 36565a906c..4d4ca06113 100755 +index 5faff337b4..2743f96903 100755 --- a/util/crossgcc/buildgcc +++ b/util/crossgcc/buildgcc -@@ -67,11 +67,11 @@ NASM_ARCHIVE="nasm-${NASM_VERSION}.tar.bz2" +@@ -69,11 +69,11 @@ NASM_ARCHIVE="nasm-${NASM_VERSION}.tar.bz2" # to the jenkins build as well, or the builder won't download it. # GCC toolchain archive locations @@ -32,5 +32,5 @@ index 36565a906c..4d4ca06113 100755 # CLANG toolchain archive locations LLVM_BASE_URL="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}" -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0033-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch b/config/coreboot/default/patches/0033-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch deleted file mode 100644 index 39782376..00000000 --- a/config/coreboot/default/patches/0033-mb-dell-Add-Latitude-E6520-Sandy-Bridge.patch +++ /dev/null @@ -1,773 +0,0 @@ -From 5e8bff81220d4d0f663feed443e4594b76e442bf 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] mb/dell: Add Latitude E6520 (Sandy Bridge) - -Change-Id: Ibdd40cc15642b8d404159d5962670ccc4167a9ec -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/e6520/Kconfig | 38 +++++ - src/mainboard/dell/e6520/Kconfig.name | 2 + - src/mainboard/dell/e6520/Makefile.inc | 6 + - src/mainboard/dell/e6520/acpi/ec.asl | 9 + - src/mainboard/dell/e6520/acpi/platform.asl | 12 ++ - src/mainboard/dell/e6520/acpi/superio.asl | 3 + - src/mainboard/dell/e6520/acpi_tables.c | 16 ++ - src/mainboard/dell/e6520/board_info.txt | 6 + - src/mainboard/dell/e6520/cmos.default | 9 + - src/mainboard/dell/e6520/cmos.layout | 88 ++++++++++ - src/mainboard/dell/e6520/data.vbt | Bin 0 -> 6144 bytes - src/mainboard/dell/e6520/devicetree.cb | 66 +++++++ - src/mainboard/dell/e6520/dsdt.asl | 30 ++++ - src/mainboard/dell/e6520/early_init.c | 32 ++++ - src/mainboard/dell/e6520/gma-mainboard.ads | 20 +++ - src/mainboard/dell/e6520/gpio.c | 190 +++++++++++++++++++++ - src/mainboard/dell/e6520/hda_verb.c | 33 ++++ - src/mainboard/dell/e6520/mainboard.c | 21 +++ - 18 files changed, 581 insertions(+) - create mode 100644 src/mainboard/dell/e6520/Kconfig - create mode 100644 src/mainboard/dell/e6520/Kconfig.name - create mode 100644 src/mainboard/dell/e6520/Makefile.inc - create mode 100644 src/mainboard/dell/e6520/acpi/ec.asl - create mode 100644 src/mainboard/dell/e6520/acpi/platform.asl - create mode 100644 src/mainboard/dell/e6520/acpi/superio.asl - create mode 100644 src/mainboard/dell/e6520/acpi_tables.c - create mode 100644 src/mainboard/dell/e6520/board_info.txt - create mode 100644 src/mainboard/dell/e6520/cmos.default - create mode 100644 src/mainboard/dell/e6520/cmos.layout - create mode 100644 src/mainboard/dell/e6520/data.vbt - create mode 100644 src/mainboard/dell/e6520/devicetree.cb - create mode 100644 src/mainboard/dell/e6520/dsdt.asl - create mode 100644 src/mainboard/dell/e6520/early_init.c - create mode 100644 src/mainboard/dell/e6520/gma-mainboard.ads - create mode 100644 src/mainboard/dell/e6520/gpio.c - create mode 100644 src/mainboard/dell/e6520/hda_verb.c - create mode 100644 src/mainboard/dell/e6520/mainboard.c - -diff --git a/src/mainboard/dell/e6520/Kconfig b/src/mainboard/dell/e6520/Kconfig -new file mode 100644 -index 0000000000..db9f25b4ac ---- /dev/null -+++ b/src/mainboard/dell/e6520/Kconfig -@@ -0,0 +1,38 @@ -+if BOARD_DELL_LATITUDE_E6520 -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ select BOARD_ROMSIZE_KB_10240 -+ select EC_ACPI -+ select EC_DELL_MEC5035 -+ select GFX_GMA_PANEL_1_ON_LVDS -+ select HAVE_ACPI_RESUME -+ select HAVE_ACPI_TABLES -+ select HAVE_CMOS_DEFAULT -+ select HAVE_OPTION_TABLE -+ select INTEL_GMA_HAVE_VBT -+ select INTEL_INT15 -+ select MAINBOARD_HAS_LIBGFXINIT -+ select MAINBOARD_USES_IFD_GBE_REGION -+ select NORTHBRIDGE_INTEL_SANDYBRIDGE -+ select SERIRQ_CONTINUOUS_MODE -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ select SYSTEM_TYPE_LAPTOP -+ select USE_NATIVE_RAMINIT -+ -+config DRAM_RESET_GATE_GPIO -+ default 60 -+ -+config MAINBOARD_DIR -+ default "dell/e6520" -+ -+config MAINBOARD_PART_NUMBER -+ default "Latitude E6520" -+ -+config USBDEBUG_HCD_INDEX -+ default 2 -+ -+config VGA_BIOS_ID -+ default "8086,0116" -+ -+endif # BOARD_DELL_LATITUDE_E6520 -diff --git a/src/mainboard/dell/e6520/Kconfig.name b/src/mainboard/dell/e6520/Kconfig.name -new file mode 100644 -index 0000000000..25968e80e5 ---- /dev/null -+++ b/src/mainboard/dell/e6520/Kconfig.name -@@ -0,0 +1,2 @@ -+config BOARD_DELL_LATITUDE_E6520 -+ bool "Latitude E6520" -diff --git a/src/mainboard/dell/e6520/Makefile.inc b/src/mainboard/dell/e6520/Makefile.inc -new file mode 100644 -index 0000000000..ba64e93eb8 ---- /dev/null -+++ b/src/mainboard/dell/e6520/Makefile.inc -@@ -0,0 +1,6 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+bootblock-y += early_init.c -+bootblock-y += gpio.c -+romstage-y += early_init.c -+romstage-y += gpio.c -+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads -diff --git a/src/mainboard/dell/e6520/acpi/ec.asl b/src/mainboard/dell/e6520/acpi/ec.asl -new file mode 100644 -index 0000000000..0d429410a9 ---- /dev/null -+++ b/src/mainboard/dell/e6520/acpi/ec.asl -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Device(EC) -+{ -+ Name (_HID, EISAID("PNP0C09")) -+ Name (_UID, 0) -+ Name (_GPE, 16) -+/* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e6520/acpi/platform.asl b/src/mainboard/dell/e6520/acpi/platform.asl -new file mode 100644 -index 0000000000..2d24bbd9b9 ---- /dev/null -+++ b/src/mainboard/dell/e6520/acpi/platform.asl -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Method(_WAK, 1) -+{ -+ /* FIXME: EC support */ -+ Return(Package() {0, 0}) -+} -+ -+Method(_PTS,1) -+{ -+ /* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e6520/acpi/superio.asl b/src/mainboard/dell/e6520/acpi/superio.asl -new file mode 100644 -index 0000000000..55b1db5b11 ---- /dev/null -+++ b/src/mainboard/dell/e6520/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/dell/e6520/acpi_tables.c b/src/mainboard/dell/e6520/acpi_tables.c -new file mode 100644 -index 0000000000..e2759659bf ---- /dev/null -+++ b/src/mainboard/dell/e6520/acpi_tables.c -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <acpi/acpi_gnvs.h> -+#include <soc/nvs.h> -+ -+/* FIXME: check this function. */ -+void mainboard_fill_gnvs(struct global_nvs *gnvs) -+{ -+ /* The lid is open by default. */ -+ gnvs->lids = 1; -+ -+ /* Temperature at which OS will shutdown */ -+ gnvs->tcrt = 100; -+ /* Temperature at which OS will throttle CPU */ -+ gnvs->tpsv = 90; -+} -diff --git a/src/mainboard/dell/e6520/board_info.txt b/src/mainboard/dell/e6520/board_info.txt -new file mode 100644 -index 0000000000..34d5ad9e0b ---- /dev/null -+++ b/src/mainboard/dell/e6520/board_info.txt -@@ -0,0 +1,6 @@ -+Category: laptop -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -+Release year: 2011 -diff --git a/src/mainboard/dell/e6520/cmos.default b/src/mainboard/dell/e6520/cmos.default -new file mode 100644 -index 0000000000..279415dfd1 ---- /dev/null -+++ b/src/mainboard/dell/e6520/cmos.default -@@ -0,0 +1,9 @@ -+boot_option=Fallback -+debug_level=Debug -+power_on_after_fail=Disable -+nmi=Enable -+bluetooth=Enable -+wwan=Enable -+wlan=Enable -+sata_mode=AHCI -+me_state=Disabled -diff --git a/src/mainboard/dell/e6520/cmos.layout b/src/mainboard/dell/e6520/cmos.layout -new file mode 100644 -index 0000000000..1aa7e77bce ---- /dev/null -+++ b/src/mainboard/dell/e6520/cmos.layout -@@ -0,0 +1,88 @@ -+## 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 -+ -+#400 8 r 0 reserved for century byte -+ -+# coreboot config options: southbridge -+408 1 e 1 nmi -+409 2 e 7 power_on_after_fail -+411 1 e 9 sata_mode -+ -+# coreboot config options: EC -+412 1 e 1 bluetooth -+413 1 e 1 wwan -+414 1 e 1 wlan -+ -+# coreboot config options: ME -+424 1 e 14 me_state -+425 2 h 0 me_state_prev -+ -+# coreboot config options: northbridge -+432 3 e 11 gfx_uma_size -+435 2 e 12 hybrid_graphics_mode -+440 8 h 0 volume -+ -+# VBOOT -+448 128 r 0 vbnv -+ -+# SandyBridge MRC Scrambler Seed values -+896 32 r 0 mrc_scrambler_seed -+928 32 r 0 mrc_scrambler_seed_s3 -+960 16 r 0 mrc_scrambler_seed_chk -+ -+# 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 -+9 0 AHCI -+9 1 Compatible -+11 0 32M -+11 1 64M -+11 2 96M -+11 3 128M -+11 4 160M -+11 5 192M -+11 6 224M -+14 0 Normal -+14 1 Disabled -+ -+# ----------------------------------------------------------------- -+checksums -+ -+checksum 392 447 984 -diff --git a/src/mainboard/dell/e6520/data.vbt b/src/mainboard/dell/e6520/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..0ef16ee7cb482d2cb91ea80c3f419759355f7ba0 -GIT binary patch -literal 6144 -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 -O?SW|zOncy=dEg(6JAK&z - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/e6520/devicetree.cb b/src/mainboard/dell/e6520/devicetree.cb -new file mode 100644 -index 0000000000..cfba8ef4e7 ---- /dev/null -+++ b/src/mainboard/dell/e6520/devicetree.cb -@@ -0,0 +1,66 @@ -+chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. -+ register "gfx" = "GMA_STATIC_DISPLAYS(1)" -+ register "gpu_cpu_backlight" = "0x00001312" -+ register "gpu_dp_b_hotplug" = "4" -+ register "gpu_dp_c_hotplug" = "4" -+ register "gpu_dp_d_hotplug" = "4" -+ register "gpu_panel_port_select" = "0" -+ register "gpu_panel_power_backlight_off_delay" = "2300" -+ register "gpu_panel_power_backlight_on_delay" = "2300" -+ register "gpu_panel_power_cycle_delay" = "6" -+ register "gpu_panel_power_down_delay" = "400" -+ register "gpu_panel_power_up_delay" = "400" -+ register "gpu_pch_backlight" = "0x13121312" -+ -+ register "spd_addresses" = "{0x50, 0, 0x52, 0}" -+ -+ device domain 0x0 on -+ subsystemid 0x1028 0x0494 inherit -+ -+ device ref host_bridge on end # Host bridge -+ device ref peg10 on end # PEG -+ device ref igd on end # iGPU -+ -+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH -+ register "docking_supported" = "1" -+ register "gen1_dec" = "0x007c0681" -+ register "gen2_dec" = "0x007c0901" -+ register "gen3_dec" = "0x003c07e1" -+ register "gen4_dec" = "0x001c0901" -+ register "gpi0_routing" = "2" -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 1, 0, 0, 0, 0 }" -+ register "pcie_port_coalesce" = "1" -+ register "sata_interface_speed_support" = "0x3" -+ register "sata_port_map" = "0x3b" -+ register "spi_lvscc" = "0x2005" -+ register "spi_uvscc" = "0x2005" -+ -+ device ref mei1 off end -+ device ref mei2 off end -+ device ref me_ide_r off end -+ device ref me_kt off end -+ device ref gbe on end -+ device ref ehci2 on end -+ device ref hda on end -+ device ref pcie_rp1 on end -+ device ref pcie_rp2 on end -+ device ref pcie_rp3 on end -+ device ref pcie_rp4 on end -+ device ref pcie_rp5 off end -+ device ref pcie_rp6 on end -+ device ref pcie_rp7 off end -+ device ref pcie_rp8 off end -+ device ref ehci1 on end -+ device ref pci_bridge off end -+ device ref lpc on -+ chip ec/dell/mec5035 -+ device pnp ff.0 on end -+ end -+ end -+ device ref sata1 on end -+ device ref smbus on end -+ device ref sata2 off end -+ device ref thermal off end -+ end -+ end -+end -diff --git a/src/mainboard/dell/e6520/dsdt.asl b/src/mainboard/dell/e6520/dsdt.asl -new file mode 100644 -index 0000000000..7d13c55b08 ---- /dev/null -+++ b/src/mainboard/dell/e6520/dsdt.asl -@@ -0,0 +1,30 @@ -+#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB -+#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+ -+#include <acpi/acpi.h> -+ -+DefinitionBlock( -+ "dsdt.aml", -+ "DSDT", -+ ACPI_DSDT_REV_2, -+ OEM_ID, -+ ACPI_TABLE_CREATOR, -+ 0x20141018 /* OEM revision */ -+) -+{ -+ #include <acpi/dsdt_top.asl> -+ #include "acpi/platform.asl" -+ #include <cpu/intel/common/acpi/cpu.asl> -+ #include <southbridge/intel/common/acpi/platform.asl> -+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl> -+ #include <southbridge/intel/common/acpi/sleepstates.asl> -+ -+ Device (\_SB.PCI0) -+ { -+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl> -+ #include <drivers/intel/gma/acpi/default_brightness_levels.asl> -+ #include <southbridge/intel/bd82x6x/acpi/pch.asl> -+ } -+} -diff --git a/src/mainboard/dell/e6520/early_init.c b/src/mainboard/dell/e6520/early_init.c -new file mode 100644 -index 0000000000..2a37091df6 ---- /dev/null -+++ b/src/mainboard/dell/e6520/early_init.c -@@ -0,0 +1,32 @@ -+/* 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/e6520/gma-mainboard.ads b/src/mainboard/dell/e6520/gma-mainboard.ads -new file mode 100644 -index 0000000000..2a16f44360 ---- /dev/null -+++ b/src/mainboard/dell/e6520/gma-mainboard.ads -@@ -0,0 +1,20 @@ -+-- 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 := -+ ( -+ HDMI1, -- mainboard HDMI -+ DP2, -- dock DP -+ DP3, -- dock DP -+ Analog, -- mainboard VGA -+ LVDS, -+ others => Disabled); -+ -+end GMA.Mainboard; -diff --git a/src/mainboard/dell/e6520/gpio.c b/src/mainboard/dell/e6520/gpio.c -new file mode 100644 -index 0000000000..61f01816c4 ---- /dev/null -+++ b/src/mainboard/dell/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/e6520/hda_verb.c b/src/mainboard/dell/e6520/hda_verb.c -new file mode 100644 -index 0000000000..d33eb3b4c5 ---- /dev/null -+++ b/src/mainboard/dell/e6520/hda_verb.c -@@ -0,0 +1,33 @@ -+/* 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/e6520/mainboard.c b/src/mainboard/dell/e6520/mainboard.c -new file mode 100644 -index 0000000000..31e49802fc ---- /dev/null -+++ b/src/mainboard/dell/e6520/mainboard.c -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/device.h> -+#include <drivers/intel/gma/int15.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+#include <ec/acpi/ec.h> -+#include <console/console.h> -+#include <pc80/keyboard.h> -+ -+static void mainboard_enable(struct device *dev) -+{ -+ -+ /* FIXME: fix these values. */ -+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, -+ GMA_INT15_PANEL_FIT_DEFAULT, -+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); -+} -+ -+struct chip_operations mainboard_ops = { -+ .enable_dev = mainboard_enable, -+}; --- -2.43.0 - diff --git a/config/coreboot/default/patches/0030-mb-hp-Add-Compaq-Elite-8300-CMT-port.patch b/config/coreboot/default/patches/0033-mb-hp-Add-Compaq-Elite-8300-CMT-port.patch index e0af8372..9b24c26e 100644 --- a/config/coreboot/default/patches/0030-mb-hp-Add-Compaq-Elite-8300-CMT-port.patch +++ b/config/coreboot/default/patches/0033-mb-hp-Add-Compaq-Elite-8300-CMT-port.patch @@ -1,7 +1,7 @@ -From 4e0b62e6f0977cf922b1947955538ddca63bb954 Mon Sep 17 00:00:00 2001 +From 3697d2e2df764bd2f1b05a6856e035b606f6a360 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 30/30] mb/hp: Add Compaq Elite 8300 CMT port +Subject: [PATCH 33/65] mb/hp: Add Compaq Elite 8300 CMT port Based on autoport and Z220 SuperIO code. @@ -32,7 +32,7 @@ Signed-off-by: Riku Viitanen <riku.viitanen@protonmail.com> --- .../hp/compaq_elite_8300_cmt/Kconfig | 39 ++++ .../hp/compaq_elite_8300_cmt/Kconfig.name | 2 + - .../hp/compaq_elite_8300_cmt/Makefile.inc | 7 + + .../hp/compaq_elite_8300_cmt/Makefile.mk | 7 + .../hp/compaq_elite_8300_cmt/acpi/ec.asl | 1 + .../compaq_elite_8300_cmt/acpi/platform.asl | 10 + .../hp/compaq_elite_8300_cmt/acpi/superio.asl | 29 +++ @@ -41,17 +41,17 @@ Signed-off-by: Riku Viitanen <riku.viitanen@protonmail.com> .../hp/compaq_elite_8300_cmt/cmos.default | 7 + .../hp/compaq_elite_8300_cmt/cmos.layout | 74 +++++++ .../hp/compaq_elite_8300_cmt/data.vbt | Bin 0 -> 3902 bytes - .../hp/compaq_elite_8300_cmt/devicetree.cb | 161 +++++++++++++++ + .../hp/compaq_elite_8300_cmt/devicetree.cb | 177 ++++++++++++++++ .../hp/compaq_elite_8300_cmt/dsdt.asl | 26 +++ - .../hp/compaq_elite_8300_cmt/early_init.c | 31 +++ + .../hp/compaq_elite_8300_cmt/early_init.c | 14 ++ .../compaq_elite_8300_cmt/gma-mainboard.ads | 17 ++ src/mainboard/hp/compaq_elite_8300_cmt/gpio.c | 191 ++++++++++++++++++ .../hp/compaq_elite_8300_cmt/hda_verb.c | 33 +++ .../hp/compaq_elite_8300_cmt/mainboard.c | 16 ++ - 18 files changed, 661 insertions(+) + 18 files changed, 660 insertions(+) create mode 100644 src/mainboard/hp/compaq_elite_8300_cmt/Kconfig create mode 100644 src/mainboard/hp/compaq_elite_8300_cmt/Kconfig.name - create mode 100644 src/mainboard/hp/compaq_elite_8300_cmt/Makefile.inc + create mode 100644 src/mainboard/hp/compaq_elite_8300_cmt/Makefile.mk create mode 100644 src/mainboard/hp/compaq_elite_8300_cmt/acpi/ec.asl create mode 100644 src/mainboard/hp/compaq_elite_8300_cmt/acpi/platform.asl create mode 100644 src/mainboard/hp/compaq_elite_8300_cmt/acpi/superio.asl @@ -121,11 +121,11 @@ index 0000000000..bd399b1e76 @@ -0,0 +1,2 @@ +config BOARD_HP_COMPAQ_ELITE_8300_CMT + bool "Compaq Elite 8300 CMT" -diff --git a/src/mainboard/hp/compaq_elite_8300_cmt/Makefile.inc b/src/mainboard/hp/compaq_elite_8300_cmt/Makefile.inc +diff --git a/src/mainboard/hp/compaq_elite_8300_cmt/Makefile.mk b/src/mainboard/hp/compaq_elite_8300_cmt/Makefile.mk new file mode 100644 index 0000000000..fb492d3583 --- /dev/null -+++ b/src/mainboard/hp/compaq_elite_8300_cmt/Makefile.inc ++++ b/src/mainboard/hp/compaq_elite_8300_cmt/Makefile.mk @@ -0,0 +1,7 @@ +## SPDX-License-Identifier: GPL-2.0-only + @@ -353,10 +353,10 @@ HcmV?d00001 diff --git a/src/mainboard/hp/compaq_elite_8300_cmt/devicetree.cb b/src/mainboard/hp/compaq_elite_8300_cmt/devicetree.cb new file mode 100644 -index 0000000000..f4efabd792 +index 0000000000..3d21739b72 --- /dev/null +++ b/src/mainboard/hp/compaq_elite_8300_cmt/devicetree.cb -@@ -0,0 +1,161 @@ +@@ -0,0 +1,177 @@ +# SPDX-License-Identifier: GPL-2.0-only + +chip northbridge/intel/sandybridge @@ -386,6 +386,22 @@ index 0000000000..f4efabd792 + register "superspeed_capable_ports" = "0x0000000f" + register "xhci_overcurrent_mapping" = "0x00000c03" + register "xhci_switchable_ports" = "0x0000000f" ++ register "usb_port_config" = "{ ++ { 1, 0, 0 }, ++ { 1, 0, 0 }, ++ { 1, 0, 1 }, ++ { 1, 0, 1 }, ++ { 1, 0, 2 }, ++ { 1, 0, 2 }, ++ { 1, 0, 3 }, ++ { 1, 0, 3 }, ++ { 1, 0, 4 }, ++ { 1, 0, 4 }, ++ { 1, 0, 6 }, ++ { 1, 0, 5 }, ++ { 1, 0, 5 }, ++ { 1, 0, 6 } ++ }" + + device ref xhci on end # USB 3.0 Controller + device ref mei1 off end # Management Engine Interface 1 @@ -405,7 +421,7 @@ index 0000000000..f4efabd792 + device ref pcie_rp3 on end + device ref pcie_rp4 on end + device ref pcie_rp5 on end -+ device ref pcie_rp5 on end ++ device ref pcie_rp6 on end + device ref pcie_rp7 on end + device ref pcie_rp8 on end + @@ -552,10 +568,10 @@ index 0000000000..e8e2b3a3e5 +} diff --git a/src/mainboard/hp/compaq_elite_8300_cmt/early_init.c b/src/mainboard/hp/compaq_elite_8300_cmt/early_init.c new file mode 100644 -index 0000000000..99b7891c70 +index 0000000000..8d10c6317c --- /dev/null +++ b/src/mainboard/hp/compaq_elite_8300_cmt/early_init.c -@@ -0,0 +1,31 @@ +@@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bootblock_common.h> @@ -565,23 +581,6 @@ index 0000000000..99b7891c70 + +#define SERIAL_DEV PNP_DEV(0x2e, NPCD378_SP2) + -+const struct southbridge_usb_port mainboard_usb_ports[] = { -+ { 1, 0, 0 }, -+ { 1, 0, 0 }, -+ { 1, 0, 1 }, -+ { 1, 0, 1 }, -+ { 1, 0, 2 }, -+ { 1, 0, 2 }, -+ { 1, 0, 3 }, -+ { 1, 0, 3 }, -+ { 1, 0, 4 }, -+ { 1, 0, 4 }, -+ { 1, 0, 6 }, -+ { 1, 0, 5 }, -+ { 1, 0, 5 }, -+ { 1, 0, 6 }, -+}; -+ +void bootblock_mainboard_early_init(void) +{ + if (CONFIG(CONSOLE_SERIAL)) @@ -869,5 +868,5 @@ index 0000000000..8dbd95ef96 + .enable_dev = mainboard_enable, +}; -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0034-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch b/config/coreboot/default/patches/0034-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch deleted file mode 100644 index 9a1bea26..00000000 --- a/config/coreboot/default/patches/0034-mb-dell-Add-Latitude-E5530-Ivy-Bridge.patch +++ /dev/null @@ -1,780 +0,0 @@ -From 86911e57c556389eed386bc23d5e87dd520afec9 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] mb/dell: Add Latitude E5530 (Ivy Bridge) - -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/e5530/Kconfig | 37 ++++ - src/mainboard/dell/e5530/Kconfig.name | 2 + - src/mainboard/dell/e5530/Makefile.inc | 6 + - src/mainboard/dell/e5530/acpi/ec.asl | 9 + - src/mainboard/dell/e5530/acpi/platform.asl | 12 ++ - src/mainboard/dell/e5530/acpi/superio.asl | 3 + - src/mainboard/dell/e5530/acpi_tables.c | 16 ++ - src/mainboard/dell/e5530/board_info.txt | 6 + - src/mainboard/dell/e5530/cmos.default | 9 + - src/mainboard/dell/e5530/cmos.layout | 88 ++++++++++ - src/mainboard/dell/e5530/data.vbt | Bin 0 -> 6144 bytes - src/mainboard/dell/e5530/devicetree.cb | 70 ++++++++ - src/mainboard/dell/e5530/dsdt.asl | 30 ++++ - src/mainboard/dell/e5530/early_init.c | 32 ++++ - src/mainboard/dell/e5530/gma-mainboard.ads | 20 +++ - src/mainboard/dell/e5530/gpio.c | 194 +++++++++++++++++++++ - src/mainboard/dell/e5530/hda_verb.c | 33 ++++ - src/mainboard/dell/e5530/mainboard.c | 21 +++ - 18 files changed, 588 insertions(+) - create mode 100644 src/mainboard/dell/e5530/Kconfig - create mode 100644 src/mainboard/dell/e5530/Kconfig.name - create mode 100644 src/mainboard/dell/e5530/Makefile.inc - create mode 100644 src/mainboard/dell/e5530/acpi/ec.asl - create mode 100644 src/mainboard/dell/e5530/acpi/platform.asl - create mode 100644 src/mainboard/dell/e5530/acpi/superio.asl - create mode 100644 src/mainboard/dell/e5530/acpi_tables.c - create mode 100644 src/mainboard/dell/e5530/board_info.txt - create mode 100644 src/mainboard/dell/e5530/cmos.default - create mode 100644 src/mainboard/dell/e5530/cmos.layout - create mode 100644 src/mainboard/dell/e5530/data.vbt - create mode 100644 src/mainboard/dell/e5530/devicetree.cb - create mode 100644 src/mainboard/dell/e5530/dsdt.asl - create mode 100644 src/mainboard/dell/e5530/early_init.c - create mode 100644 src/mainboard/dell/e5530/gma-mainboard.ads - create mode 100644 src/mainboard/dell/e5530/gpio.c - create mode 100644 src/mainboard/dell/e5530/hda_verb.c - create mode 100644 src/mainboard/dell/e5530/mainboard.c - -diff --git a/src/mainboard/dell/e5530/Kconfig b/src/mainboard/dell/e5530/Kconfig -new file mode 100644 -index 0000000000..3faae4ee50 ---- /dev/null -+++ b/src/mainboard/dell/e5530/Kconfig -@@ -0,0 +1,37 @@ -+if BOARD_DELL_LATITUDE_E5530 -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ select BOARD_ROMSIZE_KB_12288 -+ select EC_ACPI -+ select EC_DELL_MEC5035 -+ select GFX_GMA_PANEL_1_ON_LVDS -+ select HAVE_ACPI_RESUME -+ select HAVE_ACPI_TABLES -+ select HAVE_CMOS_DEFAULT -+ select HAVE_OPTION_TABLE -+ select INTEL_GMA_HAVE_VBT -+ select INTEL_INT15 -+ select MAINBOARD_HAS_LIBGFXINIT -+ select NORTHBRIDGE_INTEL_SANDYBRIDGE -+ select SERIRQ_CONTINUOUS_MODE -+ select SOUTHBRIDGE_INTEL_C216 -+ select SYSTEM_TYPE_LAPTOP -+ select USE_NATIVE_RAMINIT -+ -+config DRAM_RESET_GATE_GPIO -+ default 60 -+ -+config MAINBOARD_DIR -+ default "dell/e5530" -+ -+config MAINBOARD_PART_NUMBER -+ default "Latitude E5530" -+ -+config USBDEBUG_HCD_INDEX -+ default 2 -+ -+config VGA_BIOS_ID -+ default "8086,0166" -+ -+endif # BOARD_DELL_LATITUDE_E5530 -diff --git a/src/mainboard/dell/e5530/Kconfig.name b/src/mainboard/dell/e5530/Kconfig.name -new file mode 100644 -index 0000000000..775963204a ---- /dev/null -+++ b/src/mainboard/dell/e5530/Kconfig.name -@@ -0,0 +1,2 @@ -+config BOARD_DELL_LATITUDE_E5530 -+ bool "Latitude E5530" -diff --git a/src/mainboard/dell/e5530/Makefile.inc b/src/mainboard/dell/e5530/Makefile.inc -new file mode 100644 -index 0000000000..ba64e93eb8 ---- /dev/null -+++ b/src/mainboard/dell/e5530/Makefile.inc -@@ -0,0 +1,6 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+bootblock-y += early_init.c -+bootblock-y += gpio.c -+romstage-y += early_init.c -+romstage-y += gpio.c -+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads -diff --git a/src/mainboard/dell/e5530/acpi/ec.asl b/src/mainboard/dell/e5530/acpi/ec.asl -new file mode 100644 -index 0000000000..0d429410a9 ---- /dev/null -+++ b/src/mainboard/dell/e5530/acpi/ec.asl -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Device(EC) -+{ -+ Name (_HID, EISAID("PNP0C09")) -+ Name (_UID, 0) -+ Name (_GPE, 16) -+/* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e5530/acpi/platform.asl b/src/mainboard/dell/e5530/acpi/platform.asl -new file mode 100644 -index 0000000000..2d24bbd9b9 ---- /dev/null -+++ b/src/mainboard/dell/e5530/acpi/platform.asl -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Method(_WAK, 1) -+{ -+ /* FIXME: EC support */ -+ Return(Package() {0, 0}) -+} -+ -+Method(_PTS,1) -+{ -+ /* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e5530/acpi/superio.asl b/src/mainboard/dell/e5530/acpi/superio.asl -new file mode 100644 -index 0000000000..55b1db5b11 ---- /dev/null -+++ b/src/mainboard/dell/e5530/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/dell/e5530/acpi_tables.c b/src/mainboard/dell/e5530/acpi_tables.c -new file mode 100644 -index 0000000000..e2759659bf ---- /dev/null -+++ b/src/mainboard/dell/e5530/acpi_tables.c -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <acpi/acpi_gnvs.h> -+#include <soc/nvs.h> -+ -+/* FIXME: check this function. */ -+void mainboard_fill_gnvs(struct global_nvs *gnvs) -+{ -+ /* The lid is open by default. */ -+ gnvs->lids = 1; -+ -+ /* Temperature at which OS will shutdown */ -+ gnvs->tcrt = 100; -+ /* Temperature at which OS will throttle CPU */ -+ gnvs->tpsv = 90; -+} -diff --git a/src/mainboard/dell/e5530/board_info.txt b/src/mainboard/dell/e5530/board_info.txt -new file mode 100644 -index 0000000000..4601a4aaba ---- /dev/null -+++ b/src/mainboard/dell/e5530/board_info.txt -@@ -0,0 +1,6 @@ -+Category: laptop -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -+Release year: 2012 -diff --git a/src/mainboard/dell/e5530/cmos.default b/src/mainboard/dell/e5530/cmos.default -new file mode 100644 -index 0000000000..279415dfd1 ---- /dev/null -+++ b/src/mainboard/dell/e5530/cmos.default -@@ -0,0 +1,9 @@ -+boot_option=Fallback -+debug_level=Debug -+power_on_after_fail=Disable -+nmi=Enable -+bluetooth=Enable -+wwan=Enable -+wlan=Enable -+sata_mode=AHCI -+me_state=Disabled -diff --git a/src/mainboard/dell/e5530/cmos.layout b/src/mainboard/dell/e5530/cmos.layout -new file mode 100644 -index 0000000000..1aa7e77bce ---- /dev/null -+++ b/src/mainboard/dell/e5530/cmos.layout -@@ -0,0 +1,88 @@ -+## 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 -+ -+#400 8 r 0 reserved for century byte -+ -+# coreboot config options: southbridge -+408 1 e 1 nmi -+409 2 e 7 power_on_after_fail -+411 1 e 9 sata_mode -+ -+# coreboot config options: EC -+412 1 e 1 bluetooth -+413 1 e 1 wwan -+414 1 e 1 wlan -+ -+# coreboot config options: ME -+424 1 e 14 me_state -+425 2 h 0 me_state_prev -+ -+# coreboot config options: northbridge -+432 3 e 11 gfx_uma_size -+435 2 e 12 hybrid_graphics_mode -+440 8 h 0 volume -+ -+# VBOOT -+448 128 r 0 vbnv -+ -+# SandyBridge MRC Scrambler Seed values -+896 32 r 0 mrc_scrambler_seed -+928 32 r 0 mrc_scrambler_seed_s3 -+960 16 r 0 mrc_scrambler_seed_chk -+ -+# 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 -+9 0 AHCI -+9 1 Compatible -+11 0 32M -+11 1 64M -+11 2 96M -+11 3 128M -+11 4 160M -+11 5 192M -+11 6 224M -+14 0 Normal -+14 1 Disabled -+ -+# ----------------------------------------------------------------- -+checksums -+ -+checksum 392 447 984 -diff --git a/src/mainboard/dell/e5530/data.vbt b/src/mainboard/dell/e5530/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..3c54b70be7856a6420d001112d7f17f8bab46ed3 -GIT binary patch -literal 6144 -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 -Jz~2*rUjdP?m;3+# - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/e5530/devicetree.cb b/src/mainboard/dell/e5530/devicetree.cb -new file mode 100644 -index 0000000000..2af748cf27 ---- /dev/null -+++ b/src/mainboard/dell/e5530/devicetree.cb -@@ -0,0 +1,70 @@ -+chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. -+ register "gfx" = "GMA_STATIC_DISPLAYS(1)" -+ register "gpu_cpu_backlight" = "0x00000000" -+ register "gpu_dp_b_hotplug" = "4" -+ register "gpu_dp_c_hotplug" = "4" -+ register "gpu_dp_d_hotplug" = "4" -+ register "gpu_panel_port_select" = "0" -+ register "gpu_panel_power_backlight_off_delay" = "2300" -+ register "gpu_panel_power_backlight_on_delay" = "2300" -+ register "gpu_panel_power_cycle_delay" = "6" -+ register "gpu_panel_power_down_delay" = "400" -+ register "gpu_panel_power_up_delay" = "400" -+ register "gpu_pch_backlight" = "0x03d003d0" -+ -+ register "spd_addresses" = "{0x50, 0, 0x52, 0}" -+ -+ device domain 0x0 on -+ subsystemid 0x1028 0x053d inherit -+ -+ device ref host_bridge on end -+ device ref peg10 off end -+ device ref igd on end -+ -+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH -+ register "docking_supported" = "1" -+ register "gen1_dec" = "0x007c0681" -+ register "gen2_dec" = "0x005c0921" -+ register "gen3_dec" = "0x003c07e1" -+ register "gen4_dec" = "0x00000911" # Ports 0x910/0x911 for EC -+ register "gpi0_routing" = "2" -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 1, 0, 0, 0, 0 }" -+ register "pcie_port_coalesce" = "1" -+ register "sata_interface_speed_support" = "0x3" -+ register "sata_port_map" = "0x33" -+ register "spi_lvscc" = "0x2005" -+ register "spi_uvscc" = "0x2005" -+ register "superspeed_capable_ports" = "0x0000000f" -+ register "xhci_overcurrent_mapping" = "0x00000c03" -+ register "xhci_switchable_ports" = "0x0000000f" -+ -+ device ref xhci on end -+ device ref mei1 off end -+ device ref mei2 off end -+ device ref me_ide_r off end -+ device ref me_kt off end -+ device ref gbe off end -+ device ref ehci2 on end -+ device ref hda on end -+ device ref pcie_rp1 on end # WWAN Slot -+ device ref pcie_rp2 on end # SLAN Slot -+ device ref pcie_rp3 on end # ExpressCard -+ device ref pcie_rp4 off end -+ device ref pcie_rp5 on end # Extra Half Mini PCIe slot -+ device ref pcie_rp6 on end # SD/MMC Card Reader -+ device ref pcie_rp7 on end # BCM5761 Ethernet -+ device ref pcie_rp8 off end -+ device ref ehci1 on end -+ device ref pci_bridge off end -+ device ref lpc on -+ chip ec/dell/mec5035 -+ device pnp ff.0 on end -+ end -+ end -+ device ref sata1 on end -+ device ref smbus on end -+ device ref sata2 off end -+ device ref thermal off end -+ end -+ end -+end -diff --git a/src/mainboard/dell/e5530/dsdt.asl b/src/mainboard/dell/e5530/dsdt.asl -new file mode 100644 -index 0000000000..7d13c55b08 ---- /dev/null -+++ b/src/mainboard/dell/e5530/dsdt.asl -@@ -0,0 +1,30 @@ -+#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB -+#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+ -+#include <acpi/acpi.h> -+ -+DefinitionBlock( -+ "dsdt.aml", -+ "DSDT", -+ ACPI_DSDT_REV_2, -+ OEM_ID, -+ ACPI_TABLE_CREATOR, -+ 0x20141018 /* OEM revision */ -+) -+{ -+ #include <acpi/dsdt_top.asl> -+ #include "acpi/platform.asl" -+ #include <cpu/intel/common/acpi/cpu.asl> -+ #include <southbridge/intel/common/acpi/platform.asl> -+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl> -+ #include <southbridge/intel/common/acpi/sleepstates.asl> -+ -+ Device (\_SB.PCI0) -+ { -+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl> -+ #include <drivers/intel/gma/acpi/default_brightness_levels.asl> -+ #include <southbridge/intel/bd82x6x/acpi/pch.asl> -+ } -+} -diff --git a/src/mainboard/dell/e5530/early_init.c b/src/mainboard/dell/e5530/early_init.c -new file mode 100644 -index 0000000000..00fd5f6795 ---- /dev/null -+++ b/src/mainboard/dell/e5530/early_init.c -@@ -0,0 +1,32 @@ -+/* 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, 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 }, -+}; -+ -+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/e5530/gma-mainboard.ads b/src/mainboard/dell/e5530/gma-mainboard.ads -new file mode 100644 -index 0000000000..1310830c8e ---- /dev/null -+++ b/src/mainboard/dell/e5530/gma-mainboard.ads -@@ -0,0 +1,20 @@ -+-- 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 := -+ ( -+ HDMI1, -- mainboard HDMI -+ DP2, -- dock DP -+ DP3, -- dock DP -+ Analog, --mainboard VGA -+ LVDS, -+ others => Disabled); -+ -+end GMA.Mainboard; -diff --git a/src/mainboard/dell/e5530/gpio.c b/src/mainboard/dell/e5530/gpio.c -new file mode 100644 -index 0000000000..0599f13921 ---- /dev/null -+++ b/src/mainboard/dell/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/e5530/hda_verb.c b/src/mainboard/dell/e5530/hda_verb.c -new file mode 100644 -index 0000000000..4c7c36ee05 ---- /dev/null -+++ b/src/mainboard/dell/e5530/hda_verb.c -@@ -0,0 +1,33 @@ -+/* 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/e5530/mainboard.c b/src/mainboard/dell/e5530/mainboard.c -new file mode 100644 -index 0000000000..31e49802fc ---- /dev/null -+++ b/src/mainboard/dell/e5530/mainboard.c -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/device.h> -+#include <drivers/intel/gma/int15.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+#include <ec/acpi/ec.h> -+#include <console/console.h> -+#include <pc80/keyboard.h> -+ -+static void mainboard_enable(struct device *dev) -+{ -+ -+ /* FIXME: fix these values. */ -+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, -+ GMA_INT15_PANEL_FIT_DEFAULT, -+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); -+} -+ -+struct chip_operations mainboard_ops = { -+ .enable_dev = mainboard_enable, -+}; --- -2.43.0 - diff --git a/config/coreboot/default/patches/0034-mb-hp-Add-Elitebook-8560w-as-an-HP-Sandy-Ivy-Bridge-.patch b/config/coreboot/default/patches/0034-mb-hp-Add-Elitebook-8560w-as-an-HP-Sandy-Ivy-Bridge-.patch deleted file mode 100644 index 458c3723..00000000 --- a/config/coreboot/default/patches/0034-mb-hp-Add-Elitebook-8560w-as-an-HP-Sandy-Ivy-Bridge-.patch +++ /dev/null @@ -1,1556 +0,0 @@ -From dac71d8ed89f1f1d295157aa62c678e35a320222 Mon Sep 17 00:00:00 2001 -From: Iru Cai <mytbk920423@gmail.com> -Date: Tue, 5 Mar 2019 16:27:36 +0800 -Subject: [PATCH] mb/hp: Add Elitebook 8560w as an HP Sandy/Ivy Bridge laptop - variant - -Change-Id: I15181792b1efa45a2a94d78e43c6257da1acf950 -Signed-off-by: Iru Cai <mytbk920423@gmail.com> ---- - Documentation/mainboard/hp/8560w.md | 82 +++++++ - Documentation/mainboard/hp/8560w_flash.webp | Bin 0 -> 51432 bytes - Documentation/mainboard/index.md | 1 + - src/mainboard/hp/snb_ivb_laptops/Kconfig | 10 +- - src/mainboard/hp/snb_ivb_laptops/Kconfig.name | 3 + - .../variants/8560w/board_info.txt | 7 + - .../variants/8560w/early_init.c | 36 +++ - .../hp/snb_ivb_laptops/variants/8560w/gpio.c | 224 ++++++++++++++++++ - .../snb_ivb_laptops/variants/8560w/hda_verb.c | 25 ++ - .../variants/8560w/overridetree.cb | 51 ++++ - 10 files changed, 438 insertions(+), 1 deletion(-) - create mode 100644 Documentation/mainboard/hp/8560w.md - create mode 100644 Documentation/mainboard/hp/8560w_flash.webp - create mode 100644 src/mainboard/hp/snb_ivb_laptops/variants/8560w/board_info.txt - create mode 100644 src/mainboard/hp/snb_ivb_laptops/variants/8560w/early_init.c - create mode 100644 src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c - create mode 100644 src/mainboard/hp/snb_ivb_laptops/variants/8560w/hda_verb.c - create mode 100644 src/mainboard/hp/snb_ivb_laptops/variants/8560w/overridetree.cb - -diff --git a/Documentation/mainboard/hp/8560w.md b/Documentation/mainboard/hp/8560w.md -new file mode 100644 -index 0000000000..cc35a0be1f ---- /dev/null -+++ b/Documentation/mainboard/hp/8560w.md -@@ -0,0 +1,82 @@ -+# HP EliteBook 8560w -+ -+This page describes how to run coreboot on the [HP EliteBook 8560w]. -+ -+## Required proprietary blobs -+ -+- Intel Firmware Descriptor, ME and GbE firmware -+- EC: please read [HP Laptops with KBC1126 Embedded Controller](hp_kbc1126_laptops) -+ -+## Flashing instructions -+ -+HP EliteBook 8560w has an 8MiB SOIC-8 flash chip on the bottom of the -+mainboard. You just need to remove the service cover, and use an SOIC-8 -+clip to read and flash the chip. -+ -+![8560w_chip_location](8560w_flash.webp) -+ -+```eval_rst -++---------------------+------------+ -+| Type | Value | -++=====================+============+ -+| Socketed flash | no | -++---------------------+------------+ -+| Model | MX25L6406E | -++---------------------+------------+ -+| Size | 8 MiB | -++---------------------+------------+ -+| Package | SOIC-8 | -++---------------------+------------+ -+| Write protection | no | -++---------------------+------------+ -+| Dual BIOS feature | no | -++---------------------+------------+ -+| In circuit flashing | yes | -++---------------------+------------+ -+| Internal flashing | yes | -++---------------------+------------+ -+``` -+ -+## Untested -+ -+- mainboards with 4 memory slots -+ -+## Working -+ -+- i7-2720QM, 8G+8G -+- Arch Linux boot from SeaBIOS payload -+- EHCI debug: the port is beside the eSATA port -+- SATA -+- eSATA -+- USB2 and USB3 -+- keyboard -+- Gigabit Ethernet -+- WLAN -+- WWAN -+- VGA and DisplayPort -+- audio -+- EC ACPI -+- Using `me_cleaner` -+- dock: PS/2 keyboard, USB, DisplayPort -+- TPM -+- S3 suspend/resume -+ -+## Technology -+ -+```eval_rst -++------------------+--------------------------------------------------+ -+| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` | -++------------------+--------------------------------------------------+ -+| Southbridge | bd82x6x | -++------------------+--------------------------------------------------+ -+| CPU | model_206ax | -++------------------+--------------------------------------------------+ -+| Super I/O | SMSC LPC47n217 | -++------------------+--------------------------------------------------+ -+| EC | SMSC KBC1126 | -++------------------+--------------------------------------------------+ -+| Coprocessor | Intel Management Engine | -++------------------+--------------------------------------------------+ -+``` -+ -+[HP EliteBook 8560w]: https://support.hp.com/us-en/product/hp-elitebook-8560w-mobile-workstation/5071171 -diff --git a/Documentation/mainboard/hp/8560w_flash.webp b/Documentation/mainboard/hp/8560w_flash.webp -new file mode 100644 -index 0000000000000000000000000000000000000000..b8295bc6e920a4c59c4282e419200569672e8267 -GIT binary patch -literal 51432 -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 -zf6%yT*`hgRR|bP&#Z9Z4QI3#XyP{k8#Fn~f!ktpwKA<jvz&sdbBY7NY*mvYp -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 -G|JeY!zvB4- - -literal 0 -HcmV?d00001 - -diff --git a/Documentation/mainboard/index.md b/Documentation/mainboard/index.md -index 519d88873c..a6be27ae09 100644 ---- a/Documentation/mainboard/index.md -+++ b/Documentation/mainboard/index.md -@@ -84,6 +84,7 @@ The boards in this section are not real mainboards, but emulators. - - [HP Sure Start](hp/hp_sure_start.md) - - [EliteBook 2170p](hp/2170p.md) - - [EliteBook 2560p](hp/2560p.md) -+- [EliteBook 8560w](hp/8560w.md) - - [EliteBook 8760w](hp/8760w.md) - - [EliteBook Folio 9480m](hp/folio_9480m.md) - - [EliteBook 820 G2](hp/elitebook_820_g2.md) -diff --git a/src/mainboard/hp/snb_ivb_laptops/Kconfig b/src/mainboard/hp/snb_ivb_laptops/Kconfig -index f0bd55f64f..f180bca87f 100644 ---- a/src/mainboard/hp/snb_ivb_laptops/Kconfig -+++ b/src/mainboard/hp/snb_ivb_laptops/Kconfig -@@ -69,6 +69,12 @@ config BOARD_HP_8470P - select SOUTHBRIDGE_INTEL_C216 - select SUPERIO_SMSC_LPC47N217 - -+config BOARD_HP_8560W -+ select BOARD_HP_SNB_IVB_LAPTOPS_COMMON -+ select BOARD_ROMSIZE_KB_8192 -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ select SUPERIO_SMSC_LPC47N217 -+ - config BOARD_HP_8770W - select BOARD_HP_SNB_IVB_LAPTOPS_COMMON - select BOARD_ROMSIZE_KB_16384 -@@ -118,6 +124,7 @@ config VARIANT_DIR - default "2760p" if BOARD_HP_2760P - default "8460p" if BOARD_HP_8460P - default "8470p" if BOARD_HP_8470P -+ default "8560w" if BOARD_HP_8560W - default "8770w" if BOARD_HP_8770W - default "folio_9470m" if BOARD_HP_FOLIO_9470M - default "probook_6360b" if BOARD_HP_PROBOOK_6360B -@@ -130,6 +137,7 @@ config MAINBOARD_PART_NUMBER - default "EliteBook 2760p" if BOARD_HP_2760P - default "EliteBook 8460p" if BOARD_HP_8460P - default "EliteBook 8470p" if BOARD_HP_8470P -+ default "EliteBook 8560w" if BOARD_HP_8560W - default "EliteBook 8770w" if BOARD_HP_8770W - default "EliteBook Folio 9470m" if BOARD_HP_FOLIO_9470M - default "ProBook 6360b" if BOARD_HP_PROBOOK_6360B -@@ -146,7 +154,7 @@ config VGA_BIOS_ID - config USBDEBUG_HCD_INDEX - int - default 0 if BOARD_HP_2170P || BOARD_HP_FOLIO_9470M -- default 1 if BOARD_HP_2560P || BOARD_HP_2760P || BOARD_HP_8460P -+ default 1 if BOARD_HP_2560P || BOARD_HP_2760P || BOARD_HP_8460P || BOARD_HP_8560W - default 2 if BOARD_HP_2570P || BOARD_HP_8470P || BOARD_HP_8770W - default 1 if BOARD_HP_PROBOOK_6360B # FIXME: check this - default 2 if BOARD_HP_REVOLVE_810_G1 # FIXME: check this -diff --git a/src/mainboard/hp/snb_ivb_laptops/Kconfig.name b/src/mainboard/hp/snb_ivb_laptops/Kconfig.name -index f72e0f622a..fdd1b93bd7 100644 ---- a/src/mainboard/hp/snb_ivb_laptops/Kconfig.name -+++ b/src/mainboard/hp/snb_ivb_laptops/Kconfig.name -@@ -18,6 +18,9 @@ config BOARD_HP_8460P - config BOARD_HP_8470P - bool "EliteBook 8470p" - -+config BOARD_HP_8560W -+ bool "EliteBook 8560w" -+ - config BOARD_HP_8770W - bool "EliteBook 8770w" - -diff --git a/src/mainboard/hp/snb_ivb_laptops/variants/8560w/board_info.txt b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/board_info.txt -new file mode 100644 -index 0000000000..558e904a94 ---- /dev/null -+++ b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/board_info.txt -@@ -0,0 +1,7 @@ -+Category: laptop -+Board URL: https://support.hp.com/us-en/product/hp-elitebook-8560w-mobile-workstation/5071171 -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -+Release year: 2011 -diff --git a/src/mainboard/hp/snb_ivb_laptops/variants/8560w/early_init.c b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/early_init.c -new file mode 100644 -index 0000000000..20c4b68911 ---- /dev/null -+++ b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/early_init.c -@@ -0,0 +1,36 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <bootblock_common.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+#include <superio/smsc/lpc47n217/lpc47n217.h> -+#include <ec/hp/kbc1126/ec.h> -+ -+#define SERIAL_DEV PNP_DEV(0x4e, LPC47N217_SP1) -+ -+const struct southbridge_usb_port mainboard_usb_ports[] = { -+ { 1, 1, 0 }, /* USB0 */ -+ { 1, 1, 0 }, /* USB1 */ -+ { 1, 1, 1 }, /* eSATA */ -+ { 1, 1, 1 }, /* camera */ -+ { 0, 0, 2 }, -+ { 1, 0, 2 }, /* bluetooth */ -+ { 0, 0, 3 }, -+ { 1, 0, 3 }, -+ { 0, 1, 4 }, -+ { 1, 1, 4 }, /* WWAN */ -+ { 1, 0, 5 }, -+ { 1, 0, 5 }, /* dock */ -+ { 1, 0, 6 }, -+ { 1, 0, 6 }, -+}; -+ -+void bootblock_mainboard_early_init(void) -+{ -+ lpc47n217_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); -+ kbc1126_enter_conf(); -+ kbc1126_mailbox_init(); -+ kbc1126_kbc_init(); -+ kbc1126_ec_init(); -+ kbc1126_pm1_init(); -+ kbc1126_exit_conf(); -+} -diff --git a/src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c -new file mode 100644 -index 0000000000..560d668d6f ---- /dev/null -+++ b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c -@@ -0,0 +1,224 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#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_GPIO, -+ .gpio11 = GPIO_MODE_GPIO, -+ .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_GPIO, -+ .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_OUTPUT, -+ .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, -+ .gpio10 = GPIO_DIR_INPUT, -+ .gpio11 = GPIO_DIR_OUTPUT, -+ .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_OUTPUT, -+ .gpio23 = GPIO_DIR_INPUT, -+ .gpio24 = GPIO_DIR_OUTPUT, -+ .gpio27 = GPIO_DIR_OUTPUT, -+ .gpio28 = GPIO_DIR_OUTPUT, -+ .gpio29 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_level = { -+ .gpio0 = GPIO_LEVEL_LOW, -+ .gpio11 = GPIO_LEVEL_LOW, -+ .gpio17 = GPIO_LEVEL_HIGH, -+ .gpio22 = GPIO_LEVEL_HIGH, -+ .gpio24 = GPIO_LEVEL_HIGH, -+ .gpio27 = GPIO_LEVEL_LOW, -+ .gpio28 = GPIO_LEVEL_LOW, -+ .gpio29 = GPIO_LEVEL_HIGH, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_reset = { -+ .gpio24 = GPIO_RESET_RSMRST, -+ .gpio30 = GPIO_RESET_RSMRST, -+}; -+ -+static const struct pch_gpio_set1 pch_gpio_set1_invert = { -+ .gpio1 = GPIO_INVERT, -+ .gpio3 = GPIO_INVERT, -+ .gpio6 = GPIO_INVERT, -+ .gpio7 = GPIO_INVERT, -+ .gpio10 = 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_NATIVE, -+ .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_GPIO, -+ .gpio45 = GPIO_MODE_NATIVE, -+ .gpio46 = GPIO_MODE_GPIO, -+ .gpio47 = GPIO_MODE_NATIVE, -+ .gpio48 = GPIO_MODE_GPIO, -+ .gpio49 = GPIO_MODE_GPIO, -+ .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_NATIVE, -+ .gpio57 = GPIO_MODE_GPIO, -+ .gpio58 = GPIO_MODE_NATIVE, -+ .gpio59 = GPIO_MODE_NATIVE, -+ .gpio60 = GPIO_MODE_GPIO, -+ .gpio61 = GPIO_MODE_GPIO, -+ .gpio62 = GPIO_MODE_NATIVE, -+ .gpio63 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_direction = { -+ .gpio33 = GPIO_DIR_OUTPUT, -+ .gpio34 = GPIO_DIR_INPUT, -+ .gpio35 = GPIO_DIR_OUTPUT, -+ .gpio37 = GPIO_DIR_OUTPUT, -+ .gpio38 = GPIO_DIR_INPUT, -+ .gpio39 = GPIO_DIR_INPUT, -+ .gpio44 = GPIO_DIR_INPUT, -+ .gpio46 = GPIO_DIR_INPUT, -+ .gpio48 = GPIO_DIR_INPUT, -+ .gpio49 = GPIO_DIR_OUTPUT, -+ .gpio50 = GPIO_DIR_INPUT, -+ .gpio51 = GPIO_DIR_INPUT, -+ .gpio52 = GPIO_DIR_INPUT, -+ .gpio53 = GPIO_DIR_OUTPUT, -+ .gpio54 = GPIO_DIR_INPUT, -+ .gpio55 = GPIO_DIR_INPUT, -+ .gpio57 = GPIO_DIR_OUTPUT, -+ .gpio60 = GPIO_DIR_OUTPUT, -+ .gpio61 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set2 pch_gpio_set2_level = { -+ .gpio33 = GPIO_LEVEL_LOW, -+ .gpio35 = GPIO_LEVEL_LOW, -+ .gpio37 = GPIO_LEVEL_LOW, -+ .gpio49 = GPIO_LEVEL_LOW, -+ .gpio53 = GPIO_LEVEL_HIGH, -+ .gpio57 = GPIO_LEVEL_LOW, -+ .gpio60 = GPIO_LEVEL_HIGH, -+ .gpio61 = 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_GPIO, -+ .gpio73 = GPIO_MODE_GPIO, -+ .gpio74 = GPIO_MODE_GPIO, -+ .gpio75 = GPIO_MODE_NATIVE, -+}; -+ -+static const struct pch_gpio_set3 pch_gpio_set3_direction = { -+ .gpio68 = GPIO_DIR_OUTPUT, -+ .gpio69 = GPIO_DIR_INPUT, -+ .gpio70 = GPIO_DIR_OUTPUT, -+ .gpio71 = GPIO_DIR_OUTPUT, -+ .gpio72 = GPIO_DIR_OUTPUT, -+ .gpio73 = GPIO_DIR_OUTPUT, -+ .gpio74 = GPIO_DIR_OUTPUT, -+}; -+ -+static const struct pch_gpio_set3 pch_gpio_set3_level = { -+ .gpio68 = GPIO_LEVEL_HIGH, -+ .gpio70 = GPIO_LEVEL_HIGH, -+ .gpio71 = GPIO_LEVEL_HIGH, -+ .gpio72 = GPIO_LEVEL_LOW, -+ .gpio73 = GPIO_LEVEL_HIGH, -+ .gpio74 = GPIO_LEVEL_HIGH, -+}; -+ -+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/hp/snb_ivb_laptops/variants/8560w/hda_verb.c b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/hda_verb.c -new file mode 100644 -index 0000000000..2f5469fc84 ---- /dev/null -+++ b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/hda_verb.c -@@ -0,0 +1,25 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <device/azalia_device.h> -+ -+const u32 cim_verb_data[] = { -+ 0x111d7605, /* Codec Vendor / Device ID: IDT */ -+ 0x103c1631, /* Subsystem ID */ -+ -+ 11, /* Number of 4 dword sets */ -+ AZALIA_SUBVENDOR(0, 0x103c1631), -+ AZALIA_PIN_CFG(0, 0x0a, 0x40f000f0), -+ AZALIA_PIN_CFG(0, 0x0b, 0x0421401f), -+ AZALIA_PIN_CFG(0, 0x0c, 0x04a11020), -+ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), -+ AZALIA_PIN_CFG(0, 0x0e, 0x40f000f0), -+ AZALIA_PIN_CFG(0, 0x0f, 0x40f000f0), -+ AZALIA_PIN_CFG(0, 0x10, 0x40f000f0), -+ AZALIA_PIN_CFG(0, 0x11, 0x90a60130), -+ AZALIA_PIN_CFG(0, 0x1f, 0x40f000f0), -+ AZALIA_PIN_CFG(0, 0x20, 0x40f000f0), -+}; -+ -+const u32 pc_beep_verbs[0] = {}; -+ -+AZALIA_ARRAY_SIZES; -diff --git a/src/mainboard/hp/snb_ivb_laptops/variants/8560w/overridetree.cb b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/overridetree.cb -new file mode 100644 -index 0000000000..4264270ad0 ---- /dev/null -+++ b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/overridetree.cb -@@ -0,0 +1,51 @@ -+# SPDX-License-Identifier: GPL-2.0-or-later -+ -+chip northbridge/intel/sandybridge -+ register "spd_addresses" = "{0x50, 0x51, 0x52, 0x53}" -+ device domain 0 on -+ subsystemid 0x103c 0x1631 inherit -+ device pci 01.0 on end # PCIe Bridge for discrete graphics -+ device pci 02.0 off end # Internal graphics -+ -+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH -+ register "docking_supported" = "0" -+ register "gen1_dec" = "0x007c0201" -+ register "gen2_dec" = "0x000c0101" -+ register "gen3_dec" = "0x00fcfe01" -+ register "gen4_dec" = "0x000402e9" -+ register "gpi6_routing" = "2" -+ register "pcie_hotplug_map" = "{ 0, 1, 1, 0, 0, 0, 0, 0 }" -+ # HDD(0), ODD(1), eSATA(4) -+ register "sata_port_map" = "0x3b" -+ -+ device pci 1c.0 on end # PCIe Port #1, WWAN -+ device pci 1c.1 on end # PCIe Port #2, ExpressCard -+ device pci 1c.2 on end # PCIe Port #3, SD/MMC -+ device pci 1c.3 on end # PCIe Port #4, WLAN -+ device pci 1c.4 off end # PCIe Port #5 -+ device pci 1c.5 off end # PCIe Port #6 -+ device pci 1c.6 off end # PCIe Port #7 -+ device pci 1c.7 on end # PCIe Port #8, NEC USB 3.0 Host Controller -+ device pci 1f.0 on # LPC bridge -+ chip ec/hp/kbc1126 -+ register "ec_data_port" = "0x60" -+ register "ec_cmd_port" = "0x64" -+ register "ec_ctrl_reg" = "0xca" -+ register "ec_fan_ctrl_value" = "0x6b" -+ device pnp ff.1 off end -+ end -+ chip superio/smsc/lpc47n217 -+ device pnp 4e.3 on # Parallel -+ io 0x60 = 0x378 -+ irq 0x70 = 7 -+ end -+ device pnp 4e.4 on # COM1 -+ io 0x60 = 0x3f8 -+ irq 0x70 = 4 -+ end -+ device pnp 4e.5 off end # COM2 -+ end -+ end -+ end -+ end -+end --- -2.43.0 - diff --git a/config/coreboot/default/patches/0036-nb-intel-haswell-make-IOMMU-a-runtime-option.patch b/config/coreboot/default/patches/0034-nb-intel-haswell-make-IOMMU-a-runtime-option.patch index 8401e8b8..35d0046f 100644 --- a/config/coreboot/default/patches/0036-nb-intel-haswell-make-IOMMU-a-runtime-option.patch +++ b/config/coreboot/default/patches/0034-nb-intel-haswell-make-IOMMU-a-runtime-option.patch @@ -1,7 +1,7 @@ -From 7c755b4502ea007f2216ea76f2ed734452def883 Mon Sep 17 00:00:00 2001 +From 0ad294f2da8085d5612f7940ec8601d979cb2421 Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sat, 2 Mar 2024 22:51:09 +0000 -Subject: [PATCH 1/2] nb/intel/haswell: make IOMMU a runtime option +Subject: [PATCH 34/65] 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 @@ -38,10 +38,10 @@ Signed-off-by: Leah Rowe <info@minifree.org> 14 files changed, 48 insertions(+) diff --git a/src/mainboard/asrock/b85m_pro4/cmos.default b/src/mainboard/asrock/b85m_pro4/cmos.default -index c51001c03c..1c5c17f841 100644 +index 01bf20ad16..dfc8b80fb0 100644 --- a/src/mainboard/asrock/b85m_pro4/cmos.default +++ b/src/mainboard/asrock/b85m_pro4/cmos.default -@@ -2,3 +2,4 @@ boot_option=Fallback +@@ -4,3 +4,4 @@ boot_option=Fallback debug_level=Debug nmi=Enable power_on_after_fail=Disable @@ -68,10 +68,10 @@ index efdc333fc2..c9883ea71d 100644 # ----------------------------------------------------------------- diff --git a/src/mainboard/asrock/h81m-hds/cmos.default b/src/mainboard/asrock/h81m-hds/cmos.default -index c51001c03c..1c5c17f841 100644 +index 01bf20ad16..dfc8b80fb0 100644 --- a/src/mainboard/asrock/h81m-hds/cmos.default +++ b/src/mainboard/asrock/h81m-hds/cmos.default -@@ -2,3 +2,4 @@ boot_option=Fallback +@@ -4,3 +4,4 @@ boot_option=Fallback debug_level=Debug nmi=Enable power_on_after_fail=Disable @@ -101,16 +101,16 @@ index c9ba76c78f..95ee3d36fb 100644 checksums diff --git a/src/mainboard/dell/optiplex_9020/cmos.default b/src/mainboard/dell/optiplex_9020/cmos.default -index b159660aa8..8253570f19 100644 +index 6c4a2a1be7..8000eea8c0 100644 --- a/src/mainboard/dell/optiplex_9020/cmos.default +++ b/src/mainboard/dell/optiplex_9020/cmos.default -@@ -2,3 +2,4 @@ boot_option=Fallback - debug_level=Debug +@@ -4,3 +4,4 @@ debug_level=Debug nmi=Disable power_on_after_fail=Disable + fan_full_speed=Disable +iommu=Enable diff --git a/src/mainboard/dell/optiplex_9020/cmos.layout b/src/mainboard/dell/optiplex_9020/cmos.layout -index c9ba76c78f..72ff9c4bee 100644 +index d10ad95b23..4a1496a878 100644 --- a/src/mainboard/dell/optiplex_9020/cmos.layout +++ b/src/mainboard/dell/optiplex_9020/cmos.layout @@ -21,6 +21,9 @@ entries @@ -118,12 +118,12 @@ index c9ba76c78f..72ff9c4bee 100644 409 2 e 5 power_on_after_fail +# turn iommu on or off -+412 1 e 6 iommu ++411 1 e 6 iommu + - # coreboot config options: check sums - 984 16 h 0 check_sum + # coreboot config options: EC + 412 1 e 1 fan_full_speed -@@ -52,6 +55,9 @@ enumerations +@@ -55,6 +58,9 @@ enumerations 5 1 Enable 5 2 Keep @@ -202,10 +202,10 @@ index 78d44c1415..f2c602f541 100644 checksums diff --git a/src/mainboard/lenovo/haswell/cmos.default b/src/mainboard/lenovo/haswell/cmos.default -index bb8626d48b..051658d757 100644 +index 08db97c5a9..cc6b363cd9 100644 --- a/src/mainboard/lenovo/haswell/cmos.default +++ b/src/mainboard/lenovo/haswell/cmos.default -@@ -12,3 +12,4 @@ trackpoint=Enable +@@ -14,3 +14,4 @@ trackpoint=Enable backlight=Keyboard enable_dual_graphics=Disable usb_always_on=Disable @@ -232,10 +232,10 @@ index 27915d3ab7..59df76b64c 100644 # ----------------------------------------------------------------- checksums diff --git a/src/mainboard/supermicro/x10slm-f/cmos.default b/src/mainboard/supermicro/x10slm-f/cmos.default -index f4047147f7..eea2c36b88 100644 +index 7ce38fb5d7..6049e7938a 100644 --- a/src/mainboard/supermicro/x10slm-f/cmos.default +++ b/src/mainboard/supermicro/x10slm-f/cmos.default -@@ -3,3 +3,4 @@ debug_level=Debug +@@ -5,3 +5,4 @@ debug_level=Debug nmi=Enable power_on_after_fail=Keep hide_ast2400=Disable @@ -288,5 +288,5 @@ index e47deb5da6..1a7e0b1076 100644 if (capid0_a & VTD_DISABLE) return; -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0037-dell-optiplex_9020-Disable-IOMMU-by-default.patch b/config/coreboot/default/patches/0035-dell-optiplex_9020-Disable-IOMMU-by-default.patch index c8cde72e..9596d6f3 100644 --- a/config/coreboot/default/patches/0037-dell-optiplex_9020-Disable-IOMMU-by-default.patch +++ b/config/coreboot/default/patches/0035-dell-optiplex_9020-Disable-IOMMU-by-default.patch @@ -1,7 +1,7 @@ -From 61041d49b94236400e836b8ea518d3a064b95c4e Mon Sep 17 00:00:00 2001 +From 80d728b91ec793f584bcf045f00e5fe4bba5e4ae Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sat, 2 Mar 2024 23:00:09 +0000 -Subject: [PATCH 2/2] dell/optiplex_9020: Disable IOMMU by default +Subject: [PATCH 35/65] 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 @@ -15,15 +15,15 @@ Signed-off-by: Leah Rowe <info@minifree.org> 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainboard/dell/optiplex_9020/cmos.default b/src/mainboard/dell/optiplex_9020/cmos.default -index 8253570f19..7bccc80e51 100644 +index 8000eea8c0..0700f971ee 100644 --- a/src/mainboard/dell/optiplex_9020/cmos.default +++ b/src/mainboard/dell/optiplex_9020/cmos.default -@@ -2,4 +2,4 @@ boot_option=Fallback - debug_level=Debug +@@ -4,4 +4,4 @@ debug_level=Debug nmi=Disable power_on_after_fail=Disable + fan_full_speed=Disable -iommu=Enable +iommu=Disable -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0035-hp8560w-Add-MXM-System-Infomation-Structure.patch b/config/coreboot/default/patches/0035-hp8560w-Add-MXM-System-Infomation-Structure.patch deleted file mode 100644 index 68ccb801..00000000 --- a/config/coreboot/default/patches/0035-hp8560w-Add-MXM-System-Infomation-Structure.patch +++ /dev/null @@ -1,41 +0,0 @@ -From b2cf0657a2058118baf6f4ec96e356de3c9e493e Mon Sep 17 00:00:00 2001 -From: Riku Viitanen <riku.viitanen@protonmail.com> -Date: Sun, 11 Feb 2024 19:02:20 +0200 -Subject: [PATCH] hp8560w: Add MXM System Infomation Structure - -Change-Id: I45b421f2d7baf8ca8dedbd3b1ab1e38392b6219b -Signed-off-by: Riku Viitanen <riku.viitanen@protonmail.com> ---- - src/mainboard/hp/snb_ivb_laptops/Makefile.mk | 6 ++++++ - .../hp/snb_ivb_laptops/variants/8560w/mxm-30-sis | Bin 0 -> 129 bytes - 2 files changed, 6 insertions(+) - create mode 100644 src/mainboard/hp/snb_ivb_laptops/variants/8560w/mxm-30-sis - -diff --git a/src/mainboard/hp/snb_ivb_laptops/Makefile.mk b/src/mainboard/hp/snb_ivb_laptops/Makefile.mk -index c007bb68cd..7950abbc4e 100644 ---- a/src/mainboard/hp/snb_ivb_laptops/Makefile.mk -+++ b/src/mainboard/hp/snb_ivb_laptops/Makefile.mk -@@ -9,3 +9,9 @@ ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += variants/$(VARIANT_DIR)/gma-mainb - - # FIXME: Other variants with same size onboard RAM may exist. - SPD_SOURCES = hynix_4g -+ -+ifeq ($(CONFIG_BOARD_HP_8560W),y) -+cbfs-files-y += mxm-30-sis -+mxm-30-sis-file := variants/$(VARIANT_DIR)/mxm-30-sis -+mxm-30-sis-type := raw -+endif -diff --git a/src/mainboard/hp/snb_ivb_laptops/variants/8560w/mxm-30-sis b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/mxm-30-sis -new file mode 100644 -index 0000000000000000000000000000000000000000..7e4e245a50d8d5d36ddb22e3b1aed3fa87a2f57d -GIT binary patch -literal 129 -zcmeZ`@Qr6?sAMn@-0}aX9Rou`%?mKiz;Fq|&xF!hw;=rNM_^h3Dy{$(SAdE$zF=lx -o@?l{RW{6;7W}LwIl$Vj2apDSgHUS2PJFE;0Kxqas5d=FN0HAs+0RR91 - -literal 0 -HcmV?d00001 - --- -2.43.1 - diff --git a/config/coreboot/default/patches/0035-mb-dell-Add-Latitude-E5520-Sandybridge.patch b/config/coreboot/default/patches/0035-mb-dell-Add-Latitude-E5520-Sandybridge.patch deleted file mode 100644 index 1ca4b950..00000000 --- a/config/coreboot/default/patches/0035-mb-dell-Add-Latitude-E5520-Sandybridge.patch +++ /dev/null @@ -1,775 +0,0 @@ -From 7c7ce2087e1ff5f0eedb65793254163d01be3056 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] mb/dell: Add Latitude E5520 (Sandybridge) - -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/e5520/Kconfig | 37 ++++ - src/mainboard/dell/e5520/Kconfig.name | 2 + - src/mainboard/dell/e5520/Makefile.inc | 5 + - src/mainboard/dell/e5520/acpi/ec.asl | 9 + - src/mainboard/dell/e5520/acpi/platform.asl | 12 ++ - src/mainboard/dell/e5520/acpi/superio.asl | 3 + - src/mainboard/dell/e5520/acpi_tables.c | 16 ++ - src/mainboard/dell/e5520/board_info.txt | 6 + - src/mainboard/dell/e5520/cmos.default | 9 + - src/mainboard/dell/e5520/cmos.layout | 88 ++++++++++ - src/mainboard/dell/e5520/data.vbt | Bin 0 -> 6144 bytes - src/mainboard/dell/e5520/devicetree.cb | 66 +++++++ - src/mainboard/dell/e5520/dsdt.asl | 30 ++++ - src/mainboard/dell/e5520/early_init.c | 32 ++++ - src/mainboard/dell/e5520/gma-mainboard.ads | 20 +++ - src/mainboard/dell/e5520/gpio.c | 195 +++++++++++++++++++++ - src/mainboard/dell/e5520/hda_verb.c | 33 ++++ - src/mainboard/dell/e5520/mainboard.c | 21 +++ - 18 files changed, 584 insertions(+) - create mode 100644 src/mainboard/dell/e5520/Kconfig - create mode 100644 src/mainboard/dell/e5520/Kconfig.name - create mode 100644 src/mainboard/dell/e5520/Makefile.inc - create mode 100644 src/mainboard/dell/e5520/acpi/ec.asl - create mode 100644 src/mainboard/dell/e5520/acpi/platform.asl - create mode 100644 src/mainboard/dell/e5520/acpi/superio.asl - create mode 100644 src/mainboard/dell/e5520/acpi_tables.c - create mode 100644 src/mainboard/dell/e5520/board_info.txt - create mode 100644 src/mainboard/dell/e5520/cmos.default - create mode 100644 src/mainboard/dell/e5520/cmos.layout - create mode 100644 src/mainboard/dell/e5520/data.vbt - create mode 100644 src/mainboard/dell/e5520/devicetree.cb - create mode 100644 src/mainboard/dell/e5520/dsdt.asl - create mode 100644 src/mainboard/dell/e5520/early_init.c - create mode 100644 src/mainboard/dell/e5520/gma-mainboard.ads - create mode 100644 src/mainboard/dell/e5520/gpio.c - create mode 100644 src/mainboard/dell/e5520/hda_verb.c - create mode 100644 src/mainboard/dell/e5520/mainboard.c - -diff --git a/src/mainboard/dell/e5520/Kconfig b/src/mainboard/dell/e5520/Kconfig -new file mode 100644 -index 0000000000..213c54cf5c ---- /dev/null -+++ b/src/mainboard/dell/e5520/Kconfig -@@ -0,0 +1,37 @@ -+if BOARD_DELL_LATITUDE_E5520 -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ select BOARD_ROMSIZE_KB_6144 -+ select EC_ACPI -+ select EC_DELL_MEC5035 -+ select GFX_GMA_PANEL_1_ON_LVDS -+ select HAVE_ACPI_RESUME -+ select HAVE_ACPI_TABLES -+ select HAVE_CMOS_DEFAULT -+ select HAVE_OPTION_TABLE -+ select INTEL_GMA_HAVE_VBT -+ select INTEL_INT15 -+ select MAINBOARD_HAS_LIBGFXINIT -+ select NORTHBRIDGE_INTEL_SANDYBRIDGE -+ select SERIRQ_CONTINUOUS_MODE -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ select SYSTEM_TYPE_LAPTOP -+ select USE_NATIVE_RAMINIT -+ -+config DRAM_RESET_GATE_GPIO -+ default 60 -+ -+config MAINBOARD_DIR -+ default "dell/e5520" -+ -+config MAINBOARD_PART_NUMBER -+ default "Latitude E5520" -+ -+config USBDEBUG_HCD_INDEX -+ default 2 -+ -+config VGA_BIOS_ID -+ default "8086,0126" -+ -+endif # BOARD_DELL_LATITUDE_E5520 -diff --git a/src/mainboard/dell/e5520/Kconfig.name b/src/mainboard/dell/e5520/Kconfig.name -new file mode 100644 -index 0000000000..c88913e8b3 ---- /dev/null -+++ b/src/mainboard/dell/e5520/Kconfig.name -@@ -0,0 +1,2 @@ -+config BOARD_DELL_LATITUDE_E5520 -+ bool "Latitude E5520" -diff --git a/src/mainboard/dell/e5520/Makefile.inc b/src/mainboard/dell/e5520/Makefile.inc -new file mode 100644 -index 0000000000..18391d8b18 ---- /dev/null -+++ b/src/mainboard/dell/e5520/Makefile.inc -@@ -0,0 +1,5 @@ -+bootblock-y += early_init.c -+bootblock-y += gpio.c -+romstage-y += early_init.c -+romstage-y += gpio.c -+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads -diff --git a/src/mainboard/dell/e5520/acpi/ec.asl b/src/mainboard/dell/e5520/acpi/ec.asl -new file mode 100644 -index 0000000000..0d429410a9 ---- /dev/null -+++ b/src/mainboard/dell/e5520/acpi/ec.asl -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Device(EC) -+{ -+ Name (_HID, EISAID("PNP0C09")) -+ Name (_UID, 0) -+ Name (_GPE, 16) -+/* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e5520/acpi/platform.asl b/src/mainboard/dell/e5520/acpi/platform.asl -new file mode 100644 -index 0000000000..2d24bbd9b9 ---- /dev/null -+++ b/src/mainboard/dell/e5520/acpi/platform.asl -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Method(_WAK, 1) -+{ -+ /* FIXME: EC support */ -+ Return(Package() {0, 0}) -+} -+ -+Method(_PTS,1) -+{ -+ /* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e5520/acpi/superio.asl b/src/mainboard/dell/e5520/acpi/superio.asl -new file mode 100644 -index 0000000000..55b1db5b11 ---- /dev/null -+++ b/src/mainboard/dell/e5520/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/dell/e5520/acpi_tables.c b/src/mainboard/dell/e5520/acpi_tables.c -new file mode 100644 -index 0000000000..e2759659bf ---- /dev/null -+++ b/src/mainboard/dell/e5520/acpi_tables.c -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <acpi/acpi_gnvs.h> -+#include <soc/nvs.h> -+ -+/* FIXME: check this function. */ -+void mainboard_fill_gnvs(struct global_nvs *gnvs) -+{ -+ /* The lid is open by default. */ -+ gnvs->lids = 1; -+ -+ /* Temperature at which OS will shutdown */ -+ gnvs->tcrt = 100; -+ /* Temperature at which OS will throttle CPU */ -+ gnvs->tpsv = 90; -+} -diff --git a/src/mainboard/dell/e5520/board_info.txt b/src/mainboard/dell/e5520/board_info.txt -new file mode 100644 -index 0000000000..34d5ad9e0b ---- /dev/null -+++ b/src/mainboard/dell/e5520/board_info.txt -@@ -0,0 +1,6 @@ -+Category: laptop -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -+Release year: 2011 -diff --git a/src/mainboard/dell/e5520/cmos.default b/src/mainboard/dell/e5520/cmos.default -new file mode 100644 -index 0000000000..279415dfd1 ---- /dev/null -+++ b/src/mainboard/dell/e5520/cmos.default -@@ -0,0 +1,9 @@ -+boot_option=Fallback -+debug_level=Debug -+power_on_after_fail=Disable -+nmi=Enable -+bluetooth=Enable -+wwan=Enable -+wlan=Enable -+sata_mode=AHCI -+me_state=Disabled -diff --git a/src/mainboard/dell/e5520/cmos.layout b/src/mainboard/dell/e5520/cmos.layout -new file mode 100644 -index 0000000000..1aa7e77bce ---- /dev/null -+++ b/src/mainboard/dell/e5520/cmos.layout -@@ -0,0 +1,88 @@ -+## 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 -+ -+#400 8 r 0 reserved for century byte -+ -+# coreboot config options: southbridge -+408 1 e 1 nmi -+409 2 e 7 power_on_after_fail -+411 1 e 9 sata_mode -+ -+# coreboot config options: EC -+412 1 e 1 bluetooth -+413 1 e 1 wwan -+414 1 e 1 wlan -+ -+# coreboot config options: ME -+424 1 e 14 me_state -+425 2 h 0 me_state_prev -+ -+# coreboot config options: northbridge -+432 3 e 11 gfx_uma_size -+435 2 e 12 hybrid_graphics_mode -+440 8 h 0 volume -+ -+# VBOOT -+448 128 r 0 vbnv -+ -+# SandyBridge MRC Scrambler Seed values -+896 32 r 0 mrc_scrambler_seed -+928 32 r 0 mrc_scrambler_seed_s3 -+960 16 r 0 mrc_scrambler_seed_chk -+ -+# 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 -+9 0 AHCI -+9 1 Compatible -+11 0 32M -+11 1 64M -+11 2 96M -+11 3 128M -+11 4 160M -+11 5 192M -+11 6 224M -+14 0 Normal -+14 1 Disabled -+ -+# ----------------------------------------------------------------- -+checksums -+ -+checksum 392 447 984 -diff --git a/src/mainboard/dell/e5520/data.vbt b/src/mainboard/dell/e5520/data.vbt -new file mode 100644 -index 0000000000000000000000000000000000000000..b511e75262e37fa123d674e9a7b21a8dfe427729 -GIT binary patch -literal 6144 -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 -H=7E0zE^L4Z - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/e5520/devicetree.cb b/src/mainboard/dell/e5520/devicetree.cb -new file mode 100644 -index 0000000000..bef96ac14c ---- /dev/null -+++ b/src/mainboard/dell/e5520/devicetree.cb -@@ -0,0 +1,66 @@ -+chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. -+ register "gfx" = "GMA_STATIC_DISPLAYS(1)" -+ register "gpu_cpu_backlight" = "0x00000218" -+ register "gpu_dp_b_hotplug" = "4" -+ register "gpu_dp_c_hotplug" = "4" -+ register "gpu_dp_d_hotplug" = "4" -+ register "gpu_panel_port_select" = "0" -+ register "gpu_panel_power_backlight_off_delay" = "2300" -+ register "gpu_panel_power_backlight_on_delay" = "2300" -+ register "gpu_panel_power_cycle_delay" = "6" -+ register "gpu_panel_power_down_delay" = "400" -+ register "gpu_panel_power_up_delay" = "400" -+ register "gpu_pch_backlight" = "0x13121312" -+ -+ register "spd_addresses" = "{0x50, 0, 0x52, 0}" -+ -+ device domain 0x0 on -+ subsystemid 0x1028 0x049a inherit -+ -+ device ref host_bridge on end # Host bridge -+ device ref peg10 on end # PEG -+ device ref igd on end # iGPU -+ -+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH -+ register "docking_supported" = "1" -+ register "gen1_dec" = "0x007c0681" -+ register "gen2_dec" = "0x007c0901" -+ register "gen3_dec" = "0x003c07e1" -+ register "gen4_dec" = "0x001c0901" -+ register "gpi0_routing" = "2" -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 0, 0, 0, 1, 0 }" -+ register "pcie_port_coalesce" = "1" -+ register "sata_interface_speed_support" = "0x3" -+ register "sata_port_map" = "0x3b" -+ register "spi_lvscc" = "0x2005" -+ register "spi_uvscc" = "0x2005" -+ -+ device ref mei1 off end -+ device ref mei2 off end -+ device ref me_ide_r off end -+ device ref me_kt off end -+ device ref gbe off end -+ device ref ehci2 on end -+ device ref hda on end -+ device ref pcie_rp1 on end -+ device ref pcie_rp2 on end -+ device ref pcie_rp3 on end -+ device ref pcie_rp4 off end -+ device ref pcie_rp5 on end -+ device ref pcie_rp6 on end -+ device ref pcie_rp7 on end -+ device ref pcie_rp8 off end -+ device ref ehci1 on end -+ device ref pci_bridge off end -+ device ref lpc on -+ chip ec/dell/mec5035 -+ device pnp ff.0 on end -+ end -+ end -+ device ref sata1 on end -+ device ref smbus on end -+ device ref sata2 off end -+ device ref thermal off end -+ end -+ end -+end -diff --git a/src/mainboard/dell/e5520/dsdt.asl b/src/mainboard/dell/e5520/dsdt.asl -new file mode 100644 -index 0000000000..7d13c55b08 ---- /dev/null -+++ b/src/mainboard/dell/e5520/dsdt.asl -@@ -0,0 +1,30 @@ -+#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB -+#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+ -+#include <acpi/acpi.h> -+ -+DefinitionBlock( -+ "dsdt.aml", -+ "DSDT", -+ ACPI_DSDT_REV_2, -+ OEM_ID, -+ ACPI_TABLE_CREATOR, -+ 0x20141018 /* OEM revision */ -+) -+{ -+ #include <acpi/dsdt_top.asl> -+ #include "acpi/platform.asl" -+ #include <cpu/intel/common/acpi/cpu.asl> -+ #include <southbridge/intel/common/acpi/platform.asl> -+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl> -+ #include <southbridge/intel/common/acpi/sleepstates.asl> -+ -+ Device (\_SB.PCI0) -+ { -+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl> -+ #include <drivers/intel/gma/acpi/default_brightness_levels.asl> -+ #include <southbridge/intel/bd82x6x/acpi/pch.asl> -+ } -+} -diff --git a/src/mainboard/dell/e5520/early_init.c b/src/mainboard/dell/e5520/early_init.c -new file mode 100644 -index 0000000000..7297921546 ---- /dev/null -+++ b/src/mainboard/dell/e5520/early_init.c -@@ -0,0 +1,32 @@ -+/* 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, 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 }, -+}; -+ -+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/e5520/gma-mainboard.ads b/src/mainboard/dell/e5520/gma-mainboard.ads -new file mode 100644 -index 0000000000..2a16f44360 ---- /dev/null -+++ b/src/mainboard/dell/e5520/gma-mainboard.ads -@@ -0,0 +1,20 @@ -+-- 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 := -+ ( -+ HDMI1, -- mainboard HDMI -+ DP2, -- dock DP -+ DP3, -- dock DP -+ Analog, -- mainboard VGA -+ LVDS, -+ others => Disabled); -+ -+end GMA.Mainboard; -diff --git a/src/mainboard/dell/e5520/gpio.c b/src/mainboard/dell/e5520/gpio.c -new file mode 100644 -index 0000000000..f76b93d9f0 ---- /dev/null -+++ b/src/mainboard/dell/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/e5520/hda_verb.c b/src/mainboard/dell/e5520/hda_verb.c -new file mode 100644 -index 0000000000..e2efee3646 ---- /dev/null -+++ b/src/mainboard/dell/e5520/hda_verb.c -@@ -0,0 +1,33 @@ -+/* 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/e5520/mainboard.c b/src/mainboard/dell/e5520/mainboard.c -new file mode 100644 -index 0000000000..31e49802fc ---- /dev/null -+++ b/src/mainboard/dell/e5520/mainboard.c -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/device.h> -+#include <drivers/intel/gma/int15.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+#include <ec/acpi/ec.h> -+#include <console/console.h> -+#include <pc80/keyboard.h> -+ -+static void mainboard_enable(struct device *dev) -+{ -+ -+ /* FIXME: fix these values. */ -+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, -+ GMA_INT15_PANEL_FIT_DEFAULT, -+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); -+} -+ -+struct chip_operations mainboard_ops = { -+ .enable_dev = mainboard_enable, -+}; --- -2.43.0 - diff --git a/config/coreboot/default/patches/0041-nb-haswell-Fully-disable-iGPU-when-dGPU-is-used.patch b/config/coreboot/default/patches/0036-nb-haswell-Fully-disable-iGPU-when-dGPU-is-used.patch index bc8fd55c..cf6f20bb 100644 --- a/config/coreboot/default/patches/0041-nb-haswell-Fully-disable-iGPU-when-dGPU-is-used.patch +++ b/config/coreboot/default/patches/0036-nb-haswell-Fully-disable-iGPU-when-dGPU-is-used.patch @@ -1,7 +1,7 @@ -From 0801b3ba8a0ce0109e30d27f405c912d5d705e9c Mon Sep 17 00:00:00 2001 +From dba9c3776f90bf345070a90c048ff2bae7180f73 Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sat, 6 Apr 2024 01:22:47 +0100 -Subject: [PATCH 1/1] nb/haswell: Fully disable iGPU when dGPU is used +Subject: [PATCH 36/65] 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 @@ -33,10 +33,10 @@ Signed-off-by: Leah Rowe <info@minifree.org> 1 file changed, 3 insertions(+) diff --git a/src/northbridge/intel/haswell/gma.c b/src/northbridge/intel/haswell/gma.c -index 48a0ba54c7..f0b848852d 100644 +index f7fad3183d..1b188e92e1 100644 --- a/src/northbridge/intel/haswell/gma.c +++ b/src/northbridge/intel/haswell/gma.c -@@ -465,6 +465,9 @@ static void gma_func0_disable(struct device *dev) +@@ -466,6 +466,9 @@ static void gma_func0_disable(struct device *dev) { /* Disable VGA decode */ pci_or_config16(pcidev_on_root(0, 0), GGC, 1 << 1); @@ -47,5 +47,5 @@ index 48a0ba54c7..f0b848852d 100644 static struct device_operations gma_func0_ops = { -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0037-ec-dell-mec5035-Replace-defines-with-enums.patch b/config/coreboot/default/patches/0037-ec-dell-mec5035-Replace-defines-with-enums.patch new file mode 100644 index 00000000..77011bce --- /dev/null +++ b/config/coreboot/default/patches/0037-ec-dell-mec5035-Replace-defines-with-enums.patch @@ -0,0 +1,91 @@ +From 7420608acfca1790756fd80d718b737352379dbe 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 37/38] 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.47.0 + diff --git a/config/coreboot/default/patches/0045-ec-dell-mec5035-Add-S3-suspend-SMI-handler.patch b/config/coreboot/default/patches/0038-ec-dell-mec5035-Add-S3-suspend-SMI-handler.patch index 97f14314..7c96d9f9 100644 --- a/config/coreboot/default/patches/0045-ec-dell-mec5035-Add-S3-suspend-SMI-handler.patch +++ b/config/coreboot/default/patches/0038-ec-dell-mec5035-Add-S3-suspend-SMI-handler.patch @@ -1,16 +1,37 @@ -From a8c4f7004ea1c9b8268a87dd0b700c250ec4747d Mon Sep 17 00:00:00 2001 +From 762f5d95d2314c3d09c1562d36d111dcdb9c8b93 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] ec/dell/mec5035: Add S3 suspend SMI handler +Subject: [PATCH 38/38] 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, +preventing the system from resuming. These commands were found using an +FPGA to log all LPC bus transactions between the host and the EC and +then narrowing down which ones were actually necessary. + +Interestingly, the command IDs appear to be identical to those in +ec/google/wilco, the EC used on Dell Latitude Chromebooks, and that EC +implements a similar S3 SMI handler as the one implemented in this +commit. The Wilco EC Kconfig does suggest that its firmware is a +modified version of Dell's usual Latitude EC firmware, so the +similarities seem to be intentional. + +These similarities also identified a command to enable or disable wake +sources like the power button and lid switch, and this was added to the +SMI handler to disable lid wake as the system does not yet resume +properly from a like wake with coreboot. + +Tested on the Latitude E6430 (Ivy Bridge) and the Precision M6800 +(Haswell, not yet pushed). Change-Id: I655868aba46911d128f6c24f410dc6fdf83f3070 Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> --- src/ec/dell/mec5035/Makefile.mk | 1 + src/ec/dell/mec5035/mec5035.c | 14 ++++++++++++++ - src/ec/dell/mec5035/mec5035.h | 19 +++++++++++++++++++ + src/ec/dell/mec5035/mec5035.h | 22 ++++++++++++++++++++++ src/ec/dell/mec5035/smihandler.c | 17 +++++++++++++++++ - 4 files changed, 51 insertions(+) + 4 files changed, 54 insertions(+) create mode 100644 src/ec/dell/mec5035/smihandler.c diff --git a/src/ec/dell/mec5035/Makefile.mk b/src/ec/dell/mec5035/Makefile.mk @@ -25,20 +46,13 @@ index 4ebdd811f9..be557e4599 100644 endif diff --git a/src/ec/dell/mec5035/mec5035.c b/src/ec/dell/mec5035/mec5035.c -index 68b6b2f7fb..33bf046634 100644 +index dffbb7960c..85c2ab0140 100644 --- a/src/ec/dell/mec5035/mec5035.c +++ b/src/ec/dell/mec5035/mec5035.c @@ -94,6 +94,20 @@ void mec5035_control_radio(enum ec_radio_dev dev, enum ec_radio_state state) ec_command(CMD_RADIO_CTRL); } -+void mec5035_sleep_enable(void) -+{ -+ u8 buf[SLEEP_EN_NUM_ARGS] = {3, 0}; -+ write_mailbox_regs(buf, 2, SLEEP_EN_NUM_ARGS); -+ ec_command(CMD_SLEEP_ENABLE); -+} -+ +void mec5035_change_wake(u8 source, enum ec_wake_change change) +{ + u8 buf[ACPI_WAKEUP_NUM_ARGS] = {change, source, 0, 0x40}; @@ -46,14 +60,21 @@ index 68b6b2f7fb..33bf046634 100644 + ec_command(CMD_ACPI_WAKEUP_CHANGE); +} + ++void mec5035_sleep_enable(void) ++{ ++ u8 buf[SLEEP_EN_NUM_ARGS] = {3, 0}; ++ write_mailbox_regs(buf, 2, SLEEP_EN_NUM_ARGS); ++ ec_command(CMD_SLEEP_ENABLE); ++} ++ void mec5035_early_init(void) { /* If this isn't sent the EC shuts down the system after about 15 diff --git a/src/ec/dell/mec5035/mec5035.h b/src/ec/dell/mec5035/mec5035.h -index fa15a9d621..069616fbc5 100644 +index 32f791cb01..8d4fded28b 100644 --- a/src/ec/dell/mec5035/mec5035.h +++ b/src/ec/dell/mec5035/mec5035.h -@@ -4,6 +4,7 @@ +@@ -4,12 +4,15 @@ #define _EC_DELL_MEC5035_H_ #include <stdint.h> @@ -61,37 +82,46 @@ index fa15a9d621..069616fbc5 100644 #define NUM_REGISTERS 32 -@@ -29,9 +30,27 @@ enum ec_radio_state { + enum mec5035_cmd { + CMD_MOUSE_TP = 0x1a, + CMD_RADIO_CTRL = 0x2b, ++ CMD_ACPI_WAKEUP_CHANGE = 0x4a, ++ CMD_SLEEP_ENABLE = 0x64, + CMD_CPU_OK = 0xc2, + }; + +@@ -33,9 +36,28 @@ enum ec_radio_state { RADIO_ON }; -+#define CMD_ACPI_WAKEUP_CHANGE 0x4a +#define ACPI_WAKEUP_NUM_ARGS 4 +enum ec_wake_change { + WAKE_OFF = 0, + WAKE_ON +}; ++ ++/* Copied from ec/google/wilco/commands.h. Not sure if these all apply */ +enum ec_acpi_wake_events { + EC_ACPI_WAKE_PWRB = BIT(0), /* Wake up by power button */ + EC_ACPI_WAKE_LID = BIT(1), /* Wake up by lid switch */ + EC_ACPI_WAKE_RTC = BIT(5), /* Wake up by RTC */ +}; + -+#define CMD_SLEEP_ENABLE 0x64 +#define SLEEP_EN_NUM_ARGS 2 + - 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); -+void mec5035_sleep(int slp_type); +void mec5035_change_wake(u8 source, enum ec_wake_change change); +void mec5035_sleep_enable(void); ++ ++void mec5035_smi_sleep(int slp_type); #endif /* _EC_DELL_MEC5035_H_ */ diff --git a/src/ec/dell/mec5035/smihandler.c b/src/ec/dell/mec5035/smihandler.c new file mode 100644 -index 0000000000..1db834773d +index 0000000000..958733bf97 --- /dev/null +++ b/src/ec/dell/mec5035/smihandler.c @@ -0,0 +1,17 @@ @@ -102,7 +132,7 @@ index 0000000000..1db834773d +#include <ec/acpi/ec.h> +#include "mec5035.h" + -+void mec5035_sleep(int slp_type) ++void mec5035_smi_sleep(int slp_type) +{ + switch (slp_type) { + case ACPI_S3: @@ -113,5 +143,5 @@ index 0000000000..1db834773d + } +} -- -2.44.0 +2.47.0 diff --git a/config/coreboot/default/patches/0038-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch b/config/coreboot/default/patches/0038-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch deleted file mode 100644 index 11f95a63..00000000 --- a/config/coreboot/default/patches/0038-mb-dell-Add-Latitude-E5420-Sandy-Bridge.patch +++ /dev/null @@ -1,774 +0,0 @@ -From 7dd58c8b301404a8bafee25a1e97a8a5d614b3d6 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] mb/dell: Add Latitude E5420 (Sandy Bridge) - ---- - src/mainboard/dell/e5420/Kconfig | 37 ++++ - src/mainboard/dell/e5420/Kconfig.name | 2 + - src/mainboard/dell/e5420/Makefile.mk | 5 + - src/mainboard/dell/e5420/acpi/ec.asl | 9 + - src/mainboard/dell/e5420/acpi/platform.asl | 12 ++ - src/mainboard/dell/e5420/acpi/superio.asl | 3 + - src/mainboard/dell/e5420/acpi_tables.c | 16 ++ - src/mainboard/dell/e5420/board_info.txt | 6 + - src/mainboard/dell/e5420/cmos.default | 9 + - src/mainboard/dell/e5420/cmos.layout | 88 ++++++++++ - src/mainboard/dell/e5420/data.vbt | Bin 0 -> 6144 bytes - src/mainboard/dell/e5420/devicetree.cb | 66 +++++++ - src/mainboard/dell/e5420/dsdt.asl | 30 ++++ - src/mainboard/dell/e5420/early_init.c | 32 ++++ - src/mainboard/dell/e5420/gma-mainboard.ads | 20 +++ - src/mainboard/dell/e5420/gpio.c | 195 +++++++++++++++++++++ - src/mainboard/dell/e5420/hda_verb.c | 33 ++++ - src/mainboard/dell/e5420/mainboard.c | 21 +++ - 18 files changed, 584 insertions(+) - create mode 100644 src/mainboard/dell/e5420/Kconfig - create mode 100644 src/mainboard/dell/e5420/Kconfig.name - create mode 100644 src/mainboard/dell/e5420/Makefile.mk - create mode 100644 src/mainboard/dell/e5420/acpi/ec.asl - create mode 100644 src/mainboard/dell/e5420/acpi/platform.asl - create mode 100644 src/mainboard/dell/e5420/acpi/superio.asl - create mode 100644 src/mainboard/dell/e5420/acpi_tables.c - create mode 100644 src/mainboard/dell/e5420/board_info.txt - create mode 100644 src/mainboard/dell/e5420/cmos.default - create mode 100644 src/mainboard/dell/e5420/cmos.layout - create mode 100755 src/mainboard/dell/e5420/data.vbt - create mode 100644 src/mainboard/dell/e5420/devicetree.cb - create mode 100644 src/mainboard/dell/e5420/dsdt.asl - create mode 100644 src/mainboard/dell/e5420/early_init.c - create mode 100644 src/mainboard/dell/e5420/gma-mainboard.ads - create mode 100644 src/mainboard/dell/e5420/gpio.c - create mode 100644 src/mainboard/dell/e5420/hda_verb.c - create mode 100644 src/mainboard/dell/e5420/mainboard.c - -diff --git a/src/mainboard/dell/e5420/Kconfig b/src/mainboard/dell/e5420/Kconfig -new file mode 100644 -index 0000000000..f4385045ae ---- /dev/null -+++ b/src/mainboard/dell/e5420/Kconfig -@@ -0,0 +1,37 @@ -+if BOARD_DELL_LATITUDE_E5420 -+ -+config BOARD_SPECIFIC_OPTIONS -+ def_bool y -+ select BOARD_ROMSIZE_KB_6144 -+ select EC_ACPI -+ select EC_DELL_MEC5035 -+ select GFX_GMA_PANEL_1_ON_LVDS -+ select HAVE_ACPI_RESUME -+ select HAVE_ACPI_TABLES -+ select HAVE_CMOS_DEFAULT -+ select HAVE_OPTION_TABLE -+ select INTEL_GMA_HAVE_VBT -+ select INTEL_INT15 -+ select MAINBOARD_HAS_LIBGFXINIT -+ select NORTHBRIDGE_INTEL_SANDYBRIDGE -+ select SERIRQ_CONTINUOUS_MODE -+ select SOUTHBRIDGE_INTEL_BD82X6X -+ select SYSTEM_TYPE_LAPTOP -+ select USE_NATIVE_RAMINIT -+ -+config DRAM_RESET_GATE_GPIO -+ default 60 -+ -+config MAINBOARD_DIR -+ default "dell/e5420" -+ -+config MAINBOARD_PART_NUMBER -+ default "Latitude E5420" -+ -+config USBDEBUG_HCD_INDEX -+ default 2 -+ -+config VGA_BIOS_ID -+ default "8086,0116" -+ -+endif # BOARD_DELL_LATITUDE_E5420 -diff --git a/src/mainboard/dell/e5420/Kconfig.name b/src/mainboard/dell/e5420/Kconfig.name -new file mode 100644 -index 0000000000..eb495fb705 ---- /dev/null -+++ b/src/mainboard/dell/e5420/Kconfig.name -@@ -0,0 +1,2 @@ -+config BOARD_DELL_LATITUDE_E5420 -+ bool "Latitude E5420" -diff --git a/src/mainboard/dell/e5420/Makefile.mk b/src/mainboard/dell/e5420/Makefile.mk -new file mode 100644 -index 0000000000..18391d8b18 ---- /dev/null -+++ b/src/mainboard/dell/e5420/Makefile.mk -@@ -0,0 +1,5 @@ -+bootblock-y += early_init.c -+bootblock-y += gpio.c -+romstage-y += early_init.c -+romstage-y += gpio.c -+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads -diff --git a/src/mainboard/dell/e5420/acpi/ec.asl b/src/mainboard/dell/e5420/acpi/ec.asl -new file mode 100644 -index 0000000000..0d429410a9 ---- /dev/null -+++ b/src/mainboard/dell/e5420/acpi/ec.asl -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Device(EC) -+{ -+ Name (_HID, EISAID("PNP0C09")) -+ Name (_UID, 0) -+ Name (_GPE, 16) -+/* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e5420/acpi/platform.asl b/src/mainboard/dell/e5420/acpi/platform.asl -new file mode 100644 -index 0000000000..2d24bbd9b9 ---- /dev/null -+++ b/src/mainboard/dell/e5420/acpi/platform.asl -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+Method(_WAK, 1) -+{ -+ /* FIXME: EC support */ -+ Return(Package() {0, 0}) -+} -+ -+Method(_PTS,1) -+{ -+ /* FIXME: EC support */ -+} -diff --git a/src/mainboard/dell/e5420/acpi/superio.asl b/src/mainboard/dell/e5420/acpi/superio.asl -new file mode 100644 -index 0000000000..55b1db5b11 ---- /dev/null -+++ b/src/mainboard/dell/e5420/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/dell/e5420/acpi_tables.c b/src/mainboard/dell/e5420/acpi_tables.c -new file mode 100644 -index 0000000000..e2759659bf ---- /dev/null -+++ b/src/mainboard/dell/e5420/acpi_tables.c -@@ -0,0 +1,16 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <acpi/acpi_gnvs.h> -+#include <soc/nvs.h> -+ -+/* FIXME: check this function. */ -+void mainboard_fill_gnvs(struct global_nvs *gnvs) -+{ -+ /* The lid is open by default. */ -+ gnvs->lids = 1; -+ -+ /* Temperature at which OS will shutdown */ -+ gnvs->tcrt = 100; -+ /* Temperature at which OS will throttle CPU */ -+ gnvs->tpsv = 90; -+} -diff --git a/src/mainboard/dell/e5420/board_info.txt b/src/mainboard/dell/e5420/board_info.txt -new file mode 100644 -index 0000000000..34d5ad9e0b ---- /dev/null -+++ b/src/mainboard/dell/e5420/board_info.txt -@@ -0,0 +1,6 @@ -+Category: laptop -+ROM package: SOIC-8 -+ROM protocol: SPI -+ROM socketed: n -+Flashrom support: y -+Release year: 2011 -diff --git a/src/mainboard/dell/e5420/cmos.default b/src/mainboard/dell/e5420/cmos.default -new file mode 100644 -index 0000000000..279415dfd1 ---- /dev/null -+++ b/src/mainboard/dell/e5420/cmos.default -@@ -0,0 +1,9 @@ -+boot_option=Fallback -+debug_level=Debug -+power_on_after_fail=Disable -+nmi=Enable -+bluetooth=Enable -+wwan=Enable -+wlan=Enable -+sata_mode=AHCI -+me_state=Disabled -diff --git a/src/mainboard/dell/e5420/cmos.layout b/src/mainboard/dell/e5420/cmos.layout -new file mode 100644 -index 0000000000..1aa7e77bce ---- /dev/null -+++ b/src/mainboard/dell/e5420/cmos.layout -@@ -0,0 +1,88 @@ -+## 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 -+ -+#400 8 r 0 reserved for century byte -+ -+# coreboot config options: southbridge -+408 1 e 1 nmi -+409 2 e 7 power_on_after_fail -+411 1 e 9 sata_mode -+ -+# coreboot config options: EC -+412 1 e 1 bluetooth -+413 1 e 1 wwan -+414 1 e 1 wlan -+ -+# coreboot config options: ME -+424 1 e 14 me_state -+425 2 h 0 me_state_prev -+ -+# coreboot config options: northbridge -+432 3 e 11 gfx_uma_size -+435 2 e 12 hybrid_graphics_mode -+440 8 h 0 volume -+ -+# VBOOT -+448 128 r 0 vbnv -+ -+# SandyBridge MRC Scrambler Seed values -+896 32 r 0 mrc_scrambler_seed -+928 32 r 0 mrc_scrambler_seed_s3 -+960 16 r 0 mrc_scrambler_seed_chk -+ -+# 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 -+9 0 AHCI -+9 1 Compatible -+11 0 32M -+11 1 64M -+11 2 96M -+11 3 128M -+11 4 160M -+11 5 192M -+11 6 224M -+14 0 Normal -+14 1 Disabled -+ -+# ----------------------------------------------------------------- -+checksums -+ -+checksum 392 447 984 -diff --git a/src/mainboard/dell/e5420/data.vbt b/src/mainboard/dell/e5420/data.vbt -new file mode 100755 -index 0000000000000000000000000000000000000000..98b82fe6110fd295b5749041ec7f8c084ace5f57 -GIT binary patch -literal 6144 -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 -X1LGbT_rSOZ#yv3ZfpHH!G!Og(1Xg~J - -literal 0 -HcmV?d00001 - -diff --git a/src/mainboard/dell/e5420/devicetree.cb b/src/mainboard/dell/e5420/devicetree.cb -new file mode 100644 -index 0000000000..f26413557d ---- /dev/null -+++ b/src/mainboard/dell/e5420/devicetree.cb -@@ -0,0 +1,66 @@ -+chip northbridge/intel/sandybridge # FIXME: GPU registers may not always apply. -+ register "gfx" = "GMA_STATIC_DISPLAYS(1)" -+ register "gpu_cpu_backlight" = "0x00000c31" -+ register "gpu_dp_b_hotplug" = "4" -+ register "gpu_dp_c_hotplug" = "4" -+ register "gpu_dp_d_hotplug" = "4" -+ register "gpu_panel_port_select" = "0" -+ register "gpu_panel_power_backlight_off_delay" = "2300" -+ register "gpu_panel_power_backlight_on_delay" = "2300" -+ register "gpu_panel_power_cycle_delay" = "6" -+ register "gpu_panel_power_down_delay" = "400" -+ register "gpu_panel_power_up_delay" = "400" -+ register "gpu_pch_backlight" = "0x13121312" -+ -+ register "spd_addresses" = "{0x50, 0, 0x52, 0}" -+ -+ device domain 0x0 on -+ subsystemid 0x1028 0x049b inherit -+ -+ device ref host_bridge on end # Host bridge -+ device ref peg10 on end # PEG -+ device ref igd on end # iGPU -+ -+ chip southbridge/intel/bd82x6x # Intel Series 6 Cougar Point PCH -+ register "docking_supported" = "1" -+ register "gen1_dec" = "0x007c0681" -+ register "gen2_dec" = "0x007c0901" -+ register "gen3_dec" = "0x003c07e1" -+ register "gen4_dec" = "0x001c0901" -+ register "gpi0_routing" = "2" -+ register "pcie_hotplug_map" = "{ 0, 0, 1, 0, 0, 0, 1, 0 }" -+ register "pcie_port_coalesce" = "1" -+ register "sata_interface_speed_support" = "0x3" -+ register "sata_port_map" = "0x3b" -+ register "spi_lvscc" = "0x2005" -+ register "spi_uvscc" = "0x2005" -+ -+ device ref mei1 off end -+ device ref mei2 off end -+ device ref me_ide_r off end -+ device ref me_kt off end -+ device ref gbe off end -+ device ref ehci2 on end -+ device ref hda on end -+ device ref pcie_rp1 on end -+ device ref pcie_rp2 on end -+ device ref pcie_rp3 on end -+ device ref pcie_rp4 off end -+ device ref pcie_rp5 on end -+ device ref pcie_rp6 on end -+ device ref pcie_rp7 on end -+ device ref pcie_rp8 off end -+ device ref ehci1 on end -+ device ref pci_bridge off end -+ device ref lpc on -+ chip ec/dell/mec5035 -+ device pnp ff.0 on end -+ end -+ end -+ device ref sata1 on end -+ device ref smbus on end -+ device ref sata2 off end -+ device ref thermal off end -+ end -+ end -+end -diff --git a/src/mainboard/dell/e5420/dsdt.asl b/src/mainboard/dell/e5420/dsdt.asl -new file mode 100644 -index 0000000000..7d13c55b08 ---- /dev/null -+++ b/src/mainboard/dell/e5420/dsdt.asl -@@ -0,0 +1,30 @@ -+#define BRIGHTNESS_UP \_SB.PCI0.GFX0.INCB -+#define BRIGHTNESS_DOWN \_SB.PCI0.GFX0.DECB -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+ -+#include <acpi/acpi.h> -+ -+DefinitionBlock( -+ "dsdt.aml", -+ "DSDT", -+ ACPI_DSDT_REV_2, -+ OEM_ID, -+ ACPI_TABLE_CREATOR, -+ 0x20141018 /* OEM revision */ -+) -+{ -+ #include <acpi/dsdt_top.asl> -+ #include "acpi/platform.asl" -+ #include <cpu/intel/common/acpi/cpu.asl> -+ #include <southbridge/intel/common/acpi/platform.asl> -+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl> -+ #include <southbridge/intel/common/acpi/sleepstates.asl> -+ -+ Device (\_SB.PCI0) -+ { -+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl> -+ #include <drivers/intel/gma/acpi/default_brightness_levels.asl> -+ #include <southbridge/intel/bd82x6x/acpi/pch.asl> -+ } -+} -diff --git a/src/mainboard/dell/e5420/early_init.c b/src/mainboard/dell/e5420/early_init.c -new file mode 100644 -index 0000000000..7297921546 ---- /dev/null -+++ b/src/mainboard/dell/e5420/early_init.c -@@ -0,0 +1,32 @@ -+/* 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, 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 }, -+}; -+ -+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/e5420/gma-mainboard.ads b/src/mainboard/dell/e5420/gma-mainboard.ads -new file mode 100644 -index 0000000000..2a16f44360 ---- /dev/null -+++ b/src/mainboard/dell/e5420/gma-mainboard.ads -@@ -0,0 +1,20 @@ -+-- 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 := -+ ( -+ HDMI1, -- mainboard HDMI -+ DP2, -- dock DP -+ DP3, -- dock DP -+ Analog, -- mainboard VGA -+ LVDS, -+ others => Disabled); -+ -+end GMA.Mainboard; -diff --git a/src/mainboard/dell/e5420/gpio.c b/src/mainboard/dell/e5420/gpio.c -new file mode 100644 -index 0000000000..f76b93d9f0 ---- /dev/null -+++ b/src/mainboard/dell/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/e5420/hda_verb.c b/src/mainboard/dell/e5420/hda_verb.c -new file mode 100644 -index 0000000000..70e7c2e79a ---- /dev/null -+++ b/src/mainboard/dell/e5420/hda_verb.c -@@ -0,0 +1,33 @@ -+/* 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/e5420/mainboard.c b/src/mainboard/dell/e5420/mainboard.c -new file mode 100644 -index 0000000000..31e49802fc ---- /dev/null -+++ b/src/mainboard/dell/e5420/mainboard.c -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <device/device.h> -+#include <drivers/intel/gma/int15.h> -+#include <southbridge/intel/bd82x6x/pch.h> -+#include <ec/acpi/ec.h> -+#include <console/console.h> -+#include <pc80/keyboard.h> -+ -+static void mainboard_enable(struct device *dev) -+{ -+ -+ /* FIXME: fix these values. */ -+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_INT_LVDS, -+ GMA_INT15_PANEL_FIT_DEFAULT, -+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0); -+} -+ -+struct chip_operations mainboard_ops = { -+ .enable_dev = mainboard_enable, -+}; --- -2.44.0 - diff --git a/config/coreboot/default/patches/0039-fix-sata-ports-on-dell-9020-sff-and-mt.patch b/config/coreboot/default/patches/0039-fix-sata-ports-on-dell-9020-sff-and-mt.patch deleted file mode 100644 index f4c3939c..00000000 --- a/config/coreboot/default/patches/0039-fix-sata-ports-on-dell-9020-sff-and-mt.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 4889f08306f1530211dcc6f6a4e999c6cc72f3ac Mon Sep 17 00:00:00 2001 -From: Leah Rowe <info@minifree.org> -Date: Sat, 30 Mar 2024 05:57:54 +0000 -Subject: [PATCH 1/1] fix sata ports on dell 9020 sff and mt - -mate kukri has a patch under review on coreboot that sets -sata port map to 0x7 on sff and 0xf on mt. - -see: intel 8 series pch datasheet, section 13.1.35 - -basically, the 6 least significant bits enable the sata -slots; 1 for enable and 0 for disable. there can be up -to 6 ports. least significant bit is port 0, then next -is port 1, and so on. - -coreboot currently enables ports 0, 1, 4 and 5, making this -value 0x33 (converted to binary: 00110011). sff has ports -0, 1 and 2 wired, so mate changed that to 0x7 (00000111). - -on mt, the blue ports are ports 0 and 1, but the two white -ports don't work, but coreboot enables 4 and 5; it is -likely that the blue ports are in fact 0 and 1, and the -white ports are 2 and 3, but we've not tested this! - -it could be that the blue ports are ports 4 and 5, and -the white ports are 2 and 3! we have not yet determined -this, but mate set it to 0xf, meaning ports 0 1 2 and 3 -are enabled, in his patch under review. the chance that -it's 2, 3, 4 and 5 on the board is unlikely, but it is -theoretically possible and has not been confirmed. - -therefore, for now, i will set the value to 0x3f, which -in binary is 00111111, thus enabling all 6 slots. the two -that aren't physically wired don't really matter. enabling -ports (from the pch) that electrically aren't there and -then powering on is electrically equivalent to those ports -being actually being wired, but with no devices plugged -into them. therefore, 0x3f is an effective shotgun fix. - -i'll remove this patch and use mate's fix when the latter -has been tested on MT; it has already been tested on SFF. - -this patch fixes the 3rd sata slot on 9020 sff, and the 3rd -and 4th sata slots on 9020 MT - -Signed-off-by: Leah Rowe <info@minifree.org> ---- - src/mainboard/dell/optiplex_9020/devicetree.cb | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/mainboard/dell/optiplex_9020/devicetree.cb b/src/mainboard/dell/optiplex_9020/devicetree.cb -index c0b17a15ff..7bfa6736a6 100644 ---- a/src/mainboard/dell/optiplex_9020/devicetree.cb -+++ b/src/mainboard/dell/optiplex_9020/devicetree.cb -@@ -23,7 +23,7 @@ chip northbridge/intel/haswell - register "gen2_dec" = "0x007c0901" - register "gen3_dec" = "0x003c07e1" - register "gen4_dec" = "0x001c0901" -- register "sata_port_map" = "0x33" -+ register "sata_port_map" = "0x3f" - - device pci 14.0 on end # xHCI controller - device pci 16.0 on end # Management Engine interface 1 --- -2.39.2 - diff --git a/config/coreboot/default/patches/0047-nb-haswell-lock-policy-regs-when-disabling-IOMMU.patch b/config/coreboot/default/patches/0039-nb-haswell-lock-policy-regs-when-disabling-IOMMU.patch index a7af707e..2b5173c5 100644 --- a/config/coreboot/default/patches/0047-nb-haswell-lock-policy-regs-when-disabling-IOMMU.patch +++ b/config/coreboot/default/patches/0039-nb-haswell-lock-policy-regs-when-disabling-IOMMU.patch @@ -1,7 +1,7 @@ -From fa4f05e39744eb4c4606f940b8acc7fd053b11d4 Mon Sep 17 00:00:00 2001 +From b24c5caf5a8f63555d3b71e7a786c822a4c262cc Mon Sep 17 00:00:00 2001 From: Leah Rowe <info@minifree.org> Date: Sat, 4 May 2024 02:00:53 +0100 -Subject: [PATCH 1/1] nb/haswell: lock policy regs when disabling IOMMU +Subject: [PATCH 39/65] 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 @@ -51,5 +51,5 @@ index 1a7e0b1076..e9506ee830 100644 /* Set L3HIT2PEND_DIS, lock GFXVTBAR policy config registers */ u32 reg32; -- -2.39.2 +2.39.5 diff --git a/config/coreboot/default/patches/0040-nb-haswell-Disable-iGPU-when-dGPU-is-used.patch b/config/coreboot/default/patches/0040-nb-haswell-Disable-iGPU-when-dGPU-is-used.patch deleted file mode 100644 index 7a02d902..00000000 --- a/config/coreboot/default/patches/0040-nb-haswell-Disable-iGPU-when-dGPU-is-used.patch +++ /dev/null @@ -1,54 +0,0 @@ -From c6ce9c635e6576c86c546177c3d770dec2f3c9ae Mon Sep 17 00:00:00 2001 -From: Leah Rowe <info@minifree.org> -Date: Fri, 23 Feb 2024 13:33:31 +0000 -Subject: [PATCH 1/1] nb/haswell: Disable iGPU when dGPU is used - -This is usually is handled by Haswell mrc.bin, disabling VGA -decode on the iGPU when a dGPU is installed. However, Broadwell -mrc.bin does not, so the iGPU and dGPU are both enabled. - -This patch disables legacy VGA cycles for iGPU, under such -conditions. It has been tested on Broadwell mrc.bin when -using a graphics card on Dell OptiPlex 9020 SFF (currently -under review at this time of writing, submitted by Mate -Kukri). - -This patch has also been tested when Haswell mrc.bin is used, -and there are seemingly no breaking changes caused by it. - -Change-Id: I1df0a3aa42f8475b7741007bf3e28c2e089d916b -Signed-off-by: Leah Rowe <info@minifree.org> -Reviewed-on: https://review.coreboot.org/c/coreboot/+/80717 -Tested-by: build bot (Jenkins) <no-reply@coreboot.org> -Reviewed-by: Nico Huber <nico.h@gmx.de> ---- - src/northbridge/intel/haswell/gma.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/src/northbridge/intel/haswell/gma.c b/src/northbridge/intel/haswell/gma.c -index 6e6948b70f..48a0ba54c7 100644 ---- a/src/northbridge/intel/haswell/gma.c -+++ b/src/northbridge/intel/haswell/gma.c -@@ -461,12 +461,19 @@ static void gma_generate_ssdt(const struct device *dev) - drivers_intel_gma_displays_ssdt_generate(&chip->gfx); - } - -+static void gma_func0_disable(struct device *dev) -+{ -+ /* Disable VGA decode */ -+ pci_or_config16(pcidev_on_root(0, 0), GGC, 1 << 1); -+} -+ - static struct device_operations gma_func0_ops = { - .read_resources = pci_dev_read_resources, - .set_resources = pci_dev_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = gma_func0_init, - .acpi_fill_ssdt = gma_generate_ssdt, -+ .vga_disable = gma_func0_disable, - .ops_pci = &pci_dev_ops_pci, - }; - --- -2.39.2 - diff --git a/config/coreboot/default/patches/0040-nb-intel-gm45-Make-DDR2-raminit-work.patch b/config/coreboot/default/patches/0040-nb-intel-gm45-Make-DDR2-raminit-work.patch new file mode 100644 index 00000000..a75edd47 --- /dev/null +++ b/config/coreboot/default/patches/0040-nb-intel-gm45-Make-DDR2-raminit-work.patch @@ -0,0 +1,223 @@ +From c41e97f85f2a2677c742d62e3080af7cfeb2ef23 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Mon, 10 May 2021 22:40:59 +0200 +Subject: [PATCH 40/65] nb/intel/gm45: Make DDR2 raminit work + +List of changes: + - Update some timing and ODT values + - Patch RCOMP calibration to better match what MRC binaries do + - Replay a hardcoded list of RCOMP codes after RcvEn + +This makes raminit work at DDR2-800 speeds and fixes S3 resume as well. +Tested on Toshiba Satellite A300-1ME with two 2 GiB DDR2-800 SO-DIMMs. + +Change-Id: Ibaee524b8ff652ddadd66cb0eb680401b988ff7c +Signed-off-by: Angel Pons <th3fanbus@gmail.com> +--- + src/northbridge/intel/gm45/gm45.h | 2 +- + src/northbridge/intel/gm45/raminit.c | 90 +++++++++++++++++-- + .../intel/gm45/raminit_rcomp_calibration.c | 27 ++++-- + 3 files changed, 106 insertions(+), 13 deletions(-) + +diff --git a/src/northbridge/intel/gm45/gm45.h b/src/northbridge/intel/gm45/gm45.h +index 5d9ac56606..338260ea7a 100644 +--- a/src/northbridge/intel/gm45/gm45.h ++++ b/src/northbridge/intel/gm45/gm45.h +@@ -420,7 +420,7 @@ void igd_compute_ggc(sysinfo_t *const sysinfo); + int raminit_read_vco_index(void); + u32 raminit_get_rank_addr(unsigned int channel, unsigned int rank); + +-void raminit_rcomp_calibration(stepping_t stepping); ++void raminit_rcomp_calibration(int ddr_type, stepping_t stepping); + void raminit_reset_readwrite_pointers(void); + void raminit_receive_enable_calibration(int ddr_type, const timings_t *, const dimminfo_t *); + void raminit_write_training(const mem_clock_t, const dimminfo_t *, int s3resume); +diff --git a/src/northbridge/intel/gm45/raminit.c b/src/northbridge/intel/gm45/raminit.c +index b7e013959a..df8f46fbbc 100644 +--- a/src/northbridge/intel/gm45/raminit.c ++++ b/src/northbridge/intel/gm45/raminit.c +@@ -1047,7 +1047,7 @@ static void rcomp_initialization(const int spd_type, const stepping_t stepping, + } + + /* Perform RCOMP calibration for DDR3. */ +- raminit_rcomp_calibration(stepping); ++ raminit_rcomp_calibration(spd_type, stepping); + + /* Run initial RCOMP. */ + mchbar_setbits32(0x418, 1 << 17); +@@ -1117,7 +1117,7 @@ static void dram_program_timings(const int spd_type, const timings_t *const timi + reg = (reg & ~(0xf << 10)) | (2 << 10); + else + reg = (reg & ~(0xf << 10)) | (3 << 10); +- reg = (reg & ~(0x7 << 5)) | (3 << 5); ++ reg = (reg & ~(0x7 << 5)) | (2 << 5); + } else if (timings->mem_clock != MEM_CLOCK_1067MT) { + reg = (reg & ~(0x7 << 15)) | ((9 - timings->CAS) << 15); + reg = (reg & ~(0xf << 10)) | ((timings->CAS - 3) << 10); +@@ -1286,11 +1286,11 @@ static void ddr2_odt_setup(const timings_t *const timings, const int sff) + reg = (reg & ~(0xf << (44 - 32))) | (8 << (44 - 32)); + reg = (reg & ~(0xf << (40 - 32))) | (7 << (40 - 32)); + if (timings->mem_clock == MEM_CLOCK_667MT) { +- reg = (reg & ~(0xf << (36 - 32))) | (4 << (36 - 32)); +- reg = (reg & ~(0xf << (32 - 32))) | (4 << (32 - 32)); ++ reg = (reg & ~(0xf << (36 - 32))) | (8 << (36 - 32)); ++ reg = (reg & ~(0xf << (32 - 32))) | (8 << (32 - 32)); + } else { +- reg = (reg & ~(0xf << (36 - 32))) | (5 << (36 - 32)); +- reg = (reg & ~(0xf << (32 - 32))) | (5 << (32 - 32)); ++ reg = (reg & ~(0xf << (36 - 32))) | (9 << (36 - 32)); ++ reg = (reg & ~(0xf << (32 - 32))) | (9 << (32 - 32)); + } + mchbar_write32(CxODT_HIGH(ch), reg); + +@@ -2209,6 +2209,84 @@ void raminit(sysinfo_t *const sysinfo, const int s3resume) + raminit_write_training(timings->mem_clock, dimms, s3resume); + } + ++ /* ++ * Program hardcoded DDR2-800 RCOMP SRAM codes. This must be done ++ * after receiver enable calibration, otherwise raminit sometimes ++ * completes with non-working memory. ++ */ ++ mchbar_write32(0x0530, 0x06060005); ++ mchbar_write32(0x0680, 0x06060606); ++ mchbar_write32(0x0684, 0x08070606); ++ mchbar_write32(0x0688, 0x0e0e0c0a); ++ mchbar_write32(0x068c, 0x0e0e0e0e); ++ mchbar_write32(0x0698, 0x06060606); ++ mchbar_write32(0x069c, 0x08070606); ++ mchbar_write32(0x06a0, 0x0c0c0b0a); ++ mchbar_write32(0x06a4, 0x0c0c0c0c); ++ ++ mchbar_write32(0x06c0, 0x02020202); ++ mchbar_write32(0x06c4, 0x03020202); ++ mchbar_write32(0x06c8, 0x04040403); ++ mchbar_write32(0x06cc, 0x04040404); ++ mchbar_write32(0x06d8, 0x02020202); ++ mchbar_write32(0x06dc, 0x03020202); ++ mchbar_write32(0x06e0, 0x04040403); ++ mchbar_write32(0x06e4, 0x04040404); ++ ++ mchbar_write32(0x0700, 0x02020202); ++ mchbar_write32(0x0704, 0x03020202); ++ mchbar_write32(0x0708, 0x04040403); ++ mchbar_write32(0x070c, 0x04040404); ++ mchbar_write32(0x0718, 0x02020202); ++ mchbar_write32(0x071c, 0x03020202); ++ mchbar_write32(0x0720, 0x04040403); ++ mchbar_write32(0x0724, 0x04040404); ++ ++ mchbar_write32(0x0740, 0x02020202); ++ mchbar_write32(0x0744, 0x03020202); ++ mchbar_write32(0x0748, 0x04040403); ++ mchbar_write32(0x074c, 0x04040404); ++ mchbar_write32(0x0758, 0x02020202); ++ mchbar_write32(0x075c, 0x03020202); ++ mchbar_write32(0x0760, 0x04040403); ++ mchbar_write32(0x0764, 0x04040404); ++ ++ mchbar_write32(0x0780, 0x06060606); ++ mchbar_write32(0x0784, 0x09070606); ++ mchbar_write32(0x0788, 0x0e0e0c0b); ++ mchbar_write32(0x078c, 0x0e0e0e0e); ++ mchbar_write32(0x0798, 0x06060606); ++ mchbar_write32(0x079c, 0x09070606); ++ mchbar_write32(0x07a0, 0x0d0d0c0b); ++ mchbar_write32(0x07a4, 0x0d0d0d0d); ++ ++ mchbar_write32(0x07c0, 0x06060606); ++ mchbar_write32(0x07c4, 0x09070606); ++ mchbar_write32(0x07c8, 0x0e0e0c0b); ++ mchbar_write32(0x07cc, 0x0e0e0e0e); ++ mchbar_write32(0x07d8, 0x06060606); ++ mchbar_write32(0x07dc, 0x09070606); ++ mchbar_write32(0x07e0, 0x0d0d0c0b); ++ mchbar_write32(0x07e4, 0x0d0d0d0d); ++ ++ mchbar_write32(0x0840, 0x06060606); ++ mchbar_write32(0x0844, 0x08070606); ++ mchbar_write32(0x0848, 0x0e0e0c0a); ++ mchbar_write32(0x084c, 0x0e0e0e0e); ++ mchbar_write32(0x0858, 0x06060606); ++ mchbar_write32(0x085c, 0x08070606); ++ mchbar_write32(0x0860, 0x0c0c0b0a); ++ mchbar_write32(0x0864, 0x0c0c0c0c); ++ ++ mchbar_write32(0x0880, 0x02020202); ++ mchbar_write32(0x0884, 0x03020202); ++ mchbar_write32(0x0888, 0x04040403); ++ mchbar_write32(0x088c, 0x04040404); ++ mchbar_write32(0x0898, 0x02020202); ++ mchbar_write32(0x089c, 0x03020202); ++ mchbar_write32(0x08a0, 0x04040403); ++ mchbar_write32(0x08a4, 0x04040404); ++ + igd_compute_ggc(sysinfo); + + /* Program final memory map (with real values). */ +diff --git a/src/northbridge/intel/gm45/raminit_rcomp_calibration.c b/src/northbridge/intel/gm45/raminit_rcomp_calibration.c +index aef863f05a..b74765fd9c 100644 +--- a/src/northbridge/intel/gm45/raminit_rcomp_calibration.c ++++ b/src/northbridge/intel/gm45/raminit_rcomp_calibration.c +@@ -161,11 +161,13 @@ static void lookup_and_write(const int a1step, + mchbar += 4; + } + } +-void raminit_rcomp_calibration(const stepping_t stepping) { ++void raminit_rcomp_calibration(int ddr_type, const stepping_t stepping) { + const int a1step = stepping >= STEPPING_CONVERSION_A1; + + int i; + ++ char magic_comp[2] = {0}; ++ + enum { + PULL_UP = 0, + PULL_DOWN = 1, +@@ -196,6 +198,10 @@ void raminit_rcomp_calibration(const stepping_t stepping) { + reg = mchbar_read32(0x518); + lut_idx[channel][group][PULL_UP] = (reg >> 24) & 0x7f; + lut_idx[channel][group][PULL_DOWN] = (reg >> 16) & 0x7f; ++ if (i == 1) { ++ magic_comp[0] = (reg >> 8) & 0x3f; ++ magic_comp[1] = (reg >> 0) & 0x3f; ++ } + } + /* Cleanup? */ + mchbar_setbits32(0x400, 1 << 3); +@@ -216,13 +222,19 @@ void raminit_rcomp_calibration(const stepping_t stepping) { + for (channel = 0; channel < 2; ++channel) { + for (group = 0; group < 6; ++group) { + for (pu_pd = PULL_DOWN; pu_pd >= PULL_UP; --pu_pd) { +- lookup_and_write( +- a1step, +- lut_idx[channel][group][pu_pd] - 7, +- ddr3_lookup_schedule[group][pu_pd], +- mchbar); ++ if (ddr_type == DDR3) { ++ lookup_and_write( ++ a1step, ++ lut_idx[channel][group][pu_pd] - 7, ++ ddr3_lookup_schedule[group][pu_pd], ++ mchbar); ++ } + mchbar += 0x0018; + } ++ if (ddr_type == DDR2) { ++ mchbar_clrsetbits32(mchbar + 0, 0x7f << 24, lut_idx[channel][group][PULL_DOWN] << 24); ++ mchbar_clrsetbits32(mchbar + 4, 0x7f << 0, lut_idx[channel][group][PULL_UP] << 0); ++ } + mchbar += 0x0010; + /* Channel B knows only the first two groups. */ + if ((1 == channel) && (1 == group)) +@@ -230,4 +242,7 @@ void raminit_rcomp_calibration(const stepping_t stepping) { + } + mchbar += 0x0040; + } ++ ++ mchbar_clrsetbits32(0x4d0, 0x3f << 26, magic_comp[0] << 26); ++ mchbar_clrsetbits32(0x4d0, 0x3f << 20, magic_comp[1] << 20); + } +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0041-nb-gm45-Fix-Angel-s-DDR2-RCOMP-fix-on-DDR3-boards.patch b/config/coreboot/default/patches/0041-nb-gm45-Fix-Angel-s-DDR2-RCOMP-fix-on-DDR3-boards.patch new file mode 100644 index 00000000..6ec32987 --- /dev/null +++ b/config/coreboot/default/patches/0041-nb-gm45-Fix-Angel-s-DDR2-RCOMP-fix-on-DDR3-boards.patch @@ -0,0 +1,240 @@ +From 3110c4392d40175716f167be5ef8234f2b4cd030 Mon Sep 17 00:00:00 2001 +From: Leah Rowe <info@minifree.org> +Date: Tue, 6 Aug 2024 00:50:24 +0100 +Subject: [PATCH 41/65] nb/gm45: Fix Angel's DDR2 RCOMP fix on DDR3 boards + +We add this patch: + +commit commit_id_here +Author: Angel Pons <th3fanbus@gmail.com> +Date: Mon May 10 22:40:59 2021 +0200 + + nb/intel/gm45: Make DDR2 raminit work + +This patch was original applied, in lbmk, only on coreboot/dell, +separately from coreboot/default, which was wasteful because it +meant having an entire coreboot tree just for a single board. We +did this, because the DDR2 RCOMP fix happened to break DDR3 init +on other boards. + +What *this* new patch does on top of Angel's patch, is make sure +that their changes only apply to DDR2, while DDR3 behaviour remains +unchanged. This means that the Dell Latitude E6400 can be supported +in the main coreboot tree, within lbmk. + +Essentially, this patch restores the old behaviour, prior to applying +Angel's patch, only when DDR3 memory is used. + +Signed-off-by: Leah Rowe <info@minifree.org> +--- + src/northbridge/intel/gm45/raminit.c | 161 +++++++++--------- + .../intel/gm45/raminit_rcomp_calibration.c | 9 +- + 2 files changed, 88 insertions(+), 82 deletions(-) + +diff --git a/src/northbridge/intel/gm45/raminit.c b/src/northbridge/intel/gm45/raminit.c +index df8f46fbbc..433db3a68c 100644 +--- a/src/northbridge/intel/gm45/raminit.c ++++ b/src/northbridge/intel/gm45/raminit.c +@@ -1117,7 +1117,10 @@ static void dram_program_timings(const int spd_type, const timings_t *const timi + reg = (reg & ~(0xf << 10)) | (2 << 10); + else + reg = (reg & ~(0xf << 10)) | (3 << 10); +- reg = (reg & ~(0x7 << 5)) | (2 << 5); ++ if (spd_type == DDR2) ++ reg = (reg & ~(0x7 << 5)) | (2 << 5); ++ else ++ reg = (reg & ~(0x7 << 5)) | (3 << 5); + } else if (timings->mem_clock != MEM_CLOCK_1067MT) { + reg = (reg & ~(0x7 << 15)) | ((9 - timings->CAS) << 15); + reg = (reg & ~(0xf << 10)) | ((timings->CAS - 3) << 10); +@@ -2209,83 +2212,85 @@ void raminit(sysinfo_t *const sysinfo, const int s3resume) + raminit_write_training(timings->mem_clock, dimms, s3resume); + } + +- /* +- * Program hardcoded DDR2-800 RCOMP SRAM codes. This must be done +- * after receiver enable calibration, otherwise raminit sometimes +- * completes with non-working memory. +- */ +- mchbar_write32(0x0530, 0x06060005); +- mchbar_write32(0x0680, 0x06060606); +- mchbar_write32(0x0684, 0x08070606); +- mchbar_write32(0x0688, 0x0e0e0c0a); +- mchbar_write32(0x068c, 0x0e0e0e0e); +- mchbar_write32(0x0698, 0x06060606); +- mchbar_write32(0x069c, 0x08070606); +- mchbar_write32(0x06a0, 0x0c0c0b0a); +- mchbar_write32(0x06a4, 0x0c0c0c0c); +- +- mchbar_write32(0x06c0, 0x02020202); +- mchbar_write32(0x06c4, 0x03020202); +- mchbar_write32(0x06c8, 0x04040403); +- mchbar_write32(0x06cc, 0x04040404); +- mchbar_write32(0x06d8, 0x02020202); +- mchbar_write32(0x06dc, 0x03020202); +- mchbar_write32(0x06e0, 0x04040403); +- mchbar_write32(0x06e4, 0x04040404); +- +- mchbar_write32(0x0700, 0x02020202); +- mchbar_write32(0x0704, 0x03020202); +- mchbar_write32(0x0708, 0x04040403); +- mchbar_write32(0x070c, 0x04040404); +- mchbar_write32(0x0718, 0x02020202); +- mchbar_write32(0x071c, 0x03020202); +- mchbar_write32(0x0720, 0x04040403); +- mchbar_write32(0x0724, 0x04040404); +- +- mchbar_write32(0x0740, 0x02020202); +- mchbar_write32(0x0744, 0x03020202); +- mchbar_write32(0x0748, 0x04040403); +- mchbar_write32(0x074c, 0x04040404); +- mchbar_write32(0x0758, 0x02020202); +- mchbar_write32(0x075c, 0x03020202); +- mchbar_write32(0x0760, 0x04040403); +- mchbar_write32(0x0764, 0x04040404); +- +- mchbar_write32(0x0780, 0x06060606); +- mchbar_write32(0x0784, 0x09070606); +- mchbar_write32(0x0788, 0x0e0e0c0b); +- mchbar_write32(0x078c, 0x0e0e0e0e); +- mchbar_write32(0x0798, 0x06060606); +- mchbar_write32(0x079c, 0x09070606); +- mchbar_write32(0x07a0, 0x0d0d0c0b); +- mchbar_write32(0x07a4, 0x0d0d0d0d); +- +- mchbar_write32(0x07c0, 0x06060606); +- mchbar_write32(0x07c4, 0x09070606); +- mchbar_write32(0x07c8, 0x0e0e0c0b); +- mchbar_write32(0x07cc, 0x0e0e0e0e); +- mchbar_write32(0x07d8, 0x06060606); +- mchbar_write32(0x07dc, 0x09070606); +- mchbar_write32(0x07e0, 0x0d0d0c0b); +- mchbar_write32(0x07e4, 0x0d0d0d0d); +- +- mchbar_write32(0x0840, 0x06060606); +- mchbar_write32(0x0844, 0x08070606); +- mchbar_write32(0x0848, 0x0e0e0c0a); +- mchbar_write32(0x084c, 0x0e0e0e0e); +- mchbar_write32(0x0858, 0x06060606); +- mchbar_write32(0x085c, 0x08070606); +- mchbar_write32(0x0860, 0x0c0c0b0a); +- mchbar_write32(0x0864, 0x0c0c0c0c); +- +- mchbar_write32(0x0880, 0x02020202); +- mchbar_write32(0x0884, 0x03020202); +- mchbar_write32(0x0888, 0x04040403); +- mchbar_write32(0x088c, 0x04040404); +- mchbar_write32(0x0898, 0x02020202); +- mchbar_write32(0x089c, 0x03020202); +- mchbar_write32(0x08a0, 0x04040403); +- mchbar_write32(0x08a4, 0x04040404); ++ if (sysinfo->spd_type == DDR2) { ++ /* ++ * Program hardcoded DDR2-800 RCOMP SRAM codes. This must be done ++ * after receiver enable calibration, otherwise raminit sometimes ++ * completes with non-working memory. ++ */ ++ mchbar_write32(0x0530, 0x06060005); ++ mchbar_write32(0x0680, 0x06060606); ++ mchbar_write32(0x0684, 0x08070606); ++ mchbar_write32(0x0688, 0x0e0e0c0a); ++ mchbar_write32(0x068c, 0x0e0e0e0e); ++ mchbar_write32(0x0698, 0x06060606); ++ mchbar_write32(0x069c, 0x08070606); ++ mchbar_write32(0x06a0, 0x0c0c0b0a); ++ mchbar_write32(0x06a4, 0x0c0c0c0c); ++ ++ mchbar_write32(0x06c0, 0x02020202); ++ mchbar_write32(0x06c4, 0x03020202); ++ mchbar_write32(0x06c8, 0x04040403); ++ mchbar_write32(0x06cc, 0x04040404); ++ mchbar_write32(0x06d8, 0x02020202); ++ mchbar_write32(0x06dc, 0x03020202); ++ mchbar_write32(0x06e0, 0x04040403); ++ mchbar_write32(0x06e4, 0x04040404); ++ ++ mchbar_write32(0x0700, 0x02020202); ++ mchbar_write32(0x0704, 0x03020202); ++ mchbar_write32(0x0708, 0x04040403); ++ mchbar_write32(0x070c, 0x04040404); ++ mchbar_write32(0x0718, 0x02020202); ++ mchbar_write32(0x071c, 0x03020202); ++ mchbar_write32(0x0720, 0x04040403); ++ mchbar_write32(0x0724, 0x04040404); ++ ++ mchbar_write32(0x0740, 0x02020202); ++ mchbar_write32(0x0744, 0x03020202); ++ mchbar_write32(0x0748, 0x04040403); ++ mchbar_write32(0x074c, 0x04040404); ++ mchbar_write32(0x0758, 0x02020202); ++ mchbar_write32(0x075c, 0x03020202); ++ mchbar_write32(0x0760, 0x04040403); ++ mchbar_write32(0x0764, 0x04040404); ++ ++ mchbar_write32(0x0780, 0x06060606); ++ mchbar_write32(0x0784, 0x09070606); ++ mchbar_write32(0x0788, 0x0e0e0c0b); ++ mchbar_write32(0x078c, 0x0e0e0e0e); ++ mchbar_write32(0x0798, 0x06060606); ++ mchbar_write32(0x079c, 0x09070606); ++ mchbar_write32(0x07a0, 0x0d0d0c0b); ++ mchbar_write32(0x07a4, 0x0d0d0d0d); ++ ++ mchbar_write32(0x07c0, 0x06060606); ++ mchbar_write32(0x07c4, 0x09070606); ++ mchbar_write32(0x07c8, 0x0e0e0c0b); ++ mchbar_write32(0x07cc, 0x0e0e0e0e); ++ mchbar_write32(0x07d8, 0x06060606); ++ mchbar_write32(0x07dc, 0x09070606); ++ mchbar_write32(0x07e0, 0x0d0d0c0b); ++ mchbar_write32(0x07e4, 0x0d0d0d0d); ++ ++ mchbar_write32(0x0840, 0x06060606); ++ mchbar_write32(0x0844, 0x08070606); ++ mchbar_write32(0x0848, 0x0e0e0c0a); ++ mchbar_write32(0x084c, 0x0e0e0e0e); ++ mchbar_write32(0x0858, 0x06060606); ++ mchbar_write32(0x085c, 0x08070606); ++ mchbar_write32(0x0860, 0x0c0c0b0a); ++ mchbar_write32(0x0864, 0x0c0c0c0c); ++ ++ mchbar_write32(0x0880, 0x02020202); ++ mchbar_write32(0x0884, 0x03020202); ++ mchbar_write32(0x0888, 0x04040403); ++ mchbar_write32(0x088c, 0x04040404); ++ mchbar_write32(0x0898, 0x02020202); ++ mchbar_write32(0x089c, 0x03020202); ++ mchbar_write32(0x08a0, 0x04040403); ++ mchbar_write32(0x08a4, 0x04040404); ++ } + + igd_compute_ggc(sysinfo); + +diff --git a/src/northbridge/intel/gm45/raminit_rcomp_calibration.c b/src/northbridge/intel/gm45/raminit_rcomp_calibration.c +index b74765fd9c..5d4505e063 100644 +--- a/src/northbridge/intel/gm45/raminit_rcomp_calibration.c ++++ b/src/northbridge/intel/gm45/raminit_rcomp_calibration.c +@@ -198,7 +198,7 @@ void raminit_rcomp_calibration(int ddr_type, const stepping_t stepping) { + reg = mchbar_read32(0x518); + lut_idx[channel][group][PULL_UP] = (reg >> 24) & 0x7f; + lut_idx[channel][group][PULL_DOWN] = (reg >> 16) & 0x7f; +- if (i == 1) { ++ if ((i == 1) && (ddr_type == DDR2)) { + magic_comp[0] = (reg >> 8) & 0x3f; + magic_comp[1] = (reg >> 0) & 0x3f; + } +@@ -242,7 +242,8 @@ void raminit_rcomp_calibration(int ddr_type, const stepping_t stepping) { + } + mchbar += 0x0040; + } +- +- mchbar_clrsetbits32(0x4d0, 0x3f << 26, magic_comp[0] << 26); +- mchbar_clrsetbits32(0x4d0, 0x3f << 20, magic_comp[1] << 20); ++ if (ddr_type == DDR2) { ++ mchbar_clrsetbits32(0x4d0, 0x3f << 26, magic_comp[0] << 26); ++ mchbar_clrsetbits32(0x4d0, 0x3f << 20, magic_comp[1] << 20); ++ } + } +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0042-mb-dell-e6400-Use-100-MHz-reference-clock-for-displa.patch b/config/coreboot/default/patches/0042-mb-dell-e6400-Use-100-MHz-reference-clock-for-displa.patch new file mode 100644 index 00000000..0131af84 --- /dev/null +++ b/config/coreboot/default/patches/0042-mb-dell-e6400-Use-100-MHz-reference-clock-for-displa.patch @@ -0,0 +1,52 @@ +From 265fb9f4fd017de635bc44b5a762c69a8bec6158 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 42/65] 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 +the more common 1280 x 800 display panels, the numerical error was not +large enough to cause noticable issues, but the actual pixel clock +frequency derived from a 100 MHz reference using PLL configs calculated +assuming a 96 MHz reference was not close enough for 1440 x 900 panels, +which require a much higher pixel clock. This resulted in a garbled +display in the pre-OS graphics environment provided by libgfxinit. + +Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> +--- + src/mainboard/dell/e6400/Kconfig | 3 +++ + src/northbridge/intel/gm45/Kconfig | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/src/mainboard/dell/e6400/Kconfig b/src/mainboard/dell/e6400/Kconfig +index 417d95fd5d..6fe1b1c456 100644 +--- a/src/mainboard/dell/e6400/Kconfig ++++ b/src/mainboard/dell/e6400/Kconfig +@@ -19,6 +19,9 @@ config BOARD_SPECIFIC_OPTIONS + select INTEL_GMA_HAVE_VBT + select EC_DELL_MEC5035 + ++config INTEL_GMA_DPLL_REF_FREQ ++ default 100000000 ++ + config MAINBOARD_DIR + default "dell/e6400" + +diff --git a/src/northbridge/intel/gm45/Kconfig b/src/northbridge/intel/gm45/Kconfig +index 8059e7ee80..5df5a93296 100644 +--- a/src/northbridge/intel/gm45/Kconfig ++++ b/src/northbridge/intel/gm45/Kconfig +@@ -14,6 +14,10 @@ config NORTHBRIDGE_INTEL_GM45 + + if NORTHBRIDGE_INTEL_GM45 + ++config INTEL_GMA_DPLL_REF_FREQ ++ int ++ default 96000000 ++ + config VBOOT + select VBOOT_STARTS_IN_BOOTBLOCK + +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0042-mb-dell-optiplex_9020-Implement-late-HWM-initializat.patch b/config/coreboot/default/patches/0042-mb-dell-optiplex_9020-Implement-late-HWM-initializat.patch deleted file mode 100644 index 37353e20..00000000 --- a/config/coreboot/default/patches/0042-mb-dell-optiplex_9020-Implement-late-HWM-initializat.patch +++ /dev/null @@ -1,602 +0,0 @@ -From c58e0fea2a4e591e5ecd8a1f376c3b3af0fbb306 Mon Sep 17 00:00:00 2001 -From: Mate Kukri <kukri.mate@gmail.com> -Date: Thu, 18 Apr 2024 20:28:45 +0100 -Subject: [PATCH 1/1] mb/dell/optiplex_9020: Implement late HWM initialization - -There are 4 different chassis types specified by vendor firmware, each -with a slightly different HWM configuration. - -The chassis type to use is determined at runtime by reading a set of -4 PCH GPIOs: 70, 38, 17, and 1. - -Additionally vendor firmware also provides an option to run the fans at -full speed. This is substituted with a coreboot nvram option in this -implementation. - -This was tested to make fan control work on my OptiPlex 7020 SFF. - -NOTE: This is superficially similar to the OptiPlex 9010's SCH5545 -however the OptiPlex 9020's SCH5555 does not use externally -programmed EC firmware. - -Change-Id: Ibdccd3fc7364e03e84ca606592928410624eed43 -Signed-off-by: Mate Kukri <kukri.mate@gmail.com> ---- - src/mainboard/dell/optiplex_9020/Makefile.inc | 3 +- - src/mainboard/dell/optiplex_9020/bootblock.c | 25 +- - src/mainboard/dell/optiplex_9020/cmos.default | 1 + - src/mainboard/dell/optiplex_9020/cmos.layout | 5 +- - src/mainboard/dell/optiplex_9020/mainboard.c | 387 ++++++++++++++++++ - src/mainboard/dell/optiplex_9020/sch5555_ec.c | 54 +++ - src/mainboard/dell/optiplex_9020/sch5555_ec.h | 10 + - 7 files changed, 463 insertions(+), 22 deletions(-) - create mode 100644 src/mainboard/dell/optiplex_9020/sch5555_ec.c - create mode 100644 src/mainboard/dell/optiplex_9020/sch5555_ec.h - -diff --git a/src/mainboard/dell/optiplex_9020/Makefile.inc b/src/mainboard/dell/optiplex_9020/Makefile.inc -index 6ca2f2afaa..08e2e53577 100644 ---- a/src/mainboard/dell/optiplex_9020/Makefile.inc -+++ b/src/mainboard/dell/optiplex_9020/Makefile.inc -@@ -2,4 +2,5 @@ - - romstage-y += gpio.c - ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads --bootblock-y += bootblock.c -+ramstage-y += sch5555_ec.c -+bootblock-y += bootblock.c sch5555_ec.c -diff --git a/src/mainboard/dell/optiplex_9020/bootblock.c b/src/mainboard/dell/optiplex_9020/bootblock.c -index 2837cf9cf1..e5e759273e 100644 ---- a/src/mainboard/dell/optiplex_9020/bootblock.c -+++ b/src/mainboard/dell/optiplex_9020/bootblock.c -@@ -4,29 +4,14 @@ - #include <device/pnp_ops.h> - #include <superio/smsc/sch555x/sch555x.h> - #include <southbridge/intel/lynxpoint/pch.h> -- --static void ec_write(uint8_t addr1, uint16_t addr2, uint8_t val) --{ -- // Clear EC-to-Host mailbox -- uint8_t tmp = inb(SCH555x_EMI_IOBASE + 1); -- outb(tmp, SCH555x_EMI_IOBASE + 1); -- -- // Send address and value to the EC -- sch555x_emi_write16(0, (addr1 * 2) | 0x101); -- sch555x_emi_write32(4, val | (addr2 << 16)); -- -- // Wait for acknowledgement message from EC -- outb(1, SCH555x_EMI_IOBASE); -- size_t timeout = 0; -- do {} while (++timeout < 0xfff && (inb(SCH555x_EMI_IOBASE + 1) & 1) == 0); --} -+#include "sch5555_ec.h" - - struct ec_init_entry { - uint16_t addr; - uint8_t val; - }; - --static void ec_init(void) -+static void bootblock_ec_init(void) - { - /* - * Tables from CORE_PEI -@@ -108,9 +93,9 @@ void mainboard_config_superio(void) - outb(0x01, SCH555x_RUNTIME_IOBASE + SCH555x_RUNTIME_UNK1); - outb(0x0f, SCH555x_RUNTIME_IOBASE + SCH555x_RUNTIME_LED); - -- // Magic EC init -- ec_init(); -+ // Perform bootblock EC initialization -+ bootblock_ec_init(); - -- // Magic EC init is needed for UART1 initialization to work -+ // Bootblock EC initialization is required for UART1 to work - sch555x_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE); - } -diff --git a/src/mainboard/dell/optiplex_9020/cmos.default b/src/mainboard/dell/optiplex_9020/cmos.default -index 7bccc80e51..1909abcb9f 100644 ---- a/src/mainboard/dell/optiplex_9020/cmos.default -+++ b/src/mainboard/dell/optiplex_9020/cmos.default -@@ -3,3 +3,4 @@ debug_level=Debug - nmi=Disable - power_on_after_fail=Disable - iommu=Disable -+fan_full_speed=Disable -diff --git a/src/mainboard/dell/optiplex_9020/cmos.layout b/src/mainboard/dell/optiplex_9020/cmos.layout -index 72ff9c4bee..4a1496a878 100644 ---- a/src/mainboard/dell/optiplex_9020/cmos.layout -+++ b/src/mainboard/dell/optiplex_9020/cmos.layout -@@ -22,7 +22,10 @@ entries - 409 2 e 5 power_on_after_fail - - # turn iommu on or off --412 1 e 6 iommu -+411 1 e 6 iommu -+ -+# coreboot config options: EC -+412 1 e 1 fan_full_speed - - # coreboot config options: check sums - 984 16 h 0 check_sum -diff --git a/src/mainboard/dell/optiplex_9020/mainboard.c b/src/mainboard/dell/optiplex_9020/mainboard.c -index c834fea5d3..0b7829c736 100644 ---- a/src/mainboard/dell/optiplex_9020/mainboard.c -+++ b/src/mainboard/dell/optiplex_9020/mainboard.c -@@ -1,7 +1,12 @@ - /* SPDX-License-Identifier: GPL-2.0-only */ - -+#include <bootstate.h> -+#include <cpu/x86/msr.h> - #include <device/device.h> - #include <drivers/intel/gma/int15.h> -+#include <option.h> -+#include <southbridge/intel/common/gpio.h> -+#include "sch5555_ec.h" - - static void mainboard_enable(struct device *dev) - { -@@ -13,3 +18,385 @@ static void mainboard_enable(struct device *dev) - struct chip_operations mainboard_ops = { - .enable_dev = mainboard_enable, - }; -+ -+#define HWM_TAB_ADD_TEMP_TARGET 1 -+#define HWM_TAB_PKG_POWER_ANY 0xffff -+#define CHASSIS_TYPE_UNKNOWN 0xff -+ -+struct hwm_tab_entry { -+ uint16_t addr; -+ uint8_t val; -+ uint8_t flags; -+ uint16_t pkg_power; -+}; -+ -+struct hwm_tab_entry HWM_TAB3[] = { -+ { 0x005, 0x33, 0, 0xffff }, -+ { 0x018, 0x2f, 0, 0xffff }, -+ { 0x019, 0x2f, 0, 0xffff }, -+ { 0x01a, 0x2f, 0, 0xffff }, -+ { 0x080, 0x00, 0, 0xffff }, -+ { 0x081, 0x00, 0, 0xffff }, -+ { 0x083, 0xbb, 0, 0xffff }, -+ { 0x085, 0x8a, 0, 0x0010 }, -+ { 0x086, 0x4c, 0, 0x0010 }, -+ { 0x08a, 0x66, 0, 0x0010 }, -+ { 0x08b, 0x5b, 0, 0x0010 }, -+ { 0x090, 0x65, 0, 0xffff }, -+ { 0x091, 0x70, 0, 0xffff }, -+ { 0x092, 0x86, 0, 0xffff }, -+ { 0x096, 0xa4, 0, 0xffff }, -+ { 0x097, 0xa4, 0, 0xffff }, -+ { 0x098, 0xa4, 0, 0xffff }, -+ { 0x09b, 0xa4, 0, 0xffff }, -+ { 0x0a0, 0x0e, 0, 0xffff }, -+ { 0x0a1, 0x0e, 0, 0xffff }, -+ { 0x0ae, 0x7c, 0, 0xffff }, -+ { 0x0af, 0x86, 0, 0xffff }, -+ { 0x0b0, 0x9a, 0, 0xffff }, -+ { 0x0b3, 0x9a, 0, 0xffff }, -+ { 0x0b6, 0x08, 0, 0xffff }, -+ { 0x0b7, 0x08, 0, 0xffff }, -+ { 0x0ea, 0x64, 0, 0x0020 }, -+ { 0x0ea, 0x5c, 0, 0x0010 }, -+ { 0x0ef, 0xff, 0, 0xffff }, -+ { 0x0f8, 0x15, 0, 0xffff }, -+ { 0x0f9, 0x00, 0, 0xffff }, -+ { 0x0f0, 0x30, 0, 0xffff }, -+ { 0x0fd, 0x01, 0, 0xffff }, -+ { 0x1a1, 0x00, 0, 0xffff }, -+ { 0x1a2, 0x00, 0, 0xffff }, -+ { 0x1b1, 0x08, 0, 0xffff }, -+ { 0x1be, 0x99, 0, 0xffff }, -+ { 0x280, 0xa0, 0, 0x0010 }, -+ { 0x281, 0x0f, 0, 0x0010 }, -+ { 0x282, 0x03, 0, 0xffff }, -+ { 0x283, 0x0a, 0, 0xffff }, -+ { 0x284, 0x80, 0, 0xffff }, -+ { 0x285, 0x03, 0, 0xffff }, -+ { 0x288, 0x68, 0, 0x0010 }, -+ { 0x289, 0x10, 0, 0x0010 }, -+ { 0x28a, 0x03, 0, 0xffff }, -+ { 0x28b, 0x0a, 0, 0xffff }, -+ { 0x28c, 0x80, 0, 0xffff }, -+ { 0x28d, 0x03, 0, 0xffff }, -+}; -+ -+struct hwm_tab_entry HWM_TAB4[] = { -+ { 0x005, 0x33, 0, 0xffff }, -+ { 0x018, 0x2f, 0, 0xffff }, -+ { 0x019, 0x2f, 0, 0xffff }, -+ { 0x01a, 0x2f, 0, 0xffff }, -+ { 0x080, 0x00, 0, 0xffff }, -+ { 0x081, 0x00, 0, 0xffff }, -+ { 0x083, 0xbb, 0, 0xffff }, -+ { 0x085, 0x99, 0, 0x0020 }, -+ { 0x085, 0xad, 0, 0x0010 }, -+ { 0x086, 0x1c, 0, 0xffff }, -+ { 0x08a, 0x39, 0, 0x0020 }, -+ { 0x08a, 0x41, 0, 0x0010 }, -+ { 0x08b, 0x76, 0, 0x0020 }, -+ { 0x08b, 0x8b, 0, 0x0010 }, -+ { 0x090, 0x5e, 0, 0xffff }, -+ { 0x091, 0x5e, 0, 0xffff }, -+ { 0x092, 0x86, 0, 0xffff }, -+ { 0x096, 0xa4, 0, 0xffff }, -+ { 0x097, 0xa4, 0, 0xffff }, -+ { 0x098, 0xa4, 0, 0xffff }, -+ { 0x09b, 0xa4, 0, 0xffff }, -+ { 0x0a0, 0x0a, 0, 0xffff }, -+ { 0x0a1, 0x0a, 0, 0xffff }, -+ { 0x0ae, 0x7c, 0, 0xffff }, -+ { 0x0af, 0x7c, 0, 0xffff }, -+ { 0x0b0, 0x9a, 0, 0xffff }, -+ { 0x0b3, 0x7c, 0, 0xffff }, -+ { 0x0b6, 0x08, 0, 0xffff }, -+ { 0x0b7, 0x08, 0, 0xffff }, -+ { 0x0ea, 0x64, 0, 0x0020 }, -+ { 0x0ea, 0x5c, 0, 0x0010 }, -+ { 0x0ef, 0xff, 0, 0xffff }, -+ { 0x0f8, 0x15, 0, 0xffff }, -+ { 0x0f9, 0x00, 0, 0xffff }, -+ { 0x0f0, 0x30, 0, 0xffff }, -+ { 0x0fd, 0x01, 0, 0xffff }, -+ { 0x1a1, 0x00, 0, 0xffff }, -+ { 0x1a2, 0x00, 0, 0xffff }, -+ { 0x1b1, 0x08, 0, 0xffff }, -+ { 0x1be, 0x90, 0, 0xffff }, -+ { 0x280, 0x94, 0, 0x0020 }, -+ { 0x281, 0x11, 0, 0x0020 }, -+ { 0x280, 0x94, 0, 0x0010 }, -+ { 0x281, 0x11, 0, 0x0010 }, -+ { 0x282, 0x03, 0, 0xffff }, -+ { 0x283, 0x0a, 0, 0xffff }, -+ { 0x284, 0x80, 0, 0xffff }, -+ { 0x285, 0x03, 0, 0xffff }, -+ { 0x288, 0x28, 0, 0x0020 }, -+ { 0x289, 0x0a, 0, 0x0020 }, -+ { 0x288, 0x28, 0, 0x0010 }, -+ { 0x289, 0x0a, 0, 0x0010 }, -+ { 0x28a, 0x03, 0, 0xffff }, -+ { 0x28b, 0x0a, 0, 0xffff }, -+ { 0x28c, 0x80, 0, 0xffff }, -+ { 0x28d, 0x03, 0, 0xffff }, -+}; -+ -+struct hwm_tab_entry HWM_TAB5[] = { -+ { 0x005, 0x33, 0, 0xffff }, -+ { 0x018, 0x2f, 0, 0xffff }, -+ { 0x019, 0x2f, 0, 0xffff }, -+ { 0x01a, 0x2f, 0, 0xffff }, -+ { 0x080, 0x00, 0, 0xffff }, -+ { 0x081, 0x00, 0, 0xffff }, -+ { 0x083, 0xbb, 0, 0xffff }, -+ { 0x085, 0x66, 0, 0x0020 }, -+ { 0x085, 0x5d, 0, 0x0010 }, -+ { 0x086, 0x1c, 0, 0xffff }, -+ { 0x08a, 0x39, 0, 0x0020 }, -+ { 0x08a, 0x41, 0, 0x0010 }, -+ { 0x08b, 0x76, 0, 0x0020 }, -+ { 0x08b, 0x80, 0, 0x0010 }, -+ { 0x090, 0x5d, 0, 0x0020 }, -+ { 0x090, 0x5e, 0, 0x0010 }, -+ { 0x091, 0x5e, 0, 0xffff }, -+ { 0x092, 0x86, 0, 0xffff }, -+ { 0x096, 0xa4, 0, 0xffff }, -+ { 0x097, 0xa4, 0, 0xffff }, -+ { 0x098, 0xa3, 0, 0x0020 }, -+ { 0x098, 0xa4, 0, 0x0010 }, -+ { 0x09b, 0xa4, 0, 0xffff }, -+ { 0x0a0, 0x08, 0, 0xffff }, -+ { 0x0a1, 0x0a, 0, 0xffff }, -+ { 0x0ae, 0x7c, 0, 0xffff }, -+ { 0x0af, 0x7c, 0, 0xffff }, -+ { 0x0b0, 0x9a, 0, 0xffff }, -+ { 0x0b3, 0x7c, 0, 0xffff }, -+ { 0x0b6, 0x08, 0, 0xffff }, -+ { 0x0b7, 0x08, 0, 0xffff }, -+ { 0x0ea, 0x64, 0, 0x0020 }, -+ { 0x0ea, 0x5c, 0, 0x0010 }, -+ { 0x0ef, 0xff, 0, 0xffff }, -+ { 0x0f8, 0x15, 0, 0xffff }, -+ { 0x0f9, 0x00, 0, 0xffff }, -+ { 0x0f0, 0x30, 0, 0xffff }, -+ { 0x0fd, 0x01, 0, 0xffff }, -+ { 0x1a1, 0x00, 0, 0xffff }, -+ { 0x1a2, 0x00, 0, 0xffff }, -+ { 0x1b1, 0x08, 0, 0xffff }, -+ { 0x1be, 0x98, 0, 0x0020 }, -+ { 0x1be, 0x90, 0, 0x0010 }, -+ { 0x280, 0x94, 0, 0x0020 }, -+ { 0x281, 0x11, 0, 0x0020 }, -+ { 0x280, 0x94, 0, 0x0010 }, -+ { 0x281, 0x11, 0, 0x0010 }, -+ { 0x282, 0x03, 0, 0xffff }, -+ { 0x283, 0x0a, 0, 0xffff }, -+ { 0x284, 0x80, 0, 0xffff }, -+ { 0x285, 0x03, 0, 0xffff }, -+ { 0x288, 0x28, 0, 0x0020 }, -+ { 0x289, 0x0a, 0, 0x0020 }, -+ { 0x288, 0x28, 0, 0x0010 }, -+ { 0x289, 0x0a, 0, 0x0010 }, -+ { 0x28a, 0x03, 0, 0xffff }, -+ { 0x28b, 0x0a, 0, 0xffff }, -+ { 0x28c, 0x80, 0, 0xffff }, -+ { 0x28d, 0x03, 0, 0xffff }, -+}; -+ -+struct hwm_tab_entry HWM_TAB6[] = { -+ { 0x005, 0x33, 0, 0xffff }, -+ { 0x018, 0x2f, 0, 0xffff }, -+ { 0x019, 0x2f, 0, 0xffff }, -+ { 0x01a, 0x2f, 0, 0xffff }, -+ { 0x080, 0x00, 0, 0xffff }, -+ { 0x081, 0x00, 0, 0xffff }, -+ { 0x083, 0xbb, 0, 0xffff }, -+ { 0x085, 0x98, 0, 0xffff }, -+ { 0x086, 0x3c, 0, 0xffff }, -+ { 0x08a, 0x39, 0, 0x0020 }, -+ { 0x08a, 0x3d, 0, 0x0010 }, -+ { 0x08b, 0x44, 0, 0x0020 }, -+ { 0x08b, 0x51, 0, 0x0010 }, -+ { 0x090, 0x61, 0, 0xffff }, -+ { 0x091, 0x6d, 0, 0xffff }, -+ { 0x092, 0x86, 0, 0xffff }, -+ { 0x096, 0xa4, 0, 0xffff }, -+ { 0x097, 0xa4, 0, 0xffff }, -+ { 0x098, 0x9f, 0, 0x0020 }, -+ { 0x098, 0xa4, 0, 0x0010 }, -+ { 0x09b, 0xa4, 0, 0xffff }, -+ { 0x0a0, 0x0e, 0, 0xffff }, -+ { 0x0a1, 0x0e, 0, 0xffff }, -+ { 0x0ae, 0x7c, 0, 0xffff }, -+ { 0x0af, 0x7c, 0, 0xffff }, -+ { 0x0b0, 0x9b, 0, 0x0020 }, -+ { 0x0b0, 0x98, 0, 0x0010 }, -+ { 0x0b3, 0x9a, 0, 0xffff }, -+ { 0x0b6, 0x08, 0, 0xffff }, -+ { 0x0b7, 0x08, 0, 0xffff }, -+ { 0x0ea, 0x64, 0, 0x0020 }, -+ { 0x0ea, 0x5c, 0, 0x0010 }, -+ { 0x0ef, 0xff, 0, 0xffff }, -+ { 0x0f8, 0x15, 0, 0xffff }, -+ { 0x0f9, 0x00, 0, 0xffff }, -+ { 0x0f0, 0x30, 0, 0xffff }, -+ { 0x0fd, 0x01, 0, 0xffff }, -+ { 0x1a1, 0x00, 0, 0xffff }, -+ { 0x1a2, 0x00, 0, 0xffff }, -+ { 0x1b1, 0x08, 0, 0xffff }, -+ { 0x1be, 0x9a, 0, 0x0020 }, -+ { 0x1be, 0x96, 0, 0x0010 }, -+ { 0x280, 0x94, 0, 0x0020 }, -+ { 0x281, 0x11, 0, 0x0020 }, -+ { 0x280, 0x94, 0, 0x0010 }, -+ { 0x281, 0x11, 0, 0x0010 }, -+ { 0x282, 0x03, 0, 0xffff }, -+ { 0x283, 0x0a, 0, 0xffff }, -+ { 0x284, 0x80, 0, 0xffff }, -+ { 0x285, 0x03, 0, 0xffff }, -+ { 0x288, 0x94, 0, 0x0020 }, -+ { 0x289, 0x11, 0, 0x0020 }, -+ { 0x288, 0x94, 0, 0x0010 }, -+ { 0x289, 0x11, 0, 0x0010 }, -+ { 0x28a, 0x03, 0, 0xffff }, -+ { 0x28b, 0x0a, 0, 0xffff }, -+ { 0x28c, 0x80, 0, 0xffff }, -+ { 0x28d, 0x03, 0, 0xffff }, -+}; -+ -+static uint8_t get_chassis_type(void) -+{ -+ uint8_t gpio_chassis_type; -+ -+ // Read chassis type from GPIO -+ gpio_chassis_type = get_gpio(70) << 3 | get_gpio(38) << 2 | -+ get_gpio(17) << 1 | get_gpio(1); -+ -+ printk(BIOS_DEBUG, "GPIO chassis type = %#x\n", gpio_chassis_type); -+ -+ // Turn it into internal chassis index -+ switch (gpio_chassis_type) { -+ case 0x08: -+ case 0x0a: -+ return 4; -+ case 0x0b: -+ return 3; -+ case 0x0c: -+ return 5; -+ case 0x0d: // SFF -+ case 0x0e: -+ case 0x0f: -+ return 6; -+ default: -+ return CHASSIS_TYPE_UNKNOWN; -+ } -+ -+} -+ -+static uint8_t get_temp_target(void) -+{ -+ uint8_t val = rdmsr(0x1a2).lo >> 8 & 0xff; -+ if (!val) -+ val = 20; -+ return 0x95 - val; -+} -+ -+static uint16_t get_pkg_power(void) -+{ -+ uint8_t rapl_power_unit = rdmsr(0x606).lo & 0xf; -+ if (rapl_power_unit) -+ rapl_power_unit = 2 << (rapl_power_unit - 1); -+ uint16_t pkg_power_info = rdmsr(0x614).lo & 0x7fff; -+ if (pkg_power_info / rapl_power_unit > 0x41) -+ return 32; -+ else -+ return 16; -+} -+ -+static void apply_hwm_tab(struct hwm_tab_entry *arr, size_t size) -+{ -+ uint8_t temp_target = get_temp_target(); -+ uint16_t pkg_power = get_pkg_power(); -+ -+ printk(BIOS_DEBUG, "Temp target = %#x\n", temp_target); -+ printk(BIOS_DEBUG, "Package power = %#x\n", pkg_power); -+ -+ for (size_t i = 0; i < size; ++i) { -+ // Skip entry if it doesn't apply for this package power -+ if (arr[i].pkg_power != pkg_power && -+ arr[i].pkg_power != HWM_TAB_PKG_POWER_ANY) -+ continue; -+ -+ uint8_t val = arr[i].val; -+ -+ // Add temp target to value if requested (current tables never do) -+ if (arr[i].flags & HWM_TAB_ADD_TEMP_TARGET) -+ val += temp_target; -+ -+ // Perform write -+ ec_write(1, arr[i].addr, val); -+ -+ } -+} -+ -+static void sch5555_ec_hwm_init(void *arg) -+{ -+ uint8_t chassis_type, saved_2fc; -+ -+ printk(BIOS_DEBUG, "OptiPlex 9020 late HWM init\n"); -+ -+ saved_2fc = ec_read(1, 0x2fc); -+ ec_write(1, 0x2fc, 0xa0); -+ ec_write(1, 0x2fd, 0x32); -+ -+ chassis_type = get_chassis_type(); -+ -+ if (chassis_type != CHASSIS_TYPE_UNKNOWN) { -+ printk(BIOS_DEBUG, "Chassis type = %#x\n", chassis_type); -+ } else { -+ printk(BIOS_DEBUG, "WARNING: Unknown chassis type\n"); -+ } -+ -+ // Apply HWM table based on chassis type -+ switch (chassis_type) { -+ case 3: -+ apply_hwm_tab(HWM_TAB3, ARRAY_SIZE(HWM_TAB3)); -+ break; -+ case 4: -+ apply_hwm_tab(HWM_TAB4, ARRAY_SIZE(HWM_TAB4)); -+ break; -+ case 5: -+ apply_hwm_tab(HWM_TAB5, ARRAY_SIZE(HWM_TAB5)); -+ break; -+ case 6: -+ apply_hwm_tab(HWM_TAB6, ARRAY_SIZE(HWM_TAB6)); -+ break; -+ } -+ -+ // NOTE: vendor firmware applies these when "max core address" > 2 -+ // i think this is always the case -+ ec_write(1, 0x9e, 0x30); -+ ec_write(1, 0xeb, ec_read(1, 0xea)); -+ -+ ec_write(1, 0x2fc, saved_2fc); -+ -+ // Apply full speed fan config if requested or if the chassis type is unknown -+ if (chassis_type == CHASSIS_TYPE_UNKNOWN || get_uint_option("fan_full_speed", 0)) { -+ printk(BIOS_DEBUG, "Setting full fan speed\n"); -+ ec_write(1, 0x80, 0x60 | ec_read(1, 0x80)); -+ ec_write(1, 0x81, 0x60 | ec_read(1, 0x81)); -+ } -+ -+ ec_read(1, 0xb8); -+ -+ if ((chassis_type == 4 || chassis_type == 5) && ec_read(1, 0x26) == 0) { -+ ec_write(1, 0xa0, ec_read(1, 0xa0) & 0xfb); -+ ec_write(1, 0xa1, ec_read(1, 0xa1) & 0xfb); -+ ec_write(1, 0xa2, ec_read(1, 0xa2) & 0xfb); -+ ec_write(1, 0x8a, 0x99); -+ ec_write(1, 0x8b, 0x47); -+ ec_write(1, 0x8c, 0x91); -+ } -+} -+ -+BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, sch5555_ec_hwm_init, NULL); -diff --git a/src/mainboard/dell/optiplex_9020/sch5555_ec.c b/src/mainboard/dell/optiplex_9020/sch5555_ec.c -new file mode 100644 -index 0000000000..a1067ac063 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/sch5555_ec.c -@@ -0,0 +1,54 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <arch/io.h> -+#include <device/pnp_ops.h> -+#include <superio/smsc/sch555x/sch555x.h> -+#include "sch5555_ec.h" -+ -+uint8_t ec_read(uint8_t addr1, uint16_t addr2) -+{ -+ // clear ec-to-host mailbox -+ uint8_t tmp = inb(SCH555x_EMI_IOBASE + 1); -+ outb(tmp, SCH555x_EMI_IOBASE + 1); -+ -+ // send address -+ outw(0 | 0x8001, SCH555x_EMI_IOBASE + 2); -+ outw((addr1 * 2) | 0x100, SCH555x_EMI_IOBASE + 4); -+ -+ outw(4 | 0x8002, SCH555x_EMI_IOBASE + 2); -+ outl(addr2 << 16, SCH555x_EMI_IOBASE + 4); -+ -+ // send message to ec -+ outb(1, SCH555x_EMI_IOBASE); -+ -+ // wait for ack -+ for (size_t retry = 0; retry < 0xfff; ++retry) -+ if (inb(SCH555x_EMI_IOBASE + 1) & 1) -+ break; -+ -+ // read result -+ outw(4 | 0x8000, SCH555x_EMI_IOBASE + 2); -+ return inb(SCH555x_EMI_IOBASE + 4); -+} -+ -+void ec_write(uint8_t addr1, uint16_t addr2, uint8_t val) -+{ -+ // clear ec-to-host mailbox -+ uint8_t tmp = inb(SCH555x_EMI_IOBASE + 1); -+ outb(tmp, SCH555x_EMI_IOBASE + 1); -+ -+ // send address and value -+ outw(0 | 0x8001, SCH555x_EMI_IOBASE + 2); -+ outw((addr1 * 2) | 0x101, SCH555x_EMI_IOBASE + 4); -+ -+ outw(4 | 0x8002, SCH555x_EMI_IOBASE + 2); -+ outl(val | (addr2 << 16), SCH555x_EMI_IOBASE + 4); -+ -+ // send message to ec -+ outb(1, SCH555x_EMI_IOBASE); -+ -+ // wait for ack -+ for (size_t retry = 0; retry < 0xfff; ++retry) -+ if (inb(SCH555x_EMI_IOBASE + 1) & 1) -+ break; -+} -diff --git a/src/mainboard/dell/optiplex_9020/sch5555_ec.h b/src/mainboard/dell/optiplex_9020/sch5555_ec.h -new file mode 100644 -index 0000000000..7e399e8e74 ---- /dev/null -+++ b/src/mainboard/dell/optiplex_9020/sch5555_ec.h -@@ -0,0 +1,10 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#ifndef __SCH5555_EC_H__ -+#define __SCH5555_EC_H__ -+ -+uint8_t ec_read(uint8_t addr1, uint16_t addr2); -+ -+void ec_write(uint8_t addr1, uint16_t addr2, uint8_t val); -+ -+#endif --- -2.39.2 - diff --git a/config/coreboot/default/patches/0043-haswell-NRI-Initialise-MPLL.patch b/config/coreboot/default/patches/0043-haswell-NRI-Initialise-MPLL.patch new file mode 100644 index 00000000..c571fe3b --- /dev/null +++ b/config/coreboot/default/patches/0043-haswell-NRI-Initialise-MPLL.patch @@ -0,0 +1,348 @@ +From ab36967cce0593dd17f3018ab4a6661e4219d242 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Thu, 11 Apr 2024 17:25:07 +0200 +Subject: [PATCH 43/65] 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/0043-mb-dell-optiplex_9020-Add-support-for-TPM1.2-device.patch b/config/coreboot/default/patches/0043-mb-dell-optiplex_9020-Add-support-for-TPM1.2-device.patch deleted file mode 100644 index 556e8e07..00000000 --- a/config/coreboot/default/patches/0043-mb-dell-optiplex_9020-Add-support-for-TPM1.2-device.patch +++ /dev/null @@ -1,49 +0,0 @@ -From cd3c553a313a26494e5dc31ff8323c3a919f190a Mon Sep 17 00:00:00 2001 -From: Mate Kukri <kukri.mate@gmail.com> -Date: Wed, 10 Apr 2024 20:31:35 +0100 -Subject: [PATCH 1/1] mb/dell/optiplex_9020: Add support for TPM1.2 device - -These machines come with a TPM1.2 device by default. It is somewhat -obsolete these days, but there is no harm in enabling it. - -Change-Id: Iec05321862aed58695c256b00494e5953219786d -Signed-off-by: Mate Kukri <kukri.mate@gmail.com> -Reviewed-on: https://review.coreboot.org/c/coreboot/+/81827 -Reviewed-by: Angel Pons <th3fanbus@gmail.com> -Tested-by: build bot (Jenkins) <no-reply@coreboot.org> ---- - src/mainboard/dell/optiplex_9020/Kconfig | 2 ++ - src/mainboard/dell/optiplex_9020/devicetree.cb | 3 +++ - 2 files changed, 5 insertions(+) - -diff --git a/src/mainboard/dell/optiplex_9020/Kconfig b/src/mainboard/dell/optiplex_9020/Kconfig -index 774a72f161..296938aa8d 100644 ---- a/src/mainboard/dell/optiplex_9020/Kconfig -+++ b/src/mainboard/dell/optiplex_9020/Kconfig -@@ -12,7 +12,9 @@ config BOARD_SPECIFIC_OPTIONS - select INTEL_GMA_HAVE_VBT - select INTEL_INT15 - select MAINBOARD_HAS_LIBGFXINIT -+ select MAINBOARD_HAS_TPM1 - select MAINBOARD_USES_IFD_GBE_REGION -+ select MEMORY_MAPPED_TPM - select NORTHBRIDGE_INTEL_HASWELL - select SERIRQ_CONTINUOUS_MODE - select SOUTHBRIDGE_INTEL_LYNXPOINT -diff --git a/src/mainboard/dell/optiplex_9020/devicetree.cb b/src/mainboard/dell/optiplex_9020/devicetree.cb -index 7bfa6736a6..e5cbd64127 100644 ---- a/src/mainboard/dell/optiplex_9020/devicetree.cb -+++ b/src/mainboard/dell/optiplex_9020/devicetree.cb -@@ -70,6 +70,9 @@ chip northbridge/intel/haswell - device pnp 2e.b off end # Floppy Controller - device pnp 2e.11 off end # Parallel Port - end -+ chip drivers/pc80/tpm -+ device pnp 0c31.0 on end -+ end - end - device pci 1f.2 on end # SATA controller 1 - device pci 1f.3 on end # SMBus --- -2.39.2 - diff --git a/config/coreboot/default/patches/0044-haswell-NRI-Post-process-selected-timings.patch b/config/coreboot/default/patches/0044-haswell-NRI-Post-process-selected-timings.patch new file mode 100644 index 00000000..69e32d2f --- /dev/null +++ b/config/coreboot/default/patches/0044-haswell-NRI-Post-process-selected-timings.patch @@ -0,0 +1,249 @@ +From 876011559681881d950ad3b6742b40322f1f5a6d Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sat, 7 May 2022 16:29:55 +0200 +Subject: [PATCH 44/65] 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/0044-hp-8560w-turn-on-wifi.patch b/config/coreboot/default/patches/0044-hp-8560w-turn-on-wifi.patch deleted file mode 100644 index bb4a7b47..00000000 --- a/config/coreboot/default/patches/0044-hp-8560w-turn-on-wifi.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 4ccef4fffd98071c339cb4135e2d8c805e554378 Mon Sep 17 00:00:00 2001 -From: Leah Rowe <info@minifree.org> -Date: Fri, 3 May 2024 17:45:52 +0100 -Subject: [PATCH 1/1] hp/8560w: turn on wifi - -according to angel pons, this gpio is WLAN_TRN_OFF# -and setting it high will make wifi work. testing with -this change as suggested by angel. see: - -https://review.coreboot.org/c/coreboot/+/39398/4/src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c#158 - -if it makes it into a libreboot release, you can assume -the fix works. right now we have this problem: - -https://codeberg.org/libreboot/lbmk/issues/201 - -Riku reported: - -[ 333.890080] atkbd serio0: Unknown key pressed (translated set 2, code 0xf8 on isa0060/serio0). -[ 333.890102] atkbd serio0: Use 'setkeycodes e078 <keycode>' to make it known. -[ 334.104069] atkbd serio0: Unknown key released (translated set 2, code 0xf8 on isa0060/serio0). -[ 334.104090] atkbd serio0: Use 'setkeycodes e078 <keycode>' to make it known. - -The wifi stays to hardblocked in rfkill. When the wireless button -is pressed, nothing changes except for these lines in dmesg. - -Signed-off-by: Leah Rowe <info@minifree.org> ---- - src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c -index 560d668d6f..10cd11ce48 100644 ---- a/src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c -+++ b/src/mainboard/hp/snb_ivb_laptops/variants/8560w/gpio.c -@@ -155,7 +155,7 @@ static const struct pch_gpio_set2 pch_gpio_set2_level = { - .gpio37 = GPIO_LEVEL_LOW, - .gpio49 = GPIO_LEVEL_LOW, - .gpio53 = GPIO_LEVEL_HIGH, -- .gpio57 = GPIO_LEVEL_LOW, -+ .gpio57 = GPIO_LEVEL_HIGH, - .gpio60 = GPIO_LEVEL_HIGH, - .gpio61 = GPIO_LEVEL_HIGH, - }; --- -2.39.2 - diff --git a/config/coreboot/default/patches/0045-haswell-NRI-Configure-initial-MC-settings.patch b/config/coreboot/default/patches/0045-haswell-NRI-Configure-initial-MC-settings.patch new file mode 100644 index 00000000..eefd17a9 --- /dev/null +++ b/config/coreboot/default/patches/0045-haswell-NRI-Configure-initial-MC-settings.patch @@ -0,0 +1,1594 @@ +From e91b308fe5848b14cabbd29be4af60e3a9b7938d Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sat, 7 May 2022 17:22:07 +0200 +Subject: [PATCH 45/65] 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/0046-haswell-NRI-Add-timings-refresh-programming.patch b/config/coreboot/default/patches/0046-haswell-NRI-Add-timings-refresh-programming.patch new file mode 100644 index 00000000..73234ac5 --- /dev/null +++ b/config/coreboot/default/patches/0046-haswell-NRI-Add-timings-refresh-programming.patch @@ -0,0 +1,541 @@ +From 694d1650cad8573e899916c0d0a25604885f6e3b Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sat, 7 May 2022 20:59:58 +0200 +Subject: [PATCH 46/65] 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/0046-mb-dell-Add-S3-SMI-handler-for-SNB-IVB-Latitudes.patch b/config/coreboot/default/patches/0046-mb-dell-Add-S3-SMI-handler-for-SNB-IVB-Latitudes.patch deleted file mode 100644 index 34d92278..00000000 --- a/config/coreboot/default/patches/0046-mb-dell-Add-S3-SMI-handler-for-SNB-IVB-Latitudes.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 9ff35368733c5e5a852ebd6295f262710553913b 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] mb/dell/: Add S3 SMI handler for SNB/IVB Latitudes - -This should fix S3 suspend on these systems - -Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> ---- - src/mainboard/dell/e5420/smihandler.c | 9 +++++++++ - src/mainboard/dell/e5520/smihandler.c | 9 +++++++++ - src/mainboard/dell/e5530/smihandler.c | 9 +++++++++ - src/mainboard/dell/e6420/smihandler.c | 9 +++++++++ - src/mainboard/dell/e6430/smihandler.c | 9 +++++++++ - src/mainboard/dell/e6520/smihandler.c | 9 +++++++++ - src/mainboard/dell/e6530/smihandler.c | 9 +++++++++ - 7 files changed, 63 insertions(+) - create mode 100644 src/mainboard/dell/e5420/smihandler.c - create mode 100644 src/mainboard/dell/e5520/smihandler.c - create mode 100644 src/mainboard/dell/e5530/smihandler.c - create mode 100644 src/mainboard/dell/e6420/smihandler.c - create mode 100644 src/mainboard/dell/e6430/smihandler.c - create mode 100644 src/mainboard/dell/e6520/smihandler.c - create mode 100644 src/mainboard/dell/e6530/smihandler.c - -diff --git a/src/mainboard/dell/e5420/smihandler.c b/src/mainboard/dell/e5420/smihandler.c -new file mode 100644 -index 0000000000..334d7b1a5f ---- /dev/null -+++ b/src/mainboard/dell/e5420/smihandler.c -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <cpu/x86/smm.h> -+#include <ec/dell/mec5035/mec5035.h> -+ -+void mainboard_smi_sleep(u8 slp_typ) -+{ -+ mec5035_sleep(slp_typ); -+} -diff --git a/src/mainboard/dell/e5520/smihandler.c b/src/mainboard/dell/e5520/smihandler.c -new file mode 100644 -index 0000000000..334d7b1a5f ---- /dev/null -+++ b/src/mainboard/dell/e5520/smihandler.c -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <cpu/x86/smm.h> -+#include <ec/dell/mec5035/mec5035.h> -+ -+void mainboard_smi_sleep(u8 slp_typ) -+{ -+ mec5035_sleep(slp_typ); -+} -diff --git a/src/mainboard/dell/e5530/smihandler.c b/src/mainboard/dell/e5530/smihandler.c -new file mode 100644 -index 0000000000..334d7b1a5f ---- /dev/null -+++ b/src/mainboard/dell/e5530/smihandler.c -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <cpu/x86/smm.h> -+#include <ec/dell/mec5035/mec5035.h> -+ -+void mainboard_smi_sleep(u8 slp_typ) -+{ -+ mec5035_sleep(slp_typ); -+} -diff --git a/src/mainboard/dell/e6420/smihandler.c b/src/mainboard/dell/e6420/smihandler.c -new file mode 100644 -index 0000000000..334d7b1a5f ---- /dev/null -+++ b/src/mainboard/dell/e6420/smihandler.c -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <cpu/x86/smm.h> -+#include <ec/dell/mec5035/mec5035.h> -+ -+void mainboard_smi_sleep(u8 slp_typ) -+{ -+ mec5035_sleep(slp_typ); -+} -diff --git a/src/mainboard/dell/e6430/smihandler.c b/src/mainboard/dell/e6430/smihandler.c -new file mode 100644 -index 0000000000..334d7b1a5f ---- /dev/null -+++ b/src/mainboard/dell/e6430/smihandler.c -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <cpu/x86/smm.h> -+#include <ec/dell/mec5035/mec5035.h> -+ -+void mainboard_smi_sleep(u8 slp_typ) -+{ -+ mec5035_sleep(slp_typ); -+} -diff --git a/src/mainboard/dell/e6520/smihandler.c b/src/mainboard/dell/e6520/smihandler.c -new file mode 100644 -index 0000000000..334d7b1a5f ---- /dev/null -+++ b/src/mainboard/dell/e6520/smihandler.c -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <cpu/x86/smm.h> -+#include <ec/dell/mec5035/mec5035.h> -+ -+void mainboard_smi_sleep(u8 slp_typ) -+{ -+ mec5035_sleep(slp_typ); -+} -diff --git a/src/mainboard/dell/e6530/smihandler.c b/src/mainboard/dell/e6530/smihandler.c -new file mode 100644 -index 0000000000..334d7b1a5f ---- /dev/null -+++ b/src/mainboard/dell/e6530/smihandler.c -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+ -+#include <cpu/x86/smm.h> -+#include <ec/dell/mec5035/mec5035.h> -+ -+void mainboard_smi_sleep(u8 slp_typ) -+{ -+ mec5035_sleep(slp_typ); -+} --- -2.44.0 - diff --git a/config/coreboot/default/patches/0047-haswell-NRI-Program-memory-map.patch b/config/coreboot/default/patches/0047-haswell-NRI-Program-memory-map.patch new file mode 100644 index 00000000..58a2f556 --- /dev/null +++ b/config/coreboot/default/patches/0047-haswell-NRI-Program-memory-map.patch @@ -0,0 +1,263 @@ +From 70d7333e1e0c2b0ce0f2a7e4c4c3ac5c1aca2094 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sat, 7 May 2022 21:24:50 +0200 +Subject: [PATCH 47/65] 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/0048-haswell-NRI-Add-DDR3-JEDEC-reset-and-init.patch b/config/coreboot/default/patches/0048-haswell-NRI-Add-DDR3-JEDEC-reset-and-init.patch new file mode 100644 index 00000000..b4108c7b --- /dev/null +++ b/config/coreboot/default/patches/0048-haswell-NRI-Add-DDR3-JEDEC-reset-and-init.patch @@ -0,0 +1,1036 @@ +From cc302630662eee011a903df4fd7a36d82bd22203 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sat, 7 May 2022 21:49:40 +0200 +Subject: [PATCH 48/65] 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/0049-haswell-NRI-Add-pre-training-steps.patch b/config/coreboot/default/patches/0049-haswell-NRI-Add-pre-training-steps.patch new file mode 100644 index 00000000..ffec948d --- /dev/null +++ b/config/coreboot/default/patches/0049-haswell-NRI-Add-pre-training-steps.patch @@ -0,0 +1,392 @@ +From 0f160dee563155e93422fc77c53251419043d4dc Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sat, 7 May 2022 23:12:18 +0200 +Subject: [PATCH 49/65] 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/0050-haswell-NRI-Add-REUT-I-O-test-library.patch b/config/coreboot/default/patches/0050-haswell-NRI-Add-REUT-I-O-test-library.patch new file mode 100644 index 00000000..a65a6ea1 --- /dev/null +++ b/config/coreboot/default/patches/0050-haswell-NRI-Add-REUT-I-O-test-library.patch @@ -0,0 +1,1130 @@ +From 78b25eb96baef7da2f5481572a6df2b88ee2b3d4 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sun, 8 May 2022 00:11:29 +0200 +Subject: [PATCH 50/65] 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/0051-haswell-NRI-Add-range-tracking-library.patch b/config/coreboot/default/patches/0051-haswell-NRI-Add-range-tracking-library.patch new file mode 100644 index 00000000..2ec35e26 --- /dev/null +++ b/config/coreboot/default/patches/0051-haswell-NRI-Add-range-tracking-library.patch @@ -0,0 +1,222 @@ +From ca6d92e13278832dfddbe7dcb4cbefa5861041e8 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sun, 8 May 2022 00:56:00 +0200 +Subject: [PATCH 51/65] 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/0052-haswell-NRI-Add-library-to-change-margins.patch b/config/coreboot/default/patches/0052-haswell-NRI-Add-library-to-change-margins.patch new file mode 100644 index 00000000..ffd76fc4 --- /dev/null +++ b/config/coreboot/default/patches/0052-haswell-NRI-Add-library-to-change-margins.patch @@ -0,0 +1,294 @@ +From f6d7bd420640a9ccb137113d69b97bc13fe6b0da Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sun, 8 May 2022 01:11:03 +0200 +Subject: [PATCH 52/65] 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/0053-haswell-NRI-Add-RcvEn-training.patch b/config/coreboot/default/patches/0053-haswell-NRI-Add-RcvEn-training.patch new file mode 100644 index 00000000..fdb8d270 --- /dev/null +++ b/config/coreboot/default/patches/0053-haswell-NRI-Add-RcvEn-training.patch @@ -0,0 +1,708 @@ +From d3cd9ccb7d2eed7ecd5bcdc33d73a5e28b029dba Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sun, 8 May 2022 00:05:41 +0200 +Subject: [PATCH 53/65] 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/0054-haswell-NRI-Add-function-to-change-margins.patch b/config/coreboot/default/patches/0054-haswell-NRI-Add-function-to-change-margins.patch new file mode 100644 index 00000000..58cc9d82 --- /dev/null +++ b/config/coreboot/default/patches/0054-haswell-NRI-Add-function-to-change-margins.patch @@ -0,0 +1,272 @@ +From dbf0fc28bbb939fe5a90c991b752f790828d462d Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sun, 8 May 2022 11:58:59 +0200 +Subject: [PATCH 54/65] 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/0055-haswell-NRI-Add-read-MPR-training.patch b/config/coreboot/default/patches/0055-haswell-NRI-Add-read-MPR-training.patch new file mode 100644 index 00000000..be0ddd13 --- /dev/null +++ b/config/coreboot/default/patches/0055-haswell-NRI-Add-read-MPR-training.patch @@ -0,0 +1,332 @@ +From 0a557e3d09a9a53bb085c43e6bdb99fa4cd78b85 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sun, 8 May 2022 11:35:49 +0200 +Subject: [PATCH 55/65] 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/0056-haswell-NRI-Add-write-leveling.patch b/config/coreboot/default/patches/0056-haswell-NRI-Add-write-leveling.patch new file mode 100644 index 00000000..0791fb80 --- /dev/null +++ b/config/coreboot/default/patches/0056-haswell-NRI-Add-write-leveling.patch @@ -0,0 +1,689 @@ +From e8f50deac2a671f7ec3958b376c37dd6b9bad5bd Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sun, 8 May 2022 12:56:04 +0200 +Subject: [PATCH 56/65] 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/0057-haswell-NRI-Add-final-raminit-steps.patch b/config/coreboot/default/patches/0057-haswell-NRI-Add-final-raminit-steps.patch new file mode 100644 index 00000000..3cd8c758 --- /dev/null +++ b/config/coreboot/default/patches/0057-haswell-NRI-Add-final-raminit-steps.patch @@ -0,0 +1,570 @@ +From 990ee284d48b66f06adb6c43a96439f7628390f5 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sun, 8 May 2022 14:29:05 +0200 +Subject: [PATCH 57/65] 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/0058-Haswell-NRI-Implement-fast-boot-path.patch b/config/coreboot/default/patches/0058-Haswell-NRI-Implement-fast-boot-path.patch new file mode 100644 index 00000000..b5d04b99 --- /dev/null +++ b/config/coreboot/default/patches/0058-Haswell-NRI-Implement-fast-boot-path.patch @@ -0,0 +1,722 @@ +From 63e9aa1f998ebd41b4c638fa66bdb1a6272a9e85 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Sat, 13 Apr 2024 01:16:30 +0200 +Subject: [PATCH 58/65] 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/0059-haswell-NRI-Do-sense-amplifier-offset-training.patch b/config/coreboot/default/patches/0059-haswell-NRI-Do-sense-amplifier-offset-training.patch new file mode 100644 index 00000000..0310e671 --- /dev/null +++ b/config/coreboot/default/patches/0059-haswell-NRI-Do-sense-amplifier-offset-training.patch @@ -0,0 +1,476 @@ +From c22e06a8ef87f74cc9955ffc259e7052742269c4 Mon Sep 17 00:00:00 2001 +From: Angel Pons <th3fanbus@gmail.com> +Date: Wed, 17 Apr 2024 13:20:32 +0200 +Subject: [PATCH 59/65] 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 + diff --git a/config/coreboot/default/patches/0060-nb-x4x-define-INTEL_GMA_DPLL_REF_FREQ.patch b/config/coreboot/default/patches/0060-nb-x4x-define-INTEL_GMA_DPLL_REF_FREQ.patch new file mode 100644 index 00000000..a899693b --- /dev/null +++ b/config/coreboot/default/patches/0060-nb-x4x-define-INTEL_GMA_DPLL_REF_FREQ.patch @@ -0,0 +1,52 @@ +From c0e95144b426ab323e0397942579261fbb7b922b Mon Sep 17 00:00:00 2001 +From: Leah Rowe <info@minifree.org> +Date: Mon, 12 Aug 2024 02:15:24 +0100 +Subject: [PATCH 60/65] 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: + +hw-gfx-gma-plls.adb:465:46: error: "INTEL_GMA_DPLL_REF_FREQ" not declared in "Config" +make: *** [Makefile:423: build/ramstage/libgfxinit/common/g45/hw-gfx-gma-plls.o] Error 1 + +this error was introduced when merging coreboot/dell +into coreboot/default in lbmk. nicholas chin's fix in lbmk +was as follows: + +commit 8629873a6043067affc137be275b7aa69cb1f10c +Author: Nicholas Chin <nic.c3.14@gmail.com> +Date: Mon May 20 10:46:25 2024 -0600 + + Fix E6400 display issue with 1440 x 900 panel + +this currently corresponds to the patch in lbmk, +as of 12 august 2024: + +0042-mb-dell-e6400-Use-100-MHz-reference-clock-for-displa.patch + +The assumption prior to Nicholas's fix was 96MHz, so set +it accordingly on x4x northbridge. + +Signed-off-by: Leah Rowe <info@minifree.org> +--- + src/northbridge/intel/x4x/Kconfig | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/northbridge/intel/x4x/Kconfig b/src/northbridge/intel/x4x/Kconfig +index 9af063819b..93ba575b95 100644 +--- a/src/northbridge/intel/x4x/Kconfig ++++ b/src/northbridge/intel/x4x/Kconfig +@@ -14,6 +14,10 @@ config NORTHBRIDGE_INTEL_X4X + + if NORTHBRIDGE_INTEL_X4X + ++config INTEL_GMA_DPLL_REF_FREQ ++ int ++ default 96000000 ++ + config CBFS_SIZE + default 0x100000 if !SOUTHBRIDGE_INTEL_I82801GX + +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0062-mb-dell-Convert-E6400-into-a-variant.patch b/config/coreboot/default/patches/0062-mb-dell-Convert-E6400-into-a-variant.patch new file mode 100644 index 00000000..acd7074c --- /dev/null +++ b/config/coreboot/default/patches/0062-mb-dell-Convert-E6400-into-a-variant.patch @@ -0,0 +1,243 @@ +From 0caa5d97b67b2acf571e4fab2b7f85ef3d3a7260 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 62/65] 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 +share code with each other. + +Change-Id: I8094fce56eaaadb20aef173644cd3b2c0b008e95 +Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> +--- + src/mainboard/dell/e6400/Makefile.mk | 10 -------- + .../dell/{e6400 => gm45_latitude}/Kconfig | 22 +++++++++++++----- + .../{e6400 => gm45_latitude}/Kconfig.name | 0 + src/mainboard/dell/gm45_latitude/Makefile.mk | 11 +++++++++ + .../dell/{e6400 => gm45_latitude}/acpi/ec.asl | 0 + .../acpi/ich9_pci_irqs.asl | 0 + .../{e6400 => gm45_latitude}/acpi/superio.asl | 0 + .../dell/{e6400 => gm45_latitude}/blc.c | 0 + .../{e6400 => gm45_latitude}/board_info.txt | 0 + .../dell/{e6400 => gm45_latitude}/bootblock.c | 0 + .../{e6400 => gm45_latitude}/cmos.default | 0 + .../dell/{e6400 => gm45_latitude}/cmos.layout | 0 + .../dell/{e6400 => gm45_latitude}/cstates.c | 0 + .../{e6400 => gm45_latitude}/devicetree.cb | 1 - + .../dell/{e6400 => gm45_latitude}/dsdt.asl | 0 + .../dell/{e6400 => gm45_latitude}/mainboard.c | 0 + .../dell/{e6400 => gm45_latitude}/romstage.c | 0 + .../variants}/e6400/data.vbt | Bin + .../variants}/e6400/gma-mainboard.ads | 0 + .../{ => gm45_latitude/variants}/e6400/gpio.c | 0 + .../variants}/e6400/hda_verb.c | 0 + .../variants/e6400/overridetree.cb | 7 ++++++ + 22 files changed, 34 insertions(+), 17 deletions(-) + delete mode 100644 src/mainboard/dell/e6400/Makefile.mk + rename src/mainboard/dell/{e6400 => gm45_latitude}/Kconfig (64%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/Kconfig.name (100%) + create mode 100644 src/mainboard/dell/gm45_latitude/Makefile.mk + rename src/mainboard/dell/{e6400 => gm45_latitude}/acpi/ec.asl (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/acpi/ich9_pci_irqs.asl (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/acpi/superio.asl (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/blc.c (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/board_info.txt (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/bootblock.c (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/cmos.default (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/cmos.layout (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/cstates.c (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/devicetree.cb (98%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/dsdt.asl (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/mainboard.c (100%) + rename src/mainboard/dell/{e6400 => gm45_latitude}/romstage.c (100%) + rename src/mainboard/dell/{ => gm45_latitude/variants}/e6400/data.vbt (100%) + rename src/mainboard/dell/{ => gm45_latitude/variants}/e6400/gma-mainboard.ads (100%) + rename src/mainboard/dell/{ => gm45_latitude/variants}/e6400/gpio.c (100%) + rename src/mainboard/dell/{ => gm45_latitude/variants}/e6400/hda_verb.c (100%) + create mode 100644 src/mainboard/dell/gm45_latitude/variants/e6400/overridetree.cb + +diff --git a/src/mainboard/dell/e6400/Makefile.mk b/src/mainboard/dell/e6400/Makefile.mk +deleted file mode 100644 +index ca3a82db48..0000000000 +--- a/src/mainboard/dell/e6400/Makefile.mk ++++ /dev/null +@@ -1,10 +0,0 @@ +-## SPDX-License-Identifier: GPL-2.0-only +- +-bootblock-y += bootblock.c +- +-romstage-y += gpio.c +- +-ramstage-y += cstates.c +-ramstage-y += blc.c +- +-ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads +diff --git a/src/mainboard/dell/e6400/Kconfig b/src/mainboard/dell/gm45_latitude/Kconfig +similarity index 64% +rename from src/mainboard/dell/e6400/Kconfig +rename to src/mainboard/dell/gm45_latitude/Kconfig +index 6fe1b1c456..ba76fb6e8c 100644 +--- a/src/mainboard/dell/e6400/Kconfig ++++ b/src/mainboard/dell/gm45_latitude/Kconfig +@@ -1,9 +1,7 @@ + ## SPDX-License-Identifier: GPL-2.0-only + +-if BOARD_DELL_E6400 +- +-config BOARD_SPECIFIC_OPTIONS +- def_bool y ++config BOARD_DELL_GM45_LATITUDE_COMMON ++ def_bool n + select SYSTEM_TYPE_LAPTOP + select CPU_INTEL_SOCKET_P + select NORTHBRIDGE_INTEL_GM45 +@@ -19,19 +17,31 @@ config BOARD_SPECIFIC_OPTIONS + select INTEL_GMA_HAVE_VBT + select EC_DELL_MEC5035 + ++ ++config BOARD_DELL_E6400 ++ select BOARD_DELL_GM45_LATITUDE_COMMON ++ ++if BOARD_DELL_GM45_LATITUDE_COMMON ++ + config INTEL_GMA_DPLL_REF_FREQ + default 100000000 + + config MAINBOARD_DIR +- default "dell/e6400" ++ default "dell/gm45_latitude" + + config MAINBOARD_PART_NUMBER + default "Latitude E6400" if BOARD_DELL_E6400 + ++config OVERRIDE_DEVICETREE ++ default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb" ++ ++config VARIANT_DIR ++ default "e6400" if BOARD_DELL_E6400 ++ + config USBDEBUG_HCD_INDEX + default 1 + + config CBFS_SIZE + default 0x1A0000 + +-endif # BOARD_DELL_E6400 ++endif # BOARD_DELL_GM45_LATITUDE_COMMON +diff --git a/src/mainboard/dell/e6400/Kconfig.name b/src/mainboard/dell/gm45_latitude/Kconfig.name +similarity index 100% +rename from src/mainboard/dell/e6400/Kconfig.name +rename to src/mainboard/dell/gm45_latitude/Kconfig.name +diff --git a/src/mainboard/dell/gm45_latitude/Makefile.mk b/src/mainboard/dell/gm45_latitude/Makefile.mk +new file mode 100644 +index 0000000000..5295d5be22 +--- /dev/null ++++ b/src/mainboard/dell/gm45_latitude/Makefile.mk +@@ -0,0 +1,11 @@ ++## SPDX-License-Identifier: GPL-2.0-only ++ ++bootblock-y += bootblock.c ++ ++romstage-y += variants/$(VARIANT_DIR)/gpio.c ++ ++ramstage-y += cstates.c ++ramstage-y += blc.c ++ramstage-y += variants/$(VARIANT_DIR)/hda_verb.c ++ ++ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += variants/$(VARIANT_DIR)/gma-mainboard.ads +diff --git a/src/mainboard/dell/e6400/acpi/ec.asl b/src/mainboard/dell/gm45_latitude/acpi/ec.asl +similarity index 100% +rename from src/mainboard/dell/e6400/acpi/ec.asl +rename to src/mainboard/dell/gm45_latitude/acpi/ec.asl +diff --git a/src/mainboard/dell/e6400/acpi/ich9_pci_irqs.asl b/src/mainboard/dell/gm45_latitude/acpi/ich9_pci_irqs.asl +similarity index 100% +rename from src/mainboard/dell/e6400/acpi/ich9_pci_irqs.asl +rename to src/mainboard/dell/gm45_latitude/acpi/ich9_pci_irqs.asl +diff --git a/src/mainboard/dell/e6400/acpi/superio.asl b/src/mainboard/dell/gm45_latitude/acpi/superio.asl +similarity index 100% +rename from src/mainboard/dell/e6400/acpi/superio.asl +rename to src/mainboard/dell/gm45_latitude/acpi/superio.asl +diff --git a/src/mainboard/dell/e6400/blc.c b/src/mainboard/dell/gm45_latitude/blc.c +similarity index 100% +rename from src/mainboard/dell/e6400/blc.c +rename to src/mainboard/dell/gm45_latitude/blc.c +diff --git a/src/mainboard/dell/e6400/board_info.txt b/src/mainboard/dell/gm45_latitude/board_info.txt +similarity index 100% +rename from src/mainboard/dell/e6400/board_info.txt +rename to src/mainboard/dell/gm45_latitude/board_info.txt +diff --git a/src/mainboard/dell/e6400/bootblock.c b/src/mainboard/dell/gm45_latitude/bootblock.c +similarity index 100% +rename from src/mainboard/dell/e6400/bootblock.c +rename to src/mainboard/dell/gm45_latitude/bootblock.c +diff --git a/src/mainboard/dell/e6400/cmos.default b/src/mainboard/dell/gm45_latitude/cmos.default +similarity index 100% +rename from src/mainboard/dell/e6400/cmos.default +rename to src/mainboard/dell/gm45_latitude/cmos.default +diff --git a/src/mainboard/dell/e6400/cmos.layout b/src/mainboard/dell/gm45_latitude/cmos.layout +similarity index 100% +rename from src/mainboard/dell/e6400/cmos.layout +rename to src/mainboard/dell/gm45_latitude/cmos.layout +diff --git a/src/mainboard/dell/e6400/cstates.c b/src/mainboard/dell/gm45_latitude/cstates.c +similarity index 100% +rename from src/mainboard/dell/e6400/cstates.c +rename to src/mainboard/dell/gm45_latitude/cstates.c +diff --git a/src/mainboard/dell/e6400/devicetree.cb b/src/mainboard/dell/gm45_latitude/devicetree.cb +similarity index 98% +rename from src/mainboard/dell/e6400/devicetree.cb +rename to src/mainboard/dell/gm45_latitude/devicetree.cb +index e9f3915d17..76dae87153 100644 +--- a/src/mainboard/dell/e6400/devicetree.cb ++++ b/src/mainboard/dell/gm45_latitude/devicetree.cb +@@ -15,7 +15,6 @@ chip northbridge/intel/gm45 + register "pci_mmio_size" = "2048" + + device domain 0 on +- subsystemid 0x1028 0x0233 inherit + ops gm45_pci_domain_ops + + device pci 00.0 on end # host bridge +diff --git a/src/mainboard/dell/e6400/dsdt.asl b/src/mainboard/dell/gm45_latitude/dsdt.asl +similarity index 100% +rename from src/mainboard/dell/e6400/dsdt.asl +rename to src/mainboard/dell/gm45_latitude/dsdt.asl +diff --git a/src/mainboard/dell/e6400/mainboard.c b/src/mainboard/dell/gm45_latitude/mainboard.c +similarity index 100% +rename from src/mainboard/dell/e6400/mainboard.c +rename to src/mainboard/dell/gm45_latitude/mainboard.c +diff --git a/src/mainboard/dell/e6400/romstage.c b/src/mainboard/dell/gm45_latitude/romstage.c +similarity index 100% +rename from src/mainboard/dell/e6400/romstage.c +rename to src/mainboard/dell/gm45_latitude/romstage.c +diff --git a/src/mainboard/dell/e6400/data.vbt b/src/mainboard/dell/gm45_latitude/variants/e6400/data.vbt +similarity index 100% +rename from src/mainboard/dell/e6400/data.vbt +rename to src/mainboard/dell/gm45_latitude/variants/e6400/data.vbt +diff --git a/src/mainboard/dell/e6400/gma-mainboard.ads b/src/mainboard/dell/gm45_latitude/variants/e6400/gma-mainboard.ads +similarity index 100% +rename from src/mainboard/dell/e6400/gma-mainboard.ads +rename to src/mainboard/dell/gm45_latitude/variants/e6400/gma-mainboard.ads +diff --git a/src/mainboard/dell/e6400/gpio.c b/src/mainboard/dell/gm45_latitude/variants/e6400/gpio.c +similarity index 100% +rename from src/mainboard/dell/e6400/gpio.c +rename to src/mainboard/dell/gm45_latitude/variants/e6400/gpio.c +diff --git a/src/mainboard/dell/e6400/hda_verb.c b/src/mainboard/dell/gm45_latitude/variants/e6400/hda_verb.c +similarity index 100% +rename from src/mainboard/dell/e6400/hda_verb.c +rename to src/mainboard/dell/gm45_latitude/variants/e6400/hda_verb.c +diff --git a/src/mainboard/dell/gm45_latitude/variants/e6400/overridetree.cb b/src/mainboard/dell/gm45_latitude/variants/e6400/overridetree.cb +new file mode 100644 +index 0000000000..acc34a2252 +--- /dev/null ++++ b/src/mainboard/dell/gm45_latitude/variants/e6400/overridetree.cb +@@ -0,0 +1,7 @@ ++## SPDX-License-Identifier: GPL-2.0-or-later ++ ++chip northbridge/intel/gm45 ++ device domain 0 on ++ subsystemid 0x1028 0x0233 inherit ++ end ++end +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0063-mb-dell-gm45_latitudes-Add-E4300-variant.patch b/config/coreboot/default/patches/0063-mb-dell-gm45_latitudes-Add-E4300-variant.patch new file mode 100644 index 00000000..1e76adfe --- /dev/null +++ b/config/coreboot/default/patches/0063-mb-dell-gm45_latitudes-Add-E4300-variant.patch @@ -0,0 +1,332 @@ +From bc9836ac2708687dfe43656adba2833493fa4199 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 63/65] mb/dell/gm45_latitudes: Add E4300 variant + +Change-Id: I0f2059501b11be103187e3ce1a7c04ab85ae63d2 +Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> +--- + src/mainboard/dell/gm45_latitude/Kconfig | 5 + + src/mainboard/dell/gm45_latitude/Kconfig.name | 3 + + .../gm45_latitude/variants/e4300/data.vbt | Bin 0 -> 3881 bytes + .../variants/e4300/gma-mainboard.ads | 17 +++ + .../dell/gm45_latitude/variants/e4300/gpio.c | 138 ++++++++++++++++++ + .../gm45_latitude/variants/e4300/hda_verb.c | 37 +++++ + .../variants/e4300/overridetree.cb | 10 ++ + 7 files changed, 210 insertions(+) + create mode 100644 src/mainboard/dell/gm45_latitude/variants/e4300/data.vbt + create mode 100644 src/mainboard/dell/gm45_latitude/variants/e4300/gma-mainboard.ads + create mode 100644 src/mainboard/dell/gm45_latitude/variants/e4300/gpio.c + create mode 100644 src/mainboard/dell/gm45_latitude/variants/e4300/hda_verb.c + create mode 100644 src/mainboard/dell/gm45_latitude/variants/e4300/overridetree.cb + +diff --git a/src/mainboard/dell/gm45_latitude/Kconfig b/src/mainboard/dell/gm45_latitude/Kconfig +index ba76fb6e8c..144f9bcdf0 100644 +--- a/src/mainboard/dell/gm45_latitude/Kconfig ++++ b/src/mainboard/dell/gm45_latitude/Kconfig +@@ -21,6 +21,9 @@ config BOARD_DELL_GM45_LATITUDE_COMMON + config BOARD_DELL_E6400 + select BOARD_DELL_GM45_LATITUDE_COMMON + ++config BOARD_DELL_E4300 ++ select BOARD_DELL_GM45_LATITUDE_COMMON ++ + if BOARD_DELL_GM45_LATITUDE_COMMON + + config INTEL_GMA_DPLL_REF_FREQ +@@ -31,12 +34,14 @@ config MAINBOARD_DIR + + config MAINBOARD_PART_NUMBER + default "Latitude E6400" if BOARD_DELL_E6400 ++ default "Latitude E4300" if BOARD_DELL_E4300 + + config OVERRIDE_DEVICETREE + default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb" + + config VARIANT_DIR + default "e6400" if BOARD_DELL_E6400 ++ default "e4300" if BOARD_DELL_E4300 + + config USBDEBUG_HCD_INDEX + default 1 +diff --git a/src/mainboard/dell/gm45_latitude/Kconfig.name b/src/mainboard/dell/gm45_latitude/Kconfig.name +index aefe777109..4dc95f46be 100644 +--- a/src/mainboard/dell/gm45_latitude/Kconfig.name ++++ b/src/mainboard/dell/gm45_latitude/Kconfig.name +@@ -1,4 +1,7 @@ + ## SPDX-License-Identifier: GPL-2.0-only + ++config BOARD_DELL_E4300 ++ bool "Latitude E4300" ++ + config BOARD_DELL_E6400 + bool "Latitude E6400" +diff --git a/src/mainboard/dell/gm45_latitude/variants/e4300/data.vbt b/src/mainboard/dell/gm45_latitude/variants/e4300/data.vbt +new file mode 100644 +index 0000000000000000000000000000000000000000..fa2f3db13f688b5687df16a155781d8674ea26f3 +GIT binary patch +literal 3881 +zcmdT`eQXp(6#wnV-R;foUbovquV-n84`GWGmlkRzXWaG>Td6>yG#51CN?M@?>DeM+ +zBI$}GlK6F+nD{}Y|ClJzh>3}Rm=N?2Y5a<biIGGii6#d8gP4#QmGpeGyBx))(i;53 +zx0(69nR)Nco0&Inc1d4HFVD7b?CrX@org342aOf$sh&<9U7NP<Sl8a$zN4diQ+5M? +z9rN*fa`GZDAW257d6jcVwtw%wp<VsFPss9IbIT6VyT7@GKQuhTyNCDm-+uql-l6R9 +zaA9y{CEr#U=-)Ruz;_Pq?H?H$9GyPr&Fjey7akuO+O>Nhx3i7B*>RjEs#<v0-hG36 +zcy@TCu#&g$*~7O8nNhxFaCC5F|KPw%gBc7st!SzQND;)Ih9pfkBd$T$U~A~qu#ltO +zMczfDhAs`eH4JHpsJLH4lZIP4`dyfi4M|pkg+SayZ(n(7kunGFvl<qe=w81$=+A#a +zN=hgb2&njUcPLB!=P$(o-$={^mxQGIHvtVGBS4IU%YyNVhd3krw*m^es@B12UftTZ +zHsf}zTi<zK_vS6VeYx!qdQTpH>PQ-s5C6@#q~ze8SUuLOHbzw$htxKlQYWCt9NZmC +zVLO$_s2tQZ9MvqmM&%tUr>K0RF`T3FGnHSdOj6O}3>K9-D$(bpD<v6uK&w=s5=N^P +zn1nKYZrHyr#A-t5vRX$dPN$Pl=yivfA{67CP>h$)OQqAIh6jOwCxuw)qvS0N+Nk!? +zI~I-~3&u$!iZQuCQ3;=xYZQ&}1^JS!6aFCSvPt-}q{`KV7o=aLI=_ERh8gM+`g(-E +z9-*&C=<5;sdVc?y{2iwmrKs|~Kw5}Heji&vYYqJOG&As1`1?G0hsr2Y&r%2qq-H)u +z>=c836bj~sR4T<{m@IvjLaC(P1v(j%W}uLfs)L<DD#SV;6@`cGC4?jgJ8YLq>~qi^ +z4yaW6zjKK*SSa$dvbC#eRZDAgQ@dDEfr?l)G{1I<Q#e&+8Yy!=BeKi&0@sfte<K0& +zMgsgs0(vE~6cP&098SWEom4ZZF%<l!OeEuw4n?=)Y_tg#&wy^{e@5{s`F9qRm`5m; +zi_|4iQq@4&R8mD)tJIvCw3$`@-B9JV=`1}s_;B_rjtcVXpQ!o`MAJ$M5w65C7t<Ku +z%xfIo$p$+0N}Qe(C7MY#!0SQ1({^-qFj5ylEHjhwn>8}OhGtOw#1e$Fn9w<r1Zp}l +zPz$#mOP$ow*1(UHvmCGVz;T^IRnSxa*6jz+_oSD)xmT|Cbl&YcJ5M&d?&+&NDI2Y0 +zO0ai&>sUmbC8g}vF{$V$Y~rFp!qRJP)Z!2NYEhIpf^PzD_^ptxacQ#R+9@(N>ibe6 +z@|mz|d=bjIxSe3u0>+jxdmFQMG4?34k2C9i#y(>91!n!pSR`S$B&>T9Y*WHMl(1e% +zuvZiInS^yV!G28GmAbW9XHB~OfNnjavje*Qrfz+xvyXNAl5R-`OBnW@hPA<9+YI|D +z!+P0Z#|`^S!}`Hs7Yw^5X*DKUOVaL7TBAv}d|dV9^O8rYn%=4o&5GjdSWeb`yeyf7 +zk&0z-2#I*9^ljWL^79K!Ex#yORz2-nxRYGT$+NdKUcs>{SI2Fyx@<{2w?w*#&%hG* +zeY&DumV{4Nw4(1*^g5r`avbR44Nj-miiQs;Ii;O}*rL^|oYl8hQ9P@{Qf5}Gn;uRg +zI{c?gKNv~R$<jgIlQvzm9GD`y{Dh<T(H)!WlUUWvtFvzDqaVV>&eHj<So5w}UG%+7 +zt=J~1YHpT3TjRY{XlrmCz6QBZ$WqGr>8!uus22Br_GkCD$Q)pf!<P$30Ez;o=qDzr +z7@f;LJ+ZPlo=?}4PvMm&OKLGLZ0h1&n7U8@9GP~;8!wz(OqQ<s6e;@8hfYU0ht*9> +zGh%f}_&(hXOZrW-WCWJVw`DdrczV_sXGaOvzjt%F!O;{7J-K<j&AXad#XeO8mgw(v +z_Gj1VBJZIpZ<>`tJBTNGZHe^T`VrkY0pv~u^?l~DG9UD8p8(692<oYlGx5_cte6LX +JE5(FU=`RLB=-&VU + +literal 0 +HcmV?d00001 + +diff --git a/src/mainboard/dell/gm45_latitude/variants/e4300/gma-mainboard.ads b/src/mainboard/dell/gm45_latitude/variants/e4300/gma-mainboard.ads +new file mode 100644 +index 0000000000..89b81b3d69 +--- /dev/null ++++ b/src/mainboard/dell/gm45_latitude/variants/e4300/gma-mainboard.ads +@@ -0,0 +1,17 @@ ++-- 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, -- dock DP ++ Analog, -- mainboard VGA ++ LVDS, ++ others => Disabled); ++ ++end GMA.Mainboard; +diff --git a/src/mainboard/dell/gm45_latitude/variants/e4300/gpio.c b/src/mainboard/dell/gm45_latitude/variants/e4300/gpio.c +new file mode 100644 +index 0000000000..b50f8da0b5 +--- /dev/null ++++ b/src/mainboard/dell/gm45_latitude/variants/e4300/gpio.c +@@ -0,0 +1,138 @@ ++/* 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_GPIO, ++ .gpio2 = GPIO_MODE_GPIO, ++ .gpio3 = GPIO_MODE_GPIO, ++ .gpio4 = GPIO_MODE_GPIO, ++ .gpio5 = GPIO_MODE_GPIO, ++ .gpio6 = GPIO_MODE_GPIO, ++ .gpio7 = GPIO_MODE_GPIO, ++ .gpio8 = GPIO_MODE_GPIO, ++ .gpio9 = GPIO_MODE_NATIVE, ++ .gpio10 = GPIO_MODE_NATIVE, ++ .gpio11 = GPIO_MODE_NATIVE, ++ .gpio12 = GPIO_MODE_NATIVE, ++ .gpio13 = GPIO_MODE_GPIO, ++ .gpio14 = GPIO_MODE_GPIO, ++ .gpio15 = GPIO_MODE_NATIVE, ++ .gpio16 = GPIO_MODE_NATIVE, ++ .gpio17 = GPIO_MODE_GPIO, ++ .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_NATIVE, ++ .gpio30 = GPIO_MODE_NATIVE, ++ .gpio31 = GPIO_MODE_NATIVE, ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_direction = { ++ .gpio1 = GPIO_DIR_INPUT, ++ .gpio2 = GPIO_DIR_INPUT, ++ .gpio3 = GPIO_DIR_INPUT, ++ .gpio4 = GPIO_DIR_INPUT, ++ .gpio5 = GPIO_DIR_INPUT, ++ .gpio6 = GPIO_DIR_INPUT, ++ .gpio7 = GPIO_DIR_INPUT, ++ .gpio8 = GPIO_DIR_INPUT, ++ .gpio13 = GPIO_DIR_INPUT, ++ .gpio14 = GPIO_DIR_INPUT, ++ .gpio17 = GPIO_DIR_INPUT, ++ .gpio18 = GPIO_DIR_INPUT, ++ .gpio19 = GPIO_DIR_INPUT, ++ .gpio20 = GPIO_DIR_INPUT, ++ .gpio21 = GPIO_DIR_INPUT, ++ .gpio22 = GPIO_DIR_INPUT, ++ .gpio24 = GPIO_DIR_INPUT, ++ .gpio27 = GPIO_DIR_INPUT, ++ .gpio28 = GPIO_DIR_INPUT, ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_level = { ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_blink = { ++}; ++ ++static const struct pch_gpio_set1 pch_gpio_set1_invert = { ++ .gpio1 = GPIO_INVERT, ++ .gpio7 = GPIO_INVERT, ++ .gpio8 = GPIO_INVERT, ++}; ++ ++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_NATIVE, ++ .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_GPIO, ++ .gpio53 = GPIO_MODE_GPIO, ++ .gpio54 = GPIO_MODE_NATIVE, ++ .gpio55 = GPIO_MODE_NATIVE, ++ .gpio56 = GPIO_MODE_GPIO, ++ .gpio57 = GPIO_MODE_GPIO, ++ .gpio58 = GPIO_MODE_NATIVE, ++ .gpio59 = GPIO_MODE_NATIVE, ++ .gpio60 = GPIO_MODE_GPIO, ++}; ++ ++static const struct pch_gpio_set2 pch_gpio_set2_direction = { ++ .gpio33 = GPIO_DIR_INPUT, ++ .gpio34 = GPIO_DIR_INPUT, ++ .gpio36 = GPIO_DIR_INPUT, ++ .gpio37 = GPIO_DIR_INPUT, ++ .gpio38 = GPIO_DIR_INPUT, ++ .gpio39 = GPIO_DIR_INPUT, ++ .gpio48 = GPIO_DIR_INPUT, ++ .gpio49 = GPIO_DIR_INPUT, ++ .gpio52 = GPIO_DIR_INPUT, ++ .gpio53 = GPIO_DIR_INPUT, ++ .gpio56 = GPIO_DIR_INPUT, ++ .gpio57 = GPIO_DIR_INPUT, ++ .gpio60 = GPIO_DIR_INPUT, ++}; ++ ++static const struct pch_gpio_set2 pch_gpio_set2_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, ++ }, ++}; +diff --git a/src/mainboard/dell/gm45_latitude/variants/e4300/hda_verb.c b/src/mainboard/dell/gm45_latitude/variants/e4300/hda_verb.c +new file mode 100644 +index 0000000000..a9948a93dd +--- /dev/null ++++ b/src/mainboard/dell/gm45_latitude/variants/e4300/hda_verb.c +@@ -0,0 +1,37 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <device/azalia_device.h> ++ ++const u32 cim_verb_data[] = { ++ /* coreboot specific header */ ++ 0x111d76b2, /* IDT 92HD71B7X */ ++ 0x1028024d, /* Subsystem ID */ ++ 13, /* Number of entries */ ++ ++ /* Pin Widget Verb Table */ ++ ++ AZALIA_PIN_CFG(0, 0x0a, 0x0421101f), ++ AZALIA_PIN_CFG(0, 0x0b, 0x04a11021), ++ AZALIA_PIN_CFG(0, 0x0c, 0x40f000f0), ++ AZALIA_PIN_CFG(0, 0x0d, 0x90170110), ++ AZALIA_PIN_CFG(0, 0x0e, 0x23a1102e), ++ AZALIA_PIN_CFG(0, 0x0f, 0x23011050), ++ AZALIA_PIN_CFG(0, 0x14, 0x40f000f2), ++ AZALIA_PIN_CFG(0, 0x18, 0x90a601a0), ++ AZALIA_PIN_CFG(0, 0x19, 0x40f000f4), ++ AZALIA_PIN_CFG(0, 0x1e, 0x40f000f5), ++ AZALIA_PIN_CFG(0, 0x1f, 0x40f000f6), ++ AZALIA_PIN_CFG(0, 0x20, 0x40f000f7), ++ AZALIA_PIN_CFG(0, 0x27, 0x40f000f0), ++}; ++ ++const u32 pc_beep_verbs[] = { ++ 0x00170500, /* power up codec */ ++ 0x00d70500, /* power up speakers */ ++ 0x00d70102, /* select mixer (input 0x2) for speakers */ ++ 0x00d70740, /* enable speakers output */ ++ 0x02770720, /* enable beep input */ ++ 0x01737217, /* unmute beep (mixer's input 0x2), set amp 0dB */ ++ 0x00d37000, /* unmute speakers */ ++}; ++AZALIA_ARRAY_SIZES; +diff --git a/src/mainboard/dell/gm45_latitude/variants/e4300/overridetree.cb b/src/mainboard/dell/gm45_latitude/variants/e4300/overridetree.cb +new file mode 100644 +index 0000000000..20dfa245fb +--- /dev/null ++++ b/src/mainboard/dell/gm45_latitude/variants/e4300/overridetree.cb +@@ -0,0 +1,10 @@ ++## SPDX-License-Identifier: GPL-2.0-or-later ++ ++chip northbridge/intel/gm45 ++ device domain 0 on ++ subsystemid 0x1028 0x024d inherit ++ chip southbridge/intel/i82801ix ++ device pci 1c.2 off end # PCIe Port #3 ++ end ++ end ++end +-- +2.39.5 + diff --git a/config/coreboot/default/patches/0066-mb-dell-Add-S3-SMI-handler-for-Dell-Latitudes.patch b/config/coreboot/default/patches/0066-mb-dell-Add-S3-SMI-handler-for-Dell-Latitudes.patch new file mode 100644 index 00000000..d58968a1 --- /dev/null +++ b/config/coreboot/default/patches/0066-mb-dell-Add-S3-SMI-handler-for-Dell-Latitudes.patch @@ -0,0 +1,70 @@ +From 0fe1d4b9fe56a0f27a6ff39cfb94d63559b729b8 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 66/67] 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. +The E6400 does not require the EC command to sucessfully suspend and +resume from S3, though sending it does enable the breathing effect on +the power LED while in S3. Without it, all LEDs turn off during S3. + +Change-Id: Ic0d887f75be13c3fb9f6df62153ac458895e0283 +Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> +--- + src/mainboard/dell/e7240/smihandler.c | 9 +++++++++ + src/mainboard/dell/gm45_latitude/smihandler.c | 9 +++++++++ + src/mainboard/dell/snb_ivb_latitude/smihandler.c | 9 +++++++++ + 3 files changed, 27 insertions(+) + create mode 100644 src/mainboard/dell/e7240/smihandler.c + create mode 100644 src/mainboard/dell/gm45_latitude/smihandler.c + create mode 100644 src/mainboard/dell/snb_ivb_latitude/smihandler.c + +diff --git a/src/mainboard/dell/e7240/smihandler.c b/src/mainboard/dell/e7240/smihandler.c +new file mode 100644 +index 0000000000..00e55b51db +--- /dev/null ++++ b/src/mainboard/dell/e7240/smihandler.c +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <cpu/x86/smm.h> ++#include <ec/dell/mec5035/mec5035.h> ++ ++void mainboard_smi_sleep(u8 slp_typ) ++{ ++ mec5035_smi_sleep(slp_typ); ++} +diff --git a/src/mainboard/dell/gm45_latitude/smihandler.c b/src/mainboard/dell/gm45_latitude/smihandler.c +new file mode 100644 +index 0000000000..00e55b51db +--- /dev/null ++++ b/src/mainboard/dell/gm45_latitude/smihandler.c +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <cpu/x86/smm.h> ++#include <ec/dell/mec5035/mec5035.h> ++ ++void mainboard_smi_sleep(u8 slp_typ) ++{ ++ mec5035_smi_sleep(slp_typ); ++} +diff --git a/src/mainboard/dell/snb_ivb_latitude/smihandler.c b/src/mainboard/dell/snb_ivb_latitude/smihandler.c +new file mode 100644 +index 0000000000..00e55b51db +--- /dev/null ++++ b/src/mainboard/dell/snb_ivb_latitude/smihandler.c +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++ ++#include <cpu/x86/smm.h> ++#include <ec/dell/mec5035/mec5035.h> ++ ++void mainboard_smi_sleep(u8 slp_typ) ++{ ++ mec5035_smi_sleep(slp_typ); ++} +-- +2.47.0 + diff --git a/config/coreboot/default/patches/0067-ec-dell-mec5035-Route-power-button-event-to-host.patch b/config/coreboot/default/patches/0067-ec-dell-mec5035-Route-power-button-event-to-host.patch new file mode 100644 index 00000000..d8662e40 --- /dev/null +++ b/config/coreboot/default/patches/0067-ec-dell-mec5035-Route-power-button-event-to-host.patch @@ -0,0 +1,92 @@ +From 32118fa1d21fad517f85cee5eb4edff5f2fd91ea 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 67/67] 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 +the OS cleanly shutting itself down. This command and argument tells the +EC to route power button events to the host so that it can determine +what to do. + +The EC command was identified from the ec/google/wilco code, which is +used for Dell's Latitude Chromebooks. According to the EC_GOOGLE_WILCO +Kconfig help text, those ECs run a modified version of Dell's typical +Latitude EC firmware, so it is likely that the two firmware +implementations use similar commands. Examining LPC traffic between the +host and the EC on the Latitude E6400 did reveal that the same command +was being sent by the vendor firmware to the EC, but this does not +confirm that it has the same meaning as the command from the Wilco code. +Sending the command using inb/outb calls in a userspace C program while +running coreboot without this patch did allow subsequent power button +events to be handled by the host, confirming that the command was indeed +the same. + +Change-Id: I5ded315270c0e1efbbc90cfa9d9d894b872e99a2 +Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com> +--- + src/ec/dell/mec5035/mec5035.c | 8 ++++++++ + src/ec/dell/mec5035/mec5035.h | 7 +++++++ + 2 files changed, 15 insertions(+) + +diff --git a/src/ec/dell/mec5035/mec5035.c b/src/ec/dell/mec5035/mec5035.c +index 85c2ab0140..bdae929a27 100644 +--- a/src/ec/dell/mec5035/mec5035.c ++++ b/src/ec/dell/mec5035/mec5035.c +@@ -94,6 +94,13 @@ void mec5035_control_radio(enum ec_radio_dev dev, enum ec_radio_state state) + ec_command(CMD_RADIO_CTRL); + } + ++void mec5035_power_button_route(enum ec_power_button_route target) ++{ ++ u8 buf = (u8)target; ++ write_mailbox_regs(&buf, 2, 1); ++ ec_command(CMD_POWER_BUTTON_TO_HOST); ++} ++ + void mec5035_change_wake(u8 source, enum ec_wake_change change) + { + u8 buf[ACPI_WAKEUP_NUM_ARGS] = {change, source, 0, 0x40}; +@@ -121,6 +128,7 @@ static void mec5035_init(struct device *dev) + /* Unconditionally use this argument for now as this setting + is probably the most sensible default out of the 3 choices. */ + mec5035_mouse_touchpad(TP_PS2_MOUSE); ++ mec5035_power_button_route(HOST); + + pc_keyboard_init(NO_AUX_DEVICE); + +diff --git a/src/ec/dell/mec5035/mec5035.h b/src/ec/dell/mec5035/mec5035.h +index 8d4fded28b..51422598c4 100644 +--- a/src/ec/dell/mec5035/mec5035.h ++++ b/src/ec/dell/mec5035/mec5035.h +@@ -11,6 +11,7 @@ + enum mec5035_cmd { + CMD_MOUSE_TP = 0x1a, + CMD_RADIO_CTRL = 0x2b, ++ CMD_POWER_BUTTON_TO_HOST = 0x3e, + CMD_ACPI_WAKEUP_CHANGE = 0x4a, + CMD_SLEEP_ENABLE = 0x64, + CMD_CPU_OK = 0xc2, +@@ -36,6 +37,11 @@ enum ec_radio_state { + RADIO_ON + }; + ++enum ec_power_button_route { ++ EC = 0, ++ HOST ++}; ++ + #define ACPI_WAKEUP_NUM_ARGS 4 + enum ec_wake_change { + WAKE_OFF = 0, +@@ -55,6 +61,7 @@ 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); ++void mec5035_power_button_route(enum ec_power_button_route target); + void mec5035_change_wake(u8 source, enum ec_wake_change change); + void mec5035_sleep_enable(void); + +-- +2.47.0 + |