<p>Marshall Dawson has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/22408">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">amd/stoneyridge: Add SPI controller driver<br><br>Add more definitions for the controller registers and fields.  Add<br>source that is adapted from hudson and updated for Stoney Ridge.<br><br>This was tested with follow-on patches that write S3 data to flash.<br><br>BUG=b:68992021<br><br>Change-Id: I61d64cfdb4fce11c068113680da7ba6a199d6893<br>Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com><br>---<br>M src/soc/amd/stoneyridge/Makefile.inc<br>M src/soc/amd/stoneyridge/include/soc/southbridge.h<br>A src/soc/amd/stoneyridge/spi.c<br>3 files changed, 192 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/08/22408/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/src/soc/amd/stoneyridge/Makefile.inc b/src/soc/amd/stoneyridge/Makefile.inc<br>index 921691f..a4cdcf5 100644<br>--- a/src/soc/amd/stoneyridge/Makefile.inc<br>+++ b/src/soc/amd/stoneyridge/Makefile.inc<br>@@ -90,12 +90,14 @@<br> ramstage-$(CONFIG_STONEYRIDGE_UART) += uart.c<br> ramstage-y += usb.c<br> ramstage-y += tsc_freq.c<br>+ramstage-$(CONFIG_SPI_FLASH) += spi.c<br> <br> smm-y += smihandler.c<br> smm-y += smi_util.c<br> smm-y += sb_util.c<br> smm-y += tsc_freq.c<br> smm-$(CONFIG_DEBUG_SMI) += uart.c<br>+smm-$(CONFIG_SPI_FLASH) += spi.c<br> <br> CPPFLAGS_common += -I$(src)/soc/amd/stoneyridge<br> CPPFLAGS_common += -I$(src)/soc/amd/stoneyridge/include<br>diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h<br>index f088be5..cc85fdb 100644<br>--- a/src/soc/amd/stoneyridge/include/soc/southbridge.h<br>+++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h<br>@@ -181,7 +181,11 @@<br> #define LPC_HOST_CONTROL               0xbb<br> #define   SPI_FROM_HOST_PREFETCH_EN      BIT(0)<br> <br>+/* SPI Controller */<br>+#define SPI_FIFO_DEPTH                       8<br>+<br> #define SPI_CNTRL0                       0x00<br>+#define   SPI_BUSY                       BIT(31)<br> #define   SPI_READ_MODE_MASK          (BIT(30) | BIT(29) | BIT(18))<br> /* Nominal is 16.7MHz on older devices, 33MHz on newer */<br> #define   SPI_READ_MODE_NOM         0x00000000<br>@@ -191,14 +195,34 @@<br> #define   SPI_READ_MODE_QUAD144             (BIT(30) |           BIT(18))<br> #define   SPI_READ_MODE_NORMAL66        (BIT(30) | BIT(29)          )<br> #define   SPI_READ_MODE_FAST            (BIT(30) | BIT(29) | BIT(18))<br>+#define   SPI_FIFO_PTR_CLR              BIT(20)<br> #define   SPI_ARB_ENABLE              BIT(19)<br>-<br>+#define   EXEC_OPCODE                      BIT(16)<br>+#define SPI_REG_CNTRL01                       0x01<br>+#define SPI_REG_CNTRL02                  0x02<br>+#define   SPI_FIFO_PTR_CLR02             (SPI_FIFO_PTR_CLR >> 16)<br> #define SPI_CNTRL1                     0x0c<br>+#define  SPI_FIFO_PTR_MASK               (BIT(8) | BIT(9) | BIT(10))<br>+#define SPI_CNTRL11                       0x0d<br>+#define  SPI_FIFO_PTR_MASK11             (SPI_FIFO_PTR_MASK >> 8)<br>+<br>+#define SPI100_SPEED_CONFIG         0x22<br> /* Use SPI_SPEED_16M-SPI_SPEED_66M below for the southbridge */<br> #define   SPI_CNTRL1_SPEED_MASK                (BIT(15) | BIT(14) | BIT(13) | BIT(12))<br> #define   SPI_NORM_SPEED_SH           12<br> #define   SPI_FAST_SPEED_SH                8<br> <br>+#define SPI_EXT_INDEX                    0x1e<br>+#define SPI_EXT_DATA                     0x1f<br>+#define   SPI_DDR_CMD                    0x0<br>+#define   SPI_QDR_CMD                     0x1<br>+#define   SPI_DPR_CMD                     0x2<br>+#define   SPI_QPR_CMD                     0x3<br>+#define   SPI_MODE_BYTE                   0x4<br>+#define   SPI_TX_BYTE_COUNT               0x5<br>+#define   SPI_RX_BYTE_COUNT               0x6<br>+#define   SPI_SPI_DATA_FIFO_PTR           0x7<br>+<br> #define SPI100_ENABLE                  0x20<br> #define   SPI_USE_SPI100         BIT(0)<br> <br>diff --git a/src/soc/amd/stoneyridge/spi.c b/src/soc/amd/stoneyridge/spi.c<br>new file mode 100644<br>index 0000000..49fa00d<br>--- /dev/null<br>+++ b/src/soc/amd/stoneyridge/spi.c<br>@@ -0,0 +1,165 @@<br>+/*<br>+ * This file is part of the coreboot project.<br>+ *<br>+ * Copyright (C) 2012 Advanced Micro Devices, Inc.<br>+ *<br>+ * This program is free software; you can redistribute it and/or modify<br>+ * it under the terms of the GNU General Public License as published by<br>+ * the Free Software Foundation; version 2 of the License.<br>+ *<br>+ * This program is distributed in the hope that it will be useful,<br>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>+ * GNU General Public License for more details.<br>+ */<br>+<br>+#include <stdint.h><br>+#include <stdlib.h><br>+#include <string.h><br>+#include <arch/io.h><br>+#include <console/console.h><br>+#include <spi_flash.h><br>+#include <spi-generic.h><br>+#include <device/device.h><br>+#include <device/pci.h><br>+#include <device/pci_ops.h><br>+#include <soc/southbridge.h><br>+#include <soc/pci_devs.h><br>+#include <soc/imc.h><br>+<br>+static uintptr_t spibar;<br>+<br>+static inline uint8_t spi_read8(uint8_t reg)<br>+{<br>+     return read8((void *)(spibar + reg));<br>+}<br>+<br>+static inline uint32_t spi_read32(uint8_t reg)<br>+{<br>+    return read32((void *)(spibar + reg));<br>+}<br>+<br>+static inline void spi_write8(uint8_t reg, uint8_t val)<br>+{<br>+  write8((void *)(spibar + reg), val);<br>+}<br>+<br>+static inline void spi_write32(uint8_t reg, uint32_t val)<br>+{<br>+  write32((void *)(spibar + reg), val);<br>+}<br>+<br>+static void reset_internal_fifo_pointer(void)<br>+{<br>+     uint8_t reg;<br>+ do {<br>+         reg = spi_read8(SPI_REG_CNTRL02);<br>+            reg |= SPI_FIFO_PTR_CLR02;<br>+           spi_write8(SPI_REG_CNTRL02, reg);<br>+    /* wait for ptr=0 without reading the tx/rx port in CPI_CNTRL1[7:0] */<br>+       } while (spi_read8(SPI_CNTRL11) & (SPI_FIFO_PTR_MASK11));<br>+}<br>+<br>+static void execute_command(void)<br>+{<br>+ uint32_t reg;<br>+<br>+     reg = spi_read32(SPI_CNTRL0);<br>+        reg |= EXEC_OPCODE;<br>+  spi_write32(SPI_CNTRL0, reg);<br>+<br>+     while ((spi_read32(SPI_CNTRL0) & (EXEC_OPCODE | SPI_BUSY)))<br>+              ;<br>+}<br>+<br>+void spi_init(void)<br>+{<br>+   spibar = pci_read_config32(SOC_LPC_DEV, SPIROM_BASE_ADDRESS_REGISTER);<br>+       spibar = ALIGN_DOWN(spibar, 64);<br>+}<br>+<br>+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,<br>+         size_t bytesout, void *din, size_t bytesin)<br>+{<br>+      /* First byte is cmd which can not being sent through FIFO. */<br>+       u8 cmd = *(u8 *)dout++;<br>+      u8 readoffby1;<br>+       size_t count;<br>+<br>+     bytesout--;<br>+<br>+       /*<br>+    * Check if this is a write command attempting to transfer more bytes<br>+         * than the controller can handle.  Iterations for writes are not<br>+     * supported here because each SPI write command needs to be preceded<br>+         * and followed by other SPI commands, and this sequence is controlled<br>+        * by the SPI chip driver.<br>+    */<br>+  if (bytesout > SPI_FIFO_DEPTH) {<br>+          printk(BIOS_DEBUG, "FCH SPI: Too much to write. Does your SPI"<br>+                             " chip driver use spi_crop_chunk()?\n");<br>+           return -1;<br>+   }<br>+<br>+ readoffby1 = bytesout ? 0 : 1;<br>+<br>+    spi_write8(SPI_EXT_INDEX, SPI_TX_BYTE_COUNT);<br>+        spi_write8(SPI_EXT_DATA, bytesout); /* SpiExtRegIndx [5] - TxByteCnt */<br>+      spi_write8(SPI_EXT_INDEX, SPI_RX_BYTE_COUNT);<br>+        spi_write8(SPI_EXT_DATA, bytesin);  /* SpiExtRegIndx [6] - RxByteCnt */<br>+      spi_write8(SPI_CNTRL0, cmd);<br>+<br>+      reset_internal_fifo_pointer();<br>+       for (count = 0; count < bytesout; count++, dout++) {<br>+              spi_write8(SPI_CNTRL1, *(uint8_t *)dout);<br>+    }<br>+<br>+ reset_internal_fifo_pointer();<br>+       execute_command();<br>+<br>+        reset_internal_fifo_pointer();<br>+       /* Skip the bytes we sent. */<br>+        for (count = 0; count < bytesout; count++) {<br>+              cmd = spi_read8(SPI_CNTRL1);<br>+ }<br>+<br>+ for (count = 0; count < bytesin; count++, din++)<br>+          *(uint8_t *)din = spi_read8(SPI_CNTRL1);<br>+<br>+  return 0;<br>+}<br>+<br>+int chipset_volatile_group_begin(const struct spi_flash *flash)<br>+{<br>+       if (!IS_ENABLED(CONFIG_STONEYRIDGE_IMC_FWM))<br>+         return 0;<br>+<br>+ imc_sleep();<br>+ return 0;<br>+}<br>+<br>+int chipset_volatile_group_end(const struct spi_flash *flash)<br>+{<br>+ if (!IS_ENABLED(CONFIG_STONEYRIDGE_IMC_FWM))<br>+         return 0;<br>+<br>+ imc_wakeup();<br>+        return 0;<br>+}<br>+<br>+static const struct spi_ctrlr spi_ctrlr = {<br>+       .xfer = spi_ctrlr_xfer,<br>+      .xfer_vector = spi_xfer_two_vectors,<br>+ .max_xfer_size = SPI_FIFO_DEPTH,<br>+     .deduct_cmd_len = true,<br>+};<br>+<br>+const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {<br>+       {<br>+            .ctrlr = &spi_ctrlr,<br>+             .bus_start = 0,<br>+              .bus_end = 0,<br>+        },<br>+};<br>+<br>+const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);<br></pre><p>To view, visit <a href="https://review.coreboot.org/22408">change 22408</a>. To unsubscribe, 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/22408"/><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: I61d64cfdb4fce11c068113680da7ba6a199d6893 </div>
<div style="display:none"> Gerrit-Change-Number: 22408 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Marshall Dawson <marshalldawson3rd@gmail.com> </div>