drivers/spi: Add support for TX or RX only modes on DW driver

As for RX only, computing the NDF will be used for EEPROM mode.
Only a way to determine EEPROM mode is missing.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2017-05-15 15:52:15 +02:00 committed by Carles Cufí
commit 57a1f7b4f1
4 changed files with 73 additions and 11 deletions

View file

@ -248,6 +248,26 @@ static int spi_dw_configure(const struct spi_dw_config *info,
return 0;
}
static uint32_t spi_dw_compute_ndf(const struct spi_buf *rx_bufs,
size_t rx_count, u8_t dfs)
{
u32_t len = 0;
for (; rx_count; rx_bufs++, rx_count--) {
if (len > (UINT16_MAX - rx_bufs->len)) {
goto error;
}
len += rx_bufs->len;
}
if (len) {
return (len / dfs) - 1;
}
error:
return UINT32_MAX;
}
static int transceive(struct device *dev,
const struct spi_config *config,
const struct spi_buf_set *tx_bufs,
@ -257,9 +277,9 @@ static int transceive(struct device *dev,
{
const struct spi_dw_config *info = dev->config->config_info;
struct spi_dw_data *spi = dev->driver_data;
u32_t rx_thsld = DW_SPI_RXFTLR_DFLT;
u32_t imask = DW_SPI_IMR_UNMASK;
int ret = 0;
u32_t tmod = DW_SPI_CTRLR0_TMOD_TX_RX;
u32_t reg_data;
int ret;
/* Check status */
if (test_bit_ssienr(info->regs) || test_bit_sr_busy(info->regs)) {
@ -275,6 +295,30 @@ static int transceive(struct device *dev,
goto out;
}
if (!rx_bufs || !rx_bufs->buffers) {
tmod = DW_SPI_CTRLR0_TMOD_TX;
} else if (!tx_bufs || !tx_bufs->buffers) {
tmod = DW_SPI_CTRLR0_TMOD_RX;
}
/* ToDo: add a way to determine EEPROM mode */
if (tmod >= DW_SPI_CTRLR0_TMOD_RX) {
reg_data = spi_dw_compute_ndf(rx_bufs->buffers,
rx_bufs->count, spi->dfs);
if (reg_data == UINT32_MAX) {
ret = -EINVAL;
goto out;
}
write_ctrlr1(reg_data, info->regs);
} else {
write_ctrlr1(0, info->regs);
}
/* Updating TMOD in CTRLR0 register */
write_ctrlr0(read_ctrlr0(info->regs) | tmod, info->regs);
/* Set buffers info */
spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, spi->dfs);
@ -284,20 +328,18 @@ static int transceive(struct device *dev,
write_txftlr(DW_SPI_TXFTLR_DFLT, info->regs);
/* Does Rx thresholds needs to be lower? */
reg_data = DW_SPI_RXFTLR_DFLT;
if (spi->ctx.rx_len && spi->ctx.rx_len < DW_SPI_FIFO_DEPTH) {
rx_thsld = spi->ctx.rx_len - 1;
reg_data = spi->ctx.rx_len - 1;
}
/* Rx Threshold */
write_rxftlr(rx_thsld, info->regs);
if (!rx_bufs) {
/* if there is no rx buffer, keep all rx interrupts masked */
imask &= DW_SPI_IMR_MASK_RX;
}
write_rxftlr(reg_data, info->regs);
/* Enable interrupts */
write_imr(imask, info->regs);
reg_data = !rx_bufs ?
DW_SPI_IMR_UNMASK & DW_SPI_IMR_MASK_RX : DW_SPI_IMR_UNMASK;
write_imr(reg_data, info->regs);
spi_context_cs_control(&spi->ctx, true);

View file

@ -124,6 +124,12 @@ struct spi_dw_data {
#define DW_SPI_CTRLR0_SCPOL BIT(DW_SPI_CTRLR0_SCPOL_BIT)
#define DW_SPI_CTRLR0_SRL BIT(DW_SPI_CTRLR0_SRL_BIT)
#define DW_SPI_CTRLR0_TMOD_SHIFT (8)
#define DW_SPI_CTRLR0_TMOD_TX_RX (0)
#define DW_SPI_CTRLR0_TMOD_TX (1 << DW_SPI_CTRLR0_TMOD_SHIFT)
#define DW_SPI_CTRLR0_TMOD_RX (2 << DW_SPI_CTRLR0_TMOD_SHIFT)
#define DW_SPI_CTRLR0_TMOD_EEPROM (3 << DW_SPI_CTRLR0_TMOD_SHIFT)
#define DW_SPI_CTRLR0_DFS_16(__bpw) ((__bpw) - 1)
#define DW_SPI_CTRLR0_DFS_32(__bpw) (((__bpw) - 1) << 16)

View file

@ -59,6 +59,11 @@ extern "C" {
* *_b function only used for creating proper ser one
*/
DEFINE_MM_REG_READ(ctrlr0_b, DW_SPI_REG_CTRLR0, 16)
static inline u32_t read_ctrlr0(u32_t addr)
{
return read_ctrlr0_b(addr);
}
DEFINE_MM_REG_WRITE(ctrlr0_b, DW_SPI_REG_CTRLR0, 16)
static inline void write_ctrlr0(u32_t data, u32_t addr)
{
@ -66,6 +71,13 @@ static inline void write_ctrlr0(u32_t data, u32_t addr)
data, addr);
}
DEFINE_MM_REG_READ(ctrlr1_b, DW_SPI_REG_CTRLR0, 32)
DEFINE_MM_REG_WRITE(ctrlr1_b, DW_SPI_REG_CTRLR0, 32)
static inline void write_ctrlr1(u32_t data, u32_s addr)
{
write_ctrlr1_b((read_ctrlr1_b(addr) & (data << 16)), addr);
}
DEFINE_MM_REG_READ(ssienr_b, DW_SPI_REG_SSIENR, 8)
DEFINE_MM_REG_WRITE(ssienr_b, DW_SPI_REG_SSIENR, 8)
static inline void write_ser(u32_t data, u32_t addr)

View file

@ -42,6 +42,8 @@ extern "C" {
/* Register helpers */
DEFINE_MM_REG_WRITE(ctrlr0, DW_SPI_REG_CTRLR0, 32)
DEFINE_MM_REG_READ(ctrlr0, DW_SPI_REG_CTRLR0, 32)
DEFINE_MM_REG_WRITE(ctrlr1, DW_SPI_REG_CTRLR1, 16)
DEFINE_MM_REG_WRITE(ser, DW_SPI_REG_SER, 8)
DEFINE_MM_REG_WRITE(txftlr, DW_SPI_REG_TXFTLR, 32)
DEFINE_MM_REG_WRITE(rxftlr, DW_SPI_REG_RXFTLR, 32)