<p>Philipp Deppenwiese <strong>merged</strong> this change.</p><p><a href="https://review.coreboot.org/25082">View Change</a></p><div style="white-space:pre-wrap">Approvals:
build bot (Jenkins): Verified
Julius Werner: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">drivers/spi: Read Winbond's flash protection bits<br><br>Extend the generic flash interface to probe for write protected regions.<br>Add Winbond custom code to return flash protection.<br><br>Tested on Cavium EVB CN81xx using W25Q128.<br><br>Change-Id: I933a8abdc28174ec32acf323c102d606b58c1ea5<br>Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com><br>Reviewed-on: https://review.coreboot.org/25082<br>Reviewed-by: Julius Werner <jwerner@chromium.org><br>Tested-by: build bot (Jenkins) <no-reply@coreboot.org><br>---<br>M src/drivers/spi/spi_flash.c<br>M src/drivers/spi/winbond.c<br>M src/include/spi_flash.h<br>3 files changed, 202 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c</span><br><span>index f271479..c484088 100644</span><br><span>--- a/src/drivers/spi/spi_flash.c</span><br><span>+++ b/src/drivers/spi/spi_flash.c</span><br><span>@@ -432,6 +432,28 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int spi_flash_is_write_protected(const struct spi_flash *flash,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct region *region)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct region flash_region = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!flash || !region)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ flash_region.size = flash->size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!region_is_subregion(&flash_region, region))</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!flash->ops->get_write_protection) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_WARNING, "SPI: Write-protection gathering not "</span><br><span style="color: hsl(120, 100%, 40%);">+ "implemented for this vendor.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return flash->ops->get_write_protection(flash, region);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static uint32_t volatile_group_count CAR_GLOBAL;</span><br><span> </span><br><span> int spi_flash_volatile_group_begin(const struct spi_flash *flash)</span><br><span>diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c</span><br><span>index a25c9a6..a0e3884 100644</span><br><span>--- a/src/drivers/spi/winbond.c</span><br><span>+++ b/src/drivers/spi/winbond.c</span><br><span>@@ -9,6 +9,7 @@</span><br><span> #include <spi_flash.h></span><br><span> #include <spi-generic.h></span><br><span> #include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span> </span><br><span> #include "spi_flash_internal.h"</span><br><span> </span><br><span>@@ -17,6 +18,8 @@</span><br><span> #define CMD_W25_WRDI 0x04 /* Write Disable */</span><br><span> #define CMD_W25_RDSR 0x05 /* Read Status Register */</span><br><span> #define CMD_W25_WRSR 0x01 /* Write Status Register */</span><br><span style="color: hsl(120, 100%, 40%);">+#define CMD_W25_RDSR2 0x35 /* Read Status2 Register */</span><br><span style="color: hsl(120, 100%, 40%);">+#define CMD_W25_WRSR2 0x31 /* Write Status2 Register */</span><br><span> #define CMD_W25_READ 0x03 /* Read Data Bytes */</span><br><span> #define CMD_W25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */</span><br><span> #define CMD_W25_PP 0x02 /* Page Program */</span><br><span>@@ -32,9 +35,46 @@</span><br><span> uint8_t pages_per_sector_shift : 4;</span><br><span> uint8_t sectors_per_block_shift : 4;</span><br><span> uint8_t nr_blocks_shift;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t bp_bits : 3;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t protection_granularity_shift : 5;</span><br><span> char name[10];</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+union status_reg1_bp3 {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t u;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t busy : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t wel : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t bp : 3;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t tb : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t sec : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t srp0 : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+union status_reg1_bp4 {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t u;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t busy : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t wel : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t bp : 4;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t tb : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t srp0 : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+union status_reg2 {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t u;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t srp1 : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t qe : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t res : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t lb : 3;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t cmp : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t sus : 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {</span><br><span> {</span><br><span> .id = 0x3015,</span><br><span>@@ -75,6 +115,8 @@</span><br><span> .sectors_per_block_shift = 4,</span><br><span> .nr_blocks_shift = 5,</span><br><span> .name = "W25Q16",</span><br><span style="color: hsl(120, 100%, 40%);">+ .protection_granularity_shift = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bp_bits = 3,</span><br><span> },</span><br><span> {</span><br><span> .id = 0x4016,</span><br><span>@@ -83,6 +125,8 @@</span><br><span> .sectors_per_block_shift = 4,</span><br><span> .nr_blocks_shift = 6,</span><br><span> .name = "W25Q32",</span><br><span style="color: hsl(120, 100%, 40%);">+ .protection_granularity_shift = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bp_bits = 3,</span><br><span> },</span><br><span> {</span><br><span> .id = 0x6016,</span><br><span>@@ -91,6 +135,8 @@</span><br><span> .sectors_per_block_shift = 4,</span><br><span> .nr_blocks_shift = 6,</span><br><span> .name = "W25Q32DW",</span><br><span style="color: hsl(120, 100%, 40%);">+ .protection_granularity_shift = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bp_bits = 3,</span><br><span> },</span><br><span> {</span><br><span> .id = 0x4017,</span><br><span>@@ -99,6 +145,8 @@</span><br><span> .sectors_per_block_shift = 4,</span><br><span> .nr_blocks_shift = 7,</span><br><span> .name = "W25Q64",</span><br><span style="color: hsl(120, 100%, 40%);">+ .protection_granularity_shift = 17,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bp_bits = 3,</span><br><span> },</span><br><span> {</span><br><span> .id = 0x6017,</span><br><span>@@ -107,6 +155,8 @@</span><br><span> .sectors_per_block_shift = 4,</span><br><span> .nr_blocks_shift = 7,</span><br><span> .name = "W25Q64DW",</span><br><span style="color: hsl(120, 100%, 40%);">+ .protection_granularity_shift = 17,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bp_bits = 3,</span><br><span> },</span><br><span> {</span><br><span> .id = 0x4018,</span><br><span>@@ -115,6 +165,8 @@</span><br><span> .sectors_per_block_shift = 4,</span><br><span> .nr_blocks_shift = 8,</span><br><span> .name = "W25Q128",</span><br><span style="color: hsl(120, 100%, 40%);">+ .protection_granularity_shift = 18,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bp_bits = 3,</span><br><span> },</span><br><span> {</span><br><span> .id = 0x6018,</span><br><span>@@ -123,6 +175,8 @@</span><br><span> .sectors_per_block_shift = 4,</span><br><span> .nr_blocks_shift = 8,</span><br><span> .name = "W25Q128FW",</span><br><span style="color: hsl(120, 100%, 40%);">+ .protection_granularity_shift = 18,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bp_bits = 3,</span><br><span> },</span><br><span> {</span><br><span> .id = 0x4019,</span><br><span>@@ -131,6 +185,8 @@</span><br><span> .sectors_per_block_shift = 4,</span><br><span> .nr_blocks_shift = 9,</span><br><span> .name = "W25Q256",</span><br><span style="color: hsl(120, 100%, 40%);">+ .protection_granularity_shift = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+ .bp_bits = 4,</span><br><span> },</span><br><span> };</span><br><span> </span><br><span>@@ -191,6 +247,102 @@</span><br><span> return ret;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Convert BPx, TB and CMP to a region.</span><br><span style="color: hsl(120, 100%, 40%);">+ * SEC (if available) must be zero.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void winbond_bpbits_to_region(const size_t granularity,</span><br><span style="color: hsl(120, 100%, 40%);">+ const u8 bp,</span><br><span style="color: hsl(120, 100%, 40%);">+ bool tb,</span><br><span style="color: hsl(120, 100%, 40%);">+ const bool cmp,</span><br><span style="color: hsl(120, 100%, 40%);">+ const size_t flash_size,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct region *out)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t protected_size =</span><br><span style="color: hsl(120, 100%, 40%);">+ min(bp ? granularity << (bp - 1) : 0, flash_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cmp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ protected_size = flash_size - protected_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ tb = !tb;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ out->offset = tb ? flash_size - protected_size : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ out->size = protected_size;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Available on all devices.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Read block protect bits from Status/Status2 Reg.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Converts block protection bits to a region.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns:</span><br><span style="color: hsl(120, 100%, 40%);">+ * -1 on error</span><br><span style="color: hsl(120, 100%, 40%);">+ * 1 if region is covered by write protection</span><br><span style="color: hsl(120, 100%, 40%);">+ * 0 if a part of region isn't covered by write protection</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int winbond_get_write_protection(const struct spi_flash *flash,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct region *region)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct winbond_spi_flash_params *params;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct region wp_region;</span><br><span style="color: hsl(120, 100%, 40%);">+ union status_reg2 reg2;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 bp, tb;</span><br><span style="color: hsl(120, 100%, 40%);">+ int ret;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ params = (const struct winbond_spi_flash_params *)flash->driver_private;</span><br><span style="color: hsl(120, 100%, 40%);">+ const size_t granularity = (1 << params->protection_granularity_shift);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (params->bp_bits == 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+ union status_reg1_bp3 reg1_bp3;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = spi_flash_cmd(&flash->spi, flash->status_cmd, ®1_bp3.u,</span><br><span style="color: hsl(120, 100%, 40%);">+ sizeof(reg1_bp3.u));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ret)</span><br><span style="color: hsl(120, 100%, 40%);">+ return ret;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (reg1_bp3.sec) {</span><br><span style="color: hsl(120, 100%, 40%);">+ // FIXME: not supported</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bp = reg1_bp3.bp;</span><br><span style="color: hsl(120, 100%, 40%);">+ tb = reg1_bp3.tb;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (params->bp_bits == 4) {</span><br><span style="color: hsl(120, 100%, 40%);">+ union status_reg1_bp4 reg1_bp4;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = spi_flash_cmd(&flash->spi, flash->status_cmd, ®1_bp4.u,</span><br><span style="color: hsl(120, 100%, 40%);">+ sizeof(reg1_bp4.u));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ret)</span><br><span style="color: hsl(120, 100%, 40%);">+ return ret;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bp = reg1_bp4.bp;</span><br><span style="color: hsl(120, 100%, 40%);">+ tb = reg1_bp4.tb;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ // FIXME: not supported</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = spi_flash_cmd(&flash->spi, CMD_W25_RDSR2, ®2.u,</span><br><span style="color: hsl(120, 100%, 40%);">+ sizeof(reg2.u));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ret)</span><br><span style="color: hsl(120, 100%, 40%);">+ return ret;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ winbond_bpbits_to_region(granularity, bp, tb, reg2.cmp, flash->size,</span><br><span style="color: hsl(120, 100%, 40%);">+ &wp_region);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!reg2.srp1 || !wp_region.size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "WINBOND: flash isn't protected\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "WINBOND: flash protected range 0x%08zx-0x%08zx\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ wp_region.offset, wp_region.size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return region_is_subregion(&wp_region, region);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct spi_flash_ops spi_flash_ops = {</span><br><span> .write = winbond_write,</span><br><span> .erase = spi_flash_cmd_erase,</span><br><span>@@ -200,6 +352,7 @@</span><br><span> #else</span><br><span> .read = spi_flash_cmd_read_fast,</span><br><span> #endif</span><br><span style="color: hsl(120, 100%, 40%);">+ .get_write_protection = winbond_get_write_protection,</span><br><span> };</span><br><span> </span><br><span> int spi_flash_probe_winbond(const struct spi_slave *spi, u8 *idcode,</span><br><span>@@ -234,6 +387,7 @@</span><br><span> flash->status_cmd = CMD_W25_RDSR;</span><br><span> </span><br><span> flash->ops = &spi_flash_ops;</span><br><span style="color: hsl(120, 100%, 40%);">+ flash->driver_private = params;</span><br><span> </span><br><span> return 0;</span><br><span> }</span><br><span>diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h</span><br><span>index f7f3b3d..9f8d2d0 100644</span><br><span>--- a/src/include/spi_flash.h</span><br><span>+++ b/src/include/spi_flash.h</span><br><span>@@ -40,6 +40,16 @@</span><br><span> const void *buf);</span><br><span> int (*erase)(const struct spi_flash *flash, u32 offset, size_t len);</span><br><span> int (*status)(const struct spi_flash *flash, u8 *reg);</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns 1 if the whole region is software write protected.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Hardware write protection mechanism aren't accounted.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If the write protection could be changed, due to unlocked status</span><br><span style="color: hsl(120, 100%, 40%);">+ * register for example, 0 should be returned.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns -1 on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ int (*get_write_protection)(const struct spi_flash *flash,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct region *region);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> };</span><br><span> </span><br><span> struct spi_flash {</span><br><span>@@ -51,6 +61,7 @@</span><br><span> u8 erase_cmd;</span><br><span> u8 status_cmd;</span><br><span> const struct spi_flash_ops *ops;</span><br><span style="color: hsl(120, 100%, 40%);">+ const void *driver_private;</span><br><span> };</span><br><span> </span><br><span> void lb_spi_flash(struct lb_header *header);</span><br><span>@@ -93,6 +104,21 @@</span><br><span> const void *buf);</span><br><span> int spi_flash_erase(const struct spi_flash *flash, u32 offset, size_t len);</span><br><span> int spi_flash_status(const struct spi_flash *flash, u8 *reg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return the vendor dependent SPI flash write protection state.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param flash : A SPI flash device</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param region: A subregion of the device's region</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns:</span><br><span style="color: hsl(120, 100%, 40%);">+ * -1 on error</span><br><span style="color: hsl(120, 100%, 40%);">+ * 0 if the device doesn't support block protection</span><br><span style="color: hsl(120, 100%, 40%);">+ * 0 if the device doesn't enable block protection</span><br><span style="color: hsl(120, 100%, 40%);">+ * 0 if given range isn't covered by block protection</span><br><span style="color: hsl(120, 100%, 40%);">+ * 1 if given range is covered by block protection</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int spi_flash_is_write_protected(const struct spi_flash *flash,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct region *region);</span><br><span> /*</span><br><span> * Some SPI controllers require exclusive access to SPI flash when volatile</span><br><span> * operations like erase or write are being performed. In such cases,</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/25082">change 25082</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/25082"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I933a8abdc28174ec32acf323c102d606b58c1ea5 </div>
<div style="display:none"> Gerrit-Change-Number: 25082 </div>
<div style="display:none"> Gerrit-PatchSet: 21 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com> </div>
<div style="display:none"> Gerrit-Reviewer: David Hendricks <david.hendricks@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Julius Werner <jwerner@chromium.org> </div>
<div style="display:none"> Gerrit-Reviewer: Patrick Rudolph <patrick.rudolph@9elements.com> </div>
<div style="display:none"> Gerrit-Reviewer: Paul Menzel <paulepanter@users.sourceforge.net> </div>
<div style="display:none"> Gerrit-Reviewer: Philipp Deppenwiese <zaolin.daisuki@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org> </div>
<div style="display:none"> Gerrit-CC: Furquan Shaikh <furquan@google.com> </div>