<p>Arthur Heymans has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/23146">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">[UNTESTED]sb/intel/common/spi.c: Add a SPI write protect function<br><br>Could be useful to WP for instance the MRC_CACHE region.<br><br>Change-Id: Id0a9a0de639c5d6761a77a56ceba6d89110a4ea1<br>Signed-off-by: Arthur Heymans <arthur@aheymans.xyz><br>---<br>M src/southbridge/intel/common/spi.c<br>1 file changed, 69 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/46/23146/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c</span><br><span>index 63f6e57..a0c58a6 100644</span><br><span>--- a/src/southbridge/intel/common/spi.c</span><br><span>+++ b/src/southbridge/intel/common/spi.c</span><br><span>@@ -83,6 +83,7 @@</span><br><span>        uint16_t preop;</span><br><span>      uint16_t optype;</span><br><span>     uint8_t opmenu[8];</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t pbr[3];</span><br><span> } __packed ich7_spi_regs;</span><br><span> </span><br><span> typedef struct ich9_spi_regs {</span><br><span>@@ -134,6 +135,7 @@</span><br><span>    uint8_t *status;</span><br><span>     uint16_t *control;</span><br><span>   uint32_t *bbar;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t *fpr;</span><br><span> } ich_spi_controller;</span><br><span> </span><br><span> static ich_spi_controller cntlr;</span><br><span>@@ -319,6 +321,7 @@</span><br><span>                cntlr.control = &ich7_spi->spic;</span><br><span>              cntlr.bbar = &ich7_spi->bbar;</span><br><span>                 cntlr.preop = &ich7_spi->preop;</span><br><span style="color: hsl(120, 100%, 40%);">+                cntlr.fpr = ich7_spi->pbr;</span><br><span>        } else {</span><br><span>             ich9_spi = (ich9_spi_regs *)(rcrb + 0x3800);</span><br><span>                 cntlr.ich9_spi = ich9_spi;</span><br><span>@@ -335,6 +338,7 @@</span><br><span>             cntlr.control = (uint16_t *)ich9_spi->ssfc;</span><br><span>               cntlr.bbar = &ich9_spi->bbar;</span><br><span>                 cntlr.preop = &ich9_spi->preop;</span><br><span style="color: hsl(120, 100%, 40%);">+                cntlr.fpr = ich9_spi->pr;</span><br><span> </span><br><span>             if (cntlr.hsfs & HSFS_FDV) {</span><br><span>                     writel_ (4, &ich9_spi->fdoc);</span><br><span>@@ -953,11 +957,76 @@</span><br><span>         return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define SPI_FPR_SHIFT               12</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICH7_SPI_FPR_MASK           0xfff</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICH9_SPI_FPR_MASK                0x1fff</span><br><span style="color: hsl(120, 100%, 40%);">+#define SPI_FPR_BASE_SHIFT      0</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICH7_SPI_FPR_LIMIT_SHIFT     12</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICH9_SPI_FPR_LIMIT_SHIFT    16</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICH9_SPI_FPR_RPE            (1 << 15) /* Read Protect */</span><br><span style="color: hsl(120, 100%, 40%);">+#define SPI_FPR_WPE         (1 << 31) /* Write Protect */</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICH7_SPI_FPR(base, limit)  \</span><br><span style="color: hsl(120, 100%, 40%);">+     (((((limit) >> SPI_FPR_SHIFT) & ICH7_SPI_FPR_MASK) << ICH7_SPI_FPR_LIMIT_SHIFT) |\</span><br><span style="color: hsl(120, 100%, 40%);">+     ((((base) >> SPI_FPR_SHIFT) & ICH7_SPI_FPR_MASK) << SPI_FPR_BASE_SHIFT))</span><br><span style="color: hsl(120, 100%, 40%);">+#define ICH9_SPI_FPR(base, limit)    \</span><br><span style="color: hsl(120, 100%, 40%);">+     (((((limit) >> SPI_FPR_SHIFT) & ICH9_SPI_FPR_MASK) << ICH9_SPI_FPR_LIMIT_SHIFT) |\</span><br><span style="color: hsl(120, 100%, 40%);">+     ((((base) >> SPI_FPR_SHIFT) & ICH9_SPI_FPR_MASK) << SPI_FPR_BASE_SHIFT))</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%);">+ * Protect range of SPI flash defined by [start, start+size-1] using Flash</span><br><span style="color: hsl(120, 100%, 40%);">+ * Protected Range (FPR) register if available.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int spi_flash_protect(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%);">+       u32 start = region_offset(region);</span><br><span style="color: hsl(120, 100%, 40%);">+    u32 end = start + region_sz(region) - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      u32 reg;</span><br><span style="color: hsl(120, 100%, 40%);">+      int fpr;</span><br><span style="color: hsl(120, 100%, 40%);">+      uintptr_t fpr_base;</span><br><span style="color: hsl(120, 100%, 40%);">+   const int spibar_fpr_max = (sizeof(cntlr.fpr) / sizeof(cntlr.fpr[0]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      fpr_base = (uintptr_t)cntlr.fpr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Find first empty FPR */</span><br><span style="color: hsl(120, 100%, 40%);">+    for (fpr = 0; fpr < spibar_fpr_max; fpr++) {</span><br><span style="color: hsl(120, 100%, 40%);">+               reg = read32((void *)fpr_base);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (reg == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+                fpr_base += sizeof(uint32_t);</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%);">+   if (fpr >= spibar_fpr_max) {</span><br><span style="color: hsl(120, 100%, 40%);">+               printk(BIOS_ERR, "ERROR: No SPI FPR free!\n");</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%);">+   /* Set protected range base and limit */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX))</span><br><span style="color: hsl(120, 100%, 40%);">+            reg = ICH7_SPI_FPR(start, end) | SPI_FPR_WPE;</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+          reg = ICH9_SPI_FPR(start, end) | SPI_FPR_WPE;           </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Set the FPR register and verify it is protected */</span><br><span style="color: hsl(120, 100%, 40%);">+ write32((void *)fpr_base, reg);</span><br><span style="color: hsl(120, 100%, 40%);">+       reg = read32((void *)fpr_base);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!(reg & SPI_FPR_WPE)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               printk(BIOS_ERR, "ERROR: Unable to set SPI FPR %d\n", fpr);</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%);">+   printk(BIOS_INFO, "%s: FPR %d is enabled for range 0x%08x-0x%08x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               __func__, fpr, start, end);</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%);">+</span><br><span> static const struct spi_ctrlr spi_ctrlr = {</span><br><span>      .xfer = spi_ctrlr_xfer,</span><br><span>      .xfer_vector = spi_xfer_two_vectors,</span><br><span>         .max_xfer_size = member_size(ich9_spi_regs, fdata),</span><br><span>  .flash_probe = spi_flash_programmer_probe,</span><br><span style="color: hsl(120, 100%, 40%);">+    .flash_protect = spi_flash_protect,</span><br><span> };</span><br><span> </span><br><span> const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/23146">change 23146</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/23146"/><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: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Id0a9a0de639c5d6761a77a56ceba6d89110a4ea1 </div>
<div style="display:none"> Gerrit-Change-Number: 23146 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Arthur Heymans <arthur@aheymans.xyz> </div>