soc/intel/alderlake: Add support to update descriptor at runtime
On nereid, we need to update the descriptor based on fw_config (see the follow-up patch), so add support to update the descriptor at runtime. This is a temporary workaround while we find a better solution. This is basically adding back the configure_pmc_descriptor() function removed in CB:63339, just making it generic and allowing it to update multiple bytes at once. BUG=b:226848617 TEST=With the following patch, Type-C and HDMI work on nereid. Change-Id: I43c4d2888706561e42ff6b8ce0377eedbc38dbfe Signed-off-by: Reka Norman <rekanorman@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/63365 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Eric Lai <eric_lai@quanta.corp-partner.google.com> Reviewed-by: Sam McNally <sammc@google.com>
This commit is contained in:
parent
d7cdeee74d
commit
e790f929bd
|
@ -112,6 +112,13 @@ config CPU_SPECIFIC_OPTIONS
|
|||
select UDK_202005_BINDING
|
||||
select USE_FSP_NOTIFY_PHASE_POST_PCI_ENUM
|
||||
|
||||
config ALDERLAKE_CONFIGURE_DESCRIPTOR
|
||||
bool
|
||||
help
|
||||
Select this if the descriptor needs to be updated at runtime. This
|
||||
can only be done if the descriptor region is writable, and should only
|
||||
be used as a temporary workaround.
|
||||
|
||||
config ALDERLAKE_CAR_ENHANCED_NEM
|
||||
bool
|
||||
default y if !INTEL_CAR_NEM
|
||||
|
|
|
@ -16,6 +16,7 @@ bootblock-y += bootblock/report_platform.c
|
|||
bootblock-y += espi.c
|
||||
bootblock-y += gpio.c
|
||||
bootblock-y += p2sb.c
|
||||
bootblock-$(CONFIG_ALDERLAKE_CONFIGURE_DESCRIPTOR) += bootblock/update_descriptor.c
|
||||
|
||||
romstage-y += espi.c
|
||||
romstage-y += gpio.c
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <arch/mmio.h>
|
||||
#include <cf9_reset.h>
|
||||
#include <commonlib/region.h>
|
||||
#include <console/console.h>
|
||||
#include <cpu/intel/cpu_ids.h>
|
||||
#include <fmap.h>
|
||||
#include <intelblocks/pmclib.h>
|
||||
#include <soc/bootblock.h>
|
||||
#include <types.h>
|
||||
|
||||
/* Flash Master 1 : HOST/BIOS */
|
||||
#define FLMSTR1 0x80
|
||||
|
||||
/* Flash signature Offset */
|
||||
#define FLASH_SIGN_OFFSET 0x10
|
||||
#define FLMSTR_WR_SHIFT_V2 20
|
||||
#define FLASH_VAL_SIGN 0xFF0A55A
|
||||
|
||||
/* It checks whether host (Flash Master 1) has write access to the Descriptor Region or not */
|
||||
static bool is_descriptor_writeable(uint8_t *desc)
|
||||
{
|
||||
/* Check flash has valid signature */
|
||||
if (read32((void *)(desc + FLASH_SIGN_OFFSET)) != FLASH_VAL_SIGN) {
|
||||
printk(BIOS_ERR, "Flash Descriptor is not valid\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check host has write access to the Descriptor Region */
|
||||
if (!((read32((void *)(desc + FLMSTR1)) >> FLMSTR_WR_SHIFT_V2) & BIT(0))) {
|
||||
printk(BIOS_ERR, "Host doesn't have write access to Descriptor Region\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void configure_descriptor(struct descriptor_byte *bytes, size_t num)
|
||||
{
|
||||
uint8_t si_desc_buf[CONFIG_SI_DESC_REGION_SZ];
|
||||
struct region_device desc_rdev;
|
||||
bool update_required = false;
|
||||
|
||||
if (fmap_locate_area_as_rdev_rw(CONFIG_SI_DESC_REGION, &desc_rdev) < 0) {
|
||||
printk(BIOS_ERR, "Failed to locate %s in the FMAP\n", CONFIG_SI_DESC_REGION);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rdev_readat(&desc_rdev, si_desc_buf, 0, CONFIG_SI_DESC_REGION_SZ) !=
|
||||
CONFIG_SI_DESC_REGION_SZ) {
|
||||
printk(BIOS_ERR, "Failed to read Descriptor Region from SPI Flash\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_descriptor_writeable(si_desc_buf))
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
size_t offset = bytes[i].offset;
|
||||
uint8_t desired_value = bytes[i].desired_value;
|
||||
printk(BIOS_DEBUG, "Current value of Descriptor byte 0x%lx: 0x%x\n",
|
||||
offset, si_desc_buf[offset]);
|
||||
if (si_desc_buf[offset] != desired_value) {
|
||||
update_required = true;
|
||||
si_desc_buf[offset] = desired_value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!update_required) {
|
||||
printk(BIOS_DEBUG, "Update of Descriptor is not required!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rdev_eraseat(&desc_rdev, 0, CONFIG_SI_DESC_REGION_SZ) != CONFIG_SI_DESC_REGION_SZ) {
|
||||
printk(BIOS_ERR, "Failed to erase Descriptor Region area\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rdev_writeat(&desc_rdev, si_desc_buf, 0, CONFIG_SI_DESC_REGION_SZ)
|
||||
!= CONFIG_SI_DESC_REGION_SZ) {
|
||||
printk(BIOS_ERR, "Failed to update Descriptor Region\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "Update of Descriptor successful, trigger GLOBAL RESET\n");
|
||||
|
||||
pmc_global_reset_enable(true);
|
||||
do_full_reset();
|
||||
die("Failed to trigger GLOBAL RESET\n");
|
||||
}
|
|
@ -9,6 +9,11 @@
|
|||
#error "Please select exactly one PCH type"
|
||||
#endif
|
||||
|
||||
struct descriptor_byte {
|
||||
size_t offset;
|
||||
uint8_t desired_value;
|
||||
};
|
||||
|
||||
/* Bootblock pre console init programming */
|
||||
void bootblock_pch_early_init(void);
|
||||
|
||||
|
@ -17,4 +22,6 @@ void bootblock_pch_init(void);
|
|||
void pch_early_iorange_init(void);
|
||||
void report_platform_info(void);
|
||||
|
||||
void configure_descriptor(struct descriptor_byte *bytes, size_t num);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue