<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, &reg1_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, &reg1_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, &reg2.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>