mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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:
		
							parent
							
								
									973fbce69e
								
							
						
					
					
						commit
						9298bc7273
					
				
					 2 changed files with 66 additions and 69 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue