<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>