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 <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/87827
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com>
This commit is contained in:
Angel Pons 2025-05-25 09:55:18 +02:00 committed by Matt DeVillier
commit ae68ef3684
4 changed files with 75 additions and 59 deletions

View file

@ -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

View file

@ -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)
{

View file

@ -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)

View file

@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <console/console.h>
#include <delay.h>
#include <northbridge/intel/haswell/haswell.h>
#include <types.h>
#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;
}