spi: s3c64xx: add sleep during transfer
authorJaewon Kim <jaewon02.kim@samsung.com>
Tue, 2 May 2023 06:28:12 +0000 (15:28 +0900)
committerMark Brown <broonie@kernel.org>
Mon, 8 May 2023 00:10:51 +0000 (09:10 +0900)
In polling mode, the status register is continuously read to check data
transfer completion. It can cause excessive CPU usage.
To reduce this, we can calculate the transfer time and put the sleep during
transfer.

When test on ExynosAuto9 SADK board, throughput remained the same, but
100% CPU utilization decreased to 40%.

Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org
Link: https://lore.kernel.org/r/20230502062813.112434-3-jaewon02.kim@samsung.com
Signed-off-by: Mark Brown <broonie@kernel.org
drivers/spi/spi-s3c64xx.c

index 5f59d6f..38cc206 100644 (file)
@@ -561,11 +561,18 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd,
        u32 cpy_len;
        u8 *buf;
        int ms;
+       unsigned long time_us;
 
-       /* millisecs to xfer 'len' bytes @ 'cur_speed' */
-       ms = xfer->len * 8 * 1000 / sdd->cur_speed;
+       /* microsecs to xfer 'len' bytes @ 'cur_speed' */
+       time_us = (xfer->len * 8 * 1000 * 1000) / sdd->cur_speed;
+       ms = (time_us / 1000);
        ms += 10; /* some tolerance */
 
+       /* sleep during signal transfer time */
+       status = readl(regs + S3C64XX_SPI_STATUS);
+       if (RX_FIFO_LVL(status, sdd) < xfer->len)
+               usleep_range(time_us / 2, time_us);
+
        val = msecs_to_loops(ms);
        do {
                status = readl(regs + S3C64XX_SPI_STATUS);