Furquan Shaikh has uploaded this change for review.

View Change

soc/amd/common/block/spi: Add support for common SPI configuration

This change adds support for following SPI configuration functions to
common block SPI driver and exposes them to be used by SoC:
1. fch_spi_early_init(): Sets up SPI ROM base, enables SPI ROM,
enables prefetching, disables 4dw burst mode and sets SPI speed and mode.
2. fch_spi_config_modes(): This allows SoC to configure SPI speed and
mode. It uses SPI settings from soc_amd_common_config to configure the
speed and mode.

These functions expect SoC to include soc_amd_common_config in SoC
chip config and mainboard to configure these settings in device tree.

Signed-off-by: Furquan Shaikh <furquan@google.com>
Change-Id: Ia4f231bab69e8450005dd6abe7a8e014d5eb7261
---
M src/soc/amd/common/block/include/amdblocks/chip.h
A src/soc/amd/common/block/include/amdblocks/spi.h
M src/soc/amd/common/block/spi/Makefile.inc
A src/soc/amd/common/block/spi/fch_spi.c
M src/soc/amd/common/block/spi/fch_spi_ctrl.c
5 files changed, 202 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/48/41248/1
diff --git a/src/soc/amd/common/block/include/amdblocks/chip.h b/src/soc/amd/common/block/include/amdblocks/chip.h
index 26ad26a..9281bd8 100644
--- a/src/soc/amd/common/block/include/amdblocks/chip.h
+++ b/src/soc/amd/common/block/include/amdblocks/chip.h
@@ -4,7 +4,19 @@
#ifndef __AMDBLOCKS_CHIP_H__
#define __AMDBLOCKS_CHIP_H__

+#include <amdblocks/spi.h>
+
struct soc_amd_common_config {
+ /*
+ * SPI configuration
+ * Default values if not overriden by mainboard:
+ * Read mode - Normal 33MHz
+ * Normal speed - 66MHz
+ * Fast speed - 66MHz
+ * Alt speed - 66MHz
+ * TPM speed - 66MHz
+ */
+ struct spi_config spi_config;
};

