diff --git a/src/soc/intel/broadwell/Kconfig b/src/soc/intel/broadwell/Kconfig index 2e70f45eea..e14476abbd 100644 --- a/src/soc/intel/broadwell/Kconfig +++ b/src/soc/intel/broadwell/Kconfig @@ -16,6 +16,7 @@ config CPU_SPECIFIC_OPTIONS select BACKUP_DEFAULT_SMM_REGION select CACHE_MRC_BIN select CACHE_MRC_SETTINGS + select MRC_SETTINGS_PROTECT select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM select CACHE_ROM select CAR_MIGRATION diff --git a/src/soc/intel/broadwell/include/soc/spi.h b/src/soc/intel/broadwell/include/soc/spi.h index 8b95f70a5f..1449e29cda 100644 --- a/src/soc/intel/broadwell/include/soc/spi.h +++ b/src/soc/intel/broadwell/include/soc/spi.h @@ -35,6 +35,14 @@ #define SPIBAR_FDOC 0xb0 #define SPIBAR_FDOD 0xb4 +#define SPI_PRR_MAX 5 +#define SPI_PRR(x) (0x74 + ((x) * 4)) +#define SPI_PRR_SHIFT 12 +#define SPI_PRR_MASK 0x1fff +#define SPI_PRR_BASE_SHIFT 0 +#define SPI_PRR_LIMIT_SHIFT 16 +#define SPI_PRR_WPE (1 << 31) + #define SPIBAR_PREOP 0x94 #define SPIBAR_OPTYPE 0x96 #define SPIBAR_OPMENU_LOWER 0x98 @@ -97,4 +105,6 @@ #define SPIBAR_SSFC_DATA (1 << 14) #define SPIBAR_SSFC_GO (1 << 1) +int spi_flash_protect(u32 start, u32 size); + #endif diff --git a/src/soc/intel/broadwell/spi.c b/src/soc/intel/broadwell/spi.c index 6d2f103d8a..0fca05951b 100644 --- a/src/soc/intel/broadwell/spi.c +++ b/src/soc/intel/broadwell/spi.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #ifdef __SMM__ #define pci_read_config_byte(dev, reg, targ)\ @@ -637,3 +639,40 @@ int spi_xfer(struct spi_slave *slave, const void *dout, return 0; } + +/* Use first empty Protected Range Register to cover region of flash */ +int spi_flash_protect(u32 start, u32 size) +{ + u32 end = start + size - 1; + u32 reg; + int prr; + + /* Find first empty PRR */ + for (prr = 0; prr < SPI_PRR_MAX; prr++) { + reg = SPIBAR32(SPI_PRR(prr)); + if (reg == 0) + break; + } + if (prr >= SPI_PRR_MAX) { + printk(BIOS_ERR, "ERROR: No SPI PRR free!\n"); + return -1; + } + + /* Set protected range base and limit */ + reg = ((end >> SPI_PRR_SHIFT) & SPI_PRR_MASK); + reg <<= SPI_PRR_LIMIT_SHIFT; + reg |= ((start >> SPI_PRR_SHIFT) & SPI_PRR_MASK); + reg |= SPI_PRR_WPE; + + /* Set the PRR register and verify it is protected */ + SPIBAR32(SPI_PRR(prr)) = reg; + reg = SPIBAR32(SPI_PRR(prr)); + if (!(reg & SPI_PRR_WPE)) { + printk(BIOS_ERR, "ERROR: Unable to set SPI PRR %d\n", prr); + return -1; + } + + printk(BIOS_INFO, "%s: PRR %d is enabled for range 0x%08x-0x%08x\n", + __func__, prr, start, end); + return 0; +}