mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	spi: atmel: Switch to transfer_one transfer method
Switch from using our own transfer_one_message routine to using the one provided by the SPI core. Signed-off-by: Dan Sneddon <dan.sneddon@microchip.com> Link: https://lore.kernel.org/r/20210602160816.4890-1-dan.sneddon@microchip.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
		
							parent
							
								
									ec679bda63
								
							
						
					
					
						commit
						5fa5e6dec7
					
				
					 1 changed files with 33 additions and 91 deletions
				
			
		| 
						 | 
					@ -863,7 +863,6 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
 | 
				
			||||||
 * lock is held, spi irq is blocked
 | 
					 * lock is held, spi irq is blocked
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void atmel_spi_pdc_next_xfer(struct spi_master *master,
 | 
					static void atmel_spi_pdc_next_xfer(struct spi_master *master,
 | 
				
			||||||
					struct spi_message *msg,
 | 
					 | 
				
			||||||
					struct spi_transfer *xfer)
 | 
										struct spi_transfer *xfer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct atmel_spi	*as = spi_master_get_devdata(master);
 | 
						struct atmel_spi	*as = spi_master_get_devdata(master);
 | 
				
			||||||
| 
						 | 
					@ -879,12 +878,12 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
 | 
				
			||||||
	spi_writel(as, RPR, rx_dma);
 | 
						spi_writel(as, RPR, rx_dma);
 | 
				
			||||||
	spi_writel(as, TPR, tx_dma);
 | 
						spi_writel(as, TPR, tx_dma);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (msg->spi->bits_per_word > 8)
 | 
						if (xfer->bits_per_word > 8)
 | 
				
			||||||
		len >>= 1;
 | 
							len >>= 1;
 | 
				
			||||||
	spi_writel(as, RCR, len);
 | 
						spi_writel(as, RCR, len);
 | 
				
			||||||
	spi_writel(as, TCR, len);
 | 
						spi_writel(as, TCR, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(&msg->spi->dev,
 | 
						dev_dbg(&master->dev,
 | 
				
			||||||
		"  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
 | 
							"  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
 | 
				
			||||||
		xfer, xfer->len, xfer->tx_buf,
 | 
							xfer, xfer->len, xfer->tx_buf,
 | 
				
			||||||
		(unsigned long long)xfer->tx_dma, xfer->rx_buf,
 | 
							(unsigned long long)xfer->tx_dma, xfer->rx_buf,
 | 
				
			||||||
| 
						 | 
					@ -898,12 +897,12 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master,
 | 
				
			||||||
		spi_writel(as, RNPR, rx_dma);
 | 
							spi_writel(as, RNPR, rx_dma);
 | 
				
			||||||
		spi_writel(as, TNPR, tx_dma);
 | 
							spi_writel(as, TNPR, tx_dma);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (msg->spi->bits_per_word > 8)
 | 
							if (xfer->bits_per_word > 8)
 | 
				
			||||||
			len >>= 1;
 | 
								len >>= 1;
 | 
				
			||||||
		spi_writel(as, RNCR, len);
 | 
							spi_writel(as, RNCR, len);
 | 
				
			||||||
		spi_writel(as, TNCR, len);
 | 
							spi_writel(as, TNCR, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dev_dbg(&msg->spi->dev,
 | 
							dev_dbg(&master->dev,
 | 
				
			||||||
			"  next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
 | 
								"  next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
 | 
				
			||||||
			xfer, xfer->len, xfer->tx_buf,
 | 
								xfer, xfer->len, xfer->tx_buf,
 | 
				
			||||||
			(unsigned long long)xfer->tx_dma, xfer->rx_buf,
 | 
								(unsigned long long)xfer->tx_dma, xfer->rx_buf,
 | 
				
			||||||
| 
						 | 
					@ -1273,12 +1272,28 @@ static int atmel_spi_setup(struct spi_device *spi)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void atmel_spi_set_cs(struct spi_device *spi, bool enable)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct atmel_spi *as = spi_master_get_devdata(spi->master);
 | 
				
			||||||
 | 
						/* the core doesn't really pass us enable/disable, but CS HIGH vs CS LOW
 | 
				
			||||||
 | 
						 * since we already have routines for activate/deactivate translate
 | 
				
			||||||
 | 
						 * high/low to active/inactive
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						enable = (!!(spi->mode & SPI_CS_HIGH) == enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (enable) {
 | 
				
			||||||
 | 
							cs_activate(as, spi);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							cs_deactivate(as, spi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int atmel_spi_one_transfer(struct spi_master *master,
 | 
					static int atmel_spi_one_transfer(struct spi_master *master,
 | 
				
			||||||
					struct spi_message *msg,
 | 
										struct spi_device *spi,
 | 
				
			||||||
					struct spi_transfer *xfer)
 | 
										struct spi_transfer *xfer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct atmel_spi	*as;
 | 
						struct atmel_spi	*as;
 | 
				
			||||||
	struct spi_device	*spi = msg->spi;
 | 
					 | 
				
			||||||
	u8			bits;
 | 
						u8			bits;
 | 
				
			||||||
	u32			len;
 | 
						u32			len;
 | 
				
			||||||
	struct atmel_spi_device	*asd;
 | 
						struct atmel_spi_device	*asd;
 | 
				
			||||||
| 
						 | 
					@ -1287,11 +1302,8 @@ static int atmel_spi_one_transfer(struct spi_master *master,
 | 
				
			||||||
	unsigned long		dma_timeout;
 | 
						unsigned long		dma_timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	as = spi_master_get_devdata(master);
 | 
						as = spi_master_get_devdata(master);
 | 
				
			||||||
 | 
						/* This lock was orignally taken in atmel_spi_trasfer_one_message */
 | 
				
			||||||
	if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
 | 
						atmel_spi_lock(as);
 | 
				
			||||||
		dev_dbg(&spi->dev, "missing rx or tx buf\n");
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	asd = spi->controller_state;
 | 
						asd = spi->controller_state;
 | 
				
			||||||
	bits = (asd->csr >> 4) & 0xf;
 | 
						bits = (asd->csr >> 4) & 0xf;
 | 
				
			||||||
| 
						 | 
					@ -1305,13 +1317,13 @@ static int atmel_spi_one_transfer(struct spi_master *master,
 | 
				
			||||||
	 * DMA map early, for performance (empties dcache ASAP) and
 | 
						 * DMA map early, for performance (empties dcache ASAP) and
 | 
				
			||||||
	 * better fault reporting.
 | 
						 * better fault reporting.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if ((!msg->is_dma_mapped)
 | 
						if ((!master->cur_msg_mapped)
 | 
				
			||||||
		&& as->use_pdc) {
 | 
							&& as->use_pdc) {
 | 
				
			||||||
		if (atmel_spi_dma_map_xfer(as, xfer) < 0)
 | 
							if (atmel_spi_dma_map_xfer(as, xfer) < 0)
 | 
				
			||||||
			return -ENOMEM;
 | 
								return -ENOMEM;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	atmel_spi_set_xfer_speed(as, msg->spi, xfer);
 | 
						atmel_spi_set_xfer_speed(as, spi, xfer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	as->done_status = 0;
 | 
						as->done_status = 0;
 | 
				
			||||||
	as->current_transfer = xfer;
 | 
						as->current_transfer = xfer;
 | 
				
			||||||
| 
						 | 
					@ -1320,7 +1332,7 @@ static int atmel_spi_one_transfer(struct spi_master *master,
 | 
				
			||||||
		reinit_completion(&as->xfer_completion);
 | 
							reinit_completion(&as->xfer_completion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (as->use_pdc) {
 | 
							if (as->use_pdc) {
 | 
				
			||||||
			atmel_spi_pdc_next_xfer(master, msg, xfer);
 | 
								atmel_spi_pdc_next_xfer(master, xfer);
 | 
				
			||||||
		} else if (atmel_spi_use_dma(as, xfer)) {
 | 
							} else if (atmel_spi_use_dma(as, xfer)) {
 | 
				
			||||||
			len = as->current_remaining_bytes;
 | 
								len = as->current_remaining_bytes;
 | 
				
			||||||
			ret = atmel_spi_next_xfer_dma_submit(master,
 | 
								ret = atmel_spi_next_xfer_dma_submit(master,
 | 
				
			||||||
| 
						 | 
					@ -1328,7 +1340,8 @@ static int atmel_spi_one_transfer(struct spi_master *master,
 | 
				
			||||||
			if (ret) {
 | 
								if (ret) {
 | 
				
			||||||
				dev_err(&spi->dev,
 | 
									dev_err(&spi->dev,
 | 
				
			||||||
					"unable to use DMA, fallback to PIO\n");
 | 
										"unable to use DMA, fallback to PIO\n");
 | 
				
			||||||
				atmel_spi_next_xfer_pio(master, xfer);
 | 
									as->done_status = ret;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				as->current_remaining_bytes -= len;
 | 
									as->current_remaining_bytes -= len;
 | 
				
			||||||
				if (as->current_remaining_bytes < 0)
 | 
									if (as->current_remaining_bytes < 0)
 | 
				
			||||||
| 
						 | 
					@ -1381,90 +1394,18 @@ static int atmel_spi_one_transfer(struct spi_master *master,
 | 
				
			||||||
		} else if (atmel_spi_use_dma(as, xfer)) {
 | 
							} else if (atmel_spi_use_dma(as, xfer)) {
 | 
				
			||||||
			atmel_spi_stop_dma(master);
 | 
								atmel_spi_stop_dma(master);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!msg->is_dma_mapped
 | 
					 | 
				
			||||||
			&& as->use_pdc)
 | 
					 | 
				
			||||||
			atmel_spi_dma_unmap_xfer(master, xfer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/* only update length if no error */
 | 
					 | 
				
			||||||
		msg->actual_length += xfer->len;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!msg->is_dma_mapped
 | 
						if (!master->cur_msg_mapped
 | 
				
			||||||
		&& as->use_pdc)
 | 
							&& as->use_pdc)
 | 
				
			||||||
		atmel_spi_dma_unmap_xfer(master, xfer);
 | 
							atmel_spi_dma_unmap_xfer(master, xfer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spi_transfer_delay_exec(xfer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (xfer->cs_change) {
 | 
					 | 
				
			||||||
		if (list_is_last(&xfer->transfer_list,
 | 
					 | 
				
			||||||
				 &msg->transfers)) {
 | 
					 | 
				
			||||||
			as->keep_cs = true;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			cs_deactivate(as, msg->spi);
 | 
					 | 
				
			||||||
			udelay(10);
 | 
					 | 
				
			||||||
			cs_activate(as, msg->spi);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int atmel_spi_transfer_one_message(struct spi_master *master,
 | 
					 | 
				
			||||||
						struct spi_message *msg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct atmel_spi *as;
 | 
					 | 
				
			||||||
	struct spi_transfer *xfer;
 | 
					 | 
				
			||||||
	struct spi_device *spi = msg->spi;
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	as = spi_master_get_devdata(master);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_dbg(&spi->dev, "new message %p submitted for %s\n",
 | 
					 | 
				
			||||||
					msg, dev_name(&spi->dev));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	atmel_spi_lock(as);
 | 
					 | 
				
			||||||
	cs_activate(as, spi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	as->keep_cs = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	msg->status = 0;
 | 
					 | 
				
			||||||
	msg->actual_length = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 | 
					 | 
				
			||||||
		trace_spi_transfer_start(msg, xfer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret = atmel_spi_one_transfer(master, msg, xfer);
 | 
					 | 
				
			||||||
		if (ret)
 | 
					 | 
				
			||||||
			goto msg_done;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		trace_spi_transfer_stop(msg, xfer);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (as->use_pdc)
 | 
						if (as->use_pdc)
 | 
				
			||||||
		atmel_spi_disable_pdc_transfer(as);
 | 
							atmel_spi_disable_pdc_transfer(as);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 | 
					 | 
				
			||||||
		dev_dbg(&spi->dev,
 | 
					 | 
				
			||||||
			"  xfer %p: len %u tx %p/%pad rx %p/%pad\n",
 | 
					 | 
				
			||||||
			xfer, xfer->len,
 | 
					 | 
				
			||||||
			xfer->tx_buf, &xfer->tx_dma,
 | 
					 | 
				
			||||||
			xfer->rx_buf, &xfer->rx_dma);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
msg_done:
 | 
					 | 
				
			||||||
	if (!as->keep_cs)
 | 
					 | 
				
			||||||
		cs_deactivate(as, msg->spi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	atmel_spi_unlock(as);
 | 
						atmel_spi_unlock(as);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msg->status = as->done_status;
 | 
						return as->done_status;
 | 
				
			||||||
	spi_finalize_current_message(spi->master);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void atmel_spi_cleanup(struct spi_device *spi)
 | 
					static void atmel_spi_cleanup(struct spi_device *spi)
 | 
				
			||||||
| 
						 | 
					@ -1554,7 +1495,8 @@ static int atmel_spi_probe(struct platform_device *pdev)
 | 
				
			||||||
	master->num_chipselect = 4;
 | 
						master->num_chipselect = 4;
 | 
				
			||||||
	master->setup = atmel_spi_setup;
 | 
						master->setup = atmel_spi_setup;
 | 
				
			||||||
	master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX);
 | 
						master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX);
 | 
				
			||||||
	master->transfer_one_message = atmel_spi_transfer_one_message;
 | 
						master->transfer_one = atmel_spi_one_transfer;
 | 
				
			||||||
 | 
						master->set_cs = atmel_spi_set_cs;
 | 
				
			||||||
	master->cleanup = atmel_spi_cleanup;
 | 
						master->cleanup = atmel_spi_cleanup;
 | 
				
			||||||
	master->auto_runtime_pm = true;
 | 
						master->auto_runtime_pm = true;
 | 
				
			||||||
	master->max_dma_len = SPI_MAX_DMA_XFER;
 | 
						master->max_dma_len = SPI_MAX_DMA_XFER;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue