summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/mrc_cache/mrc_cache.c4
-rw-r--r--src/drivers/spi/spi_flash.c5
-rw-r--r--src/include/spi-generic.h9
-rw-r--r--src/include/spi_flash.h3
-rw-r--r--src/soc/intel/broadwell/include/soc/spi.h1
-rw-r--r--src/soc/intel/broadwell/spi.c24
-rw-r--r--src/soc/intel/common/block/fast_spi/fast_spi_flash.c23
-rw-r--r--src/southbridge/intel/common/spi.c27
8 files changed, 82 insertions, 14 deletions
diff --git a/src/drivers/mrc_cache/mrc_cache.c b/src/drivers/mrc_cache/mrc_cache.c
index 4dd0dbc434..84bbdb05b3 100644
--- a/src/drivers/mrc_cache/mrc_cache.c
+++ b/src/drivers/mrc_cache/mrc_cache.c
@@ -456,13 +456,15 @@ static int nvm_is_write_protected(void)
/* Apply protection to a range of flash */
static int nvm_protect(const struct region *r)
{
+ const struct spi_flash *flash = boot_device_spi_flash();
+
if (!IS_ENABLED(CONFIG_MRC_SETTINGS_PROTECT))
return 0;
if (!IS_ENABLED(CONFIG_BOOT_DEVICE_SPI_FLASH))
return 0;
- return spi_flash_ctrlr_protect_region(boot_device_spi_flash(), r);
+ return spi_flash_ctrlr_protect_region(flash, r, WRITE_PROTECT);
}
/* Protect mrc region with a Protected Range Register */
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c
index f06de2a11a..204f607889 100644
--- a/src/drivers/spi/spi_flash.c
+++ b/src/drivers/spi/spi_flash.c
@@ -572,7 +572,8 @@ void lb_spi_flash(struct lb_header *header)
int spi_flash_ctrlr_protect_region(const struct spi_flash *flash,
- const struct region *region)
+ const struct region *region,
+ const enum ctrlr_prot_type type)
{
const struct spi_ctrlr *ctrlr;
struct region flash_region = { 0 };
@@ -591,7 +592,7 @@ int spi_flash_ctrlr_protect_region(const struct spi_flash *flash,
return -1;
if (ctrlr->flash_protect)
- return ctrlr->flash_protect(flash, region);
+ return ctrlr->flash_protect(flash, region, type);
return -1;
}
diff --git a/src/include/spi-generic.h b/src/include/spi-generic.h
index e3e7f829f7..c24aadd926 100644
--- a/src/include/spi-generic.h
+++ b/src/include/spi-generic.h
@@ -97,6 +97,12 @@ struct spi_cfg {
struct spi_flash;
+enum ctrlr_prot_type {
+ READ_PROTECT = 1,
+ WRITE_PROTECT = 2,
+ READ_WRITE_PROTECT = 3,
+};
+
enum {
/* Deduct the command length from the spi_crop_chunk() calculation for
sizing a transaction. */
@@ -144,7 +150,8 @@ struct spi_ctrlr {
int (*flash_probe)(const struct spi_slave *slave,
struct spi_flash *flash);
int (*flash_protect)(const struct spi_flash *flash,
- const struct region *region);
+ const struct region *region,
+ const enum ctrlr_prot_type type);
};
/*-----------------------------------------------------------------------
diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h
index 09908eb9f8..936b0abe85 100644
--- a/src/include/spi_flash.h
+++ b/src/include/spi_flash.h
@@ -207,7 +207,8 @@ const struct spi_flash *boot_device_spi_flash(void);
/* Protect a region of spi flash using its controller, if available. Returns
* < 0 on error, else 0 on success. */
int spi_flash_ctrlr_protect_region(const struct spi_flash *flash,
- const struct region *region);
+ const struct region *region,
+ const enum ctrlr_prot_type type);
/*
* This function is provided to support spi flash command-response transactions.
diff --git a/src/soc/intel/broadwell/include/soc/spi.h b/src/soc/intel/broadwell/include/soc/spi.h
index 588af17609..5ad62fd19d 100644
--- a/src/soc/intel/broadwell/include/soc/spi.h
+++ b/src/soc/intel/broadwell/include/soc/spi.h
@@ -38,6 +38,7 @@
#define SPI_PRR_BASE_SHIFT 0
#define SPI_PRR_LIMIT_SHIFT 16
#define SPI_PRR_WPE (1 << 31)
+#define SPI_PRR_RPE (1 << 15)
#define SPIBAR_PREOP 0x94
#define SPIBAR_OPTYPE 0x96
diff --git a/src/soc/intel/broadwell/spi.c b/src/soc/intel/broadwell/spi.c
index 2317c9a137..de3d061aea 100644
--- a/src/soc/intel/broadwell/spi.c
+++ b/src/soc/intel/broadwell/spi.c
@@ -615,11 +615,13 @@ static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
/* Use first empty Protected Range Register to cover region of flash */
static int spi_flash_protect(const struct spi_flash *flash,
- const struct region *region)
+ const struct region *region,
+ const enum ctrlr_prot_type type)
{
u32 start = region_offset(region);
u32 end = start + region_sz(region) - 1;
u32 reg;
+ u32 protect_mask = 0;
int prr;
/* Find first empty PRR */
@@ -637,12 +639,28 @@ static int spi_flash_protect(const struct spi_flash *flash,
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;
+
+ switch (type) {
+ case WRITE_PROTECT:
+ protect_mask |= SPI_PRR_WPE;
+ break;
+ case READ_PROTECT:
+ protect_mask |= SPI_PRR_RPE;
+ break;
+ case READ_WRITE_PROTECT:
+ protect_mask |= (SPI_PRR_RPE | SPI_PRR_WPE);
+ break;
+ default:
+ printk(BIOS_ERR, "ERROR: Seeking invalid protection!\n");
+ return -1;
+ }
+
+ reg |= protect_mask;
/* Set the PRR register and verify it is protected */
SPIBAR32(SPI_PRR(prr)) = reg;
reg = SPIBAR32(SPI_PRR(prr));
- if (!(reg & SPI_PRR_WPE)) {
+ if (!(reg & protect_mask)) {
printk(BIOS_ERR, "ERROR: Unable to set SPI PRR %d\n", prr);
return -1;
}
diff --git a/src/soc/intel/common/block/fast_spi/fast_spi_flash.c b/src/soc/intel/common/block/fast_spi/fast_spi_flash.c
index 4579b19151..65708a6b19 100644
--- a/src/soc/intel/common/block/fast_spi/fast_spi_flash.c
+++ b/src/soc/intel/common/block/fast_spi/fast_spi_flash.c
@@ -367,11 +367,13 @@ static int fast_spi_flash_ctrlr_setup(const struct spi_slave *dev)
* Protected Range (FPR) register if available.
*/
static int fast_spi_flash_protect(const struct spi_flash *flash,
- const struct region *region)
+ const struct region *region,
+ const enum ctrlr_prot_type type)
{
u32 start = region_offset(region);
u32 end = start + region_sz(region) - 1;
u32 reg;
+ u32 protect_mask = 0;
int fpr;
uintptr_t fpr_base;
BOILERPLATE_CREATE_CTX(ctx);
@@ -391,13 +393,28 @@ static int fast_spi_flash_protect(const struct spi_flash *flash,
return -1;
}
+ switch (type) {
+ case WRITE_PROTECT:
+ protect_mask |= SPI_FPR_WPE;
+ break;
+ case READ_PROTECT:
+ protect_mask |= SPI_FPR_RPE;
+ break;
+ case READ_WRITE_PROTECT:
+ protect_mask |= (SPI_FPR_RPE | SPI_FPR_WPE);
+ break;
+ default:
+ printk(BIOS_ERR, "ERROR: Seeking invalid protection!\n");
+ return -1;
+ }
+
/* Set protected range base and limit */
- reg = SPI_FPR(start, end) | SPI_FPR_WPE;
+ reg = SPI_FPR(start, end) | protect_mask;
/* Set the FPR register and verify it is protected */
write32((void *)fpr_base, reg);
reg = read32((void *)fpr_base);
- if (!(reg & SPI_FPR_WPE)) {
+ if (!(reg & protect_mask)) {
printk(BIOS_ERR, "ERROR: Unable to set SPI FPR %d\n", fpr);
return -1;
}
diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c
index 9bc34140a9..4c5939963f 100644
--- a/src/southbridge/intel/common/spi.c
+++ b/src/southbridge/intel/common/spi.c
@@ -1010,12 +1010,14 @@ static u32 spi_fpr(u32 base, u32 limit)
* Returns 0 on success, -1 on failure of programming fpr registers.
*/
static int spi_flash_protect(const struct spi_flash *flash,
- const struct region *region)
+ const struct region *region,
+ const enum ctrlr_prot_type type)
{
ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
u32 start = region_offset(region);
u32 end = start + region_sz(region) - 1;
u32 reg;
+ u32 protect_mask = 0;
int fpr;
uint32_t *fpr_base;
@@ -1033,13 +1035,32 @@ static int spi_flash_protect(const struct spi_flash *flash,
return -1;
}
+ switch (type) {
+ case WRITE_PROTECT:
+ protect_mask |= SPI_FPR_WPE;
+ break;
+ case READ_PROTECT:
+ if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX))
+ return -1;
+ protect_mask |= ICH9_SPI_FPR_RPE;
+ break;
+ case READ_WRITE_PROTECT:
+ if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX))
+ return -1;
+ protect_mask |= (ICH9_SPI_FPR_RPE | SPI_FPR_WPE);
+ break;
+ default:
+ printk(BIOS_ERR, "ERROR: Seeking invalid protection!\n");
+ return -1;
+ }
+
/* Set protected range base and limit */
- reg = spi_fpr(start, end) | SPI_FPR_WPE;
+ reg = spi_fpr(start, end) | protect_mask;
/* Set the FPR register and verify it is protected */
write32(&fpr_base[fpr], reg);
reg = read32(&fpr_base[fpr]);
- if (!(reg & SPI_FPR_WPE)) {
+ if (!(reg & protect_mask)) {
printk(BIOS_ERR, "ERROR: Unable to set SPI FPR %d\n", fpr);
return -1;
}