[coreboot-gerrit] New patch to review for coreboot: 7486e1a armv7/exynos5420: Change SPI module to standard <spi-generic> interface.

Gabe Black (gabeblack@chromium.org) gerrit at coreboot.org
Tue Jul 9 05:29:42 CEST 2013


Gabe Black (gabeblack at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3710

-gerrit

commit 7486e1a729c0cf3307a3959614eb740a37dea903
Author: Hung-Te Lin <hungte at chromium.org>
Date:   Wed Jun 26 20:16:13 2013 +0800

    armv7/exynos5420: Change SPI module to standard <spi-generic> interface.
    
    The SPI module in Exynos 5420 didn't follow Coreboot's SPI API standard
    (spi-generic.h) and will be a problem when we want to share SPI drivers.
    
    This commit replaces exynos_spi_* by spi_* functions.
    
    Note, exynos_spi_read is kept and changed to a static function because its usage
    is different from the standard API "spi_xfer".
    
    Change-Id: I6de301bc6b46a09f87b0336c60247fedbe844ca3
    Signed-off-by: Hung-Te Lin <hungte at chromium.org>
    Signed-off-by: Gabe Black <gabeblack at chromium.org>
---
 src/cpu/samsung/exynos5420/spi.c | 89 ++++++++++++++++++++++++++++++++++------
 src/cpu/samsung/exynos5420/spi.h |  5 ---
 2 files changed, 76 insertions(+), 18 deletions(-)

diff --git a/src/cpu/samsung/exynos5420/spi.c b/src/cpu/samsung/exynos5420/spi.c
index 35fccb2..e3029b8 100644
--- a/src/cpu/samsung/exynos5420/spi.c
+++ b/src/cpu/samsung/exynos5420/spi.c
@@ -22,17 +22,61 @@
 #include <arch/io.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <spi_flash.h>
 
+#include "cpu.h"
 #include "spi.h"
 
-#define EXYNOS_BASE_SPI1 ((void *)0x12d30000)
-
 #if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI
 # define DEBUG_SPI(x,...)	printk(BIOS_DEBUG, "EXYNOS_SPI: " x)
 #else
 # define DEBUG_SPI(x,...)
 #endif
 
+struct exynos_spi_slave {
+	struct spi_slave slave;
+	struct exynos_spi *regs;
+	unsigned int fifo_size;
+	uint8_t half_duplex;
+	uint8_t frame_header;  /* header byte to detect in half-duplex mode. */
+};
+
+static inline struct exynos_spi_slave *to_exynos_spi(struct spi_slave *slave)
+{
+	return container_of(slave, struct exynos_spi_slave, slave);
+}
+
+void spi_init(void)
+{
+	printk(BIOS_INFO, "Exynos SPI driver initiated.\n");
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode)
+{
+	// TODO(hungte) Provide Exynos SPI device setup.
+	return NULL;
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	// TODO(hungte) Detect and check if BUS/CS is valid.
+	return 0;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	struct exynos_spi *regs = to_exynos_spi(slave)->regs;
+	// TODO(hungte) Add some delay if too many transactions happen at once.
+	clrbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct exynos_spi *regs = to_exynos_spi(slave)->regs;
+	setbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT);
+}
+
 static void exynos_spi_rx_tx(struct exynos_spi *regs, int todo,
 			     void *dinp, void const *doutp, int i)
 {
@@ -75,8 +119,11 @@ static void exynos_spi_rx_tx(struct exynos_spi *regs, int todo,
 }
 
 /* set up SPI channel */
-int exynos_spi_open(struct exynos_spi *regs)
+int spi_claim_bus(struct spi_slave *slave)
 {
+	struct exynos_spi_slave *espi = to_exynos_spi(slave);
+	struct exynos_spi *regs = espi->regs;
+
 	/* set the spi1 GPIO */
 
 	/* set pktcnt and enable it */
@@ -103,8 +150,17 @@ int exynos_spi_open(struct exynos_spi *regs)
 	return 0;
 }
 
-int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off)
+int spi_xfer(struct spi_slave *slave, const void *dout, unsigned int bitsout,
+	     void *din, unsigned int bitsin)
+{
+	// TODO(hungte) Invoke exynos_spi_rx_tx to transfer data.
+	return -1;
+}
+
+static int exynos_spi_read(struct spi_slave *slave, void *dest, uint32_t len,
+			   uint32_t off)
 {
+	struct exynos_spi *regs = to_exynos_spi(slave)->regs;
 	int upto, todo;
 	int i;
 	clrbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */
@@ -125,8 +181,9 @@ int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off)
 	return len;
 }
 
