[coreboot-gerrit] Change in coreboot[master]: soc/intel/common: Add support for common GSPI controller

Furquan Shaikh (Code Review) gerrit at coreboot.org
Tue Apr 4 01:52:02 CEST 2017


Furquan Shaikh has uploaded a new change for review. ( https://review.coreboot.org/19098 )

Change subject: soc/intel/common: Add support for common GSPI controller
......................................................................

soc/intel/common: Add support for common GSPI controller

Add support for GSPI controller in Intel PCH. This controller is
compliant with PXA2xx SPI controller with some additional registers to
provide more fine-grained control of the SPI bus. Currently, DMA is
not enabled as this driver might be used before memory is up (e.g. TPM
on SPI).

BUG=b:35583330

Change-Id: I0eb91eba2c523be457fee8922c44fb500a9fa140
Signed-off-by: Furquan Shaikh <furquan at chromium.org>
---
A src/soc/intel/common/block/gspi/Kconfig
A src/soc/intel/common/block/gspi/Makefile.inc
A src/soc/intel/common/block/gspi/gspi.c
A src/soc/intel/common/block/include/intelblocks/gspi.h
4 files changed, 583 insertions(+), 0 deletions(-)


  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/98/19098/1

diff --git a/src/soc/intel/common/block/gspi/Kconfig b/src/soc/intel/common/block/gspi/Kconfig
new file mode 100644
index 0000000..d2c907a
--- /dev/null
+++ b/src/soc/intel/common/block/gspi/Kconfig
@@ -0,0 +1,12 @@
+config SOC_INTEL_COMMON_BLOCK_GSPI
+	bool
+	help
+	  Intel Processor Common GSPI support
+
+config SOC_INTEL_COMMON_BLOCK_GSPI_CLK_MHZ
+	int
+	depends on SOC_INTEL_COMMON_BLOCK_GSPI
+	help
+	  The clock speed that the GSPI controller is running at, in MHz.
+	  This is an SoC-specific value and must be provided by the SoC when it
+	  selects this driver.
diff --git a/src/soc/intel/common/block/gspi/Makefile.inc b/src/soc/intel/common/block/gspi/Makefile.inc
new file mode 100644
index 0000000..85cb18e
--- /dev/null
+++ b/src/soc/intel/common/block/gspi/Makefile.inc
@@ -0,0 +1,4 @@
+bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI) += gspi.c
+romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI) += gspi.c
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI) += gspi.c
+verstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI) += gspi.c
diff --git a/src/soc/intel/common/block/gspi/gspi.c b/src/soc/intel/common/block/gspi/gspi.c
new file mode 100644
index 0000000..8ece724
--- /dev/null
+++ b/src/soc/intel/common/block/gspi/gspi.c
@@ -0,0 +1,523 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/io.h>
+#include <assert.h>
+#include <console/console.h>
+#include <delay.h>
+#include <intelblocks/gspi.h>
+#include <timer.h>
+
+/* GSPI Memory Mapped Registers */
+#define SSCR0			0x0	/* SSP Control Register 0 */
+#define   SSCR0_EDSS_0		(0 << 20)
+#define   SSCR0_EDSS_1		(1 << 20)
+#define   SSCR0_SCR_SHIFT	(8)
+#define   SSCR0_SCR_MASK	(0xFFF)
+#define   SSCR0_SSE_DISABLE	(0 << 7)
+#define   SSCR0_SSE_ENABLE	(1 << 7)
+#define   SSCR0_ECS_ON_CHIP	(0 << 6)
+#define   SSCR0_FRF_MOTOROLA	(0 << 4)
+#define   SSCR0_DSS_SHIFT	(0)
+#define   SSCR0_DSS_MASK	(0xF)
+#define SSCR1			0x4	/* SSP Control Register 1 */
+#define   SSCR1_IFS_LOW	(0 << 16)
+#define   SSCR1_IFS_HIGH	(1 << 16)
+#define   SSCR1_SPH_FIRST	(0 << 4)
+#define   SSCR1_SPH_SECOND	(1 << 4)
+#define   SSCR1_SPO_LOW	(0 << 3)
+#define   SSCR1_SPO_HIGH	(1 << 3)
+#define SSSR			0x8	/* SSP Status Register */
+#define   SSSR_TUR		(1 << 21)  /* Tx FIFO underrun */
+#define   SSSR_TINT		(1 << 19)  /* Rx Time-out interrupt */
+#define   SSSR_PINT		(1 << 18)  /* Peripheral trailing byte
+					      interrupt */
+#define   SSSR_ROR		(1 << 7)   /* Rx FIFO Overrun */
+#define   SSSR_BSY		(1 << 4)   /* SSP Busy */
+#define   SSSR_RNE		(1 << 3)   /* Receive FIFO not empty */
+#define   SSSR_TNF		(1 << 2)   /* Transmit FIFO not full */
+#define SSDR			0x10	/* SSP Data Register */
+#define SSTO			0x28	/* SSP Time out */
+#define SITF			0x44	/* SPI Transmit FIFO */
+#define   SITF_LEVEL_SHIFT	(16)
+#define   SITF_LEVEL_MASK	(0x3f)
+#define   SITF_LWM_SHIFT	(8)
+#define   SITF_LWM_MASK	(0x3f)
+#define   SITF_LWM(x)		((((x) - 1) & SITF_LWM_MASK) << SITF_LWM_SHIFT)
+#define   SITF_HWM_SHIFT	(0)
+#define   SITF_HWM_MASK	(0x3f)
+#define   SITF_HWM(x)		((((x) - 1) & SITF_HWM_MASK) << SITF_HWM_SHIFT)
+#define SIRF			0x48	/* SPI Receive FIFO */
+#define   SIRF_LEVEL_SHIFT	(8)
+#define   SIRF_LEVEL_MASK	(0x3f)
+#define   SIRF_WM_SHIFT	(0)
+#define   SIRF_WM_MASK		(0x3f)
+#define   SIRF_WM(x)		((((x) - 1) & SIRF_WM_MASK) << SIRF_WM_SHIFT)
+
+/* GSPI Additional Registers */
+#define CLOCKS			0x200	/* Clocks */
+#define   CLOCKS_UPDATE	(1 << 31)
+#define   CLOCKS_N_SHIFT	(16)
+#define   CLOCKS_N_MASK	(0x7fff)
+#define   CLOCKS_M_SHIFT	(1)
+#define   CLOCKS_M_MASK	(0x7fff)
+#define   CLOCKS_DISABLE	(0 << 0)
+#define   CLOCKS_ENABLE	(1 << 0)
+#define RESETS			0x204	/* Resets */
+#define   DMA_RESET		(0 << 2)
+#define   DMA_ACTIVE		(1 << 2)
+#define   CTRLR_RESET		(0 << 0)
+#define   CTRLR_ACTIVE		(3 << 0)
+#define ACTIVELTR_VALUE	0x210	/* Active LTR */
+#define IDLELTR_VALUE		0x214	/* Idle LTR Value */
+#define TX_BIT_COUNT		0x218	/* Tx Bit Count */
+#define RX_BIT_COUNT		0x21c	/* Rx Bit Count */
+#define SSP_REG		0x220	/* SSP Reg */
+#define   DMA_FINISH_DISABLE	(1 << 0)
+#define SPI_CS_CONTROL		0x224	/* SPI CS Control */
+#define   CS_POLARITY_LOW	(0 << 12)
+#define   CS_POLARITY_HIGH	(1 << 12)
+#define   CS_0			(0 << 8)
+#define   CS_STATE_LOW		(0 << 1)
+#define   CS_STATE_HIGH	(1 << 1)
+#define   CS_STATE_MASK	(1 << 1)
+#define   CS_MODE_HW		(0 << 0)
+#define   CS_MODE_SW		(1 << 0)
+
+#define GSPI_DATA_BIT_LENGTH	(8)
+
+int __attribute__((weak)) gspi_get_bus_config(unsigned int bus,
+						struct spi_cfg *cfg)
+{
+	cfg->clk_phase = SPI_CLOCK_PHASE_FIRST;
+	cfg->clk_polarity = SPI_POLARITY_LOW;
+	cfg->cs_polarity = SPI_POLARITY_LOW;
+	cfg->wire_mode = SPI_4_WIRE_MODE;
+	cfg->data_bit_length = GSPI_DATA_BIT_LENGTH;
+
+	return 0;
+}
+
+static int gspi_ctrlr_get_config(const struct spi_slave *dev,
+				struct spi_cfg *cfg)
+{
+	/* Currently, only chip select 0 is supported. */
+	if (dev->cs != 0) {
+		printk(BIOS_ERR, "%s: Unsupported device bus=%u,cs=%u!\n",
+			__func__, dev->bus, dev->cs);
+		return -1;
+	}
+
+	return gspi_get_bus_config(dev->bus, cfg);
+}
+
+static int gspi_read_mmio_reg(const struct spi_slave *dev, uint32_t offset,
+				uint32_t *value)
+{
+	uintptr_t base = gspi_get_bus_base_address(dev->bus);
+
+	if (!base) {
+		printk(BIOS_ERR, "%s: base address not found for bus %u."
+		       " Read failed for 0x%x.\n",__func__, dev->bus, offset);
+		return -1;
+	}
+
+	*value = read32((void *)(base + offset));
+	return 0;
+}
+
+static int gspi_write_mmio_reg(const struct spi_slave *dev, uint32_t offset,
+				uint32_t value)
+{
+	uintptr_t base = gspi_get_bus_base_address(dev->bus);
+
+	if (!base) {
+		printk(BIOS_ERR, "%s: base address not found for bus %u."
+		       " Write failed for 0x%x.\n",__func__, dev->bus, offset);
+		return -1;
+	}
+
+	write32((void *)(base + offset), value);
+	return 0;
+}
+
+/* If status read fails for any reason, value returned is 0. */
+static uint32_t gspi_read_status(const struct spi_slave *dev)
+{
+	uint32_t sssr = 0;
+	gspi_read_mmio_reg(dev, SSSR, &sssr);
+	return sssr;
+}
+
+/*
+ * If status clear fails, xfer operation is not stopped right away. Instead, let
+ * it continue and see if we can go through with the transfer.
+ */
+static void gspi_clear_status(const struct spi_slave *dev)
+{
+	const uint32_t sssr = SSSR_TUR | SSSR_TINT | SSSR_PINT | SSSR_ROR;
+	gspi_write_mmio_reg(dev, SSSR, sssr);
+}
+
+/* Read SSDR and return lowest byte. */
+static int gspi_read_byte(const struct spi_slave *dev, uint8_t *data)
+{
+	uint32_t ssdr;
+	if (gspi_read_mmio_reg(dev, SSDR, &ssdr))
+		return -1;
+	if (data)
+		*data = ssdr & 0xFF;
+	return 0;
+}
+
+/* Write 32-bit word with "data" in lowest byte to SSDR. */
+static int gspi_write_byte(const struct spi_slave *dev, uint8_t data)
+{
+	return gspi_write_mmio_reg(dev, SSDR, data);
+}
+
+enum cs_assert {
+	CS_ASSERT,
+	CS_DEASSERT,
+};
+
+static int gspi_cs_change(const struct spi_slave *dev, enum cs_assert assert)
+{
+	uint32_t cs_ctrl, state;
+
+	if (gspi_read_mmio_reg(dev, SPI_CS_CONTROL, &cs_ctrl))
+		return -1;
+
+	cs_ctrl &= ~CS_STATE_MASK;
+
+	if (cs_ctrl & CS_POLARITY_HIGH)
+		state = (assert == CS_ASSERT) ? CS_STATE_HIGH : CS_STATE_LOW;
+	else
+		state = (assert == CS_ASSERT) ? CS_STATE_LOW : CS_STATE_HIGH;
+
+	cs_ctrl |= state;
+
+	if (gspi_write_mmio_reg(dev, SPI_CS_CONTROL, cs_ctrl))
+		return -1;
+
+	return 0;
+}
+
+static int gspi_cs_assert(const struct spi_slave *dev)
+{
+	return gspi_cs_change(dev, CS_ASSERT);
+}
+
+static void gspi_cs_deassert(const struct spi_slave *dev)
+{
+	gspi_cs_change(dev, CS_DEASSERT);
+}
+
+static uint32_t gspi_get_clk_div(const struct spi_slave *dev)
+{
+	const uint32_t ref_clk_mhz = CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_CLK_MHZ;
+	const uint32_t gspi_clk_mhz = gspi_get_bus_clk_mhz(dev->bus);
+
+	assert(gspi_clk_mhz != 0);
+	assert(ref_clk_mhz != 0);
+	return (ref_clk_mhz/gspi_clk_mhz - 1) & SSCR0_SCR_MASK;
+}
+
+static int gspi_ctrlr_setup(const struct spi_slave *dev)
+{
+	struct spi_cfg cfg;
+	uint32_t cs_ctrl, sscr0, sscr1, clocks, sitf, sirf;
+
+	/* Only chip select 0 is supported. */
+	if (dev->cs != 0) {
+		printk(BIOS_ERR, "%s: Unsupported device bus=%u,cs=%u!\n",
+			__func__, dev->bus, dev->cs);
+		return -1;
+	}
+
+	/* Obtain SPI bus configuration for the device. */
+	if (spi_get_config(dev, &cfg)) {
+		printk(BIOS_ERR, "%s: Failed to get config for bus=%u.\n",
+			__func__, dev->bus);
+		return -1;
+	}
+
+	/* Take controller out of reset, keeping DMA in reset. */
+	if (gspi_write_mmio_reg(dev, RESETS, CTRLR_ACTIVE | DMA_RESET))
+		return -1;
+
+	/* De-assert SPI chip. */
+	gspi_cs_deassert(dev);
+
+	/*
+	 * CS control:
+	 * - Set SW mode.
+	 * - Set chip select to 0.
+	 * - Set polarity based on device configuration.
+	 * - Do not assert CS.
+	 */
+	cs_ctrl = CS_MODE_SW | CS_0;
+	if (cfg.cs_polarity == SPI_POLARITY_LOW)
+		cs_ctrl |= CS_POLARITY_LOW | CS_STATE_HIGH;
+	else
+		cs_ctrl |= CS_POLARITY_HIGH | CS_STATE_LOW;
+	if (gspi_write_mmio_reg(dev, SPI_CS_CONTROL, cs_ctrl))
+		return -1;
+
+	/* Disable SPI controller. */
+	if (gspi_write_mmio_reg(dev, SSCR0, SSCR0_SSE_DISABLE))
+		return -1;
+
+	/*
+	 * SSCR0 configuration:
+	 * clk_div - Based on reference clock and expected clock frequency.
+	 * data bit length - assumed to be 8, hence EDSS = 0.
+	 * ECS - Use on-chip clock
+	 * FRF - Frame format set to Motorola SPI
+	 */
+	sscr0 = gspi_get_clk_div(dev) << SSCR0_SCR_SHIFT;
+	assert(GSPI_DATA_BIT_LENGTH == 8);
+	sscr0 |= ((GSPI_DATA_BIT_LENGTH - 1) << SSCR0_DSS_SHIFT) | SSCR0_EDSS_0;
+	sscr0 |= SSCR0_ECS_ON_CHIP | SSCR0_FRF_MOTOROLA;
+	if (gspi_write_mmio_reg(dev, SSCR0, sscr0))
+		return -1;
+
+	/*
+	 * SSCR1 configuration:
+	 * - Chip select polarity
+	 * - Clock phase setting
+	 * - Clock polarity
+	 */
+	sscr1 = (cfg.cs_polarity == SPI_POLARITY_LOW) ? SSCR1_IFS_LOW :
+		SSCR1_IFS_HIGH;
+	sscr1 |= (cfg.clk_phase == SPI_CLOCK_PHASE_FIRST) ? SSCR1_SPH_FIRST :
+		SSCR1_SPH_SECOND;
+	sscr1 |= (cfg.clk_polarity == SPI_POLARITY_LOW) ? SSCR1_SPO_LOW :
+		SSCR1_SPO_HIGH;
+	if (gspi_write_mmio_reg(dev, SSCR1, sscr1))
+		return -1;
+
+	/*
+	 * Program m/n divider.
+	 * Set m and n to 1, so that this divider acts as a pass-through.
+	 */
+	clocks = (1 << CLOCKS_N_SHIFT) | (1 << CLOCKS_M_SHIFT) | CLOCKS_ENABLE;
+	if (gspi_write_mmio_reg(dev, CLOCKS, clocks))
+		return -1;
+	udelay(10);
+
+	/*
+	 * Tx FIFO Threshold.
+	 * Low watermark threshold = 1
+	 * High watermark threshold = 1
+	 */
+	sitf = SITF_LWM(1) | SITF_HWM(1);
+	if (gspi_write_mmio_reg(dev, SITF, sitf))
+		return -1;
+	gspi_read_mmio_reg(dev, SITF, &sitf);
+
+	/* Rx FIFO Threshold (set to 1). */
+	sirf = SIRF_WM(1);
+	if (gspi_write_mmio_reg(dev, SIRF, sirf))
+		return -1;
+
+	/* Enable GSPI controller. */
+	sscr0 |= SSCR0_SSE_ENABLE;
+	if (gspi_write_mmio_reg(dev, SSCR0, sscr0))
+		return -1;
+
+	return 0;
+}
+
+static bool gspi_tx_fifo_full(const struct spi_slave *dev)
+{
+        return !(gspi_read_status(dev) & SSSR_TNF);
+}
+
+static bool gspi_rx_fifo_empty(const struct spi_slave *dev)
+{
+	return !(gspi_read_status(dev) & SSSR_RNE);
+}
+
+static bool gspi_rx_fifo_overrun(const struct spi_slave *dev)
+{
+	if (gspi_read_status(dev) & SSSR_ROR) {
+		printk(BIOS_ERR, "%s:GSPI receive FIFO overrun!"
+		       " (bus=%u).\n", __func__, dev->bus);
+		return true;
+	}
+
+	return false;
+}
+
+static int gspi_ctrlr_flush(const struct spi_slave *dev)
+{
+	const uint32_t timeout_ms = 500;
+	struct stopwatch sw;
+
+	/* Wait 500ms to allow Rx FIFO to be empty. */
+	stopwatch_init_msecs_expire(&sw, timeout_ms);
+
+        while(!gspi_rx_fifo_empty(dev)) {
+		if (stopwatch_expired(&sw)) {
+			printk(BIOS_ERR, "%s: Rx FIFO not empty after 500ms! "
+			       "(bus=%u)\n", __func__, dev->bus);
+			return -1;
+		}
+
+		gspi_read_byte(dev, NULL);
+	}
+
+	return 0;
+}
+
+/* Parameters for xfer operation. */
+struct gspi_xfer_params {
+	const struct spi_slave *dev;
+	uint8_t *in;
+	size_t bytesin;
+	const uint8_t *out;
+	size_t bytesout;
+};
+
+static int gspi_read_data(struct gspi_xfer_params *p)
+{
+	if (gspi_read_byte(p->dev, p->in))
+		return -1;
+	(p->in)++;
+	p->bytesin--;
+	return 0;
+}
+
+static int gspi_write_data(struct gspi_xfer_params *p)
+{
+	if (gspi_write_byte(p->dev, *(p->out)))
+		return -1;
+	(p->out)++;
+	p->bytesout--;
+	return 0;
+}
+
+static int gspi_read_dummy(struct gspi_xfer_params *p)
+{
+	if (gspi_read_byte(p->dev, NULL))
+		return -1;
+	p->bytesin--;
+	return 0;
+}
+
+static int gspi_write_dummy(struct gspi_xfer_params *p)
+{
+	if (gspi_write_byte(p->dev, 0))
+		return -1;
+	p->bytesout--;
+	return 0;
+}
+
+static int __gspi_xfer(struct gspi_xfer_params *p)
+{
+	/*
+	 * If bytesin is non-zero, then use gspi_read_data to perform
+	 * byte-by-byte read of data from SSDR and save it to "in" buffer. Else
+	 * discard the read data using gspi_read_dummy.
+	 */
+	int (*fn_read)(struct gspi_xfer_params *p) = gspi_read_data;
+
+	/*
+	 * If bytesout is non-zero, then use gspi_write_data to perform
+	 * byte-by-byte write of data from "out" buffer to SSDR. Else, use
+	 * gspi_write_dummy to write dummy "0" data to SSDR in order to trigger
+	 * read from slave.
+	 */
+	int (*fn_write)(struct gspi_xfer_params *p) = gspi_write_data;;
+
+	if (!p->bytesin) {
+		p->bytesin = p->bytesout;
+		fn_read = gspi_read_dummy;
+	}
+
+	if (!p->bytesout) {
+		p->bytesout = p->bytesin;
+		fn_write = gspi_write_dummy;
+	}
+
+	while (p->bytesout || p->bytesin) {
+		if (p->bytesout && !gspi_tx_fifo_full(p->dev))
+			if (fn_write(p))
+				return -1;
+		if (p->bytesin && !gspi_rx_fifo_empty(p->dev)) {
+			if (gspi_rx_fifo_overrun(p->dev))
+				return -1;
+			if (fn_read(p))
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int gspi_ctrlr_xfer(const struct spi_slave *dev,
+			   const void *dout, size_t bytesout,
+			   void *din, size_t bytesin)
+{
+	struct gspi_xfer_params params = {
+		.dev = dev,
+		.in = (uint8_t *)din,
+		.bytesin = bytesin,
+		.out = (const uint8_t *)dout,
+		.bytesout = bytesout,
+	};
+
+	/*
+	 * Assumptions about in and out transfers:
+	 * 1. Both bytesin and bytesout cannot be 0.
+	 * 2. If both bytesin and bytesout are non-zero, then they should be
+	 * equal i.e. if both in and out transfers are to be done in same
+	 * transaction, then they should be equal in length.
+	 * 3. Buffer corresponding to non-zero bytes (bytesin/bytesout) cannot
+	 * be NULL.
+	 */
+	if (!bytesin && !bytesout) {
+		printk(BIOS_ERR, "%s: Both in and out bytes cannot be zero!\n",
+		       __func__);
+		return -1;
+	} else if (bytesin && bytesout && (bytesin != bytesout)) {
+		printk(BIOS_ERR, "%s: bytesin(%zd) != bytesout(%zd)\n",
+		       __func__, bytesin, bytesout);
+		return -1;
+	}
+	if ((bytesin && !din) || (bytesout && !dout)) {
+		printk(BIOS_ERR, "%s: in/out buffer is NULL!\n", __func__);
+		return -1;
+	}
+
+	/* Flush out any stale data in Rx FIFO. */
+	if (gspi_ctrlr_flush(dev))
+		return -1;
+
+	/* Clear status bits. */
+	gspi_clear_status(dev);
+
+	return __gspi_xfer(&params);
+}
+
+const struct spi_ctrlr gspi_ctrlr = {
+	.get_config = gspi_ctrlr_get_config,
+	.claim_bus = gspi_cs_assert,
+	.release_bus = gspi_cs_deassert,
+	.setup = gspi_ctrlr_setup,
+	.xfer = gspi_ctrlr_xfer,
+};
diff --git a/src/soc/intel/common/block/include/intelblocks/gspi.h b/src/soc/intel/common/block/include/intelblocks/gspi.h
new file mode 100644
index 0000000..868eb53
--- /dev/null
+++ b/src/soc/intel/common/block/include/intelblocks/gspi.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2017 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef SOC_INTEL_COMMON_BLOCK_GSPI_H
+#define SOC_INTEL_COMMON_BLOCK_GSPI_H
+
+#include <spi-generic.h>
+#include <stdint.h>
+
+/* GSPI controller structure to allow SoCs to define bus-controller mapping. */
+extern const struct spi_ctrlr gspi_ctrlr;
+
+/*
+ * SoC-provided callback for returning the base address of GSPI controller
+ * controlling the bus.
+ */
+uintptr_t gspi_get_bus_base_address(unsigned int bus);
+
+/*
+ * SoC-provided callback for getting configuration of SPI bus. Driver provides
+ * weak implementation with default SPI-bus configuration.
+ *
+ * Return value:
+ * 0 = Success
+ * non-zero = Error
+ */
+int gspi_get_bus_config(unsigned int bus, struct spi_cfg *cfg);
+
+/* SoC-provided callback for getting desired clock frequency of SPI bus. */
+uint32_t gspi_get_bus_clk_mhz(unsigned int bus);
+
+#endif /* SOC_INTEL_COMMON_BLOCK_LPSS_SPI_H */

-- 
To view, visit https://review.coreboot.org/19098
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0eb91eba2c523be457fee8922c44fb500a9fa140
Gerrit-PatchSet: 1
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Owner: Furquan Shaikh <furquan at google.com>



More information about the coreboot-gerrit mailing list