/*
diff --git a/src/soc/amd/common/block/include/amdblocks/spi.h b/src/soc/amd/common/block/include/amdblocks/spi.h
new file mode 100644
index 0000000..077681d
--- /dev/null
+++ b/src/soc/amd/common/block/include/amdblocks/spi.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#ifndef __AMDBLOCKS_SPI_H__
+#define __AMDBLOCKS_SPI_H__
+
+#define SPI_CNTRL0 0x00
+#define SPI_BUSY BIT(31)
+
+enum spi_read_mode {
+ SPI_READ_MODE_NORMAL33M = 0,
+ /* 1 is reserved. */
+ SPI_READ_MODE_DUAL112 = 2,
+ SPI_READ_MODE_QUAD114 = 3,
+ SPI_READ_MODE_DUAL122 = 4,
+ SPI_READ_MODE_QUAD144 = 5,
+ SPI_READ_MODE_NORMAL66M = 6,
+ SPI_READ_MODE_FAST_READ = 7,
+};
+/*
+ * SPI read mode is split into bits 18, 29, 30 such that [30:29:18] correspond to bits [2:0] for
+ * SpiReadMode.
+ */
+#define SPI_READ_MODE_MASK (BIT(30) | BIT(29) | BIT(18))
+#define SPI_READ_MODE_UPPER_BITS(x) ((((x) >> 1) & 0x3) << 29)
+#define SPI_READ_MODE_LOWER_BITS(x) (((x) & 0x1) << 18)
+#define SPI_READ_MODE(x) (SPI_READ_MODE_UPPER_BITS(x) | \
+ SPI_READ_MODE_LOWER_BITS(x))
+#define SPI_ACCESS_MAC_ROM_EN BIT(22)
+
+#define SPI100_ENABLE 0x20
+#define SPI_USE_SPI100 BIT(0)
+
+/* Use SPI_SPEED_16M-SPI_SPEED_66M below for the southbridge */
+#define SPI100_SPEED_CONFIG 0x22
+enum spi100_speed {
+ SPI_SPEED_66M = 0,
+ SPI_SPEED_33M = 1,
+ SPI_SPEED_22M = 2,
+ SPI_SPEED_16M = 3,
+ SPI_SPEED_100M = 4,
+ SPI_SPEED_800K = 5,
+};
+
+#define SPI_SPEED_MASK 0xf
+#define SPI_SPEED_MODE(x, shift) (((x) & SPI_SPEED_MASK) << shift)
+#define SPI_NORM_SPEED(x) SPI_SPEED_MODE(x, 12)
+#define SPI_FAST_SPEED(x) SPI_SPEED_MODE(x, 8)
+#define SPI_ALT_SPEED(x) SPI_SPEED_MODE(x, 4)
+#define SPI_TPM_SPEED(x) SPI_SPEED_MODE(x, 0)
+
+#define SPI_SPEED_CFG(n, f, a, t) (SPI_NORM_SPEED(n) | SPI_FAST_SPEED(f) | \
+ SPI_ALT_SPEED(a) | SPI_TPM_SPEED(t))
+
+#define SPI100_HOST_PREF_CONFIG 0x2c
+#define SPI_RD4DW_EN_HOST BIT(15)
+
+#define SPI_FIFO 0x80
+#define SPI_FIFO_DEPTH (0xc7 - SPI_FIFO)
+
+struct spi_config {
+ /*
+ * Default values if not overriden by mainboard:
+ * Read mode - Normal 33MHz
+ * Normal speed - 66MHz
+ * Fast speed - 66MHz
+ * Alt speed - 66MHz
+ * TPM speed - 66MHz
+ */
+ enum spi_read_mode read_mode;
+ enum spi100_speed normal_speed;
+ enum spi100_speed fast_speed;
+ enum spi100_speed altio_speed;
+ enum spi100_speed tpm_speed;
+};
+
+/*
+ * Perform early SPI initialization:
+ * 1. Sets SPI ROM base and enables SPI ROM
+ * 2. Enables SPI ROM prefetching
+ * 3. Disables 4dw burst
+ * 4. Configures SPI speed and read mode.
+ *
+ * This function expects SoC to include soc_amd_common_config in chip SoC config and uses
+ * settings from mainboard devicetree to configure speed and read mode.
+ */
+void fch_spi_early_init(void);
+
+/*
+ * Configure SPI speed and read mode.
+ *
+ * This function expects SoC to include soc_amd_common_config in chip SoC config and uses
+ * settings from mainboard devicetree to configure speed and read mode.
+ */
+void fch_spi_config_modes(void);
+
+#endif /* __AMDBLOCKS_SPI_H__ */
diff --git a/src/soc/amd/common/block/spi/Makefile.inc b/src/soc/amd/common/block/spi/Makefile.inc
index 0e706ef..3d541b7 100644
--- a/src/soc/amd/common/block/spi/Makefile.inc
+++ b/src/soc/amd/common/block/spi/Makefile.inc
@@ -9,4 +9,13 @@
smm-y += fch_spi_ctrl.c
endif

