diff options
Diffstat (limited to 'drivers/spi/ep93xx_spi.c')
-rw-r--r-- | drivers/spi/ep93xx_spi.c | 272 |
1 files changed, 0 insertions, 272 deletions
diff --git a/drivers/spi/ep93xx_spi.c b/drivers/spi/ep93xx_spi.c deleted file mode 100644 index cb682dd..0000000 --- a/drivers/spi/ep93xx_spi.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * SPI Driver for EP93xx - * - * Copyright (C) 2013 Sergey Kostanabev <sergey.kostanbaev <at> fairwaves.ru> - * - * Inspired form linux kernel driver and atmel uboot driver - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <spi.h> -#include <malloc.h> - -#include <asm/io.h> - -#include <asm/arch/ep93xx.h> - -#define SSPBASE SPI_BASE - -#define SSPCR0 0x0000 -#define SSPCR0_MODE_SHIFT 6 -#define SSPCR0_SCR_SHIFT 8 -#define SSPCR0_SPH BIT(7) -#define SSPCR0_SPO BIT(6) -#define SSPCR0_FRF_SPI 0 -#define SSPCR0_DSS_8BIT 7 - -#define SSPCR1 0x0004 -#define SSPCR1_RIE BIT(0) -#define SSPCR1_TIE BIT(1) -#define SSPCR1_RORIE BIT(2) -#define SSPCR1_LBM BIT(3) -#define SSPCR1_SSE BIT(4) -#define SSPCR1_MS BIT(5) -#define SSPCR1_SOD BIT(6) - -#define SSPDR 0x0008 - -#define SSPSR 0x000c -#define SSPSR_TFE BIT(0) -#define SSPSR_TNF BIT(1) -#define SSPSR_RNE BIT(2) -#define SSPSR_RFF BIT(3) -#define SSPSR_BSY BIT(4) -#define SSPCPSR 0x0010 - -#define SSPIIR 0x0014 -#define SSPIIR_RIS BIT(0) -#define SSPIIR_TIS BIT(1) -#define SSPIIR_RORIS BIT(2) -#define SSPICR SSPIIR - -#define SSPCLOCK 14745600 -#define SSP_MAX_RATE (SSPCLOCK / 2) -#define SSP_MIN_RATE (SSPCLOCK / (254 * 256)) - -/* timeout in milliseconds */ -#define SPI_TIMEOUT 5 -/* maximum depth of RX/TX FIFO */ -#define SPI_FIFO_SIZE 8 - -struct ep93xx_spi_slave { - struct spi_slave slave; - - unsigned sspcr0; - unsigned sspcpsr; -}; - -static inline struct ep93xx_spi_slave *to_ep93xx_spi(struct spi_slave *slave) -{ - return container_of(slave, struct ep93xx_spi_slave, slave); -} - -void spi_init() -{ -} - -static inline void ep93xx_spi_write_u8(u16 reg, u8 value) -{ - writel(value, (unsigned int *)(SSPBASE + reg)); -} - -static inline u8 ep93xx_spi_read_u8(u16 reg) -{ - return readl((unsigned int *)(SSPBASE + reg)); -} - -static inline void ep93xx_spi_write_u16(u16 reg, u16 value) -{ - writel(value, (unsigned int *)(SSPBASE + reg)); -} - -static inline u16 ep93xx_spi_read_u16(u16 reg) -{ - return (u16)readl((unsigned int *)(SSPBASE + reg)); -} - -static int ep93xx_spi_init_hw(unsigned int rate, unsigned int mode, - struct ep93xx_spi_slave *slave) -{ - unsigned cpsr, scr; - - if (rate > SSP_MAX_RATE) - rate = SSP_MAX_RATE; - - if (rate < SSP_MIN_RATE) - return -1; - - /* Calculate divisors so that we can get speed according the - * following formula: - * rate = spi_clock_rate / (cpsr * (1 + scr)) - * - * cpsr must be even number and starts from 2, scr can be any number - * between 0 and 255. - */ - for (cpsr = 2; cpsr <= 254; cpsr += 2) { - for (scr = 0; scr <= 255; scr++) { - if ((SSPCLOCK / (cpsr * (scr + 1))) <= rate) { - /* Set CHPA and CPOL, SPI format and 8bit */ - unsigned sspcr0 = (scr << SSPCR0_SCR_SHIFT) | - SSPCR0_FRF_SPI | SSPCR0_DSS_8BIT; - if (mode & SPI_CPHA) - sspcr0 |= SSPCR0_SPH; - if (mode & SPI_CPOL) - sspcr0 |= SSPCR0_SPO; - - slave->sspcr0 = sspcr0; - slave->sspcpsr = cpsr; - return 0; - } - } - } - - return -1; -} - -void spi_set_speed(struct spi_slave *slave, unsigned int hz) -{ - struct ep93xx_spi_slave *as = to_ep93xx_spi(slave); - - unsigned int mode = 0; - if (as->sspcr0 & SSPCR0_SPH) - mode |= SPI_CPHA; - if (as->sspcr0 & SSPCR0_SPO) - mode |= SPI_CPOL; - - ep93xx_spi_init_hw(hz, mode, as); -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct ep93xx_spi_slave *as; - - if (!spi_cs_is_valid(bus, cs)) - return NULL; - - as = spi_alloc_slave(struct ep93xx_spi_slave, bus, cs); - if (!as) - return NULL; - - if (ep93xx_spi_init_hw(max_hz, mode, as)) { - free(as); - return NULL; - } - - return &as->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct ep93xx_spi_slave *as = to_ep93xx_spi(slave); - - free(as); -} - -int spi_claim_bus(struct spi_slave *slave) -{ - struct ep93xx_spi_slave *as = to_ep93xx_spi(slave); - - /* Enable the SPI hardware */ - ep93xx_spi_write_u8(SSPCR1, SSPCR1_SSE); - - - ep93xx_spi_write_u8(SSPCPSR, as->sspcpsr); - ep93xx_spi_write_u16(SSPCR0, as->sspcr0); - - debug("Select CS:%d SSPCPSR=%02x SSPCR0=%04x\n", - slave->cs, as->sspcpsr, as->sspcr0); - return 0; -} - -void spi_release_bus(struct spi_slave *slave) -{ - /* Disable the SPI hardware */ - ep93xx_spi_write_u8(SSPCR1, 0); -} - -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) -{ - unsigned int len_tx; - unsigned int len_rx; - unsigned int len; - u32 status; - const u8 *txp = dout; - u8 *rxp = din; - u8 value; - - debug("spi_xfer: slave %u:%u dout %p din %p bitlen %u\n", - slave->bus, slave->cs, (uint *)dout, (uint *)din, bitlen); - - - if (bitlen == 0) - /* Finish any previously submitted transfers */ - goto out; - - if (bitlen % 8) { - /* Errors always terminate an ongoing transfer */ - flags |= SPI_XFER_END; - goto out; - } - - len = bitlen / 8; - - - if (flags & SPI_XFER_BEGIN) { - /* Empty RX FIFO */ - while ((ep93xx_spi_read_u8(SSPSR) & SSPSR_RNE)) - ep93xx_spi_read_u8(SSPDR); - - spi_cs_activate(slave); - } - - for (len_tx = 0, len_rx = 0; len_rx < len; ) { - status = ep93xx_spi_read_u8(SSPSR); - - if ((len_tx < len) && (status & SSPSR_TNF)) { - if (txp) - value = *txp++; - else - value = 0xff; - - ep93xx_spi_write_u8(SSPDR, value); - len_tx++; - } - - if (status & SSPSR_RNE) { - value = ep93xx_spi_read_u8(SSPDR); - - if (rxp) - *rxp++ = value; - len_rx++; - } - } - -out: - if (flags & SPI_XFER_END) { - /* - * Wait until the transfer is completely done before - * we deactivate CS. - */ - do { - status = ep93xx_spi_read_u8(SSPSR); - } while (status & SSPSR_BSY); - - spi_cs_deactivate(slave); - } - - return 0; -} |