From ae68ef36848626e1d128359d12c31a66bbdb1b98 Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Sun, 25 May 2025 09:55:18 +0200 Subject: [PATCH] cpu/intel/haswell: Export PCODE mailbox functions The PCODE mailbox is primarily used by CPU code in ramstage. However, it is also used as part of enabling DDR 2x refresh rate, which is now implemented in coreboot as part of NRI (native RAM init). The PCODE mailbox functions in CPU code were not exported at the time NRI was being developed, so I chose to temporarily copy the functions into NRI code to make it easier to rebase NRI patches since it avoids potential merge conflicts. After a few years of rebasing patches, NRI finally got submitted, so there's no reason to keep duplicate code in the tree anymore. Put the relevant PCODE functions into a new file, which gets compiled for both ramstage (CPU init) and romstage (NRI). The BCLK calibration function is only used in ramstage so there's no need to move it. Change-Id: I340625fabc072139b8def254f1ce6b19f360adcd Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/87827 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph --- src/cpu/intel/haswell/Makefile.mk | 2 + src/cpu/intel/haswell/haswell.h | 5 +++ src/cpu/intel/haswell/haswell_init.c | 64 +++------------------------ src/cpu/intel/haswell/pcode_mailbox.c | 63 ++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 59 deletions(-) create mode 100644 src/cpu/intel/haswell/pcode_mailbox.c diff --git a/src/cpu/intel/haswell/Makefile.mk b/src/cpu/intel/haswell/Makefile.mk index 8b8e98600a..41ca9c9d98 100644 --- a/src/cpu/intel/haswell/Makefile.mk +++ b/src/cpu/intel/haswell/Makefile.mk @@ -5,6 +5,7 @@ bootblock-y += ../car/non-evict/cache_as_ram.S bootblock-y += ../car/bootblock.c bootblock-y += ../../x86/early_reset.S +romstage-y += pcode_mailbox.c romstage-y += romstage.c romstage-y += ../car/romstage.c @@ -12,6 +13,7 @@ postcar-y += ../car/non-evict/exit_car.S ramstage-y += acpi.c ramstage-y += haswell_init.c +ramstage-y += pcode_mailbox.c ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c smm-y += finalize.c diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h index f63b0ef4b3..f42199de0a 100644 --- a/src/cpu/intel/haswell/haswell.h +++ b/src/cpu/intel/haswell/haswell.h @@ -171,6 +171,11 @@ int cpu_config_tdp_levels(void); void set_max_freq(void); +/* pcode_mailbox.c */ +int pcode_ready(void); +u32 pcode_mailbox_read(u32 command); +int pcode_mailbox_write(u32 command, u32 data); + /* CPU identification */ static inline u32 cpu_family_model(void) { diff --git a/src/cpu/intel/haswell/haswell_init.c b/src/cpu/intel/haswell/haswell_init.c index 86dcbea177..8232453a57 100644 --- a/src/cpu/intel/haswell/haswell_init.c +++ b/src/cpu/intel/haswell/haswell_init.c @@ -77,25 +77,11 @@ static const u8 power_limit_time_msr_to_sec[] = { [0x11] = 128, }; -/* The core 100MHz BCLK is disabled in deeper c-states. One needs to calibrate +/* + * The core 100MHz BCLK is disabled in deeper c-states. One needs to calibrate * the 100MHz BCLK against the 24MHz BCLK to restore the clocks properly - * when a core is woken up. */ -static int pcode_ready(void) -{ - int wait_count; - const int delay_step = 10; - - wait_count = 0; - do { - if (!(mchbar_read32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY)) - return 0; - wait_count += delay_step; - udelay(delay_step); - } while (wait_count < 1000); - - return -1; -} - + * when a core is woken up. + */ static void calibrate_24mhz_bclk(void) { int err_code; @@ -117,8 +103,7 @@ static void calibrate_24mhz_bclk(void) err_code = mchbar_read32(BIOS_MAILBOX_INTERFACE) & 0xff; - printk(BIOS_DEBUG, "PCODE: 24MHz BCLK calibration response: %d\n", - err_code); + printk(BIOS_DEBUG, "PCODE: 24MHz BCLK calibration response: %d\n", err_code); /* Read the calibrated value. */ mchbar_write32(BIOS_MAILBOX_INTERFACE, @@ -133,45 +118,6 @@ static void calibrate_24mhz_bclk(void) mchbar_read32(BIOS_MAILBOX_DATA)); } -static u32 pcode_mailbox_read(u32 command) -{ - if (pcode_ready() < 0) { - printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); - return 0; - } - - /* Send command and start transaction */ - mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY); - - if (pcode_ready() < 0) { - printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); - return 0; - } - - /* Read mailbox */ - return mchbar_read32(BIOS_MAILBOX_DATA); -} - -static int pcode_mailbox_write(u32 command, u32 data) -{ - if (pcode_ready() < 0) { - printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); - return -1; - } - - mchbar_write32(BIOS_MAILBOX_DATA, data); - - /* Send command and start transaction */ - mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY); - - if (pcode_ready() < 0) { - printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); - return -1; - } - - return 0; -} - static struct device *cpu_cluster; static void initialize_vr_config(void) diff --git a/src/cpu/intel/haswell/pcode_mailbox.c b/src/cpu/intel/haswell/pcode_mailbox.c new file mode 100644 index 0000000000..7d866466e7 --- /dev/null +++ b/src/cpu/intel/haswell/pcode_mailbox.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include + +#include "haswell.h" + +int pcode_ready(void) +{ + int wait_count; + const int delay_step = 10; + + wait_count = 0; + do { + if (!(mchbar_read32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY)) + return 0; + wait_count += delay_step; + udelay(delay_step); + } while (wait_count < 1000); + + return -1; +} + +u32 pcode_mailbox_read(u32 command) +{ + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); + return 0; + } + + /* Send command and start transaction */ + mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY); + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); + return 0; + } + + /* Read mailbox */ + return mchbar_read32(BIOS_MAILBOX_DATA); +} + +int pcode_mailbox_write(u32 command, u32 data) +{ + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); + return -1; + } + + mchbar_write32(BIOS_MAILBOX_DATA, data); + + /* Send command and start transaction */ + mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY); + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); + return -1; + } + + return 0; +}