On 23. 5. 5. 18:47, Krzysztof Kozlowski wrote: > On 02/05/2023 08:28, Jaewon Kim wrote: >> Support interrupt based pio mode to optimize cpu usage. >> When transmitting data size is larget than 32 bytes, operates with >> interrupt based pio mode. >> >> By using the FIFORDY INT, an interrupt can be triggered when >> the desired size of data has been received. Using this, we can support >> interrupt based pio mode. >> >> Signed-off-by: Jaewon Kim <jaewon02.kim@xxxxxxxxxxx> >> --- >> drivers/spi/spi-s3c64xx.c | 66 ++++++++++++++++++++++++++++++++++----- >> 1 file changed, 58 insertions(+), 8 deletions(-) >> >> diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c >> index 2a8304678df9..323c6da9730b 100644 >> --- a/drivers/spi/spi-s3c64xx.c >> +++ b/drivers/spi/spi-s3c64xx.c >> @@ -58,6 +58,8 @@ >> #define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD (1<<17) >> #define S3C64XX_SPI_MODE_BUS_TSZ_WORD (2<<17) >> #define S3C64XX_SPI_MODE_BUS_TSZ_MASK (3<<17) >> +#define S3C64XX_SPI_MODE_RX_RDY_LVL GENMASK(16, 11) >> +#define S3C64XX_SPI_MODE_RX_RDY_LVL_SHIFT 11 >> #define S3C64XX_SPI_MODE_SELF_LOOPBACK (1<<3) >> #define S3C64XX_SPI_MODE_RXDMA_ON (1<<2) >> #define S3C64XX_SPI_MODE_TXDMA_ON (1<<1) >> @@ -114,6 +116,8 @@ >> >> #define S3C64XX_SPI_TRAILCNT S3C64XX_SPI_MAX_TRAILCNT >> >> +#define S3C64XX_SPI_POLLING_SIZE 32 >> + >> #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) >> #define is_polling(x) (x->cntrlr_info->polling) >> >> @@ -552,7 +556,7 @@ static int s3c64xx_wait_for_dma(struct s3c64xx_spi_driver_data *sdd, >> } >> >> static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd, >> - struct spi_transfer *xfer) >> + struct spi_transfer *xfer, bool use_irq) >> { >> void __iomem *regs = sdd->regs; >> unsigned long val; >> @@ -573,6 +577,12 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd, >> if (RX_FIFO_LVL(status, sdd) < xfer->len) >> usleep_range(time_us / 2, time_us); >> >> + if (use_irq) { >> + val = msecs_to_jiffies(ms); >> + if (!wait_for_completion_timeout(&sdd->xfer_completion, val)) >> + return -EIO; >> + } >> + >> val = msecs_to_loops(ms); >> do { >> status = readl(regs + S3C64XX_SPI_STATUS); >> @@ -735,10 +745,13 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, >> void *rx_buf = NULL; >> int target_len = 0, origin_len = 0; >> int use_dma = 0; >> + bool use_irq = false; >> int status; >> u32 speed; >> u8 bpw; >> unsigned long flags; >> + u32 rdy_lv; >> + u32 val; >> >> reinit_completion(&sdd->xfer_completion); >> >> @@ -759,17 +772,46 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, >> sdd->rx_dma.ch && sdd->tx_dma.ch) { >> use_dma = 1; >> >> - } else if (xfer->len > fifo_len) { >> + } else if (xfer->len >= fifo_len) { > I don't fully understand this. If len equals to fifo_len, everything > would fit into FIFO so no need for all this? If the FIFO is filled with data, TX Overrun & RX Underrun interrupts will occur. In CPU polling, there is no such issue because data is read before an interrupt occurs. And, RDY_LVL has only 6 bits.(max. 63). we cannot set trigger level on the FIFO max size. >> tx_buf = xfer->tx_buf; >> rx_buf = xfer->rx_buf; >> origin_len = xfer->len; >> - >> target_len = xfer->len; >> - if (xfer->len > fifo_len) >> - xfer->len = fifo_len; >> + xfer->len = fifo_len - 1; >> } >> >> do { >> + /* transfer size is greater than 32, change to IRQ mode */ >> + if (xfer->len > S3C64XX_SPI_POLLING_SIZE) >> + use_irq = true; >> + >> + if (use_irq) { >> + reinit_completion(&sdd->xfer_completion); >> + >> + rdy_lv = xfer->len; > Style is: > > /* > * > >> + /* Setup RDY_FIFO trigger Level >> + * RDY_LVL = >> + * fifo_lvl up to 64 byte -> N bytes >> + * 128 byte -> RDY_LVL * 2 bytes >> + * 256 byte -> RDY_LVL * 4 bytes > I don't understand it. Based on this equation for 256 bytes, > RDY_LVL = RDY_LVL * 4? > Didn't you mean xfer->len? In v4, I will change it to the following /* * Trigger Level = * (N = value of RDY_LVL field) * fifo_lvl up to 64 byte -> N bytes * 128 byte -> N * 2 bytes * 256 byte -> N * 4 bytes */ > > > Best regards, > Krzysztof > > Thanks Jaewon Kim