diff options
author | Hung-Te Lin <hungte@chromium.org> | 2013-06-26 20:16:13 +0800 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2013-07-10 23:16:58 +0200 |
commit | ffa5bada722a60e0115775ee69cd681c3737f17a (patch) | |
tree | 4aee73d4a49d59510dbbbac4643bc2fbcdbcb3e0 /src/cpu/samsung/exynos5420/spi.c | |
parent | 45d524d2783adad9fee62a5bf909baf675e83fc9 (diff) | |
download | coreboot-ffa5bada722a60e0115775ee69cd681c3737f17a.tar.xz |
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@chromium.org>
Signed-off-by: Gabe Black <gabeblack@chromium.org>
Reviewed-on: http://review.coreboot.org/3710
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/cpu/samsung/exynos5420/spi.c')
-rw-r--r-- | src/cpu/samsung/exynos5420/spi.c | 89 |
1 files changed, 76 insertions, 13 deletions
diff --git a/src/cpu/samsung/exynos5420/spi.c b/src/cpu/samsung/exynos5420/spi.c index 35fccb2b84..e3029b83db 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(®s->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(®s->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(®s->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(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); clrbits_le32(®s->ch_cfg, SPI_CH_RST); clrbits_le32(®s->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; |