+bootblock-y += fch_spi.c
+romstage-y += fch_spi.c
+postcar-y += fch_spi.c
+ramstage-y += fch_spi.c
+verstage-y += fch_spi.c
+ifeq ($(CONFIG_SPI_FLASH_SMM),y)
+smm-y += fch_spi.c
+endif
+
endif
diff --git a/src/soc/amd/common/block/spi/fch_spi.c b/src/soc/amd/common/block/spi/fch_spi.c
new file mode 100644
index 0000000..68af70e
--- /dev/null
+++ b/src/soc/amd/common/block/spi/fch_spi.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <amdblocks/chip.h>
+#include <amdblocks/lpc.h>
+#include <amdblocks/spi.h>
+#include <arch/mmio.h>
+#include <console/console.h>
+#include <soc/iomap.h>
+#include <stdint.h>
+
+static uintptr_t fch_spi_base(void)
+{
+ uintptr_t base;
+
+ base = lpc_get_spibase();
+
+ if (base)
+ return base;
+
+ lpc_initialize_spi_bar(SPI_BASE_ADDRESS, SPI_ROM_ENABLE);
+ return SPI_BASE_ADDRESS;
+}
+
+static void fch_spi_set_spi100(int norm, int fast, int alt, int tpm)
+{
+ uintptr_t base = fch_spi_base();
+
+ write16((void *)(base + SPI100_SPEED_CONFIG), SPI_SPEED_CFG(norm, fast, alt, tpm));
+ write16((void *)(base + SPI100_ENABLE), SPI_USE_SPI100);
+}
+
+static void fch_spi_disable_4dw_burst(void)
+{
+ uintptr_t base = fch_spi_base();
+ uint16_t val = read16((void *)(base + SPI100_HOST_PREF_CONFIG));
+
+ write16((void *)(base + SPI100_HOST_PREF_CONFIG), val & ~SPI_RD4DW_EN_HOST);
+}
+
+static void fch_spi_set_read_mode(u32 mode)
+{
+ uintptr_t base = fch_spi_base();
+ uint32_t val = read32((void *)(base + SPI_CNTRL0)) & ~SPI_READ_MODE_MASK;
+
+ write32((void *)(base + SPI_CNTRL0), val | SPI_READ_MODE(mode));
+}
+
+static void fch_spi_config_mb_modes(void)
+{
+ const struct soc_amd_common_config *cfg = soc_get_common_config();
+
+ if (!cfg)
+ die("Common config structure is NULL!\n");
+
+ const struct spi_config *spi_cfg = &cfg->spi_config;
+
+ fch_spi_set_read_mode(spi_cfg->read_mode);
+ fch_spi_set_spi100(spi_cfg->normal_speed, spi_cfg->fast_speed,
+ spi_cfg->altio_speed, spi_cfg->tpm_speed);
+}
+
+static void fch_spi_config_em100_modes(void)
+{
+ fch_spi_set_read_mode(SPI_READ_MODE_NORMAL33M);
+ fch_spi_set_spi100(SPI_SPEED_16M, SPI_SPEED_16M, SPI_SPEED_16M, SPI_SPEED_16M);
+}
+
+void fch_spi_config_modes(void)
+{
+ if (CONFIG(EM100))
+ fch_spi_config_em100_modes();
+ else
+ fch_spi_config_mb_modes();
+}
+
+void fch_spi_early_init(void)
+{
+ lpc_initialize_spi_bar(SPI_BASE_ADDRESS, SPI_ROM_ENABLE);
+ lpc_enable_spi_prefetch();
+ fch_spi_disable_4dw_burst();
+ fch_spi_config_modes();
+}
diff --git a/src/soc/amd/common/block/spi/fch_spi_ctrl.c b/src/soc/amd/common/block/spi/fch_spi_ctrl.c
index c0751a3..b048f1c 100644
--- a/src/soc/amd/common/block/spi/fch_spi_ctrl.c
+++ b/src/soc/amd/common/block/spi/fch_spi_ctrl.c
@@ -2,9 +2,9 @@

#include <console/console.h>
#include <spi_flash.h>
-#include <soc/southbridge.h>
#include <soc/pci_devs.h>
#include <amdblocks/lpc.h>
+#include <amdblocks/spi.h>
#include <device/pci_ops.h>
#include <lib.h>
#include <timer.h>

To view, visit change 41248. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Ia4f231bab69e8450005dd6abe7a8e014d5eb7261
Gerrit-Change-Number: 41248
Gerrit-PatchSet: 1
Gerrit-Owner: Furquan Shaikh <furquan@google.com>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange