aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaewon Kim <[email protected]>2023-05-02 15:28:12 +0900
committerMark Brown <[email protected]>2023-05-08 09:10:51 +0900
commit3456674f54d3cfdedb28ce8a3db2b6f975392ac8 (patch)
tree0ae125eea2a88810a0bf04e9db18ed5d81aac554
parentd1a7718ee8dbcc488d3243d52e19c755123e0024 (diff)
spi: s3c64xx: add sleep during transfer
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 <[email protected] Reviewed-by: Krzysztof Kozlowski <[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]
-rw-r--r--drivers/spi/spi-s3c64xx.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 5f59d6f8c8d8..38cc2068afce 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -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);