-int exynos_spi_close(struct exynos_spi *regs)
+void spi_release_bus(struct spi_slave *slave)
 {
+	struct exynos_spi *regs = to_exynos_spi(slave)->regs;
 	/*
 	 * Let put controller mode to BYTE as
 	 * SPI driver does not support WORD mode yet
@@ -142,25 +199,25 @@ int exynos_spi_close(struct exynos_spi *regs)
 	clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
 	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
 	clrbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
-	return 0;
 }
 
 // SPI as CBFS media.
 struct exynos_spi_media {
-	struct exynos_spi *regs;
+	struct spi_slave *slave;
 	struct cbfs_simple_buffer buffer;
 };
 
 static int exynos_spi_cbfs_open(struct cbfs_media *media) {
 	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
 	DEBUG_SPI("exynos_spi_cbfs_open\n");
-	return exynos_spi_open(spi->regs);
+	return spi_claim_bus(spi->slave);
 }
 
 static int exynos_spi_cbfs_close(struct cbfs_media *media) {
 	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
 	DEBUG_SPI("exynos_spi_cbfs_close\n");
-	return exynos_spi_close(spi->regs);
+	spi_release_bus(spi->slave);
+	return 0;
 }
 
 static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest,
@@ -168,10 +225,10 @@ static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest,
 	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
 	int bytes;
 	DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count);
-	bytes = exynos_spi_read(spi->regs, dest, count, offset);
+	bytes = exynos_spi_read(spi->slave, dest, count, offset);
 	// Flush and re-open the device.
-	exynos_spi_close(spi->regs);
-	exynos_spi_open(spi->regs);
+	spi_release_bus(spi->slave);
+	spi_claim_bus(spi->slave);
 	return bytes;
 }
 
@@ -197,9 +254,15 @@ int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
 				     size_t buffer_size) {
 	// TODO Replace static variable to support multiple streams.
 	static struct exynos_spi_media context;
+	static struct exynos_spi_slave eslave = {
+		.slave = { .bus = 1, .rw = SPI_READ_FLAG, },
+		.regs = samsung_get_base_spi1(),
+		.fifo_size = 64,
+		.half_duplex = 0,
+	};
 	DEBUG_SPI("initialize_exynos_spi_cbfs_media\n");
 
-	context.regs = EXYNOS_BASE_SPI1;
+	context.slave = &eslave.slave;
 	context.buffer.allocated = context.buffer.last_allocate = 0;
 	context.buffer.buffer = buffer_address;
 	context.buffer.size = buffer_size;
diff --git a/src/cpu/samsung/exynos5420/spi.h b/src/cpu/samsung/exynos5420/spi.h
index faf82b0..94b4fda 100644
--- a/src/cpu/samsung/exynos5420/spi.h
+++ b/src/cpu/samsung/exynos5420/spi.h
@@ -86,11 +86,6 @@ struct exynos_spi {
 #define SPI_RX_BYTE_SWAP	(1 << 6)
 #define SPI_RX_HWORD_SWAP	(1 << 7)
 
-/* API */
-int exynos_spi_open(struct exynos_spi *regs);
-int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off);
-int exynos_spi_close(struct exynos_spi *regs);
-
 /* Serve as CBFS media source */
 int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
 				     void *buffer_address,



More information about the coreboot-gerrit mailing list