Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

spi: stm32: stability & performance enhancements

Merge series from Alain Volmat <alain.volmat@foss.st.com>:

The series fixes a stability issue when dealing with <8bpw
transfers, as well as enforce an error if the DMA information
provided within the DT are incorrect.

Performance enhancement is also provided by allowing a polling
mode which is triggered when the transfer is so short that
polling mode transfer would lead to faster transfer than
if it was done in a interrupt driven manner.

+94 -12
+94 -12
drivers/spi/spi-stm32.c
··· 202 202 #define STM32_SPI_HOST_MODE(stm32_spi) (!(stm32_spi)->device_mode) 203 203 #define STM32_SPI_DEVICE_MODE(stm32_spi) ((stm32_spi)->device_mode) 204 204 205 + static unsigned int polling_limit_us = 30; 206 + module_param(polling_limit_us, uint, 0664); 207 + MODULE_PARM_DESC(polling_limit_us, "maximum time in us to run a transfer in polling mode\n"); 208 + 205 209 /** 206 210 * struct stm32_spi_reg - stm32 SPI register & bitfield desc 207 211 * @reg: register offset ··· 270 266 * @dma_rx_cb: routine to call after DMA RX channel operation is complete 271 267 * @dma_tx_cb: routine to call after DMA TX channel operation is complete 272 268 * @transfer_one_irq: routine to configure interrupts for driver 269 + * @transfer_one_poll: routine to perform a transfer via register polling 273 270 * @irq_handler_event: Interrupt handler for SPI controller events 274 271 * @irq_handler_thread: thread of interrupt handler for SPI controller 275 272 * @baud_rate_div_min: minimum baud rate divisor ··· 296 291 void (*dma_rx_cb)(void *data); 297 292 void (*dma_tx_cb)(void *data); 298 293 int (*transfer_one_irq)(struct stm32_spi *spi); 294 + int (*transfer_one_poll)(struct stm32_spi *spi); 299 295 irqreturn_t (*irq_handler_event)(int irq, void *dev_id); 300 296 irqreturn_t (*irq_handler_thread)(int irq, void *dev_id); 301 297 unsigned int baud_rate_div_min; ··· 1362 1356 } 1363 1357 1364 1358 /** 1359 + * stm32h7_spi_transfer_one_poll - transfer a single spi_transfer by direct 1360 + * register access without interrupt usage 1361 + * @spi: pointer to the spi controller data structure 1362 + * 1363 + * It must returns 0 if the transfer is finished or 1 if the transfer is still 1364 + * in progress. 1365 + */ 1366 + static int stm32h7_spi_transfer_one_poll(struct stm32_spi *spi) 1367 + { 1368 + unsigned long flags; 1369 + u32 sr; 1370 + 1371 + spin_lock_irqsave(&spi->lock, flags); 1372 + 1373 + stm32_spi_enable(spi); 1374 + 1375 + /* Be sure to have data in fifo before starting data transfer */ 1376 + if (spi->tx_buf) 1377 + stm32h7_spi_write_txfifo(spi); 1378 + 1379 + if (STM32_SPI_HOST_MODE(spi)) 1380 + stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); 1381 + 1382 + sr = readl_relaxed(spi->base + STM32H7_SPI_SR); 1383 + /* Keep writing / reading while waiting for the end of transfer */ 1384 + while (spi->tx_len || spi->rx_len || !(sr & STM32H7_SPI_SR_EOT)) { 1385 + if (spi->rx_len && (sr & (STM32H7_SPI_SR_RXP | STM32H7_SPI_SR_RXWNE | 1386 + STM32H7_SPI_SR_RXPLVL))) 1387 + stm32h7_spi_read_rxfifo(spi); 1388 + 1389 + if (spi->tx_len && (sr & STM32H7_SPI_SR_TXP)) 1390 + stm32h7_spi_write_txfifo(spi); 1391 + 1392 + sr = readl_relaxed(spi->base + STM32H7_SPI_SR); 1393 + 1394 + /* Clear suspension bit if necessary */ 1395 + if (sr & STM32H7_SPI_SR_SUSP) 1396 + writel_relaxed(sr & STM32H7_SPI_SR_SUSP, spi->base + STM32H7_SPI_IFCR); 1397 + } 1398 + 1399 + spin_unlock_irqrestore(&spi->lock, flags); 1400 + 1401 + stm32h7_spi_disable(spi); 1402 + spi_finalize_current_transfer(spi->ctrl); 1403 + 1404 + return 0; 1405 + } 1406 + 1407 + /** 1365 1408 * stm32h7_spi_transfer_one_irq - transfer a single spi_transfer using 1366 1409 * interrupts 1367 1410 * @spi: pointer to the spi controller data structure ··· 1961 1906 cfg2_clrb |= STM32H7_SPI_CFG2_MIDI; 1962 1907 if ((len > 1) && (spi->cur_midi > 0)) { 1963 1908 u32 sck_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, spi->cur_speed); 1964 - u32 midi = min_t(u32, 1965 - DIV_ROUND_UP(spi->cur_midi, sck_period_ns), 1966 - FIELD_GET(STM32H7_SPI_CFG2_MIDI, 1967 - STM32H7_SPI_CFG2_MIDI)); 1909 + u32 midi = DIV_ROUND_UP(spi->cur_midi, sck_period_ns); 1968 1910 1911 + if ((spi->cur_bpw + midi) < 8) 1912 + midi = 8 - spi->cur_bpw; 1913 + 1914 + midi = min_t(u32, midi, FIELD_MAX(STM32H7_SPI_CFG2_MIDI)); 1969 1915 1970 1916 dev_dbg(spi->dev, "period=%dns, midi=%d(=%dns)\n", 1971 1917 sck_period_ns, midi, midi * sck_period_ns); ··· 2082 2026 } 2083 2027 2084 2028 /** 2029 + * stm32_spi_can_poll - detect if poll based transfer is appropriate 2030 + * @spi: pointer to the spi controller data structure 2031 + * 2032 + * Returns true is poll is more appropriate, false otherwise. 2033 + */ 2034 + static bool stm32_spi_can_poll(struct stm32_spi *spi) 2035 + { 2036 + unsigned long hz_per_byte, byte_limit; 2037 + 2038 + /* Evaluate the transfer time and use polling if applicable */ 2039 + hz_per_byte = polling_limit_us ? 2040 + DIV_ROUND_UP(8 * USEC_PER_SEC, polling_limit_us) : 0; 2041 + byte_limit = hz_per_byte ? spi->cur_speed / hz_per_byte : 1; 2042 + 2043 + return (spi->cur_xferlen < byte_limit) ? true : false; 2044 + } 2045 + 2046 + /** 2085 2047 * stm32_spi_transfer_one - transfer a single spi_transfer 2086 2048 * @ctrl: controller interface 2087 2049 * @spi_dev: pointer to the spi device ··· 2131 2057 2132 2058 if (spi->cur_usedma) 2133 2059 return stm32_spi_transfer_one_dma(spi, transfer); 2060 + else if (spi->cfg->transfer_one_poll && stm32_spi_can_poll(spi)) 2061 + return spi->cfg->transfer_one_poll(spi); 2134 2062 else 2135 2063 return spi->cfg->transfer_one_irq(spi); 2136 2064 } ··· 2291 2215 * SPI access hence handling is performed within the SPI interrupt 2292 2216 */ 2293 2217 .transfer_one_irq = stm32h7_spi_transfer_one_irq, 2218 + .transfer_one_poll = stm32h7_spi_transfer_one_poll, 2294 2219 .irq_handler_thread = stm32h7_spi_irq_thread, 2295 2220 .baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN, 2296 2221 .baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX, ··· 2321 2244 * SPI access hence handling is performed within the SPI interrupt 2322 2245 */ 2323 2246 .transfer_one_irq = stm32h7_spi_transfer_one_irq, 2247 + .transfer_one_poll = stm32h7_spi_transfer_one_poll, 2324 2248 .irq_handler_thread = stm32h7_spi_irq_thread, 2325 2249 .baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN, 2326 2250 .baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX, ··· 2484 2406 spi->dma_tx = dma_request_chan(spi->dev, "tx"); 2485 2407 if (IS_ERR(spi->dma_tx)) { 2486 2408 ret = PTR_ERR(spi->dma_tx); 2487 - spi->dma_tx = NULL; 2488 - if (ret == -EPROBE_DEFER) 2409 + if (ret == -ENODEV) { 2410 + dev_info(&pdev->dev, "tx dma disabled\n"); 2411 + spi->dma_tx = NULL; 2412 + } else { 2413 + dev_err_probe(&pdev->dev, ret, "failed to request tx dma channel\n"); 2489 2414 goto err_clk_disable; 2490 - 2491 - dev_warn(&pdev->dev, "failed to request tx dma channel\n"); 2415 + } 2492 2416 } else { 2493 2417 ctrl->dma_tx = spi->dma_tx; 2494 2418 } ··· 2498 2418 spi->dma_rx = dma_request_chan(spi->dev, "rx"); 2499 2419 if (IS_ERR(spi->dma_rx)) { 2500 2420 ret = PTR_ERR(spi->dma_rx); 2501 - spi->dma_rx = NULL; 2502 - if (ret == -EPROBE_DEFER) 2421 + if (ret == -ENODEV) { 2422 + dev_info(&pdev->dev, "rx dma disabled\n"); 2423 + spi->dma_rx = NULL; 2424 + } else { 2425 + dev_err_probe(&pdev->dev, ret, "failed to request rx dma channel\n"); 2503 2426 goto err_dma_release; 2504 - 2505 - dev_warn(&pdev->dev, "failed to request rx dma channel\n"); 2427 + } 2506 2428 } else { 2507 2429 ctrl->dma_rx = spi->dma_rx; 2508 2430 }