Merge branch 'fix/fsl-dspi' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi into spi-fsl-dspi

This commit is contained in:
Mark Brown
2015-06-09 18:35:46 +01:00
9980 changed files with 418453 additions and 217510 deletions
+2 -3
View File
@@ -159,10 +159,9 @@ config SPI_BUTTERFLY
config SPI_CADENCE
tristate "Cadence SPI controller"
depends on ARM
help
This selects the Cadence SPI controller master driver
used by Xilinx Zynq.
used by Xilinx Zynq and ZynqMP.
config SPI_CLPS711X
tristate "CLPS711X host SPI controller"
@@ -632,7 +631,7 @@ config SPI_DW_PCI
config SPI_DW_MID_DMA
bool "DMA support for DW SPI controller on Intel MID platform"
depends on SPI_DW_PCI && INTEL_MID_DMAC
depends on SPI_DW_PCI && DW_DMAC_PCI
config SPI_DW_MMIO
tristate "Memory-mapped io interface driver for DW SPI core"
+13 -7
View File
@@ -180,11 +180,17 @@
| SPI_BF(name, value))
/* Register access macros */
#ifdef CONFIG_AVR32
#define spi_readl(port, reg) \
__raw_readl((port)->regs + SPI_##reg)
#define spi_writel(port, reg, value) \
__raw_writel((value), (port)->regs + SPI_##reg)
#else
#define spi_readl(port, reg) \
readl_relaxed((port)->regs + SPI_##reg)
#define spi_writel(port, reg, value) \
writel_relaxed((value), (port)->regs + SPI_##reg)
#endif
/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
* cache operations; better heuristics consider wordsize and bitrate.
*/
@@ -764,17 +770,17 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
(unsigned long long)xfer->rx_dma);
}
/* REVISIT: We're waiting for ENDRX before we start the next
/* REVISIT: We're waiting for RXBUFF before we start the next
* transfer because we need to handle some difficult timing
* issues otherwise. If we wait for ENDTX in one transfer and
* then starts waiting for ENDRX in the next, it's difficult
* to tell the difference between the ENDRX interrupt we're
* actually waiting for and the ENDRX interrupt of the
* issues otherwise. If we wait for TXBUFE in one transfer and
* then starts waiting for RXBUFF in the next, it's difficult
* to tell the difference between the RXBUFF interrupt we're
* actually waiting for and the RXBUFF interrupt of the
* previous transfer.
*
* It should be doable, though. Just not now...
*/
spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
spi_writel(as, IER, SPI_BIT(RXBUFF) | SPI_BIT(OVRES));
spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
}
+269 -154
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -44,7 +44,7 @@ static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms)
u32 tmp;
/* SPE bit has to be 0 before we read MSPI STATUS */
deadline = jiffies + BCM53XXSPI_SPE_TIMEOUT_MS * HZ / 1000;
deadline = jiffies + msecs_to_jiffies(BCM53XXSPI_SPE_TIMEOUT_MS);
do {
tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2);
if (!(tmp & B53SPI_MSPI_SPCR2_SPE))
@@ -56,7 +56,7 @@ static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms)
goto spi_timeout;
/* Check status */
deadline = jiffies + timeout_ms * HZ / 1000;
deadline = jiffies + msecs_to_jiffies(timeout_ms);
do {
tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_MSPI_STATUS);
if (tmp & B53SPI_MSPI_MSPI_STATUS_SPIF) {
+1 -2
View File
@@ -559,7 +559,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
struct spi_transfer *previous = NULL;
struct bfin_spi_slave_data *chip = NULL;
unsigned int bits_per_word;
u16 cr, cr_width, dma_width, dma_config;
u16 cr, cr_width = 0, dma_width, dma_config;
u32 tranf_success = 1;
u8 full_duplex = 0;
@@ -648,7 +648,6 @@ static void bfin_spi_pump_transfers(unsigned long data)
} else if (bits_per_word == 8) {
drv_data->n_bytes = bits_per_word/8;
drv_data->len = transfer->len;
cr_width = 0;
drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
}
cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
+14 -4
View File
@@ -49,12 +49,17 @@ bitbang_txrx_be_cpha0(struct spi_device *spi,
{
/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
bool oldbit = !(word & 1);
/* clock starts at inactive polarity */
for (word <<= (32 - bits); likely(bits); bits--) {
/* setup MSB (to slave) on trailing edge */
if ((flags & SPI_MASTER_NO_TX) == 0)
setmosi(spi, word & (1 << 31));
if ((flags & SPI_MASTER_NO_TX) == 0) {
if ((word & (1 << 31)) != oldbit) {
setmosi(spi, word & (1 << 31));
oldbit = word & (1 << 31);
}
}
spidelay(nsecs); /* T(setup) */
setsck(spi, !cpol);
@@ -76,13 +81,18 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,
{
/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
bool oldbit = !(word & (1 << 31));
/* clock starts at inactive polarity */
for (word <<= (32 - bits); likely(bits); bits--) {
/* setup MSB (to slave) on leading edge */
setsck(spi, !cpol);
if ((flags & SPI_MASTER_NO_TX) == 0)
setmosi(spi, word & (1 << 31));
if ((flags & SPI_MASTER_NO_TX) == 0) {
if ((word & (1 << 31)) != oldbit) {
setmosi(spi, word & (1 << 31));
oldbit = word & (1 << 31);
}
}
spidelay(nsecs); /* T(setup) */
setsck(spi, cpol);
+113 -66
View File
@@ -23,29 +23,31 @@
#include "spi-dw.h"
#ifdef CONFIG_SPI_DW_MID_DMA
#include <linux/intel_mid_dma.h>
#include <linux/pci.h>
#include <linux/platform_data/dma-dw.h>
#define RX_BUSY 0
#define TX_BUSY 1
struct mid_dma {
struct intel_mid_dma_slave dmas_tx;
struct intel_mid_dma_slave dmas_rx;
};
static struct dw_dma_slave mid_dma_tx = { .dst_id = 1 };
static struct dw_dma_slave mid_dma_rx = { .src_id = 0 };
static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
{
struct dw_spi *dws = param;
struct dw_dma_slave *s = param;
return dws->dma_dev == chan->device->dev;
if (s->dma_dev != chan->device->dev)
return false;
chan->private = s;
return true;
}
static int mid_spi_dma_init(struct dw_spi *dws)
{
struct mid_dma *dw_dma = dws->dma_priv;
struct pci_dev *dma_dev;
struct intel_mid_dma_slave *rxs, *txs;
struct dw_dma_slave *tx = dws->dma_tx;
struct dw_dma_slave *rx = dws->dma_rx;
dma_cap_mask_t mask;
/*
@@ -56,28 +58,22 @@ static int mid_spi_dma_init(struct dw_spi *dws)
if (!dma_dev)
return -ENODEV;
dws->dma_dev = &dma_dev->dev;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
/* 1. Init rx channel */
dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
rx->dma_dev = &dma_dev->dev;
dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, rx);
if (!dws->rxchan)
goto err_exit;
rxs = &dw_dma->dmas_rx;
rxs->hs_mode = LNW_DMA_HW_HS;
rxs->cfg_mode = LNW_DMA_PER_TO_MEM;
dws->rxchan->private = rxs;
dws->master->dma_rx = dws->rxchan;
/* 2. Init tx channel */
dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, dws);
tx->dma_dev = &dma_dev->dev;
dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, tx);
if (!dws->txchan)
goto free_rxchan;
txs = &dw_dma->dmas_tx;
txs->hs_mode = LNW_DMA_HW_HS;
txs->cfg_mode = LNW_DMA_MEM_TO_PER;
dws->txchan->private = txs;
dws->master->dma_tx = dws->txchan;
dws->dma_inited = 1;
return 0;
@@ -100,6 +96,42 @@ static void mid_spi_dma_exit(struct dw_spi *dws)
dma_release_channel(dws->rxchan);
}
static irqreturn_t dma_transfer(struct dw_spi *dws)
{
u16 irq_status = dw_readl(dws, DW_SPI_ISR);
if (!irq_status)
return IRQ_NONE;
dw_readl(dws, DW_SPI_ICR);
spi_reset_chip(dws);
dev_err(&dws->master->dev, "%s: FIFO overrun/underrun\n", __func__);
dws->master->cur_msg->status = -EIO;
spi_finalize_current_transfer(dws->master);
return IRQ_HANDLED;
}
static bool mid_spi_can_dma(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer)
{
struct dw_spi *dws = spi_master_get_devdata(master);
if (!dws->dma_inited)
return false;
return xfer->len > dws->fifo_len;
}
static enum dma_slave_buswidth convert_dma_width(u32 dma_width) {
if (dma_width == 1)
return DMA_SLAVE_BUSWIDTH_1_BYTE;
else if (dma_width == 2)
return DMA_SLAVE_BUSWIDTH_2_BYTES;
return DMA_SLAVE_BUSWIDTH_UNDEFINED;
}
/*
* dws->dma_chan_busy is set before the dma transfer starts, callback for tx
* channel will clear a corresponding bit.
@@ -108,37 +140,38 @@ static void dw_spi_dma_tx_done(void *arg)
{
struct dw_spi *dws = arg;
if (test_and_clear_bit(TX_BUSY, &dws->dma_chan_busy) & BIT(RX_BUSY))
clear_bit(TX_BUSY, &dws->dma_chan_busy);
if (test_bit(RX_BUSY, &dws->dma_chan_busy))
return;
dw_spi_xfer_done(dws);
spi_finalize_current_transfer(dws->master);
}
static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws)
static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws,
struct spi_transfer *xfer)
{
struct dma_slave_config txconf;
struct dma_async_tx_descriptor *txdesc;
if (!dws->tx_dma)
if (!xfer->tx_buf)
return NULL;
txconf.direction = DMA_MEM_TO_DEV;
txconf.dst_addr = dws->dma_addr;
txconf.dst_maxburst = LNW_DMA_MSIZE_16;
txconf.dst_maxburst = 16;
txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
txconf.dst_addr_width = dws->dma_width;
txconf.dst_addr_width = convert_dma_width(dws->dma_width);
txconf.device_fc = false;
dmaengine_slave_config(dws->txchan, &txconf);
memset(&dws->tx_sgl, 0, sizeof(dws->tx_sgl));
dws->tx_sgl.dma_address = dws->tx_dma;
dws->tx_sgl.length = dws->len;
txdesc = dmaengine_prep_slave_sg(dws->txchan,
&dws->tx_sgl,
1,
xfer->tx_sg.sgl,
xfer->tx_sg.nents,
DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!txdesc)
return NULL;
txdesc->callback = dw_spi_dma_tx_done;
txdesc->callback_param = dws;
@@ -153,74 +186,74 @@ static void dw_spi_dma_rx_done(void *arg)
{
struct dw_spi *dws = arg;
if (test_and_clear_bit(RX_BUSY, &dws->dma_chan_busy) & BIT(TX_BUSY))
clear_bit(RX_BUSY, &dws->dma_chan_busy);
if (test_bit(TX_BUSY, &dws->dma_chan_busy))
return;
dw_spi_xfer_done(dws);
spi_finalize_current_transfer(dws->master);
}
static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws)
static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws,
struct spi_transfer *xfer)
{
struct dma_slave_config rxconf;
struct dma_async_tx_descriptor *rxdesc;
if (!dws->rx_dma)
if (!xfer->rx_buf)
return NULL;
rxconf.direction = DMA_DEV_TO_MEM;
rxconf.src_addr = dws->dma_addr;
rxconf.src_maxburst = LNW_DMA_MSIZE_16;
rxconf.src_maxburst = 16;
rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
rxconf.src_addr_width = dws->dma_width;
rxconf.src_addr_width = convert_dma_width(dws->dma_width);
rxconf.device_fc = false;
dmaengine_slave_config(dws->rxchan, &rxconf);
memset(&dws->rx_sgl, 0, sizeof(dws->rx_sgl));
dws->rx_sgl.dma_address = dws->rx_dma;
dws->rx_sgl.length = dws->len;
rxdesc = dmaengine_prep_slave_sg(dws->rxchan,
&dws->rx_sgl,
1,
xfer->rx_sg.sgl,
xfer->rx_sg.nents,
DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!rxdesc)
return NULL;
rxdesc->callback = dw_spi_dma_rx_done;
rxdesc->callback_param = dws;
return rxdesc;
}
static void dw_spi_dma_setup(struct dw_spi *dws)
static int mid_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer)
{
u16 dma_ctrl = 0;
spi_enable_chip(dws, 0);
dw_writel(dws, DW_SPI_DMARDLR, 0xf);
dw_writel(dws, DW_SPI_DMATDLR, 0x10);
dw_writew(dws, DW_SPI_DMARDLR, 0xf);
dw_writew(dws, DW_SPI_DMATDLR, 0x10);
if (dws->tx_dma)
if (xfer->tx_buf)
dma_ctrl |= SPI_DMA_TDMAE;
if (dws->rx_dma)
if (xfer->rx_buf)
dma_ctrl |= SPI_DMA_RDMAE;
dw_writew(dws, DW_SPI_DMACR, dma_ctrl);
dw_writel(dws, DW_SPI_DMACR, dma_ctrl);
spi_enable_chip(dws, 1);
/* Set the interrupt mask */
spi_umask_intr(dws, SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI);
dws->transfer_handler = dma_transfer;
return 0;
}
static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
static int mid_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer)
{
struct dma_async_tx_descriptor *txdesc, *rxdesc;
/* 1. setup DMA related registers */
if (cs_change)
dw_spi_dma_setup(dws);
/* Prepare the TX dma transfer */
txdesc = dw_spi_dma_prepare_tx(dws, xfer);
/* 2. Prepare the TX dma transfer */
txdesc = dw_spi_dma_prepare_tx(dws);
/* 3. Prepare the RX dma transfer */
rxdesc = dw_spi_dma_prepare_rx(dws);
/* Prepare the RX dma transfer */
rxdesc = dw_spi_dma_prepare_rx(dws, xfer);
/* rx must be started before tx due to spi instinct */
if (rxdesc) {
@@ -238,10 +271,25 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, int cs_change)
return 0;
}
static void mid_spi_dma_stop(struct dw_spi *dws)
{
if (test_bit(TX_BUSY, &dws->dma_chan_busy)) {
dmaengine_terminate_all(dws->txchan);
clear_bit(TX_BUSY, &dws->dma_chan_busy);
}
if (test_bit(RX_BUSY, &dws->dma_chan_busy)) {
dmaengine_terminate_all(dws->rxchan);
clear_bit(RX_BUSY, &dws->dma_chan_busy);
}
}
static struct dw_spi_dma_ops mid_dma_ops = {
.dma_init = mid_spi_dma_init,
.dma_exit = mid_spi_dma_exit,
.dma_setup = mid_spi_dma_setup,
.can_dma = mid_spi_can_dma,
.dma_transfer = mid_spi_dma_transfer,
.dma_stop = mid_spi_dma_stop,
};
#endif
@@ -274,9 +322,8 @@ int dw_spi_mid_init(struct dw_spi *dws)
iounmap(clk_reg);
#ifdef CONFIG_SPI_DW_MID_DMA
dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL);
if (!dws->dma_priv)
return -ENOMEM;
dws->dma_tx = &mid_dma_tx;
dws->dma_rx = &mid_dma_rx;
dws->dma_ops = &mid_dma_ops;
#endif
return 0;
+2 -2
View File
@@ -36,13 +36,13 @@ struct spi_pci_desc {
static struct spi_pci_desc spi_pci_mid_desc_1 = {
.setup = dw_spi_mid_init,
.num_cs = 32,
.num_cs = 5,
.bus_num = 0,
};
static struct spi_pci_desc spi_pci_mid_desc_2 = {
.setup = dw_spi_mid_init,
.num_cs = 4,
.num_cs = 2,
.bus_num = 1,
};
+94 -216
View File
File diff suppressed because it is too large Load Diff
+21 -49
View File
@@ -91,12 +91,15 @@ struct dw_spi;
struct dw_spi_dma_ops {
int (*dma_init)(struct dw_spi *dws);
void (*dma_exit)(struct dw_spi *dws);
int (*dma_transfer)(struct dw_spi *dws, int cs_change);
int (*dma_setup)(struct dw_spi *dws, struct spi_transfer *xfer);
bool (*can_dma)(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer);
int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer);
void (*dma_stop)(struct dw_spi *dws);
};
struct dw_spi {
struct spi_master *master;
struct spi_device *cur_dev;
enum dw_ssi_type type;
char name[16];
@@ -109,41 +112,26 @@ struct dw_spi {
u16 bus_num;
u16 num_cs; /* supported slave numbers */
/* Message Transfer pump */
struct tasklet_struct pump_transfers;
/* Current message transfer state info */
struct spi_message *cur_msg;
struct spi_transfer *cur_transfer;
struct chip_data *cur_chip;
struct chip_data *prev_chip;
size_t len;
void *tx;
void *tx_end;
void *rx;
void *rx_end;
int dma_mapped;
dma_addr_t rx_dma;
dma_addr_t tx_dma;
size_t rx_map_len;
size_t tx_map_len;
u8 n_bytes; /* current is a 1/2 bytes op */
u8 max_bits_per_word; /* maxim is 16b */
u32 dma_width;
irqreturn_t (*transfer_handler)(struct dw_spi *dws);
void (*cs_control)(u32 command);
/* Dma info */
/* DMA info */
int dma_inited;
struct dma_chan *txchan;
struct scatterlist tx_sgl;
struct dma_chan *rxchan;
struct scatterlist rx_sgl;
unsigned long dma_chan_busy;
struct device *dma_dev;
dma_addr_t dma_addr; /* phy address of the Data register */
struct dw_spi_dma_ops *dma_ops;
void *dma_priv; /* platform relate info */
void *dma_tx;
void *dma_rx;
/* Bus interface info */
void *priv;
@@ -162,16 +150,6 @@ static inline void dw_writel(struct dw_spi *dws, u32 offset, u32 val)
__raw_writel(val, dws->regs + offset);
}
static inline u16 dw_readw(struct dw_spi *dws, u32 offset)
{
return __raw_readw(dws->regs + offset);
}
static inline void dw_writew(struct dw_spi *dws, u32 offset, u16 val)
{
__raw_writew(val, dws->regs + offset);
}
static inline void spi_enable_chip(struct dw_spi *dws, int enable)
{
dw_writel(dws, DW_SPI_SSIENR, (enable ? 1 : 0));
@@ -182,22 +160,6 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div)
dw_writel(dws, DW_SPI_BAUDR, div);
}
static inline void spi_chip_sel(struct dw_spi *dws, struct spi_device *spi,
int active)
{
u16 cs = spi->chip_select;
int gpio_val = active ? (spi->mode & SPI_CS_HIGH) :
!(spi->mode & SPI_CS_HIGH);
if (dws->cs_control)
dws->cs_control(active);
if (gpio_is_valid(spi->cs_gpio))
gpio_set_value(spi->cs_gpio, gpio_val);
if (active)
dw_writel(dws, DW_SPI_SER, 1 << cs);
}
/* Disable IRQ bits */
static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
{
@@ -216,16 +178,27 @@ static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
dw_writel(dws, DW_SPI_IMR, new_mask);
}
/*
* This does disable the SPI controller, interrupts, and re-enable the
* controller back. Transmit and receive FIFO buffers are cleared when the
* device is disabled.
*/
static inline void spi_reset_chip(struct dw_spi *dws)
{
spi_enable_chip(dws, 0);
spi_mask_intr(dws, 0xff);
spi_enable_chip(dws, 1);
}
/*
* Each SPI slave device to work with dw_api controller should
* has such a structure claiming its working mode (PIO/DMA etc),
* has such a structure claiming its working mode (poll or PIO/DMA),
* which can be save in the "controller_data" member of the
* struct spi_device.
*/
struct dw_spi_chip {
u8 poll_mode; /* 1 for controller polling mode */
u8 type; /* SPI/SSP/MicroWire */
u8 enable_dma;
void (*cs_control)(u32 command);
};
@@ -233,7 +206,6 @@ extern int dw_spi_add_host(struct device *dev, struct dw_spi *dws);
extern void dw_spi_remove_host(struct dw_spi *dws);
extern int dw_spi_suspend_host(struct dw_spi *dws);
extern int dw_spi_resume_host(struct dw_spi *dws);
extern void dw_spi_xfer_done(struct dw_spi *dws);
/* platform related setup */
extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
+83 -18
View File
@@ -20,6 +20,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/math64.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -29,6 +30,7 @@
#include <linux/sched.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/time.h>
#define DRIVER_NAME "fsl-dspi"
@@ -51,7 +53,7 @@
#define SPI_CTAR_CPOL(x) ((x) << 26)
#define SPI_CTAR_CPHA(x) ((x) << 25)
#define SPI_CTAR_LSBFE(x) ((x) << 24)
#define SPI_CTAR_PCSSCR(x) (((x) & 0x00000003) << 22)
#define SPI_CTAR_PCSSCK(x) (((x) & 0x00000003) << 22)
#define SPI_CTAR_PASC(x) (((x) & 0x00000003) << 20)
#define SPI_CTAR_PDT(x) (((x) & 0x00000003) << 18)
#define SPI_CTAR_PBR(x) (((x) & 0x00000003) << 16)
@@ -59,6 +61,7 @@
#define SPI_CTAR_ASC(x) (((x) & 0x0000000f) << 8)
#define SPI_CTAR_DT(x) (((x) & 0x0000000f) << 4)
#define SPI_CTAR_BR(x) ((x) & 0x0000000f)
#define SPI_CTAR_SCALE_BITS 0xf
#define SPI_CTAR0_SLAVE 0x0c
@@ -148,23 +151,66 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
16, 32, 64, 128,
256, 512, 1024, 2048,
4096, 8192, 16384, 32768 };
int temp, i = 0, j = 0;
int scale_needed, scale, minscale = INT_MAX;
int i, j;
temp = clkrate / 2 / speed_hz;
scale_needed = clkrate / speed_hz;
if (clkrate % speed_hz)
scale_needed++;
for (i = 0; i < ARRAY_SIZE(pbr_tbl); i++)
for (j = 0; j < ARRAY_SIZE(brs); j++) {
if (pbr_tbl[i] * brs[j] >= temp) {
*pbr = i;
*br = j;
return;
for (i = 0; i < ARRAY_SIZE(brs); i++)
for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) {
scale = brs[i] * pbr_tbl[j];
if (scale >= scale_needed) {
if (scale < minscale) {
minscale = scale;
*br = i;
*pbr = j;
}
break;
}
}
pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\
,we use the max prescaler value.\n", speed_hz, clkrate);
*pbr = ARRAY_SIZE(pbr_tbl) - 1;
*br = ARRAY_SIZE(brs) - 1;
if (minscale == INT_MAX) {
pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld, we use the max prescaler value.\n",
speed_hz, clkrate);
*pbr = ARRAY_SIZE(pbr_tbl) - 1;
*br = ARRAY_SIZE(brs) - 1;
}
}
static void ns_delay_scale(char *psc, char *sc, int delay_ns,
unsigned long clkrate)
{
int pscale_tbl[4] = {1, 3, 5, 7};
int scale_needed, scale, minscale = INT_MAX;
int i, j;
u32 remainder;
scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC,
&remainder);
if (remainder)
scale_needed++;
for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++)
for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) {
scale = pscale_tbl[i] * (2 << j);
if (scale >= scale_needed) {
if (scale < minscale) {
minscale = scale;
*psc = i;
*sc = j;
}
break;
}
}
if (minscale == INT_MAX) {
pr_warn("Cannot find correct scale values for %dns delay at clkrate %ld, using max prescaler value",
delay_ns, clkrate);
*psc = ARRAY_SIZE(pscale_tbl) - 1;
*sc = SPI_CTAR_SCALE_BITS;
}
}
static int dspi_transfer_write(struct fsl_dspi *dspi)
@@ -295,10 +341,10 @@ static int dspi_transfer_one_message(struct spi_master *master,
dspi->cur_msg = message;
dspi->cur_chip = spi_get_ctldata(spi);
dspi->cs = spi->chip_select;
dspi->cs_change = 0;
if (dspi->cur_transfer->transfer_list.next
== &dspi->cur_msg->transfers)
transfer->cs_change = 1;
dspi->cs_change = transfer->cs_change;
dspi->cs_change = 1;
dspi->void_write_data = dspi->cur_chip->void_write_data;
dspi->dataflags = 0;
@@ -345,7 +391,10 @@ static int dspi_setup(struct spi_device *spi)
{
struct chip_data *chip;
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
unsigned char br = 0, pbr = 0, fmsz = 0;
u32 cs_sck_delay = 0, sck_cs_delay = 0;
unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0;
unsigned char pasc = 0, asc = 0, fmsz = 0;
unsigned long clkrate;
if ((spi->bits_per_word >= 4) && (spi->bits_per_word <= 16)) {
fmsz = spi->bits_per_word - 1;
@@ -362,18 +411,34 @@ static int dspi_setup(struct spi_device *spi)
return -ENOMEM;
}
of_property_read_u32(spi->dev.of_node, "fsl,spi-cs-sck-delay",
&cs_sck_delay);
of_property_read_u32(spi->dev.of_node, "fsl,spi-sck-cs-delay",
&sck_cs_delay);
chip->mcr_val = SPI_MCR_MASTER | SPI_MCR_PCSIS |
SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
chip->void_write_data = 0;
hz_to_spi_baud(&pbr, &br,
spi->max_speed_hz, clk_get_rate(dspi->clk));
clkrate = clk_get_rate(dspi->clk);
hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate);
/* Set PCS to SCK delay scale values */
ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate);
/* Set After SCK delay scale values */
ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate);
chip->ctar_val = SPI_CTAR_FMSZ(fmsz)
| SPI_CTAR_CPOL(spi->mode & SPI_CPOL ? 1 : 0)
| SPI_CTAR_CPHA(spi->mode & SPI_CPHA ? 1 : 0)
| SPI_CTAR_LSBFE(spi->mode & SPI_LSB_FIRST ? 1 : 0)
| SPI_CTAR_PCSSCK(pcssck)
| SPI_CTAR_CSSCK(cssck)
| SPI_CTAR_PASC(pasc)
| SPI_CTAR_ASC(asc)
| SPI_CTAR_PBR(pbr)
| SPI_CTAR_BR(br);
+110 -86
View File
@@ -12,6 +12,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
@@ -122,36 +123,31 @@ static inline void spfi_start(struct img_spfi *spfi)
spfi_writel(spfi, val, SPFI_CONTROL);
}
static inline void spfi_stop(struct img_spfi *spfi)
{
u32 val;
val = spfi_readl(spfi, SPFI_CONTROL);
val &= ~SPFI_CONTROL_SPFI_EN;
spfi_writel(spfi, val, SPFI_CONTROL);
}
static inline void spfi_reset(struct img_spfi *spfi)
{
spfi_writel(spfi, SPFI_CONTROL_SOFT_RESET, SPFI_CONTROL);
udelay(1);
spfi_writel(spfi, 0, SPFI_CONTROL);
}
static void spfi_flush_tx_fifo(struct img_spfi *spfi)
static int spfi_wait_all_done(struct img_spfi *spfi)
{
unsigned long timeout = jiffies + msecs_to_jiffies(10);
unsigned long timeout = jiffies + msecs_to_jiffies(50);
spfi_writel(spfi, SPFI_INTERRUPT_SDE, SPFI_INTERRUPT_CLEAR);
while (time_before(jiffies, timeout)) {
if (spfi_readl(spfi, SPFI_INTERRUPT_STATUS) &
SPFI_INTERRUPT_SDE)
return;
u32 status = spfi_readl(spfi, SPFI_INTERRUPT_STATUS);
if (status & SPFI_INTERRUPT_ALLDONETRIG) {
spfi_writel(spfi, SPFI_INTERRUPT_ALLDONETRIG,
SPFI_INTERRUPT_CLEAR);
return 0;
}
cpu_relax();
}
dev_err(spfi->dev, "Timed out waiting for FIFO to drain\n");
dev_err(spfi->dev, "Timed out waiting for transaction to complete\n");
spfi_reset(spfi);
return -ETIMEDOUT;
}
static unsigned int spfi_pio_write32(struct img_spfi *spfi, const u32 *buf,
@@ -237,6 +233,7 @@ static int img_spfi_start_pio(struct spi_master *master,
const void *tx_buf = xfer->tx_buf;
void *rx_buf = xfer->rx_buf;
unsigned long timeout;
int ret;
if (tx_buf)
tx_bytes = xfer->len;
@@ -269,16 +266,15 @@ static int img_spfi_start_pio(struct spi_master *master,
cpu_relax();
}
ret = spfi_wait_all_done(spfi);
if (ret < 0)
return ret;
if (rx_bytes > 0 || tx_bytes > 0) {
dev_err(spfi->dev, "PIO transfer timed out\n");
spfi_reset(spfi);
return -ETIMEDOUT;
}
if (tx_buf)
spfi_flush_tx_fifo(spfi);
spfi_stop(spfi);
return 0;
}
@@ -287,14 +283,12 @@ static void img_spfi_dma_rx_cb(void *data)
struct img_spfi *spfi = data;
unsigned long flags;
spfi_wait_all_done(spfi);
spin_lock_irqsave(&spfi->lock, flags);
spfi->rx_dma_busy = false;
if (!spfi->tx_dma_busy) {
spfi_stop(spfi);
if (!spfi->tx_dma_busy)
spi_finalize_current_transfer(spfi->master);
}
spin_unlock_irqrestore(&spfi->lock, flags);
}
@@ -303,16 +297,12 @@ static void img_spfi_dma_tx_cb(void *data)
struct img_spfi *spfi = data;
unsigned long flags;
spfi_flush_tx_fifo(spfi);
spfi_wait_all_done(spfi);
spin_lock_irqsave(&spfi->lock, flags);
spfi->tx_dma_busy = false;
if (!spfi->rx_dma_busy) {
spfi_stop(spfi);
if (!spfi->rx_dma_busy)
spi_finalize_current_transfer(spfi->master);
}
spin_unlock_irqrestore(&spfi->lock, flags);
}
@@ -397,6 +387,75 @@ stop_dma:
return -EIO;
}
static void img_spfi_handle_err(struct spi_master *master,
struct spi_message *msg)
{
struct img_spfi *spfi = spi_master_get_devdata(master);
unsigned long flags;
/*
* Stop all DMA and reset the controller if the previous transaction
* timed-out and never completed it's DMA.
*/
spin_lock_irqsave(&spfi->lock, flags);
if (spfi->tx_dma_busy || spfi->rx_dma_busy) {
spfi->tx_dma_busy = false;
spfi->rx_dma_busy = false;
dmaengine_terminate_all(spfi->tx_ch);
dmaengine_terminate_all(spfi->rx_ch);
}
spin_unlock_irqrestore(&spfi->lock, flags);
}
static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg)
{
struct img_spfi *spfi = spi_master_get_devdata(master);
u32 val;
val = spfi_readl(spfi, SPFI_PORT_STATE);
if (msg->spi->mode & SPI_CPHA)
val |= SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select);
else
val &= ~SPFI_PORT_STATE_CK_PHASE(msg->spi->chip_select);
if (msg->spi->mode & SPI_CPOL)
val |= SPFI_PORT_STATE_CK_POL(msg->spi->chip_select);
else
val &= ~SPFI_PORT_STATE_CK_POL(msg->spi->chip_select);
spfi_writel(spfi, val, SPFI_PORT_STATE);
return 0;
}
static int img_spfi_unprepare(struct spi_master *master,
struct spi_message *msg)
{
struct img_spfi *spfi = spi_master_get_devdata(master);
spfi_reset(spfi);
return 0;
}
static int img_spfi_setup(struct spi_device *spi)
{
int ret;
ret = gpio_request_one(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
dev_name(&spi->dev));
if (ret)
dev_err(&spi->dev, "can't request chipselect gpio %d\n",
spi->cs_gpio);
return ret;
}
static void img_spfi_cleanup(struct spi_device *spi)
{
gpio_free(spi->cs_gpio);
}
static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer)
{
@@ -405,10 +464,10 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
/*
* output = spfi_clk * (BITCLK / 512), where BITCLK must be a
* power of 2 up to 256 (where 255 == 256 since BITCLK is 8 bits)
* power of 2 up to 128
*/
div = DIV_ROUND_UP(master->max_speed_hz, xfer->speed_hz);
div = clamp(512 / (1 << get_count_order(div)), 1, 255);
div = DIV_ROUND_UP(clk_get_rate(spfi->spfi_clk), xfer->speed_hz);
div = clamp(512 / (1 << get_count_order(div)), 1, 128);
val = spfi_readl(spfi, SPFI_DEVICE_PARAMETER(spi->chip_select));
val &= ~(SPFI_DEVICE_PARAMETER_BITCLK_MASK <<
@@ -416,6 +475,9 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
val |= div << SPFI_DEVICE_PARAMETER_BITCLK_SHIFT;
spfi_writel(spfi, val, SPFI_DEVICE_PARAMETER(spi->chip_select));
spfi_writel(spfi, xfer->len << SPFI_TRANSACTION_TSIZE_SHIFT,
SPFI_TRANSACTION);
val = spfi_readl(spfi, SPFI_CONTROL);
val &= ~(SPFI_CONTROL_SEND_DMA | SPFI_CONTROL_GET_DMA);
if (xfer->tx_buf)
@@ -429,25 +491,7 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi,
else if (xfer->tx_nbits == SPI_NBITS_QUAD &&
xfer->rx_nbits == SPI_NBITS_QUAD)
val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT;
val &= ~SPFI_CONTROL_CONTINUE;
if (!xfer->cs_change && !list_is_last(&xfer->transfer_list,
&master->cur_msg->transfers))
val |= SPFI_CONTROL_CONTINUE;
spfi_writel(spfi, val, SPFI_CONTROL);
val = spfi_readl(spfi, SPFI_PORT_STATE);
if (spi->mode & SPI_CPHA)
val |= SPFI_PORT_STATE_CK_PHASE(spi->chip_select);
else
val &= ~SPFI_PORT_STATE_CK_PHASE(spi->chip_select);
if (spi->mode & SPI_CPOL)
val |= SPFI_PORT_STATE_CK_POL(spi->chip_select);
else
val &= ~SPFI_PORT_STATE_CK_POL(spi->chip_select);
spfi_writel(spfi, val, SPFI_PORT_STATE);
spfi_writel(spfi, xfer->len << SPFI_TRANSACTION_TSIZE_SHIFT,
SPFI_TRANSACTION);
}
static int img_spfi_transfer_one(struct spi_master *master,
@@ -455,25 +499,13 @@ static int img_spfi_transfer_one(struct spi_master *master,
struct spi_transfer *xfer)
{
struct img_spfi *spfi = spi_master_get_devdata(spi->master);
bool dma_reset = false;
unsigned long flags;
int ret;
/*
* Stop all DMA and reset the controller if the previous transaction
* timed-out and never completed it's DMA.
*/
spin_lock_irqsave(&spfi->lock, flags);
if (spfi->tx_dma_busy || spfi->rx_dma_busy) {
dev_err(spfi->dev, "SPI DMA still busy\n");
dma_reset = true;
}
spin_unlock_irqrestore(&spfi->lock, flags);
if (dma_reset) {
dmaengine_terminate_all(spfi->tx_ch);
dmaengine_terminate_all(spfi->rx_ch);
spfi_reset(spfi);
if (xfer->len > SPFI_TRANSACTION_TSIZE_MASK) {
dev_err(spfi->dev,
"Transfer length (%d) is greater than the max supported (%d)",
xfer->len, SPFI_TRANSACTION_TSIZE_MASK);
return -EINVAL;
}
img_spfi_config(master, spi, xfer);
@@ -485,17 +517,6 @@ static int img_spfi_transfer_one(struct spi_master *master,
return ret;
}
static void img_spfi_set_cs(struct spi_device *spi, bool enable)
{
struct img_spfi *spfi = spi_master_get_devdata(spi->master);
u32 val;
val = spfi_readl(spfi, SPFI_PORT_STATE);
val &= ~(SPFI_PORT_STATE_DEV_SEL_MASK << SPFI_PORT_STATE_DEV_SEL_SHIFT);
val |= spi->chip_select << SPFI_PORT_STATE_DEV_SEL_SHIFT;
spfi_writel(spfi, val, SPFI_PORT_STATE);
}
static bool img_spfi_can_dma(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer)
{
@@ -584,14 +605,17 @@ static int img_spfi_probe(struct platform_device *pdev)
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL;
if (of_property_read_bool(spfi->dev->of_node, "img,supports-quad-mode"))
master->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD;
master->num_chipselect = 5;
master->dev.of_node = pdev->dev.of_node;
master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(8);
master->max_speed_hz = clk_get_rate(spfi->spfi_clk);
master->min_speed_hz = master->max_speed_hz / 512;
master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4;
master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512;
master->set_cs = img_spfi_set_cs;
master->setup = img_spfi_setup;
master->cleanup = img_spfi_cleanup;
master->transfer_one = img_spfi_transfer_one;
master->prepare_message = img_spfi_prepare;
master->unprepare_message = img_spfi_unprepare;
master->handle_err = img_spfi_handle_err;
spfi->tx_ch = dma_request_slave_channel(spfi->dev, "tx");
spfi->rx_ch = dma_request_slave_channel(spfi->dev, "rx");
+4 -4
View File
@@ -370,8 +370,6 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
if (spi_imx->dma_is_inited) {
dma = readl(spi_imx->base + MX51_ECSPI_DMA);
spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2;
spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2;
spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
@@ -868,6 +866,8 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
master->max_dma_len = MAX_SDMA_BD_BYTES;
spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
SPI_MASTER_MUST_TX;
spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2;
spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2;
spi_imx->dma_is_inited = 1;
return 0;
@@ -903,7 +903,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
if (tx) {
desc_tx = dmaengine_prep_slave_sg(master->dma_tx,
tx->sgl, tx->nents, DMA_TO_DEVICE,
tx->sgl, tx->nents, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_tx)
goto no_dma;
@@ -915,7 +915,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
if (rx) {
desc_rx = dmaengine_prep_slave_sg(master->dma_rx,
rx->sgl, rx->nents, DMA_FROM_DEVICE,
rx->sgl, rx->nents, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc_rx)
goto no_dma;
+1 -1
View File
@@ -588,7 +588,7 @@ static int mpc512x_psc_spi_of_remove(struct platform_device *op)
return mpc512x_psc_spi_do_remove(&op->dev);
}
static struct of_device_id mpc512x_psc_spi_of_match[] = {
static const struct of_device_id mpc512x_psc_spi_of_match[] = {
{ .compatible = "fsl,mpc5121-psc-spi", },
{},
};
+1 -1
View File
@@ -238,7 +238,7 @@ static int octeon_spi_remove(struct platform_device *pdev)
return 0;
}
static struct of_device_id octeon_spi_match[] = {
static const struct of_device_id octeon_spi_match[] = {
{ .compatible = "cavium,octeon-3010-spi", },
{},
};
+77 -24
View File
@@ -24,6 +24,7 @@
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
@@ -294,16 +295,6 @@ static int omap1_spi100k_setup(struct spi_device *spi)
return ret;
}
static int omap1_spi100k_prepare_hardware(struct spi_master *master)
{
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
clk_prepare_enable(spi100k->ick);
clk_prepare_enable(spi100k->fck);
return 0;
}
static int omap1_spi100k_transfer_one_message(struct spi_master *master,
struct spi_message *m)
{
@@ -372,16 +363,6 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master,
return status;
}
static int omap1_spi100k_unprepare_hardware(struct spi_master *master)
{
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
clk_disable_unprepare(spi100k->ick);
clk_disable_unprepare(spi100k->fck);
return 0;
}
static int omap1_spi100k_probe(struct platform_device *pdev)
{
struct spi_master *master;
@@ -402,14 +383,12 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
master->setup = omap1_spi100k_setup;
master->transfer_one_message = omap1_spi100k_transfer_one_message;
master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware;
master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware;
master->cleanup = NULL;
master->num_chipselect = 2;
master->mode_bits = MODEBITS;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16);
master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ;
master->auto_runtime_pm = true;
spi100k = spi_master_get_devdata(master);
@@ -434,22 +413,96 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
goto err;
}
status = clk_prepare_enable(spi100k->ick);
if (status != 0) {
dev_err(&pdev->dev, "failed to enable ick: %d\n", status);
goto err;
}
status = clk_prepare_enable(spi100k->fck);
if (status != 0) {
dev_err(&pdev->dev, "failed to enable fck: %d\n", status);
goto err_ick;
}
pm_runtime_enable(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
status = devm_spi_register_master(&pdev->dev, master);
if (status < 0)
goto err;
goto err_fck;
return status;
err_fck:
clk_disable_unprepare(spi100k->fck);
err_ick:
clk_disable_unprepare(spi100k->ick);
err:
spi_master_put(master);
return status;
}
static int omap1_spi100k_remove(struct platform_device *pdev)
{
struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(spi100k->fck);
clk_disable_unprepare(spi100k->ick);
return 0;
}
#ifdef CONFIG_PM
static int omap1_spi100k_runtime_suspend(struct device *dev)
{
struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
clk_disable_unprepare(spi100k->ick);
clk_disable_unprepare(spi100k->fck);
return 0;
}
static int omap1_spi100k_runtime_resume(struct device *dev)
{
struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
struct omap1_spi100k *spi100k = spi_master_get_devdata(master);
int ret;
ret = clk_prepare_enable(spi100k->ick);
if (ret != 0) {
dev_err(dev, "Failed to enable ick: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(spi100k->fck);
if (ret != 0) {
dev_err(dev, "Failed to enable fck: %d\n", ret);
clk_disable_unprepare(spi100k->ick);
return ret;
}
return 0;
}
#endif
static const struct dev_pm_ops omap1_spi100k_pm = {
SET_RUNTIME_PM_OPS(omap1_spi100k_runtime_suspend,
omap1_spi100k_runtime_resume, NULL)
};
static struct platform_driver omap1_spi100k_driver = {
.driver = {
.name = "omap1_spi100k",
.pm = &omap1_spi100k_pm,
},
.probe = omap1_spi100k_probe,
.remove = omap1_spi100k_remove,
};
module_platform_driver(omap1_spi100k_driver);
-1
View File
@@ -44,7 +44,6 @@
#include <linux/module.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
+8 -8
View File
@@ -285,7 +285,12 @@
*/
#define DEFAULT_SSP_REG_IMSC 0x0UL
#define DISABLE_ALL_INTERRUPTS DEFAULT_SSP_REG_IMSC
#define ENABLE_ALL_INTERRUPTS (~DEFAULT_SSP_REG_IMSC)
#define ENABLE_ALL_INTERRUPTS ( \
SSP_IMSC_MASK_RORIM | \
SSP_IMSC_MASK_RTIM | \
SSP_IMSC_MASK_RXIM | \
SSP_IMSC_MASK_TXIM \
)
#define CLEAR_ALL_INTERRUPTS 0x3
@@ -534,12 +539,12 @@ static void giveback(struct pl022 *pl022)
pl022->cur_msg = NULL;
pl022->cur_transfer = NULL;
pl022->cur_chip = NULL;
spi_finalize_current_message(pl022->master);
/* disable the SPI/SSP operation */
writew((readw(SSP_CR1(pl022->virtbase)) &
(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
spi_finalize_current_message(pl022->master);
}
/**
@@ -1251,7 +1256,6 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
struct pl022 *pl022 = dev_id;
struct spi_message *msg = pl022->cur_msg;
u16 irq_status = 0;
u16 flag = 0;
if (unlikely(!msg)) {
dev_err(&pl022->adev->dev,
@@ -1280,9 +1284,6 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
dev_err(&pl022->adev->dev,
"RXFIFO is full\n");
if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
dev_err(&pl022->adev->dev,
"TXFIFO is full\n");
/*
* Disable and clear interrupts, disable SSP,
@@ -1303,8 +1304,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
readwriter(pl022);
if ((pl022->tx == pl022->tx_end) && (flag == 0)) {
flag = 1;
if (pl022->tx == pl022->tx_end) {
/* Disable Transmit interrupt, enable receive interrupt */
writew((readw(SSP_IMSC(pl022->virtbase)) &
~SSP_IMSC_MASK_TXIM) | SSP_IMSC_MASK_RXIM,
+121 -71
View File
@@ -20,6 +20,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/spi/pxa2xx_spi.h>
#include <linux/spi/spi.h>
@@ -30,10 +31,6 @@
#include <linux/pm_runtime.h>
#include <linux/acpi.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/delay.h>
#include "spi-pxa2xx.h"
MODULE_AUTHOR("Stephen Street");
@@ -67,54 +64,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define LPSS_TX_LOTHRESH_DFLT 160
#define LPSS_TX_HITHRESH_DFLT 224
struct quark_spi_rate {
u32 bitrate;
u32 dds_clk_rate;
u32 clk_div;
};
/*
* 'rate', 'dds', 'clk_div' lookup table, which is defined in
* the Quark SPI datasheet.
*/
static const struct quark_spi_rate quark_spi_rate_table[] = {
/* bitrate, dds_clk_rate, clk_div */
{50000000, 0x800000, 0},
{40000000, 0x666666, 0},
{25000000, 0x400000, 0},
{20000000, 0x666666, 1},
{16667000, 0x800000, 2},
{13333000, 0x666666, 2},
{12500000, 0x200000, 0},
{10000000, 0x800000, 4},
{8000000, 0x666666, 4},
{6250000, 0x400000, 3},
{5000000, 0x400000, 4},
{4000000, 0x666666, 9},
{3125000, 0x80000, 0},
{2500000, 0x400000, 9},
{2000000, 0x666666, 19},
{1563000, 0x40000, 0},
{1250000, 0x200000, 9},
{1000000, 0x400000, 24},
{800000, 0x666666, 49},
{781250, 0x20000, 0},
{625000, 0x200000, 19},
{500000, 0x400000, 49},
{400000, 0x666666, 99},
{390625, 0x10000, 0},
{250000, 0x400000, 99},
{200000, 0x666666, 199},
{195313, 0x8000, 0},
{125000, 0x100000, 49},
{100000, 0x200000, 124},
{50000, 0x100000, 124},
{25000, 0x80000, 124},
{10016, 0x20000, 77},
{5040, 0x20000, 154},
{1002, 0x8000, 194},
};
/* Offset from drv_data->lpss_base */
#define GENERAL_REG 0x08
#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24)
@@ -701,25 +650,124 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
}
/*
* The Quark SPI data sheet gives a table, and for the given 'rate',
* the 'dds' and 'clk_div' can be found in the table.
* The Quark SPI has an additional 24 bit register (DDS_CLK_RATE) to multiply
* input frequency by fractions of 2^24. It also has a divider by 5.
*
* There are formulas to get baud rate value for given input frequency and
* divider parameters, such as DDS_CLK_RATE and SCR:
*
* Fsys = 200MHz
*
* Fssp = Fsys * DDS_CLK_RATE / 2^24 (1)
* Baud rate = Fsclk = Fssp / (2 * (SCR + 1)) (2)
*
* DDS_CLK_RATE either 2^n or 2^n / 5.
* SCR is in range 0 .. 255
*
* Divisor = 5^i * 2^j * 2 * k
* i = [0, 1] i = 1 iff j = 0 or j > 3
* j = [0, 23] j = 0 iff i = 1
* k = [1, 256]
* Special case: j = 0, i = 1: Divisor = 2 / 5
*
* Accordingly to the specification the recommended values for DDS_CLK_RATE
* are:
* Case 1: 2^n, n = [0, 23]
* Case 2: 2^24 * 2 / 5 (0x666666)
* Case 3: less than or equal to 2^24 / 5 / 16 (0x33333)
*
* In all cases the lowest possible value is better.
*
* The function calculates parameters for all cases and chooses the one closest
* to the asked baud rate.
*/
static u32 quark_x1000_set_clk_regvals(u32 rate, u32 *dds, u32 *clk_div)
static unsigned int quark_x1000_get_clk_div(int rate, u32 *dds)
{
unsigned int i;
unsigned long xtal = 200000000;
unsigned long fref = xtal / 2; /* mandatory division by 2,
see (2) */
/* case 3 */
unsigned long fref1 = fref / 2; /* case 1 */
unsigned long fref2 = fref * 2 / 5; /* case 2 */
unsigned long scale;
unsigned long q, q1, q2;
long r, r1, r2;
u32 mul;
for (i = 0; i < ARRAY_SIZE(quark_spi_rate_table); i++) {
if (rate >= quark_spi_rate_table[i].bitrate) {
*dds = quark_spi_rate_table[i].dds_clk_rate;
*clk_div = quark_spi_rate_table[i].clk_div;
return quark_spi_rate_table[i].bitrate;
/* Case 1 */
/* Set initial value for DDS_CLK_RATE */
mul = (1 << 24) >> 1;
/* Calculate initial quot */
q1 = DIV_ROUND_CLOSEST(fref1, rate);
/* Scale q1 if it's too big */
if (q1 > 256) {
/* Scale q1 to range [1, 512] */
scale = fls_long(q1 - 1);
if (scale > 9) {
q1 >>= scale - 9;
mul >>= scale - 9;
}
/* Round the result if we have a remainder */
q1 += q1 & 1;
}
/* Decrease DDS_CLK_RATE as much as we can without loss in precision */
scale = __ffs(q1);
q1 >>= scale;
mul >>= scale;
/* Get the remainder */
r1 = abs(fref1 / (1 << (24 - fls_long(mul))) / q1 - rate);
/* Case 2 */
q2 = DIV_ROUND_CLOSEST(fref2, rate);
r2 = abs(fref2 / q2 - rate);
/*
* Choose the best between two: less remainder we have the better. We
* can't go case 2 if q2 is greater than 256 since SCR register can
* hold only values 0 .. 255.
*/
if (r2 >= r1 || q2 > 256) {
/* case 1 is better */
r = r1;
q = q1;
} else {
/* case 2 is better */
r = r2;
q = q2;
mul = (1 << 24) * 2 / 5;
}
/* Check case 3 only If the divisor is big enough */
if (fref / rate >= 80) {
u64 fssp;
u32 m;
/* Calculate initial quot */
q1 = DIV_ROUND_CLOSEST(fref, rate);
m = (1 << 24) / q1;
/* Get the remainder */
fssp = (u64)fref * m;
do_div(fssp, 1 << 24);
r1 = abs(fssp - rate);
/* Choose this one if it suits better */
if (r1 < r) {
/* case 3 is better */
q = 1;
mul = m;
}
}
*dds = quark_spi_rate_table[i-1].dds_clk_rate;
*clk_div = quark_spi_rate_table[i-1].clk_div;
return quark_spi_rate_table[i-1].bitrate;
*dds = mul;
return q - 1;
}
static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
@@ -730,23 +778,25 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate)
rate = min_t(int, ssp_clk, rate);
if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP)
return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8;
return (ssp_clk / (2 * rate) - 1) & 0xff;
else
return ((ssp_clk / rate - 1) & 0xfff) << 8;
return (ssp_clk / rate - 1) & 0xfff;
}
static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data,
struct chip_data *chip, int rate)
{
u32 clk_div;
unsigned int clk_div;
switch (drv_data->ssp_type) {
case QUARK_X1000_SSP:
quark_x1000_set_clk_regvals(rate, &chip->dds_rate, &clk_div);
return clk_div << 8;
clk_div = quark_x1000_get_clk_div(rate, &chip->dds_rate);
break;
default:
return ssp_get_clk_div(drv_data, rate);
clk_div = ssp_get_clk_div(drv_data, rate);
break;
}
return clk_div << 8;
}
static void pump_transfers(unsigned long data)
+309 -36
View File
@@ -22,6 +22,8 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#define QUP_CONFIG 0x0000
#define QUP_STATE 0x0004
@@ -116,6 +118,8 @@
#define SPI_NUM_CHIPSELECTS 4
#define SPI_MAX_DMA_XFER (SZ_64K - 64)
/* high speed mode is when bus rate is greater then 26MHz */
#define SPI_HS_MIN_RATE 26000000
#define SPI_MAX_RATE 50000000
@@ -140,9 +144,14 @@ struct spi_qup {
struct completion done;
int error;
int w_size; /* bytes per SPI word */
int n_words;
int tx_bytes;
int rx_bytes;
int qup_v1;
int use_dma;
struct dma_slave_config rx_conf;
struct dma_slave_config tx_conf;
};
@@ -198,7 +207,6 @@ static int spi_qup_set_state(struct spi_qup *controller, u32 state)
return 0;
}
static void spi_qup_fifo_read(struct spi_qup *controller,
struct spi_transfer *xfer)
{
@@ -266,6 +274,107 @@ static void spi_qup_fifo_write(struct spi_qup *controller,
}
}
static void spi_qup_dma_done(void *data)
{
struct spi_qup *qup = data;
complete(&qup->done);
}
static int spi_qup_prep_sg(struct spi_master *master, struct spi_transfer *xfer,
enum dma_transfer_direction dir,
dma_async_tx_callback callback)
{
struct spi_qup *qup = spi_master_get_devdata(master);
unsigned long flags = DMA_PREP_INTERRUPT | DMA_PREP_FENCE;
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
struct dma_chan *chan;
dma_cookie_t cookie;
unsigned int nents;
if (dir == DMA_MEM_TO_DEV) {
chan = master->dma_tx;
nents = xfer->tx_sg.nents;
sgl = xfer->tx_sg.sgl;
} else {
chan = master->dma_rx;
nents = xfer->rx_sg.nents;
sgl = xfer->rx_sg.sgl;
}
desc = dmaengine_prep_slave_sg(chan, sgl, nents, dir, flags);
if (!desc)
return -EINVAL;
desc->callback = callback;
desc->callback_param = qup;
cookie = dmaengine_submit(desc);
return dma_submit_error(cookie);
}
static void spi_qup_dma_terminate(struct spi_master *master,
struct spi_transfer *xfer)
{
if (xfer->tx_buf)
dmaengine_terminate_all(master->dma_tx);
if (xfer->rx_buf)
dmaengine_terminate_all(master->dma_rx);
}
static int spi_qup_do_dma(struct spi_master *master, struct spi_transfer *xfer)
{
dma_async_tx_callback rx_done = NULL, tx_done = NULL;
int ret;
if (xfer->rx_buf)
rx_done = spi_qup_dma_done;
else if (xfer->tx_buf)
tx_done = spi_qup_dma_done;
if (xfer->rx_buf) {
ret = spi_qup_prep_sg(master, xfer, DMA_DEV_TO_MEM, rx_done);
if (ret)
return ret;
dma_async_issue_pending(master->dma_rx);
}
if (xfer->tx_buf) {
ret = spi_qup_prep_sg(master, xfer, DMA_MEM_TO_DEV, tx_done);
if (ret)
return ret;
dma_async_issue_pending(master->dma_tx);
}
return 0;
}
static int spi_qup_do_pio(struct spi_master *master, struct spi_transfer *xfer)
{
struct spi_qup *qup = spi_master_get_devdata(master);
int ret;
ret = spi_qup_set_state(qup, QUP_STATE_RUN);
if (ret) {
dev_warn(qup->dev, "cannot set RUN state\n");
return ret;
}
ret = spi_qup_set_state(qup, QUP_STATE_PAUSE);
if (ret) {
dev_warn(qup->dev, "cannot set PAUSE state\n");
return ret;
}
spi_qup_fifo_write(qup, xfer);
return 0;
}
static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
{
struct spi_qup *controller = dev_id;
@@ -315,11 +424,13 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
error = -EIO;
}
if (opflags & QUP_OP_IN_SERVICE_FLAG)
spi_qup_fifo_read(controller, xfer);
if (!controller->use_dma) {
if (opflags & QUP_OP_IN_SERVICE_FLAG)
spi_qup_fifo_read(controller, xfer);
if (opflags & QUP_OP_OUT_SERVICE_FLAG)
spi_qup_fifo_write(controller, xfer);
if (opflags & QUP_OP_OUT_SERVICE_FLAG)
spi_qup_fifo_write(controller, xfer);
}
spin_lock_irqsave(&controller->lock, flags);
controller->error = error;
@@ -332,13 +443,35 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
static u32
spi_qup_get_mode(struct spi_master *master, struct spi_transfer *xfer)
{
struct spi_qup *qup = spi_master_get_devdata(master);
u32 mode;
qup->w_size = 4;
if (xfer->bits_per_word <= 8)
qup->w_size = 1;
else if (xfer->bits_per_word <= 16)
qup->w_size = 2;
qup->n_words = xfer->len / qup->w_size;
if (qup->n_words <= (qup->in_fifo_sz / sizeof(u32)))
mode = QUP_IO_M_MODE_FIFO;
else
mode = QUP_IO_M_MODE_BLOCK;
return mode;
}
/* set clock freq ... bits per word */
static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
{
struct spi_qup *controller = spi_master_get_devdata(spi->master);
u32 config, iomode, mode, control;
int ret, n_words, w_size;
int ret, n_words;
if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) {
dev_err(controller->dev, "too big size for loopback %d > %d\n",
@@ -358,35 +491,54 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
return -EIO;
}
w_size = 4;
if (xfer->bits_per_word <= 8)
w_size = 1;
else if (xfer->bits_per_word <= 16)
w_size = 2;
mode = spi_qup_get_mode(spi->master, xfer);
n_words = controller->n_words;
n_words = xfer->len / w_size;
controller->w_size = w_size;
if (n_words <= (controller->in_fifo_sz / sizeof(u32))) {
mode = QUP_IO_M_MODE_FIFO;
if (mode == QUP_IO_M_MODE_FIFO) {
writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
/* must be zero for FIFO */
writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
} else {
mode = QUP_IO_M_MODE_BLOCK;
} else if (!controller->use_dma) {
writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
/* must be zero for BLOCK and BAM */
writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
} else {
mode = QUP_IO_M_MODE_BAM;
writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
if (!controller->qup_v1) {
void __iomem *input_cnt;
input_cnt = controller->base + QUP_MX_INPUT_CNT;
/*
* for DMA transfers, both QUP_MX_INPUT_CNT and
* QUP_MX_OUTPUT_CNT must be zero to all cases but one.
* That case is a non-balanced transfer when there is
* only a rx_buf.
*/
if (xfer->tx_buf)
writel_relaxed(0, input_cnt);
else
writel_relaxed(n_words, input_cnt);
writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
}
}
iomode = readl_relaxed(controller->base + QUP_IO_M_MODES);
/* Set input and output transfer mode */
iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK);
iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
if (!controller->use_dma)
iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
else
iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN;
iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT);
iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT);
@@ -428,11 +580,31 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N);
config |= xfer->bits_per_word - 1;
config |= QUP_CONFIG_SPI_MODE;
if (controller->use_dma) {
if (!xfer->tx_buf)
config |= QUP_CONFIG_NO_OUTPUT;
if (!xfer->rx_buf)
config |= QUP_CONFIG_NO_INPUT;
}
writel_relaxed(config, controller->base + QUP_CONFIG);
/* only write to OPERATIONAL_MASK when register is present */
if (!controller->qup_v1)
writel_relaxed(0, controller->base + QUP_OPERATIONAL_MASK);
if (!controller->qup_v1) {
u32 mask = 0;
/*
* mask INPUT and OUTPUT service flags to prevent IRQs on FIFO
* status change in BAM mode
*/
if (mode == QUP_IO_M_MODE_BAM)
mask = QUP_OP_IN_SERVICE_FLAG | QUP_OP_OUT_SERVICE_FLAG;
writel_relaxed(mask, controller->base + QUP_OPERATIONAL_MASK);
}
return 0;
}
@@ -461,17 +633,13 @@ static int spi_qup_transfer_one(struct spi_master *master,
controller->tx_bytes = 0;
spin_unlock_irqrestore(&controller->lock, flags);
if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
dev_warn(controller->dev, "cannot set RUN state\n");
goto exit;
}
if (controller->use_dma)
ret = spi_qup_do_dma(master, xfer);
else
ret = spi_qup_do_pio(master, xfer);
if (spi_qup_set_state(controller, QUP_STATE_PAUSE)) {
dev_warn(controller->dev, "cannot set PAUSE state\n");
if (ret)
goto exit;
}
spi_qup_fifo_write(controller, xfer);
if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
dev_warn(controller->dev, "cannot set EXECUTE state\n");
@@ -480,6 +648,7 @@ static int spi_qup_transfer_one(struct spi_master *master,
if (!wait_for_completion_timeout(&controller->done, timeout))
ret = -ETIMEDOUT;
exit:
spi_qup_set_state(controller, QUP_STATE_RESET);
spin_lock_irqsave(&controller->lock, flags);
@@ -487,6 +656,97 @@ exit:
if (!ret)
ret = controller->error;
spin_unlock_irqrestore(&controller->lock, flags);
if (ret && controller->use_dma)
spi_qup_dma_terminate(master, xfer);
return ret;
}
static bool spi_qup_can_dma(struct spi_master *master, struct spi_device *spi,
struct spi_transfer *xfer)
{
struct spi_qup *qup = spi_master_get_devdata(master);
size_t dma_align = dma_get_cache_alignment();
u32 mode;
qup->use_dma = 0;
if (xfer->rx_buf && (xfer->len % qup->in_blk_sz ||
IS_ERR_OR_NULL(master->dma_rx) ||
!IS_ALIGNED((size_t)xfer->rx_buf, dma_align)))
return false;
if (xfer->tx_buf && (xfer->len % qup->out_blk_sz ||
IS_ERR_OR_NULL(master->dma_tx) ||
!IS_ALIGNED((size_t)xfer->tx_buf, dma_align)))
return false;
mode = spi_qup_get_mode(master, xfer);
if (mode == QUP_IO_M_MODE_FIFO)
return false;
qup->use_dma = 1;
return true;
}
static void spi_qup_release_dma(struct spi_master *master)
{
if (!IS_ERR_OR_NULL(master->dma_rx))
dma_release_channel(master->dma_rx);
if (!IS_ERR_OR_NULL(master->dma_tx))
dma_release_channel(master->dma_tx);
}
static int spi_qup_init_dma(struct spi_master *master, resource_size_t base)
{
struct spi_qup *spi = spi_master_get_devdata(master);
struct dma_slave_config *rx_conf = &spi->rx_conf,
*tx_conf = &spi->tx_conf;
struct device *dev = spi->dev;
int ret;
/* allocate dma resources, if available */
master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
if (IS_ERR(master->dma_rx))
return PTR_ERR(master->dma_rx);
master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
if (IS_ERR(master->dma_tx)) {
ret = PTR_ERR(master->dma_tx);
goto err_tx;
}
/* set DMA parameters */
rx_conf->direction = DMA_DEV_TO_MEM;
rx_conf->device_fc = 1;
rx_conf->src_addr = base + QUP_INPUT_FIFO;
rx_conf->src_maxburst = spi->in_blk_sz;
tx_conf->direction = DMA_MEM_TO_DEV;
tx_conf->device_fc = 1;
tx_conf->dst_addr = base + QUP_OUTPUT_FIFO;
tx_conf->dst_maxburst = spi->out_blk_sz;
ret = dmaengine_slave_config(master->dma_rx, rx_conf);
if (ret) {
dev_err(dev, "failed to configure RX channel\n");
goto err;
}
ret = dmaengine_slave_config(master->dma_tx, tx_conf);
if (ret) {
dev_err(dev, "failed to configure TX channel\n");
goto err;
}
return 0;
err:
dma_release_channel(master->dma_tx);
err_tx:
dma_release_channel(master->dma_rx);
return ret;
}
@@ -498,7 +758,7 @@ static int spi_qup_probe(struct platform_device *pdev)
struct resource *res;
struct device *dev;
void __iomem *base;
u32 max_freq, iomode;
u32 max_freq, iomode, num_cs;
int ret, irq, size;
dev = &pdev->dev;
@@ -550,10 +810,11 @@ static int spi_qup_probe(struct platform_device *pdev)
}
/* use num-cs unless not present or out of range */
if (of_property_read_u16(dev->of_node, "num-cs",
&master->num_chipselect) ||
(master->num_chipselect > SPI_NUM_CHIPSELECTS))
if (of_property_read_u32(dev->of_node, "num-cs", &num_cs) ||
num_cs > SPI_NUM_CHIPSELECTS)
master->num_chipselect = SPI_NUM_CHIPSELECTS;
else
master->num_chipselect = num_cs;
master->bus_num = pdev->id;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
@@ -562,6 +823,8 @@ static int spi_qup_probe(struct platform_device *pdev)
master->transfer_one = spi_qup_transfer_one;
master->dev.of_node = pdev->dev.of_node;
master->auto_runtime_pm = true;
master->dma_alignment = dma_get_cache_alignment();
master->max_dma_len = SPI_MAX_DMA_XFER;
platform_set_drvdata(pdev, master);
@@ -573,6 +836,12 @@ static int spi_qup_probe(struct platform_device *pdev)
controller->cclk = cclk;
controller->irq = irq;
ret = spi_qup_init_dma(master, res->start);
if (ret == -EPROBE_DEFER)
goto error;
else if (!ret)
master->can_dma = spi_qup_can_dma;
/* set v1 flag if device is version 1 */
if (of_device_is_compatible(dev->of_node, "qcom,spi-qup-v1.1.1"))
controller->qup_v1 = 1;
@@ -609,7 +878,7 @@ static int spi_qup_probe(struct platform_device *pdev)
ret = spi_qup_set_state(controller, QUP_STATE_RESET);
if (ret) {
dev_err(dev, "cannot set RESET state\n");
goto error;
goto error_dma;
}
writel_relaxed(0, base + QUP_OPERATIONAL);
@@ -633,7 +902,7 @@ static int spi_qup_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, irq, spi_qup_qup_irq,
IRQF_TRIGGER_HIGH, pdev->name, controller);
if (ret)
goto error;
goto error_dma;
pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC);
pm_runtime_use_autosuspend(dev);
@@ -648,6 +917,8 @@ static int spi_qup_probe(struct platform_device *pdev)
disable_pm:
pm_runtime_disable(&pdev->dev);
error_dma:
spi_qup_release_dma(master);
error:
clk_disable_unprepare(cclk);
clk_disable_unprepare(iclk);
@@ -739,6 +1010,8 @@ static int spi_qup_remove(struct platform_device *pdev)
if (ret)
return ret;
spi_qup_release_dma(master);
clk_disable_unprepare(controller->cclk);
clk_disable_unprepare(controller->iclk);

Some files were not shown because too many files have changed in this diff Show More