diff options
Diffstat (limited to 'drivers/spi/spi-stm32.c')
| -rw-r--r-- | drivers/spi/spi-stm32.c | 121 | 
1 files changed, 43 insertions, 78 deletions
diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 05618a618939..9bd3fd1652f7 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -162,6 +162,8 @@  #define SPI_3WIRE_TX		3  #define SPI_3WIRE_RX		4 +#define STM32_SPI_AUTOSUSPEND_DELAY		1	/* 1 ms */ +  /*   * use PIO for small transfers, avoiding DMA setup/teardown overhead for drivers   * without fifo buffers. @@ -568,29 +570,30 @@ static void stm32f4_spi_read_rx(struct stm32_spi *spi)  /**   * stm32h7_spi_read_rxfifo - Read bytes in Receive Data Register   * @spi: pointer to the spi controller data structure - * @flush: boolean indicating that FIFO should be flushed   *   * Write in rx_buf depends on remaining bytes to avoid to write beyond   * rx_buf end.   */ -static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush) +static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi)  {  	u32 sr = readl_relaxed(spi->base + STM32H7_SPI_SR);  	u32 rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr);  	while ((spi->rx_len > 0) &&  	       ((sr & STM32H7_SPI_SR_RXP) || -		(flush && ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) { +		((sr & STM32H7_SPI_SR_EOT) && +		 ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) {  		u32 offs = spi->cur_xferlen - spi->rx_len;  		if ((spi->rx_len >= sizeof(u32)) || -		    (flush && (sr & STM32H7_SPI_SR_RXWNE))) { +		    (sr & STM32H7_SPI_SR_RXWNE)) {  			u32 *rx_buf32 = (u32 *)(spi->rx_buf + offs);  			*rx_buf32 = readl_relaxed(spi->base + STM32H7_SPI_RXDR);  			spi->rx_len -= sizeof(u32);  		} else if ((spi->rx_len >= sizeof(u16)) || -			   (flush && (rxplvl >= 2 || spi->cur_bpw > 8))) { +			   (!(sr & STM32H7_SPI_SR_RXWNE) && +			    (rxplvl >= 2 || spi->cur_bpw > 8))) {  			u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs);  			*rx_buf16 = readw_relaxed(spi->base + STM32H7_SPI_RXDR); @@ -606,8 +609,8 @@ static void stm32h7_spi_read_rxfifo(struct stm32_spi *spi, bool flush)  		rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr);  	} -	dev_dbg(spi->dev, "%s%s: %d bytes left\n", __func__, -		flush ? "(flush)" : "", spi->rx_len); +	dev_dbg(spi->dev, "%s: %d bytes left (sr=%08x)\n", +		__func__, spi->rx_len, sr);  }  /** @@ -674,18 +677,12 @@ static void stm32f4_spi_disable(struct stm32_spi *spi)   * stm32h7_spi_disable - Disable SPI controller   * @spi: pointer to the spi controller data structure   * - * RX-Fifo is flushed when SPI controller is disabled. To prevent any data - * loss, use stm32h7_spi_read_rxfifo(flush) to read the remaining bytes in - * RX-Fifo. - * Normally, if TSIZE has been configured, we should relax the hardware at the - * reception of the EOT interrupt. But in case of error, EOT will not be - * raised. So the subsystem unprepare_message call allows us to properly - * complete the transfer from an hardware point of view. + * RX-Fifo is flushed when SPI controller is disabled.   */  static void stm32h7_spi_disable(struct stm32_spi *spi)  {  	unsigned long flags; -	u32 cr1, sr; +	u32 cr1;  	dev_dbg(spi->dev, "disable controller\n"); @@ -698,25 +695,6 @@ static void stm32h7_spi_disable(struct stm32_spi *spi)  		return;  	} -	/* Wait on EOT or suspend the flow */ -	if (readl_relaxed_poll_timeout_atomic(spi->base + STM32H7_SPI_SR, -					      sr, !(sr & STM32H7_SPI_SR_EOT), -					      10, 100000) < 0) { -		if (cr1 & STM32H7_SPI_CR1_CSTART) { -			writel_relaxed(cr1 | STM32H7_SPI_CR1_CSUSP, -				       spi->base + STM32H7_SPI_CR1); -			if (readl_relaxed_poll_timeout_atomic( -						spi->base + STM32H7_SPI_SR, -						sr, !(sr & STM32H7_SPI_SR_SUSP), -						10, 100000) < 0) -				dev_warn(spi->dev, -					 "Suspend request timeout\n"); -		} -	} - -	if (!spi->cur_usedma && spi->rx_buf && (spi->rx_len > 0)) -		stm32h7_spi_read_rxfifo(spi, true); -  	if (spi->cur_usedma && spi->dma_tx)  		dmaengine_terminate_all(spi->dma_tx);  	if (spi->cur_usedma && spi->dma_rx) @@ -911,7 +889,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)  		if (__ratelimit(&rs))  			dev_dbg_ratelimited(spi->dev, "Communication suspended\n");  		if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) -			stm32h7_spi_read_rxfifo(spi, false); +			stm32h7_spi_read_rxfifo(spi);  		/*  		 * If communication is suspended while using DMA, it means  		 * that something went wrong, so stop the current transfer @@ -932,8 +910,10 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)  	if (sr & STM32H7_SPI_SR_EOT) {  		if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) -			stm32h7_spi_read_rxfifo(spi, true); -		end = true; +			stm32h7_spi_read_rxfifo(spi); +		if (!spi->cur_usedma || +		    (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX)) +			end = true;  	}  	if (sr & STM32H7_SPI_SR_TXP) @@ -942,7 +922,7 @@ static irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id)  	if (sr & STM32H7_SPI_SR_RXP)  		if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) -			stm32h7_spi_read_rxfifo(spi, false); +			stm32h7_spi_read_rxfifo(spi);  	writel_relaxed(sr & mask, spi->base + STM32H7_SPI_IFCR); @@ -1041,42 +1021,17 @@ static void stm32f4_spi_dma_tx_cb(void *data)  }  /** - * stm32f4_spi_dma_rx_cb - dma callback + * stm32_spi_dma_rx_cb - dma callback   * @data: pointer to the spi controller data structure   *   * DMA callback is called when the transfer is complete for DMA RX channel.   */ -static void stm32f4_spi_dma_rx_cb(void *data) +static void stm32_spi_dma_rx_cb(void *data)  {  	struct stm32_spi *spi = data;  	spi_finalize_current_transfer(spi->master); -	stm32f4_spi_disable(spi); -} - -/** - * stm32h7_spi_dma_cb - dma callback - * @data: pointer to the spi controller data structure - * - * DMA callback is called when the transfer is complete or when an error - * occurs. If the transfer is complete, EOT flag is raised. - */ -static void stm32h7_spi_dma_cb(void *data) -{ -	struct stm32_spi *spi = data; -	unsigned long flags; -	u32 sr; - -	spin_lock_irqsave(&spi->lock, flags); - -	sr = readl_relaxed(spi->base + STM32H7_SPI_SR); - -	spin_unlock_irqrestore(&spi->lock, flags); - -	if (!(sr & STM32H7_SPI_SR_EOT)) -		dev_warn(spi->dev, "DMA error (sr=0x%08x)\n", sr); - -	/* Now wait for EOT, or SUSP or OVR in case of error */ +	spi->cfg->disable(spi);  }  /** @@ -1242,11 +1197,13 @@ static void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi)   */  static void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi)  { -	/* Enable the interrupts relative to the end of transfer */ -	stm32_spi_set_bits(spi, STM32H7_SPI_IER, STM32H7_SPI_IER_EOTIE | -						 STM32H7_SPI_IER_TXTFIE | -						 STM32H7_SPI_IER_OVRIE | -						 STM32H7_SPI_IER_MODFIE); +	uint32_t ier = STM32H7_SPI_IER_OVRIE | STM32H7_SPI_IER_MODFIE; + +	/* Enable the interrupts */ +	if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) +		ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE; + +	stm32_spi_set_bits(spi, STM32H7_SPI_IER, ier);  	stm32_spi_enable(spi); @@ -1645,10 +1602,6 @@ static int stm32_spi_transfer_one(struct spi_master *master,  	struct stm32_spi *spi = spi_master_get_devdata(master);  	int ret; -	/* Don't do anything on 0 bytes transfers */ -	if (transfer->len == 0) -		return 0; -  	spi->tx_buf = transfer->tx_buf;  	spi->rx_buf = transfer->rx_buf;  	spi->tx_len = spi->tx_buf ? transfer->len : 0; @@ -1762,7 +1715,7 @@ static const struct stm32_spi_cfg stm32f4_spi_cfg = {  	.set_mode = stm32f4_spi_set_mode,  	.transfer_one_dma_start = stm32f4_spi_transfer_one_dma_start,  	.dma_tx_cb = stm32f4_spi_dma_tx_cb, -	.dma_rx_cb = stm32f4_spi_dma_rx_cb, +	.dma_rx_cb = stm32_spi_dma_rx_cb,  	.transfer_one_irq = stm32f4_spi_transfer_one_irq,  	.irq_handler_event = stm32f4_spi_irq_event,  	.irq_handler_thread = stm32f4_spi_irq_thread, @@ -1782,8 +1735,11 @@ static const struct stm32_spi_cfg stm32h7_spi_cfg = {  	.set_data_idleness = stm32h7_spi_data_idleness,  	.set_number_of_data = stm32h7_spi_number_of_data,  	.transfer_one_dma_start = stm32h7_spi_transfer_one_dma_start, -	.dma_rx_cb = stm32h7_spi_dma_cb, -	.dma_tx_cb = stm32h7_spi_dma_cb, +	.dma_rx_cb = stm32_spi_dma_rx_cb, +	/* +	 * dma_tx_cb is not necessary since in case of TX, dma is followed by +	 * SPI access hence handling is performed within the SPI interrupt +	 */  	.transfer_one_irq = stm32h7_spi_transfer_one_irq,  	.irq_handler_thread = stm32h7_spi_irq_thread,  	.baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN, @@ -1927,6 +1883,9 @@ static int stm32_spi_probe(struct platform_device *pdev)  	if (spi->dma_tx || spi->dma_rx)  		master->can_dma = stm32_spi_can_dma; +	pm_runtime_set_autosuspend_delay(&pdev->dev, +					 STM32_SPI_AUTOSUSPEND_DELAY); +	pm_runtime_use_autosuspend(&pdev->dev);  	pm_runtime_set_active(&pdev->dev);  	pm_runtime_get_noresume(&pdev->dev);  	pm_runtime_enable(&pdev->dev); @@ -1938,6 +1897,9 @@ static int stm32_spi_probe(struct platform_device *pdev)  		goto err_pm_disable;  	} +	pm_runtime_mark_last_busy(&pdev->dev); +	pm_runtime_put_autosuspend(&pdev->dev); +  	dev_info(&pdev->dev, "driver initialized\n");  	return 0; @@ -1946,6 +1908,7 @@ err_pm_disable:  	pm_runtime_disable(&pdev->dev);  	pm_runtime_put_noidle(&pdev->dev);  	pm_runtime_set_suspended(&pdev->dev); +	pm_runtime_dont_use_autosuspend(&pdev->dev);  err_dma_release:  	if (spi->dma_tx)  		dma_release_channel(spi->dma_tx); @@ -1970,6 +1933,8 @@ static int stm32_spi_remove(struct platform_device *pdev)  	pm_runtime_disable(&pdev->dev);  	pm_runtime_put_noidle(&pdev->dev);  	pm_runtime_set_suspended(&pdev->dev); +	pm_runtime_dont_use_autosuspend(&pdev->dev); +  	if (master->dma_tx)  		dma_release_channel(master->dma_tx);  	if (master->dma_rx)  |