spi: spi-fsl-dspi: Remove spi-bitbang

DSPI module need cs change information in
a spi transfer. According to cs change, DSPI
will give last data the right flag. Bitbang
provide cs change behind the last data in
a transfer. So DSPI can not deal the last
data in every transfer properly, so remove
the bitbang in the driver.

Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Chao Fu 2015-01-27 16:27:22 +05:30 коммит произвёл Mark Brown
Родитель 973fbce69e
Коммит 9298bc7273
2 изменённых файлов: 66 добавлений и 69 удалений

Просмотреть файл

@ -292,7 +292,6 @@ config SPI_FSL_SPI
config SPI_FSL_DSPI config SPI_FSL_DSPI
tristate "Freescale DSPI controller" tristate "Freescale DSPI controller"
select SPI_BITBANG
select REGMAP_MMIO select REGMAP_MMIO
depends on SOC_VF610 || COMPILE_TEST depends on SOC_VF610 || COMPILE_TEST
help help

Просмотреть файл

@ -106,7 +106,7 @@ struct chip_data {
}; };
struct fsl_dspi { struct fsl_dspi {
struct spi_bitbang bitbang; struct spi_master *master;
struct platform_device *pdev; struct platform_device *pdev;
struct regmap *regmap; struct regmap *regmap;
@ -114,6 +114,7 @@ struct fsl_dspi {
struct clk *clk; struct clk *clk;
struct spi_transfer *cur_transfer; struct spi_transfer *cur_transfer;
struct spi_message *cur_msg;
struct chip_data *cur_chip; struct chip_data *cur_chip;
size_t len; size_t len;
void *tx; void *tx;
@ -123,6 +124,7 @@ struct fsl_dspi {
char dataflags; char dataflags;
u8 cs; u8 cs;
u16 void_write_data; u16 void_write_data;
u32 cs_change;
wait_queue_head_t waitq; wait_queue_head_t waitq;
u32 waitflags; u32 waitflags;
@ -225,6 +227,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi)
if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) { if (dspi->len == 0 || tx_count == DSPI_FIFO_SIZE - 1) {
/* last transfer in the transfer */ /* last transfer in the transfer */
dspi_pushr |= SPI_PUSHR_EOQ; dspi_pushr |= SPI_PUSHR_EOQ;
if ((dspi->cs_change) && (!dspi->len))
dspi_pushr &= ~SPI_PUSHR_CONT;
} else if (tx_word && (dspi->len == 1)) } else if (tx_word && (dspi->len == 1))
dspi_pushr |= SPI_PUSHR_EOQ; dspi_pushr |= SPI_PUSHR_EOQ;
@ -246,6 +250,7 @@ static int dspi_transfer_read(struct fsl_dspi *dspi)
int rx_count = 0; int rx_count = 0;
int rx_word = is_double_byte_mode(dspi); int rx_word = is_double_byte_mode(dspi);
u16 d; u16 d;
while ((dspi->rx < dspi->rx_end) while ((dspi->rx < dspi->rx_end)
&& (rx_count < DSPI_FIFO_SIZE)) { && (rx_count < DSPI_FIFO_SIZE)) {
if (rx_word) { if (rx_word) {
@ -276,64 +281,67 @@ static int dspi_transfer_read(struct fsl_dspi *dspi)
return rx_count; return rx_count;
} }
static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) static int dspi_transfer_one_message(struct spi_master *master,
struct spi_message *message)
{ {
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); struct fsl_dspi *dspi = spi_master_get_devdata(master);
dspi->cur_transfer = t; struct spi_device *spi = message->spi;
dspi->cur_chip = spi_get_ctldata(spi); struct spi_transfer *transfer;
dspi->cs = spi->chip_select; int status = 0;
dspi->void_write_data = dspi->cur_chip->void_write_data; message->actual_length = 0;
dspi->dataflags = 0; list_for_each_entry(transfer, &message->transfers, transfer_list) {
dspi->tx = (void *)t->tx_buf; dspi->cur_transfer = transfer;
dspi->tx_end = dspi->tx + t->len; dspi->cur_msg = message;
dspi->rx = t->rx_buf; dspi->cur_chip = spi_get_ctldata(spi);
dspi->rx_end = dspi->rx + t->len; dspi->cs = spi->chip_select;
dspi->len = t->len; if (dspi->cur_transfer->transfer_list.next
== &dspi->cur_msg->transfers)
transfer->cs_change = 1;
dspi->cs_change = transfer->cs_change;
dspi->void_write_data = dspi->cur_chip->void_write_data;
if (!dspi->rx) dspi->dataflags = 0;
dspi->dataflags |= TRAN_STATE_RX_VOID; dspi->tx = (void *)transfer->tx_buf;
dspi->tx_end = dspi->tx + transfer->len;
dspi->rx = transfer->rx_buf;
dspi->rx_end = dspi->rx + transfer->len;
dspi->len = transfer->len;
if (!dspi->tx) if (!dspi->rx)
dspi->dataflags |= TRAN_STATE_TX_VOID; dspi->dataflags |= TRAN_STATE_RX_VOID;
regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val); if (!dspi->tx)
regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val); dspi->dataflags |= TRAN_STATE_TX_VOID;
regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
if (t->speed_hz) regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val);
regmap_update_bits(dspi->regmap, SPI_MCR,
SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF,
SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF);
regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
dspi->cur_chip->ctar_val); dspi->cur_chip->ctar_val);
if (transfer->speed_hz)
regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
dspi->cur_chip->ctar_val);
dspi_transfer_write(dspi); regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE);
message->actual_length += dspi_transfer_write(dspi);
if (wait_event_interruptible(dspi->waitq, dspi->waitflags)) if (wait_event_interruptible(dspi->waitq, dspi->waitflags))
dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n"); dev_err(&dspi->pdev->dev, "wait transfer complete fail!\n");
dspi->waitflags = 0; dspi->waitflags = 0;
return t->len - dspi->len; if (transfer->delay_usecs)
} udelay(transfer->delay_usecs);
static void dspi_chipselect(struct spi_device *spi, int value)
{
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
unsigned int pushr;
regmap_read(dspi->regmap, SPI_PUSHR, &pushr);
switch (value) {
case BITBANG_CS_ACTIVE:
pushr |= SPI_PUSHR_CONT;
break;
case BITBANG_CS_INACTIVE:
pushr &= ~SPI_PUSHR_CONT;
break;
} }
regmap_write(dspi->regmap, SPI_PUSHR, pushr); message->status = status;
spi_finalize_current_message(master);
return status;
} }
static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) static int dspi_setup(struct spi_device *spi)
{ {
struct chip_data *chip; struct chip_data *chip;
struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); struct fsl_dspi *dspi = spi_master_get_devdata(spi->master);
@ -373,14 +381,6 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
return 0; return 0;
} }
static int dspi_setup(struct spi_device *spi)
{
if (!spi->max_speed_hz)
return -EINVAL;
return dspi_setup_transfer(spi, NULL);
}
static void dspi_cleanup(struct spi_device *spi) static void dspi_cleanup(struct spi_device *spi)
{ {
struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi); struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
@ -395,22 +395,20 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
{ {
struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id;
regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); struct spi_message *msg = dspi->cur_msg;
regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF);
dspi_transfer_read(dspi); dspi_transfer_read(dspi);
if (!dspi->len) { if (!dspi->len) {
if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM)
regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16));
dspi->waitflags = 1; dspi->waitflags = 1;
wake_up_interruptible(&dspi->waitq); wake_up_interruptible(&dspi->waitq);
} else { } else
dspi_transfer_write(dspi); msg->actual_length += dspi_transfer_write(dspi);
return IRQ_HANDLED;
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -469,12 +467,12 @@ static int dspi_probe(struct platform_device *pdev)
dspi = spi_master_get_devdata(master); dspi = spi_master_get_devdata(master);
dspi->pdev = pdev; dspi->pdev = pdev;
dspi->bitbang.master = master; dspi->master = master;
dspi->bitbang.chipselect = dspi_chipselect;
dspi->bitbang.setup_transfer = dspi_setup_transfer; master->transfer = NULL;
dspi->bitbang.txrx_bufs = dspi_txrx_transfer; master->setup = dspi_setup;
dspi->bitbang.master->setup = dspi_setup; master->transfer_one_message = dspi_transfer_one_message;
dspi->bitbang.master->dev.of_node = pdev->dev.of_node; master->dev.of_node = pdev->dev.of_node;
master->cleanup = dspi_cleanup; master->cleanup = dspi_cleanup;
master->mode_bits = SPI_CPOL | SPI_CPHA; master->mode_bits = SPI_CPOL | SPI_CPHA;
@ -535,7 +533,7 @@ static int dspi_probe(struct platform_device *pdev)
init_waitqueue_head(&dspi->waitq); init_waitqueue_head(&dspi->waitq);
platform_set_drvdata(pdev, master); platform_set_drvdata(pdev, master);
ret = spi_bitbang_start(&dspi->bitbang); ret = spi_register_master(master);
if (ret != 0) { if (ret != 0) {
dev_err(&pdev->dev, "Problem registering DSPI master\n"); dev_err(&pdev->dev, "Problem registering DSPI master\n");
goto out_clk_put; goto out_clk_put;
@ -557,9 +555,9 @@ 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 */
spi_bitbang_stop(&dspi->bitbang);
clk_disable_unprepare(dspi->clk); clk_disable_unprepare(dspi->clk);
spi_master_put(dspi->bitbang.master); spi_unregister_master(dspi->master);
spi_master_put(dspi->master);
return 0; return 0;
} }