Commit 3bc1ad25 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/delay', 'spi/topic/dw',...

Merge remote-tracking branches 'spi/topic/delay', 'spi/topic/dw', 'spi/topic/fsl-dspi' and 'spi/topic/fsl-espi' into spi-next
...@@ -380,7 +380,6 @@ config SPI_FSL_DSPI ...@@ -380,7 +380,6 @@ config SPI_FSL_DSPI
config SPI_FSL_ESPI config SPI_FSL_ESPI
tristate "Freescale eSPI controller" tristate "Freescale eSPI controller"
depends on FSL_SOC depends on FSL_SOC
select SPI_FSL_LIB
help help
This enables using the Freescale eSPI controllers in master mode. This enables using the Freescale eSPI controllers in master mode.
From MPC8536, 85xx platform uses the controller, and all P10xx, From MPC8536, 85xx platform uses the controller, and all P10xx,
......
...@@ -502,6 +502,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) ...@@ -502,6 +502,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
master->handle_err = dw_spi_handle_err; master->handle_err = dw_spi_handle_err;
master->max_speed_hz = dws->max_freq; master->max_speed_hz = dws->max_freq;
master->dev.of_node = dev->of_node; master->dev.of_node = dev->of_node;
master->flags = SPI_MASTER_GPIO_SS;
/* Basic HW init */ /* Basic HW init */
spi_hw_init(dev, dws); spi_hw_init(dev, dws);
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -40,6 +42,7 @@ ...@@ -40,6 +42,7 @@
#define TRAN_STATE_WORD_ODD_NUM 0x04 #define TRAN_STATE_WORD_ODD_NUM 0x04
#define DSPI_FIFO_SIZE 4 #define DSPI_FIFO_SIZE 4
#define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024)
#define SPI_MCR 0x00 #define SPI_MCR 0x00
#define SPI_MCR_MASTER (1 << 31) #define SPI_MCR_MASTER (1 << 31)
...@@ -72,6 +75,11 @@ ...@@ -72,6 +75,11 @@
#define SPI_SR_TCFQF 0x80000000 #define SPI_SR_TCFQF 0x80000000
#define SPI_SR_CLEAR 0xdaad0000 #define SPI_SR_CLEAR 0xdaad0000
#define SPI_RSER_TFFFE BIT(25)
#define SPI_RSER_TFFFD BIT(24)
#define SPI_RSER_RFDFE BIT(17)
#define SPI_RSER_RFDFD BIT(16)
#define SPI_RSER 0x30 #define SPI_RSER 0x30
#define SPI_RSER_EOQFE 0x10000000 #define SPI_RSER_EOQFE 0x10000000
#define SPI_RSER_TCFQE 0x80000000 #define SPI_RSER_TCFQE 0x80000000
...@@ -109,6 +117,8 @@ ...@@ -109,6 +117,8 @@
#define SPI_TCR_TCNT_MAX 0x10000 #define SPI_TCR_TCNT_MAX 0x10000
#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000)
struct chip_data { struct chip_data {
u32 mcr_val; u32 mcr_val;
u32 ctar_val; u32 ctar_val;
...@@ -118,6 +128,7 @@ struct chip_data { ...@@ -118,6 +128,7 @@ struct chip_data {
enum dspi_trans_mode { enum dspi_trans_mode {
DSPI_EOQ_MODE = 0, DSPI_EOQ_MODE = 0,
DSPI_TCFQ_MODE, DSPI_TCFQ_MODE,
DSPI_DMA_MODE,
}; };
struct fsl_dspi_devtype_data { struct fsl_dspi_devtype_data {
...@@ -126,7 +137,7 @@ struct fsl_dspi_devtype_data { ...@@ -126,7 +137,7 @@ struct fsl_dspi_devtype_data {
}; };
static const struct fsl_dspi_devtype_data vf610_data = { static const struct fsl_dspi_devtype_data vf610_data = {
.trans_mode = DSPI_EOQ_MODE, .trans_mode = DSPI_DMA_MODE,
.max_clock_factor = 2, .max_clock_factor = 2,
}; };
...@@ -140,6 +151,23 @@ static const struct fsl_dspi_devtype_data ls2085a_data = { ...@@ -140,6 +151,23 @@ static const struct fsl_dspi_devtype_data ls2085a_data = {
.max_clock_factor = 8, .max_clock_factor = 8,
}; };
struct fsl_dspi_dma {
/* Length of transfer in words of DSPI_FIFO_SIZE */
u32 curr_xfer_len;
u32 *tx_dma_buf;
struct dma_chan *chan_tx;
dma_addr_t tx_dma_phys;
struct completion cmd_tx_complete;
struct dma_async_tx_descriptor *tx_desc;
u32 *rx_dma_buf;
struct dma_chan *chan_rx;
dma_addr_t rx_dma_phys;
struct completion cmd_rx_complete;
struct dma_async_tx_descriptor *rx_desc;
};
struct fsl_dspi { struct fsl_dspi {
struct spi_master *master; struct spi_master *master;
struct platform_device *pdev; struct platform_device *pdev;
...@@ -166,8 +194,11 @@ struct fsl_dspi { ...@@ -166,8 +194,11 @@ struct fsl_dspi {
u32 waitflags; u32 waitflags;
u32 spi_tcnt; u32 spi_tcnt;
struct fsl_dspi_dma *dma;
}; };
static u32 dspi_data_to_pushr(struct fsl_dspi *dspi, int tx_word);
static inline int is_double_byte_mode(struct fsl_dspi *dspi) static inline int is_double_byte_mode(struct fsl_dspi *dspi)
{ {
unsigned int val; unsigned int val;
...@@ -177,6 +208,255 @@ static inline int is_double_byte_mode(struct fsl_dspi *dspi) ...@@ -177,6 +208,255 @@ static inline int is_double_byte_mode(struct fsl_dspi *dspi)
return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1; return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1;
} }
static void dspi_tx_dma_callback(void *arg)
{
struct fsl_dspi *dspi = arg;
struct fsl_dspi_dma *dma = dspi->dma;
complete(&dma->cmd_tx_complete);
}
static void dspi_rx_dma_callback(void *arg)
{
struct fsl_dspi *dspi = arg;
struct fsl_dspi_dma *dma = dspi->dma;
int rx_word;
int i;
u16 d;
rx_word = is_double_byte_mode(dspi);
if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) {
for (i = 0; i < dma->curr_xfer_len; i++) {
d = dspi->dma->rx_dma_buf[i];
rx_word ? (*(u16 *)dspi->rx = d) :
(*(u8 *)dspi->rx = d);
dspi->rx += rx_word + 1;
}
}
complete(&dma->cmd_rx_complete);
}
static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi)
{
struct fsl_dspi_dma *dma = dspi->dma;
struct device *dev = &dspi->pdev->dev;
int time_left;
int tx_word;
int i;
tx_word = is_double_byte_mode(dspi);
for (i = 0; i < dma->curr_xfer_len; i++) {
dspi->dma->tx_dma_buf[i] = dspi_data_to_pushr(dspi, tx_word);
if ((dspi->cs_change) && (!dspi->len))
dspi->dma->tx_dma_buf[i] &= ~SPI_PUSHR_CONT;
}
dma->tx_desc = dmaengine_prep_slave_single(dma->chan_tx,
dma->tx_dma_phys,
dma->curr_xfer_len *
DMA_SLAVE_BUSWIDTH_4_BYTES,
DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!dma->tx_desc) {
dev_err(dev, "Not able to get desc for DMA xfer\n");
return -EIO;
}
dma->tx_desc->callback = dspi_tx_dma_callback;
dma->tx_desc->callback_param = dspi;
if (dma_submit_error(dmaengine_submit(dma->tx_desc))) {
dev_err(dev, "DMA submit failed\n");
return -EINVAL;
}
dma->rx_desc = dmaengine_prep_slave_single(dma->chan_rx,
dma->rx_dma_phys,
dma->curr_xfer_len *
DMA_SLAVE_BUSWIDTH_4_BYTES,
DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!dma->rx_desc) {
dev_err(dev, "Not able to get desc for DMA xfer\n");
return -EIO;
}
dma->rx_desc->callback = dspi_rx_dma_callback;
dma->rx_desc->callback_param = dspi;
if (dma_submit_error(dmaengine_submit(dma->rx_desc))) {
dev_err(dev, "DMA submit failed\n");
return -EINVAL;
}
reinit_completion(&dspi->dma->cmd_rx_complete);
reinit_completion(&dspi->dma->cmd_tx_complete);
dma_async_issue_pending(dma->chan_rx);
dma_async_issue_pending(dma->chan_tx);
time_left = wait_for_completion_timeout(&dspi->dma->cmd_tx_complete,
DMA_COMPLETION_TIMEOUT);
if (time_left == 0) {
dev_err(dev, "DMA tx timeout\n");
dmaengine_terminate_all(dma->chan_tx);
dmaengine_terminate_all(dma->chan_rx);
return -ETIMEDOUT;
}
time_left = wait_for_completion_timeout(&dspi->dma->cmd_rx_complete,
DMA_COMPLETION_TIMEOUT);
if (time_left == 0) {
dev_err(dev, "DMA rx timeout\n");
dmaengine_terminate_all(dma->chan_tx);
dmaengine_terminate_all(dma->chan_rx);
return -ETIMEDOUT;
}
return 0;
}
static int dspi_dma_xfer(struct fsl_dspi *dspi)
{
struct fsl_dspi_dma *dma = dspi->dma;
struct device *dev = &dspi->pdev->dev;
int curr_remaining_bytes;
int bytes_per_buffer;
int word = 1;
int ret = 0;
if (is_double_byte_mode(dspi))
word = 2;
curr_remaining_bytes = dspi->len;
bytes_per_buffer = DSPI_DMA_BUFSIZE / DSPI_FIFO_SIZE;
while (curr_remaining_bytes) {
/* Check if current transfer fits the DMA buffer */
dma->curr_xfer_len = curr_remaining_bytes / word;
if (dma->curr_xfer_len > bytes_per_buffer)
dma->curr_xfer_len = bytes_per_buffer;
ret = dspi_next_xfer_dma_submit(dspi);
if (ret) {
dev_err(dev, "DMA transfer failed\n");
goto exit;
} else {
curr_remaining_bytes -= dma->curr_xfer_len * word;
if (curr_remaining_bytes < 0)
curr_remaining_bytes = 0;
}
}
exit:
return ret;
}
static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
{
struct fsl_dspi_dma *dma;
struct dma_slave_config cfg;
struct device *dev = &dspi->pdev->dev;
int ret;
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
return -ENOMEM;
dma->chan_rx = dma_request_slave_channel(dev, "rx");
if (!dma->chan_rx) {
dev_err(dev, "rx dma channel not available\n");
ret = -ENODEV;
return ret;
}
dma->chan_tx = dma_request_slave_channel(dev, "tx");
if (!dma->chan_tx) {
dev_err(dev, "tx dma channel not available\n");
ret = -ENODEV;
goto err_tx_channel;
}
dma->tx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE,
&dma->tx_dma_phys, GFP_KERNEL);
if (!dma->tx_dma_buf) {
ret = -ENOMEM;
goto err_tx_dma_buf;
}
dma->rx_dma_buf = dma_alloc_coherent(dev, DSPI_DMA_BUFSIZE,
&dma->rx_dma_phys, GFP_KERNEL);
if (!dma->rx_dma_buf) {
ret = -ENOMEM;
goto err_rx_dma_buf;
}
cfg.src_addr = phy_addr + SPI_POPR;
cfg.dst_addr = phy_addr + SPI_PUSHR;
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
cfg.src_maxburst = 1;
cfg.dst_maxburst = 1;
cfg.direction = DMA_DEV_TO_MEM;
ret = dmaengine_slave_config(dma->chan_rx, &cfg);
if (ret) {
dev_err(dev, "can't configure rx dma channel\n");
ret = -EINVAL;
goto err_slave_config;
}
cfg.direction = DMA_MEM_TO_DEV;
ret = dmaengine_slave_config(dma->chan_tx, &cfg);
if (ret) {
dev_err(dev, "can't configure tx dma channel\n");
ret = -EINVAL;
goto err_slave_config;
}
dspi->dma = dma;
init_completion(&dma->cmd_tx_complete);
init_completion(&dma->cmd_rx_complete);
return 0;
err_slave_config:
dma_free_coherent(dev, DSPI_DMA_BUFSIZE,
dma->rx_dma_buf, dma->rx_dma_phys);
err_rx_dma_buf:
dma_free_coherent(dev, DSPI_DMA_BUFSIZE,
dma->tx_dma_buf, dma->tx_dma_phys);
err_tx_dma_buf:
dma_release_channel(dma->chan_tx);
err_tx_channel:
dma_release_channel(dma->chan_rx);
devm_kfree(dev, dma);
dspi->dma = NULL;
return ret;
}
static void dspi_release_dma(struct fsl_dspi *dspi)
{
struct fsl_dspi_dma *dma = dspi->dma;
struct device *dev = &dspi->pdev->dev;
if (dma) {
if (dma->chan_tx) {
dma_unmap_single(dev, dma->tx_dma_phys,
DSPI_DMA_BUFSIZE, DMA_TO_DEVICE);
dma_release_channel(dma->chan_tx);
}
if (dma->chan_rx) {
dma_unmap_single(dev, dma->rx_dma_phys,
DSPI_DMA_BUFSIZE, DMA_FROM_DEVICE);
dma_release_channel(dma->chan_rx);
}
}
}
static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
unsigned long clkrate) unsigned long clkrate)
{ {
...@@ -425,6 +705,12 @@ static int dspi_transfer_one_message(struct spi_master *master, ...@@ -425,6 +705,12 @@ static int dspi_transfer_one_message(struct spi_master *master,
regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE); regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE);
dspi_tcfq_write(dspi); dspi_tcfq_write(dspi);
break; break;
case DSPI_DMA_MODE:
regmap_write(dspi->regmap, SPI_RSER,
SPI_RSER_TFFFE | SPI_RSER_TFFFD |
SPI_RSER_RFDFE | SPI_RSER_RFDFD);
status = dspi_dma_xfer(dspi);
break;
default: default:
dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n", dev_err(&dspi->pdev->dev, "unsupported trans_mode %u\n",
trans_mode); trans_mode);
...@@ -432,9 +718,13 @@ static int dspi_transfer_one_message(struct spi_master *master, ...@@ -432,9 +718,13 @@ static int dspi_transfer_one_message(struct spi_master *master,
goto out; goto out;
} }
if (wait_event_interruptible(dspi->waitq, dspi->waitflags)) if (trans_mode != DSPI_DMA_MODE) {
dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n"); if (wait_event_interruptible(dspi->waitq,
dspi->waitflags = 0; dspi->waitflags))
dev_err(&dspi->pdev->dev,
"wait transfer complete fail!\n");
dspi->waitflags = 0;
}
if (transfer->delay_usecs) if (transfer->delay_usecs)
udelay(transfer->delay_usecs); udelay(transfer->delay_usecs);
...@@ -740,6 +1030,13 @@ static int dspi_probe(struct platform_device *pdev) ...@@ -740,6 +1030,13 @@ static int dspi_probe(struct platform_device *pdev)
if (ret) if (ret)
goto out_master_put; goto out_master_put;
if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
if (dspi_request_dma(dspi, res->start)) {
dev_err(&pdev->dev, "can't get dma channels\n");
goto out_clk_put;
}
}
master->max_speed_hz = master->max_speed_hz =
clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor; clk_get_rate(dspi->clk) / dspi->devtype_data->max_clock_factor;
...@@ -768,6 +1065,7 @@ static int dspi_remove(struct platform_device *pdev) ...@@ -768,6 +1065,7 @@ static int dspi_remove(struct platform_device *pdev)
struct fsl_dspi *dspi = spi_master_get_devdata(master); struct fsl_dspi *dspi = spi_master_get_devdata(master);
/* Disconnect from the SPI framework */ /* Disconnect from the SPI framework */
dspi_release_dma(dspi);
clk_disable_unprepare(dspi->clk); clk_disable_unprepare(dspi->clk);
spi_unregister_master(dspi->master); spi_unregister_master(dspi->master);
......
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <sysdev/fsl_soc.h> #include <sysdev/fsl_soc.h>
#include "spi-fsl-lib.h"
/* eSPI Controller registers */ /* eSPI Controller registers */
#define ESPI_SPMODE 0x00 /* eSPI mode register */ #define ESPI_SPMODE 0x00 /* eSPI mode register */
#define ESPI_SPIE 0x04 /* eSPI event register */ #define ESPI_SPIE 0x04 /* eSPI event register */
...@@ -54,8 +52,11 @@ ...@@ -54,8 +52,11 @@
#define CSMODE_AFT(x) ((x) << 8) #define CSMODE_AFT(x) ((x) << 8)
#define CSMODE_CG(x) ((x) << 3) #define CSMODE_CG(x) ((x) << 3)
#define FSL_ESPI_FIFO_SIZE 32
#define FSL_ESPI_RXTHR 15
/* Default mode/csmode for eSPI controller */ /* Default mode/csmode for eSPI controller */
#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3)) #define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(FSL_ESPI_RXTHR))
#define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \ #define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \
| CSMODE_AFT(0) | CSMODE_CG(1)) | CSMODE_AFT(0) | CSMODE_CG(1))
...@@ -90,219 +91,342 @@ ...@@ -90,219 +91,342 @@
#define AUTOSUSPEND_TIMEOUT 2000 #define AUTOSUSPEND_TIMEOUT 2000
static inline u32 fsl_espi_read_reg(struct mpc8xxx_spi *mspi, int offset) struct fsl_espi {
struct device *dev;
void __iomem *reg_base;
struct list_head *m_transfers;
struct spi_transfer *tx_t;
unsigned int tx_pos;
bool tx_done;
struct spi_transfer *rx_t;
unsigned int rx_pos;
bool rx_done;
bool swab;
unsigned int rxskip;
spinlock_t lock;
u32 spibrg; /* SPIBRG input clock */
struct completion done;
};
struct fsl_espi_cs {
u32 hw_mode;
};
static inline u32 fsl_espi_read_reg(struct fsl_espi *espi, int offset)
{ {
return ioread32be(mspi->reg_base + offset); return ioread32be(espi->reg_base + offset);
} }
static inline u8 fsl_espi_read_reg8(struct mpc8xxx_spi *mspi, int offset) static inline u16 fsl_espi_read_reg16(struct fsl_espi *espi, int offset)
{ {
return ioread8(mspi->reg_base + offset); return ioread16be(espi->reg_base + offset);
} }
static inline void fsl_espi_write_reg(struct mpc8xxx_spi *mspi, int offset, static inline u8 fsl_espi_read_reg8(struct fsl_espi *espi, int offset)
u32 val)
{ {
iowrite32be(val, mspi->reg_base + offset); return ioread8(espi->reg_base + offset);
} }
static inline void fsl_espi_write_reg8(struct mpc8xxx_spi *mspi, int offset, static inline void fsl_espi_write_reg(struct fsl_espi *espi, int offset,
u8 val) u32 val)
{ {
iowrite8(val, mspi->reg_base + offset); iowrite32be(val, espi->reg_base + offset);
} }
static void fsl_espi_copy_to_buf(struct spi_message *m, static inline void fsl_espi_write_reg16(struct fsl_espi *espi, int offset,
struct mpc8xxx_spi *mspi) u16 val)
{ {
struct spi_transfer *t; iowrite16be(val, espi->reg_base + offset);
u8 *buf = mspi->local_buf;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->tx_buf)
memcpy(buf, t->tx_buf, t->len);
else
memset(buf, 0, t->len);
buf += t->len;
}
} }
static void fsl_espi_copy_from_buf(struct spi_message *m, static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset,
struct mpc8xxx_spi *mspi) u8 val)
{ {
struct spi_transfer *t; iowrite8(val, espi->reg_base + offset);
u8 *buf = mspi->local_buf;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->rx_buf)
memcpy(t->rx_buf, buf, t->len);
buf += t->len;
}
} }
static int fsl_espi_check_message(struct spi_message *m) static int fsl_espi_check_message(struct spi_message *m)
{ {
struct mpc8xxx_spi *mspi = spi_master_get_devdata(m->spi->master); struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
struct spi_transfer *t, *first; struct spi_transfer *t, *first;
if (m->frame_length > SPCOM_TRANLEN_MAX) { if (m->frame_length > SPCOM_TRANLEN_MAX) {
dev_err(mspi->dev, "message too long, size is %u bytes\n", dev_err(espi->dev, "message too long, size is %u bytes\n",
m->frame_length); m->frame_length);
return -EMSGSIZE; return -EMSGSIZE;
} }
first = list_first_entry(&m->transfers, struct spi_transfer, first = list_first_entry(&m->transfers, struct spi_transfer,
transfer_list); transfer_list);
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
if (first->bits_per_word != t->bits_per_word || if (first->bits_per_word != t->bits_per_word ||
first->speed_hz != t->speed_hz) { first->speed_hz != t->speed_hz) {
dev_err(mspi->dev, "bits_per_word/speed_hz should be the same for all transfers\n"); dev_err(espi->dev, "bits_per_word/speed_hz should be the same for all transfers\n");
return -EINVAL; return -EINVAL;
} }
} }
/* ESPI supports MSB-first transfers for word size 8 / 16 only */
if (!(m->spi->mode & SPI_LSB_FIRST) && first->bits_per_word != 8 &&
first->bits_per_word != 16) {
dev_err(espi->dev,
"MSB-first transfer not supported for wordsize %u\n",
first->bits_per_word);
return -EINVAL;
}
return 0; return 0;
} }
static void fsl_espi_change_mode(struct spi_device *spi) static unsigned int fsl_espi_check_rxskip_mode(struct spi_message *m)
{ {
struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); struct spi_transfer *t;
struct spi_mpc8xxx_cs *cs = spi->controller_state; unsigned int i = 0, rxskip = 0;
u32 tmp;
unsigned long flags; /*
* prerequisites for ESPI rxskip mode:
/* Turn off IRQs locally to minimize time that SPI is disabled. */ * - message has two transfers
local_irq_save(flags); * - first transfer is a write and second is a read
*
/* Turn off SPI unit prior changing mode */ * In addition the current low-level transfer mechanism requires
tmp = fsl_espi_read_reg(mspi, ESPI_SPMODE); * that the rxskip bytes fit into the TX FIFO. Else the transfer
fsl_espi_write_reg(mspi, ESPI_SPMODE, tmp & ~SPMODE_ENABLE); * would hang because after the first FSL_ESPI_FIFO_SIZE bytes
fsl_espi_write_reg(mspi, ESPI_SPMODEx(spi->chip_select), * the TX FIFO isn't re-filled.
cs->hw_mode); */
fsl_espi_write_reg(mspi, ESPI_SPMODE, tmp); list_for_each_entry(t, &m->transfers, transfer_list) {
if (i == 0) {
local_irq_restore(flags); if (!t->tx_buf || t->rx_buf ||
t->len > FSL_ESPI_FIFO_SIZE)
return 0;
rxskip = t->len;
} else if (i == 1) {
if (t->tx_buf || !t->rx_buf)
return 0;
}
i++;
}
return i == 2 ? rxskip : 0;
} }
static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi) static void fsl_espi_fill_tx_fifo(struct fsl_espi *espi, u32 events)
{ {
u32 data; u32 tx_fifo_avail;
u16 data_h; unsigned int tx_left;
u16 data_l; const void *tx_buf;
const u32 *tx = mpc8xxx_spi->tx;
/* if events is zero transfer has not started and tx fifo is empty */
tx_fifo_avail = events ? SPIE_TXCNT(events) : FSL_ESPI_FIFO_SIZE;
start:
tx_left = espi->tx_t->len - espi->tx_pos;
tx_buf = espi->tx_t->tx_buf;
while (tx_fifo_avail >= min(4U, tx_left) && tx_left) {
if (tx_left >= 4) {
if (!tx_buf)
fsl_espi_write_reg(espi, ESPI_SPITF, 0);
else if (espi->swab)
fsl_espi_write_reg(espi, ESPI_SPITF,
swahb32p(tx_buf + espi->tx_pos));
else
fsl_espi_write_reg(espi, ESPI_SPITF,
*(u32 *)(tx_buf + espi->tx_pos));
espi->tx_pos += 4;
tx_left -= 4;
tx_fifo_avail -= 4;
} else if (tx_left >= 2 && tx_buf && espi->swab) {
fsl_espi_write_reg16(espi, ESPI_SPITF,
swab16p(tx_buf + espi->tx_pos));
espi->tx_pos += 2;
tx_left -= 2;
tx_fifo_avail -= 2;
} else {
if (!tx_buf)
fsl_espi_write_reg8(espi, ESPI_SPITF, 0);
else
fsl_espi_write_reg8(espi, ESPI_SPITF,
*(u8 *)(tx_buf + espi->tx_pos));
espi->tx_pos += 1;
tx_left -= 1;
tx_fifo_avail -= 1;
}
}
if (!tx) if (!tx_left) {
return 0; /* Last transfer finished, in rxskip mode only one is needed */
if (list_is_last(&espi->tx_t->transfer_list,
espi->m_transfers) || espi->rxskip) {
espi->tx_done = true;
return;
}
espi->tx_t = list_next_entry(espi->tx_t, transfer_list);
espi->tx_pos = 0;
/* continue with next transfer if tx fifo is not full */
if (tx_fifo_avail)
goto start;
}
}
data = *tx++ << mpc8xxx_spi->tx_shift; static void fsl_espi_read_rx_fifo(struct fsl_espi *espi, u32 events)
data_l = data & 0xffff; {
data_h = (data >> 16) & 0xffff; u32 rx_fifo_avail = SPIE_RXCNT(events);
swab16s(&data_l); unsigned int rx_left;
swab16s(&data_h); void *rx_buf;
data = data_h | data_l;
start:
rx_left = espi->rx_t->len - espi->rx_pos;
rx_buf = espi->rx_t->rx_buf;
while (rx_fifo_avail >= min(4U, rx_left) && rx_left) {
if (rx_left >= 4) {
u32 val = fsl_espi_read_reg(espi, ESPI_SPIRF);
if (rx_buf && espi->swab)
*(u32 *)(rx_buf + espi->rx_pos) = swahb32(val);
else if (rx_buf)
*(u32 *)(rx_buf + espi->rx_pos) = val;
espi->rx_pos += 4;
rx_left -= 4;
rx_fifo_avail -= 4;
} else if (rx_left >= 2 && rx_buf && espi->swab) {
u16 val = fsl_espi_read_reg16(espi, ESPI_SPIRF);
*(u16 *)(rx_buf + espi->rx_pos) = swab16(val);
espi->rx_pos += 2;
rx_left -= 2;
rx_fifo_avail -= 2;
} else {
u8 val = fsl_espi_read_reg8(espi, ESPI_SPIRF);
if (rx_buf)
*(u8 *)(rx_buf + espi->rx_pos) = val;
espi->rx_pos += 1;
rx_left -= 1;
rx_fifo_avail -= 1;
}
}
mpc8xxx_spi->tx = tx; if (!rx_left) {
return data; if (list_is_last(&espi->rx_t->transfer_list,
espi->m_transfers)) {
espi->rx_done = true;
return;
}
espi->rx_t = list_next_entry(espi->rx_t, transfer_list);
espi->rx_pos = 0;
/* continue with next transfer if rx fifo is not empty */
if (rx_fifo_avail)
goto start;
}
} }
static void fsl_espi_setup_transfer(struct spi_device *spi, static void fsl_espi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t) struct spi_transfer *t)
{ {
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct fsl_espi *espi = spi_master_get_devdata(spi->master);
int bits_per_word = t ? t->bits_per_word : spi->bits_per_word; int bits_per_word = t ? t->bits_per_word : spi->bits_per_word;
u32 hz = t ? t->speed_hz : spi->max_speed_hz; u32 pm, hz = t ? t->speed_hz : spi->max_speed_hz;
u8 pm; struct fsl_espi_cs *cs = spi_get_ctldata(spi);
struct spi_mpc8xxx_cs *cs = spi->controller_state; u32 hw_mode_old = cs->hw_mode;
cs->rx_shift = 0;
cs->tx_shift = 0;
cs->get_rx = mpc8xxx_spi_rx_buf_u32;
cs->get_tx = mpc8xxx_spi_tx_buf_u32;
if (bits_per_word <= 8) {
cs->rx_shift = 8 - bits_per_word;
} else {
cs->rx_shift = 16 - bits_per_word;
if (spi->mode & SPI_LSB_FIRST)
cs->get_tx = fsl_espi_tx_buf_lsb;
}
mpc8xxx_spi->rx_shift = cs->rx_shift;
mpc8xxx_spi->tx_shift = cs->tx_shift;
mpc8xxx_spi->get_rx = cs->get_rx;
mpc8xxx_spi->get_tx = cs->get_tx;
/* mask out bits we are going to set */ /* mask out bits we are going to set */
cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF)); cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF));
cs->hw_mode |= CSMODE_LEN(bits_per_word - 1); cs->hw_mode |= CSMODE_LEN(bits_per_word - 1);
if ((mpc8xxx_spi->spibrg / hz) > 64) { pm = DIV_ROUND_UP(espi->spibrg, hz * 4) - 1;
if (pm > 15) {
cs->hw_mode |= CSMODE_DIV16; cs->hw_mode |= CSMODE_DIV16;
pm = DIV_ROUND_UP(mpc8xxx_spi->spibrg, hz * 16 * 4); pm = DIV_ROUND_UP(espi->spibrg, hz * 16 * 4) - 1;
WARN_ONCE(pm > 33, "%s: Requested speed is too low: %d Hz. "
"Will use %d Hz instead.\n", dev_name(&spi->dev),
hz, mpc8xxx_spi->spibrg / (4 * 16 * (32 + 1)));
if (pm > 33)
pm = 33;
} else {
pm = DIV_ROUND_UP(mpc8xxx_spi->spibrg, hz * 4);
} }
if (pm)
pm--;
if (pm < 2)
pm = 2;
cs->hw_mode |= CSMODE_PM(pm); cs->hw_mode |= CSMODE_PM(pm);
fsl_espi_change_mode(spi); /* don't write the mode register if the mode doesn't change */
if (cs->hw_mode != hw_mode_old)
fsl_espi_write_reg(espi, ESPI_SPMODEx(spi->chip_select),
cs->hw_mode);
} }
static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
{ {
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); struct fsl_espi *espi = spi_master_get_devdata(spi->master);
u32 word; unsigned int rx_len = t->len;
u32 mask, spcom;
int ret; int ret;
mpc8xxx_spi->len = t->len; reinit_completion(&espi->done);
mpc8xxx_spi->count = roundup(t->len, 4) / 4;
mpc8xxx_spi->tx = t->tx_buf;
mpc8xxx_spi->rx = t->rx_buf;
reinit_completion(&mpc8xxx_spi->done);
/* Set SPCOM[CS] and SPCOM[TRANLEN] field */ /* Set SPCOM[CS] and SPCOM[TRANLEN] field */
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPCOM, spcom = SPCOM_CS(spi->chip_select);
(SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1))); spcom |= SPCOM_TRANLEN(t->len - 1);
/* configure RXSKIP mode */
if (espi->rxskip) {
spcom |= SPCOM_RXSKIP(espi->rxskip);
rx_len = t->len - espi->rxskip;
if (t->rx_nbits == SPI_NBITS_DUAL)
spcom |= SPCOM_DO;
}
fsl_espi_write_reg(espi, ESPI_SPCOM, spcom);
/* enable rx ints */ /* enable interrupts */
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, SPIM_RNE); mask = SPIM_DON;
if (rx_len > FSL_ESPI_FIFO_SIZE)
mask |= SPIM_RXT;
fsl_espi_write_reg(espi, ESPI_SPIM, mask);
/* transmit word */ /* Prevent filling the fifo from getting interrupted */
word = mpc8xxx_spi->get_tx(mpc8xxx_spi); spin_lock_irq(&espi->lock);
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPITF, word); fsl_espi_fill_tx_fifo(espi, 0);
spin_unlock_irq(&espi->lock);
/* Won't hang up forever, SPI bus sometimes got lost interrupts... */ /* Won't hang up forever, SPI bus sometimes got lost interrupts... */
ret = wait_for_completion_timeout(&mpc8xxx_spi->done, 2 * HZ); ret = wait_for_completion_timeout(&espi->done, 2 * HZ);
if (ret == 0) if (ret == 0)
dev_err(mpc8xxx_spi->dev, dev_err(espi->dev, "Transfer timed out!\n");
"Transaction hanging up (left %d bytes)\n",
mpc8xxx_spi->count);
/* disable rx ints */ /* disable rx ints */
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, 0); fsl_espi_write_reg(espi, ESPI_SPIM, 0);
return mpc8xxx_spi->count > 0 ? -EMSGSIZE : 0; return ret == 0 ? -ETIMEDOUT : 0;
} }
static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
{ {
struct mpc8xxx_spi *mspi = spi_master_get_devdata(m->spi->master); struct fsl_espi *espi = spi_master_get_devdata(m->spi->master);
struct spi_device *spi = m->spi; struct spi_device *spi = m->spi;
int ret; int ret;
fsl_espi_copy_to_buf(m, mspi); /* In case of LSB-first and bits_per_word > 8 byte-swap all words */
espi->swab = spi->mode & SPI_LSB_FIRST && trans->bits_per_word > 8;
espi->m_transfers = &m->transfers;
espi->tx_t = list_first_entry(&m->transfers, struct spi_transfer,
transfer_list);
espi->tx_pos = 0;
espi->tx_done = false;
espi->rx_t = list_first_entry(&m->transfers, struct spi_transfer,
transfer_list);
espi->rx_pos = 0;
espi->rx_done = false;
espi->rxskip = fsl_espi_check_rxskip_mode(m);
if (trans->rx_nbits == SPI_NBITS_DUAL && !espi->rxskip) {
dev_err(espi->dev, "Dual output mode requires RXSKIP mode!\n");
return -EINVAL;
}
/* In RXSKIP mode skip first transfer for reads */
if (espi->rxskip)
espi->rx_t = list_next_entry(espi->rx_t, transfer_list);
fsl_espi_setup_transfer(spi, trans); fsl_espi_setup_transfer(spi, trans);
ret = fsl_espi_bufs(spi, trans); ret = fsl_espi_bufs(spi, trans);
...@@ -310,19 +434,13 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) ...@@ -310,19 +434,13 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans)
if (trans->delay_usecs) if (trans->delay_usecs)
udelay(trans->delay_usecs); udelay(trans->delay_usecs);
fsl_espi_setup_transfer(spi, NULL);
if (!ret)
fsl_espi_copy_from_buf(m, mspi);
return ret; return ret;
} }
static int fsl_espi_do_one_msg(struct spi_master *master, static int fsl_espi_do_one_msg(struct spi_master *master,
struct spi_message *m) struct spi_message *m)
{ {
struct mpc8xxx_spi *mspi = spi_master_get_devdata(m->spi->master); unsigned int delay_usecs = 0, rx_nbits = 0;
unsigned int delay_usecs = 0;
struct spi_transfer *t, trans = {}; struct spi_transfer *t, trans = {};
int ret; int ret;
...@@ -333,6 +451,8 @@ static int fsl_espi_do_one_msg(struct spi_master *master, ...@@ -333,6 +451,8 @@ static int fsl_espi_do_one_msg(struct spi_master *master,
list_for_each_entry(t, &m->transfers, transfer_list) { list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->delay_usecs > delay_usecs) if (t->delay_usecs > delay_usecs)
delay_usecs = t->delay_usecs; delay_usecs = t->delay_usecs;
if (t->rx_nbits > rx_nbits)
rx_nbits = t->rx_nbits;
} }
t = list_first_entry(&m->transfers, struct spi_transfer, t = list_first_entry(&m->transfers, struct spi_transfer,
...@@ -342,8 +462,7 @@ static int fsl_espi_do_one_msg(struct spi_master *master, ...@@ -342,8 +462,7 @@ static int fsl_espi_do_one_msg(struct spi_master *master,
trans.speed_hz = t->speed_hz; trans.speed_hz = t->speed_hz;
trans.bits_per_word = t->bits_per_word; trans.bits_per_word = t->bits_per_word;
trans.delay_usecs = delay_usecs; trans.delay_usecs = delay_usecs;
trans.tx_buf = mspi->local_buf; trans.rx_nbits = rx_nbits;
trans.rx_buf = mspi->local_buf;
if (trans.len) if (trans.len)
ret = fsl_espi_trans(m, &trans); ret = fsl_espi_trans(m, &trans);
...@@ -360,12 +479,9 @@ static int fsl_espi_do_one_msg(struct spi_master *master, ...@@ -360,12 +479,9 @@ static int fsl_espi_do_one_msg(struct spi_master *master,
static int fsl_espi_setup(struct spi_device *spi) static int fsl_espi_setup(struct spi_device *spi)
{ {
struct mpc8xxx_spi *mpc8xxx_spi; struct fsl_espi *espi;
u32 loop_mode; u32 loop_mode;
struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi); struct fsl_espi_cs *cs = spi_get_ctldata(spi);
if (!spi->max_speed_hz)
return -EINVAL;
if (!cs) { if (!cs) {
cs = kzalloc(sizeof(*cs), GFP_KERNEL); cs = kzalloc(sizeof(*cs), GFP_KERNEL);
...@@ -374,12 +490,11 @@ static int fsl_espi_setup(struct spi_device *spi) ...@@ -374,12 +490,11 @@ static int fsl_espi_setup(struct spi_device *spi)
spi_set_ctldata(spi, cs); spi_set_ctldata(spi, cs);
} }
mpc8xxx_spi = spi_master_get_devdata(spi->master); espi = spi_master_get_devdata(spi->master);
pm_runtime_get_sync(mpc8xxx_spi->dev); pm_runtime_get_sync(espi->dev);
cs->hw_mode = fsl_espi_read_reg(mpc8xxx_spi, cs->hw_mode = fsl_espi_read_reg(espi, ESPI_SPMODEx(spi->chip_select));
ESPI_SPMODEx(spi->chip_select));
/* mask out bits we are going to set */ /* mask out bits we are going to set */
cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH
| CSMODE_REV); | CSMODE_REV);
...@@ -392,115 +507,74 @@ static int fsl_espi_setup(struct spi_device *spi) ...@@ -392,115 +507,74 @@ static int fsl_espi_setup(struct spi_device *spi)
cs->hw_mode |= CSMODE_REV; cs->hw_mode |= CSMODE_REV;
/* Handle the loop mode */ /* Handle the loop mode */
loop_mode = fsl_espi_read_reg(mpc8xxx_spi, ESPI_SPMODE); loop_mode = fsl_espi_read_reg(espi, ESPI_SPMODE);
loop_mode &= ~SPMODE_LOOP; loop_mode &= ~SPMODE_LOOP;
if (spi->mode & SPI_LOOP) if (spi->mode & SPI_LOOP)
loop_mode |= SPMODE_LOOP; loop_mode |= SPMODE_LOOP;
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODE, loop_mode); fsl_espi_write_reg(espi, ESPI_SPMODE, loop_mode);
fsl_espi_setup_transfer(spi, NULL); fsl_espi_setup_transfer(spi, NULL);
pm_runtime_mark_last_busy(mpc8xxx_spi->dev); pm_runtime_mark_last_busy(espi->dev);
pm_runtime_put_autosuspend(mpc8xxx_spi->dev); pm_runtime_put_autosuspend(espi->dev);
return 0; return 0;
} }
static void fsl_espi_cleanup(struct spi_device *spi) static void fsl_espi_cleanup(struct spi_device *spi)
{ {
struct spi_mpc8xxx_cs *cs = spi_get_ctldata(spi); struct fsl_espi_cs *cs = spi_get_ctldata(spi);
kfree(cs); kfree(cs);
spi_set_ctldata(spi, NULL); spi_set_ctldata(spi, NULL);
} }
static void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events) static void fsl_espi_cpu_irq(struct fsl_espi *espi, u32 events)
{ {
/* We need handle RX first */ if (!espi->rx_done)
if (events & SPIE_RNE) { fsl_espi_read_rx_fifo(espi, events);
u32 rx_data, tmp;
u8 rx_data_8;
int rx_nr_bytes = 4;
int ret;
/* Spin until RX is done */
if (SPIE_RXCNT(events) < min(4, mspi->len)) {
ret = spin_event_timeout(
!(SPIE_RXCNT(events =
fsl_espi_read_reg(mspi, ESPI_SPIE)) <
min(4, mspi->len)),
10000, 0); /* 10 msec */
if (!ret)
dev_err(mspi->dev,
"tired waiting for SPIE_RXCNT\n");
}
if (mspi->len >= 4) { if (!espi->tx_done)
rx_data = fsl_espi_read_reg(mspi, ESPI_SPIRF); fsl_espi_fill_tx_fifo(espi, events);
} else if (mspi->len <= 0) {
dev_err(mspi->dev,
"unexpected RX(SPIE_RNE) interrupt occurred,\n"
"(local rxlen %d bytes, reg rxlen %d bytes)\n",
min(4, mspi->len), SPIE_RXCNT(events));
rx_nr_bytes = 0;
} else {
rx_nr_bytes = mspi->len;
tmp = mspi->len;
rx_data = 0;
while (tmp--) {
rx_data_8 = fsl_espi_read_reg8(mspi,
ESPI_SPIRF);
rx_data |= (rx_data_8 << (tmp * 8));
}
rx_data <<= (4 - mspi->len) * 8;
}
mspi->len -= rx_nr_bytes; if (!espi->tx_done || !espi->rx_done)
return;
if (rx_nr_bytes && mspi->rx) /* we're done, but check for errors before returning */
mspi->get_rx(rx_data, mspi); events = fsl_espi_read_reg(espi, ESPI_SPIE);
}
if (!(events & SPIE_TNF)) { if (!(events & SPIE_DON))
int ret; dev_err(espi->dev,
"Transfer done but SPIE_DON isn't set!\n");
/* spin until TX is done */
ret = spin_event_timeout(((events = fsl_espi_read_reg(
mspi, ESPI_SPIE)) & SPIE_TNF), 1000, 0);
if (!ret) {
dev_err(mspi->dev, "tired waiting for SPIE_TNF\n");
complete(&mspi->done);
return;
}
}
mspi->count -= 1; if (SPIE_RXCNT(events) || SPIE_TXCNT(events) != FSL_ESPI_FIFO_SIZE)
if (mspi->count) { dev_err(espi->dev, "Transfer done but rx/tx fifo's aren't empty!\n");
u32 word = mspi->get_tx(mspi);
fsl_espi_write_reg(mspi, ESPI_SPITF, word); complete(&espi->done);
} else {
complete(&mspi->done);
}
} }
static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
{ {
struct mpc8xxx_spi *mspi = context_data; struct fsl_espi *espi = context_data;
u32 events; u32 events;
spin_lock(&espi->lock);
/* Get interrupt events(tx/rx) */ /* Get interrupt events(tx/rx) */
events = fsl_espi_read_reg(mspi, ESPI_SPIE); events = fsl_espi_read_reg(espi, ESPI_SPIE);
if (!events) if (!events) {
spin_unlock(&espi->lock);
return IRQ_NONE; return IRQ_NONE;
}
dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events); dev_vdbg(espi->dev, "%s: events %x\n", __func__, events);
fsl_espi_cpu_irq(mspi, events); fsl_espi_cpu_irq(espi, events);
/* Clear the events */ /* Clear the events */
fsl_espi_write_reg(mspi, ESPI_SPIE, events); fsl_espi_write_reg(espi, ESPI_SPIE, events);
spin_unlock(&espi->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -509,12 +583,12 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) ...@@ -509,12 +583,12 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
static int fsl_espi_runtime_suspend(struct device *dev) static int fsl_espi_runtime_suspend(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); struct fsl_espi *espi = spi_master_get_devdata(master);
u32 regval; u32 regval;
regval = fsl_espi_read_reg(mpc8xxx_spi, ESPI_SPMODE); regval = fsl_espi_read_reg(espi, ESPI_SPMODE);
regval &= ~SPMODE_ENABLE; regval &= ~SPMODE_ENABLE;
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODE, regval); fsl_espi_write_reg(espi, ESPI_SPMODE, regval);
return 0; return 0;
} }
...@@ -522,12 +596,12 @@ static int fsl_espi_runtime_suspend(struct device *dev) ...@@ -522,12 +596,12 @@ static int fsl_espi_runtime_suspend(struct device *dev)
static int fsl_espi_runtime_resume(struct device *dev) static int fsl_espi_runtime_resume(struct device *dev)
{ {
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); struct fsl_espi *espi = spi_master_get_devdata(master);
u32 regval; u32 regval;
regval = fsl_espi_read_reg(mpc8xxx_spi, ESPI_SPMODE); regval = fsl_espi_read_reg(espi, ESPI_SPMODE);
regval |= SPMODE_ENABLE; regval |= SPMODE_ENABLE;
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODE, regval); fsl_espi_write_reg(espi, ESPI_SPMODE, regval);
return 0; return 0;
} }
...@@ -538,96 +612,105 @@ static size_t fsl_espi_max_message_size(struct spi_device *spi) ...@@ -538,96 +612,105 @@ static size_t fsl_espi_max_message_size(struct spi_device *spi)
return SPCOM_TRANLEN_MAX; return SPCOM_TRANLEN_MAX;
} }
static void fsl_espi_init_regs(struct device *dev, bool initial)
{
struct spi_master *master = dev_get_drvdata(dev);
struct fsl_espi *espi = spi_master_get_devdata(master);
struct device_node *nc;
u32 csmode, cs, prop;
int ret;
/* SPI controller initializations */
fsl_espi_write_reg(espi, ESPI_SPMODE, 0);
fsl_espi_write_reg(espi, ESPI_SPIM, 0);
fsl_espi_write_reg(espi, ESPI_SPCOM, 0);
fsl_espi_write_reg(espi, ESPI_SPIE, 0xffffffff);
/* Init eSPI CS mode register */
for_each_available_child_of_node(master->dev.of_node, nc) {
/* get chip select */
ret = of_property_read_u32(nc, "reg", &cs);
if (ret || cs >= master->num_chipselect)
continue;
csmode = CSMODE_INIT_VAL;
/* check if CSBEF is set in device tree */
ret = of_property_read_u32(nc, "fsl,csbef", &prop);
if (!ret) {
csmode &= ~(CSMODE_BEF(0xf));
csmode |= CSMODE_BEF(prop);
}
/* check if CSAFT is set in device tree */
ret = of_property_read_u32(nc, "fsl,csaft", &prop);
if (!ret) {
csmode &= ~(CSMODE_AFT(0xf));
csmode |= CSMODE_AFT(prop);
}
fsl_espi_write_reg(espi, ESPI_SPMODEx(cs), csmode);
if (initial)
dev_info(dev, "cs=%u, init_csmode=0x%x\n", cs, csmode);
}
/* Enable SPI interface */
fsl_espi_write_reg(espi, ESPI_SPMODE, SPMODE_INIT_VAL | SPMODE_ENABLE);
}
static int fsl_espi_probe(struct device *dev, struct resource *mem, static int fsl_espi_probe(struct device *dev, struct resource *mem,
unsigned int irq) unsigned int irq, unsigned int num_cs)
{ {
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master; struct spi_master *master;
struct mpc8xxx_spi *mpc8xxx_spi; struct fsl_espi *espi;
struct device_node *nc; int ret;
const __be32 *prop;
u32 regval, csmode;
int i, len, ret;
master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi)); master = spi_alloc_master(dev, sizeof(struct fsl_espi));
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
dev_set_drvdata(dev, master); dev_set_drvdata(dev, master);
mpc8xxx_spi_probe(dev, mem, irq); master->mode_bits = SPI_RX_DUAL | SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
SPI_LSB_FIRST | SPI_LOOP;
master->dev.of_node = dev->of_node;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
master->setup = fsl_espi_setup; master->setup = fsl_espi_setup;
master->cleanup = fsl_espi_cleanup; master->cleanup = fsl_espi_cleanup;
master->transfer_one_message = fsl_espi_do_one_msg; master->transfer_one_message = fsl_espi_do_one_msg;
master->auto_runtime_pm = true; master->auto_runtime_pm = true;
master->max_message_size = fsl_espi_max_message_size; master->max_message_size = fsl_espi_max_message_size;
master->num_chipselect = num_cs;
mpc8xxx_spi = spi_master_get_devdata(master); espi = spi_master_get_devdata(master);
spin_lock_init(&espi->lock);
mpc8xxx_spi->local_buf = espi->dev = dev;
devm_kmalloc(dev, SPCOM_TRANLEN_MAX, GFP_KERNEL); espi->spibrg = fsl_get_sys_freq();
if (!mpc8xxx_spi->local_buf) { if (espi->spibrg == -1) {
ret = -ENOMEM; dev_err(dev, "Can't get sys frequency!\n");
ret = -EINVAL;
goto err_probe; goto err_probe;
} }
/* determined by clock divider fields DIV16/PM in register SPMODEx */
master->min_speed_hz = DIV_ROUND_UP(espi->spibrg, 4 * 16 * 16);
master->max_speed_hz = DIV_ROUND_UP(espi->spibrg, 4);
mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem); init_completion(&espi->done);
if (IS_ERR(mpc8xxx_spi->reg_base)) {
ret = PTR_ERR(mpc8xxx_spi->reg_base); espi->reg_base = devm_ioremap_resource(dev, mem);
if (IS_ERR(espi->reg_base)) {
ret = PTR_ERR(espi->reg_base);
goto err_probe; goto err_probe;
} }
/* Register for SPI Interrupt */ /* Register for SPI Interrupt */
ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_espi_irq, ret = devm_request_irq(dev, irq, fsl_espi_irq, 0, "fsl_espi", espi);
0, "fsl_espi", mpc8xxx_spi);
if (ret) if (ret)
goto err_probe; goto err_probe;
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { fsl_espi_init_regs(dev, true);
mpc8xxx_spi->rx_shift = 16;
mpc8xxx_spi->tx_shift = 24;
}
/* SPI controller initializations */
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODE, 0);
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, 0);
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPCOM, 0);
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIE, 0xffffffff);
/* Init eSPI CS mode register */
for_each_available_child_of_node(master->dev.of_node, nc) {
/* get chip select */
prop = of_get_property(nc, "reg", &len);
if (!prop || len < sizeof(*prop))
continue;
i = be32_to_cpup(prop);
if (i < 0 || i >= pdata->max_chipselect)
continue;
csmode = CSMODE_INIT_VAL;
/* check if CSBEF is set in device tree */
prop = of_get_property(nc, "fsl,csbef", &len);
if (prop && len >= sizeof(*prop)) {
csmode &= ~(CSMODE_BEF(0xf));
csmode |= CSMODE_BEF(be32_to_cpup(prop));
}
/* check if CSAFT is set in device tree */
prop = of_get_property(nc, "fsl,csaft", &len);
if (prop && len >= sizeof(*prop)) {
csmode &= ~(CSMODE_AFT(0xf));
csmode |= CSMODE_AFT(be32_to_cpup(prop));
}
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODEx(i), csmode);
dev_info(dev, "cs=%d, init_csmode=0x%x\n", i, csmode);
}
/* Enable SPI interface */
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODE, regval);
pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT); pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT);
pm_runtime_use_autosuspend(dev); pm_runtime_use_autosuspend(dev);
...@@ -639,8 +722,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, ...@@ -639,8 +722,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
if (ret < 0) if (ret < 0)
goto err_pm; goto err_pm;
dev_info(dev, "at 0x%p (irq = %d)\n", mpc8xxx_spi->reg_base, dev_info(dev, "at 0x%p (irq = %u)\n", espi->reg_base, irq);
mpc8xxx_spi->irq);
pm_runtime_mark_last_busy(dev); pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev); pm_runtime_put_autosuspend(dev);
...@@ -659,20 +741,16 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, ...@@ -659,20 +741,16 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem,
static int of_fsl_espi_get_chipselects(struct device *dev) static int of_fsl_espi_get_chipselects(struct device *dev)
{ {
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); u32 num_cs;
const u32 *prop; int ret;
int len;
prop = of_get_property(np, "fsl,espi-num-chipselects", &len); ret = of_property_read_u32(np, "fsl,espi-num-chipselects", &num_cs);
if (!prop || len < sizeof(*prop)) { if (ret) {
dev_err(dev, "No 'fsl,espi-num-chipselects' property\n"); dev_err(dev, "No 'fsl,espi-num-chipselects' property\n");
return -EINVAL; return 0;
} }
pdata->max_chipselect = *prop; return num_cs;
pdata->cs_control = NULL;
return 0;
} }
static int of_fsl_espi_probe(struct platform_device *ofdev) static int of_fsl_espi_probe(struct platform_device *ofdev)
...@@ -680,16 +758,17 @@ static int of_fsl_espi_probe(struct platform_device *ofdev) ...@@ -680,16 +758,17 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
struct device *dev = &ofdev->dev; struct device *dev = &ofdev->dev;
struct device_node *np = ofdev->dev.of_node; struct device_node *np = ofdev->dev.of_node;
struct resource mem; struct resource mem;
unsigned int irq; unsigned int irq, num_cs;
int ret; int ret;
ret = of_mpc8xxx_spi_probe(ofdev); if (of_property_read_bool(np, "mode")) {
if (ret) dev_err(dev, "mode property is not supported on ESPI!\n");
return ret; return -EINVAL;
}
ret = of_fsl_espi_get_chipselects(dev); num_cs = of_fsl_espi_get_chipselects(dev);
if (ret) if (!num_cs)
return ret; return -EINVAL;
ret = of_address_to_resource(np, 0, &mem); ret = of_address_to_resource(np, 0, &mem);
if (ret) if (ret)
...@@ -699,7 +778,7 @@ static int of_fsl_espi_probe(struct platform_device *ofdev) ...@@ -699,7 +778,7 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
if (!irq) if (!irq)
return -EINVAL; return -EINVAL;
return fsl_espi_probe(dev, &mem, irq); return fsl_espi_probe(dev, &mem, irq, num_cs);
} }
static int of_fsl_espi_remove(struct platform_device *dev) static int of_fsl_espi_remove(struct platform_device *dev)
...@@ -721,38 +800,15 @@ static int of_fsl_espi_suspend(struct device *dev) ...@@ -721,38 +800,15 @@ static int of_fsl_espi_suspend(struct device *dev)
return ret; return ret;
} }
ret = pm_runtime_force_suspend(dev); return pm_runtime_force_suspend(dev);
if (ret < 0)
return ret;
return 0;
} }
static int of_fsl_espi_resume(struct device *dev) static int of_fsl_espi_resume(struct device *dev)
{ {
struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
struct spi_master *master = dev_get_drvdata(dev); struct spi_master *master = dev_get_drvdata(dev);
struct mpc8xxx_spi *mpc8xxx_spi; int ret;
u32 regval;
int i, ret;
mpc8xxx_spi = spi_master_get_devdata(master);
/* SPI controller initializations */
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODE, 0);
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIM, 0);
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPCOM, 0);
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPIE, 0xffffffff);
/* Init eSPI CS mode register */
for (i = 0; i < pdata->max_chipselect; i++)
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODEx(i),
CSMODE_INIT_VAL);
/* Enable SPI interface */
regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
fsl_espi_write_reg(mpc8xxx_spi, ESPI_SPMODE, regval); fsl_espi_init_regs(dev, false);
ret = pm_runtime_force_resume(dev); ret = pm_runtime_force_resume(dev);
if (ret < 0) if (ret < 0)
......
...@@ -28,10 +28,6 @@ struct mpc8xxx_spi { ...@@ -28,10 +28,6 @@ struct mpc8xxx_spi {
/* rx & tx bufs from the spi_transfer */ /* rx & tx bufs from the spi_transfer */
const void *tx; const void *tx;
void *rx; void *rx;
#if IS_ENABLED(CONFIG_SPI_FSL_ESPI)
int len;
u8 *local_buf;
#endif
int subblock; int subblock;
struct spi_pram __iomem *pram; struct spi_pram __iomem *pram;
......
...@@ -1042,8 +1042,14 @@ static int spi_transfer_one_message(struct spi_master *master, ...@@ -1042,8 +1042,14 @@ static int spi_transfer_one_message(struct spi_master *master,
if (msg->status != -EINPROGRESS) if (msg->status != -EINPROGRESS)
goto out; goto out;
if (xfer->delay_usecs) if (xfer->delay_usecs) {
udelay(xfer->delay_usecs); u16 us = xfer->delay_usecs;
if (us <= 10)
udelay(us);
else
usleep_range(us, us + DIV_ROUND_UP(us, 10));
}
if (xfer->cs_change) { if (xfer->cs_change) {
if (list_is_last(&xfer->transfer_list, if (list_is_last(&xfer->transfer_list,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment