All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/9] spi: spi-imx: cleanups and performance improvements
@ 2022-05-02 16:52 ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel

Hello,

(re-post with fixed address for linux-spi - sorry)

this patch series first cleans up several sparse and checkpatch
warnings, then finished master -< controller conversion. Then PIO
based polling support is added. It's activated by default for
transfers smaller than 30 µs (like in the raspi SPI drivers). The last
patch optimized setup of the MX51_ECSPI_CONFIG register.

regards,
Marc




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [RFC 0/9] spi: spi-imx: cleanups and performance improvements
@ 2022-05-02 16:52 ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel

Hello,

(re-post with fixed address for linux-spi - sorry)

this patch series first cleans up several sparse and checkpatch
warnings, then finished master -< controller conversion. Then PIO
based polling support is added. It's activated by default for
transfers smaller than 30 µs (like in the raspi SPI drivers). The last
patch optimized setup of the MX51_ECSPI_CONFIG register.

regards,
Marc




_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [RFC 1/9] spi: spi-imx: fix sparse warning: add identifier name to function definition
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch fixes the following and similar sparse warnings by adding
the missing identifier names to the function definitions:

| WARNING: function definition argument 'struct spi_imx_data *' should also have an identifier name
| #68: FILE: drivers/spi/spi-imx.c:68:
| +       int (*prepare_message)(struct spi_imx_data *, struct spi_message *);

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index b2dd0a4d2446..bbf6fd4fe763 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -64,15 +64,15 @@ enum spi_imx_devtype {
 struct spi_imx_data;
 
 struct spi_imx_devtype_data {
-	void (*intctrl)(struct spi_imx_data *, int);
-	int (*prepare_message)(struct spi_imx_data *, struct spi_message *);
-	int (*prepare_transfer)(struct spi_imx_data *, struct spi_device *);
-	void (*trigger)(struct spi_imx_data *);
-	int (*rx_available)(struct spi_imx_data *);
-	void (*reset)(struct spi_imx_data *);
-	void (*setup_wml)(struct spi_imx_data *);
-	void (*disable)(struct spi_imx_data *);
-	void (*disable_dma)(struct spi_imx_data *);
+	void (*intctrl)(struct spi_imx_data *spi_imx, int enable);
+	int (*prepare_message)(struct spi_imx_data *spi_imx, struct spi_message *msg);
+	int (*prepare_transfer)(struct spi_imx_data *spi_imx, struct spi_device *spi);
+	void (*trigger)(struct spi_imx_data *spi_imx);
+	int (*rx_available)(struct spi_imx_data *spi_imx);
+	void (*reset)(struct spi_imx_data *spi_imx);
+	void (*setup_wml)(struct spi_imx_data *spi_imx);
+	void (*disable)(struct spi_imx_data *spi_imx);
+	void (*disable_dma)(struct spi_imx_data *spi_imx);
 	bool has_dmamode;
 	bool has_slavemode;
 	unsigned int fifo_size;
@@ -102,8 +102,8 @@ struct spi_imx_data {
 	unsigned int spi_drctl;
 
 	unsigned int count, remainder;
-	void (*tx)(struct spi_imx_data *);
-	void (*rx)(struct spi_imx_data *);
+	void (*tx)(struct spi_imx_data *spi_imx);
+	void (*rx)(struct spi_imx_data *spi_imx);
 	void *rx_buf;
 	const void *tx_buf;
 	unsigned int txfifo; /* number of words pushed in tx FIFO */

base-commit: 3123109284176b1532874591f7c81f3837bbdc17
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 1/9] spi: spi-imx: fix sparse warning: add identifier name to function definition
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch fixes the following and similar sparse warnings by adding
the missing identifier names to the function definitions:

| WARNING: function definition argument 'struct spi_imx_data *' should also have an identifier name
| #68: FILE: drivers/spi/spi-imx.c:68:
| +       int (*prepare_message)(struct spi_imx_data *, struct spi_message *);

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index b2dd0a4d2446..bbf6fd4fe763 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -64,15 +64,15 @@ enum spi_imx_devtype {
 struct spi_imx_data;
 
 struct spi_imx_devtype_data {
-	void (*intctrl)(struct spi_imx_data *, int);
-	int (*prepare_message)(struct spi_imx_data *, struct spi_message *);
-	int (*prepare_transfer)(struct spi_imx_data *, struct spi_device *);
-	void (*trigger)(struct spi_imx_data *);
-	int (*rx_available)(struct spi_imx_data *);
-	void (*reset)(struct spi_imx_data *);
-	void (*setup_wml)(struct spi_imx_data *);
-	void (*disable)(struct spi_imx_data *);
-	void (*disable_dma)(struct spi_imx_data *);
+	void (*intctrl)(struct spi_imx_data *spi_imx, int enable);
+	int (*prepare_message)(struct spi_imx_data *spi_imx, struct spi_message *msg);
+	int (*prepare_transfer)(struct spi_imx_data *spi_imx, struct spi_device *spi);
+	void (*trigger)(struct spi_imx_data *spi_imx);
+	int (*rx_available)(struct spi_imx_data *spi_imx);
+	void (*reset)(struct spi_imx_data *spi_imx);
+	void (*setup_wml)(struct spi_imx_data *spi_imx);
+	void (*disable)(struct spi_imx_data *spi_imx);
+	void (*disable_dma)(struct spi_imx_data *spi_imx);
 	bool has_dmamode;
 	bool has_slavemode;
 	unsigned int fifo_size;
@@ -102,8 +102,8 @@ struct spi_imx_data {
 	unsigned int spi_drctl;
 
 	unsigned int count, remainder;
-	void (*tx)(struct spi_imx_data *);
-	void (*rx)(struct spi_imx_data *);
+	void (*tx)(struct spi_imx_data *spi_imx);
+	void (*rx)(struct spi_imx_data *spi_imx);
 	void *rx_buf;
 	const void *tx_buf;
 	unsigned int txfifo; /* number of words pushed in tx FIFO */

base-commit: 3123109284176b1532874591f7c81f3837bbdc17
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 2/9] spi: spi-imx: avoid unnecessary line continuations
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch fixes the following checkpatch warning by removing the
trailing backslash:

| WARNING: Avoid unnecessary line continuations
| +       spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index bbf6fd4fe763..a964a7ba8c1b 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1649,8 +1649,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
 	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
 	spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
-	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
-					     | SPI_NO_CS;
+	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
 	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
 	    is_imx53_ecspi(spi_imx))
 		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 2/9] spi: spi-imx: avoid unnecessary line continuations
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch fixes the following checkpatch warning by removing the
trailing backslash:

| WARNING: Avoid unnecessary line continuations
| +       spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index bbf6fd4fe763..a964a7ba8c1b 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1649,8 +1649,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
 	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
 	spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
-	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
-					     | SPI_NO_CS;
+	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
 	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
 	    is_imx53_ecspi(spi_imx))
 		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 3/9] spi: spi-imx: mx51_ecspi_intctrl(): prefer 'unsigned int' to bare use of 'unsigned'
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch fixes the following checkpatch warning, by making val an
"unsigned int".

| WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
| +       unsigned val = 0;

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index a964a7ba8c1b..a05d823d8806 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -469,7 +469,7 @@ static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
 
 static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
-	unsigned val = 0;
+	unsigned int val = 0;
 
 	if (enable & MXC_INT_TE)
 		val |= MX51_ECSPI_INT_TEEN;
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 3/9] spi: spi-imx: mx51_ecspi_intctrl(): prefer 'unsigned int' to bare use of 'unsigned'
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch fixes the following checkpatch warning, by making val an
"unsigned int".

| WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
| +       unsigned val = 0;

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index a964a7ba8c1b..a05d823d8806 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -469,7 +469,7 @@ static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
 
 static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
 {
-	unsigned val = 0;
+	unsigned int val = 0;
 
 	if (enable & MXC_INT_TE)
 		val |= MX51_ECSPI_INT_TEEN;
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 4/9] spi: spi-imx: spi_imx_buf_rx_swap_u32(): fix sparse warning
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch fixes the following sparse warning by using a swab32()
instead of a cpu_to_be32(). The driver is used on little endian
systems only and we really want to swap the bytes.

| drivers/spi/spi-imx.c:305:29: warning: incorrect type in assignment (different base types)
| drivers/spi/spi-imx.c:305:29:    expected unsigned int val
| drivers/spi/spi-imx.c:305:29:    got restricted __be32 [usertype]
| drivers/spi/spi-imx.c:361:21: warning: incorrect type in assignment (different base types)
| drivers/spi/spi-imx.c:361:21:    expected unsigned int [assigned] [usertype] val
| drivers/spi/spi-imx.c:361:21:    got restricted __be32 [usertype]

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index a05d823d8806..a63cb26f33fc 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -297,7 +297,7 @@ static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx)
 #ifdef __LITTLE_ENDIAN
 		bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
 		if (bytes_per_word == 1)
-			val = cpu_to_be32(val);
+			val = swab32(val);
 		else if (bytes_per_word == 2)
 			val = (val << 16) | (val >> 16);
 #endif
@@ -353,7 +353,7 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
 	bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
 
 	if (bytes_per_word == 1)
-		val = cpu_to_be32(val);
+		val = swab32(val);
 	else if (bytes_per_word == 2)
 		val = (val << 16) | (val >> 16);
 #endif
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 4/9] spi: spi-imx: spi_imx_buf_rx_swap_u32(): fix sparse warning
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch fixes the following sparse warning by using a swab32()
instead of a cpu_to_be32(). The driver is used on little endian
systems only and we really want to swap the bytes.

| drivers/spi/spi-imx.c:305:29: warning: incorrect type in assignment (different base types)
| drivers/spi/spi-imx.c:305:29:    expected unsigned int val
| drivers/spi/spi-imx.c:305:29:    got restricted __be32 [usertype]
| drivers/spi/spi-imx.c:361:21: warning: incorrect type in assignment (different base types)
| drivers/spi/spi-imx.c:361:21:    expected unsigned int [assigned] [usertype] val
| drivers/spi/spi-imx.c:361:21:    got restricted __be32 [usertype]

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index a05d823d8806..a63cb26f33fc 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -297,7 +297,7 @@ static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx)
 #ifdef __LITTLE_ENDIAN
 		bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
 		if (bytes_per_word == 1)
-			val = cpu_to_be32(val);
+			val = swab32(val);
 		else if (bytes_per_word == 2)
 			val = (val << 16) | (val >> 16);
 #endif
@@ -353,7 +353,7 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
 	bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
 
 	if (bytes_per_word == 1)
-		val = cpu_to_be32(val);
+		val = swab32(val);
 	else if (bytes_per_word == 2)
 		val = (val << 16) | (val >> 16);
 #endif
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 5/9] spi: spi-imx: spi_imx_buf_rx_swap_u32(): replace open coded swahw32()
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch replaces an open coded swahw32().

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index a63cb26f33fc..e817cf95eea6 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -289,17 +289,16 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx)
 {
 	unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA);
-#ifdef __LITTLE_ENDIAN
-	unsigned int bytes_per_word;
-#endif
 
 	if (spi_imx->rx_buf) {
 #ifdef __LITTLE_ENDIAN
+		unsigned int bytes_per_word;
+
 		bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
 		if (bytes_per_word == 1)
 			val = swab32(val);
 		else if (bytes_per_word == 2)
-			val = (val << 16) | (val >> 16);
+			val = swahw32(val);
 #endif
 		*(u32 *)spi_imx->rx_buf = val;
 		spi_imx->rx_buf += sizeof(u32);
@@ -355,7 +354,7 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
 	if (bytes_per_word == 1)
 		val = swab32(val);
 	else if (bytes_per_word == 2)
-		val = (val << 16) | (val >> 16);
+		val = swahw32(val);
 #endif
 	writel(val, spi_imx->base + MXC_CSPITXDATA);
 }
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 5/9] spi: spi-imx: spi_imx_buf_rx_swap_u32(): replace open coded swahw32()
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

This patch replaces an open coded swahw32().

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index a63cb26f33fc..e817cf95eea6 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -289,17 +289,16 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx)
 {
 	unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA);
-#ifdef __LITTLE_ENDIAN
-	unsigned int bytes_per_word;
-#endif
 
 	if (spi_imx->rx_buf) {
 #ifdef __LITTLE_ENDIAN
+		unsigned int bytes_per_word;
+
 		bytes_per_word = spi_imx_bytes_per_word(spi_imx->bits_per_word);
 		if (bytes_per_word == 1)
 			val = swab32(val);
 		else if (bytes_per_word == 2)
-			val = (val << 16) | (val >> 16);
+			val = swahw32(val);
 #endif
 		*(u32 *)spi_imx->rx_buf = val;
 		spi_imx->rx_buf += sizeof(u32);
@@ -355,7 +354,7 @@ static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
 	if (bytes_per_word == 1)
 		val = swab32(val);
 	else if (bytes_per_word == 2)
-		val = (val << 16) | (val >> 16);
+		val = swahw32(val);
 #endif
 	writel(val, spi_imx->base + MXC_CSPITXDATA);
 }
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 6/9] spi: spi-imx: complete conversion from master -> controller
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

With patch:
| 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"")
the SPI "master" was generalized to "controller". This patch completed
the conversion of the spi-imx driver by replacing the remaining
occurrences of master to controller.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 162 +++++++++++++++++++++---------------------
 1 file changed, 81 insertions(+), 81 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index e817cf95eea6..bfce856f56bf 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -225,15 +225,15 @@ static int spi_imx_bytes_per_word(const int bits_per_word)
 		return 4;
 }
 
-static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
+static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device *spi,
 			 struct spi_transfer *transfer)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 
-	if (!use_dma || master->fallback)
+	if (!use_dma || controller->fallback)
 		return false;
 
-	if (!master->dma_rx)
+	if (!controller->dma_rx)
 		return false;
 
 	if (spi_imx->slave_mode)
@@ -1152,12 +1152,12 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int spi_imx_dma_configure(struct spi_master *master)
+static int spi_imx_dma_configure(struct spi_controller *controller)
 {
 	int ret;
 	enum dma_slave_buswidth buswidth;
 	struct dma_slave_config rx = {}, tx = {};
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 
 	switch (spi_imx_bytes_per_word(spi_imx->bits_per_word)) {
 	case 4:
@@ -1177,7 +1177,7 @@ static int spi_imx_dma_configure(struct spi_master *master)
 	tx.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
 	tx.dst_addr_width = buswidth;
 	tx.dst_maxburst = spi_imx->wml;
-	ret = dmaengine_slave_config(master->dma_tx, &tx);
+	ret = dmaengine_slave_config(controller->dma_tx, &tx);
 	if (ret) {
 		dev_err(spi_imx->dev, "TX dma configuration failed with %d\n", ret);
 		return ret;
@@ -1187,7 +1187,7 @@ static int spi_imx_dma_configure(struct spi_master *master)
 	rx.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
 	rx.src_addr_width = buswidth;
 	rx.src_maxburst = spi_imx->wml;
-	ret = dmaengine_slave_config(master->dma_rx, &rx);
+	ret = dmaengine_slave_config(controller->dma_rx, &rx);
 	if (ret) {
 		dev_err(spi_imx->dev, "RX dma configuration failed with %d\n", ret);
 		return ret;
@@ -1199,7 +1199,7 @@ static int spi_imx_dma_configure(struct spi_master *master)
 static int spi_imx_setupxfer(struct spi_device *spi,
 				 struct spi_transfer *t)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 
 	if (!t)
 		return 0;
@@ -1263,50 +1263,50 @@ static int spi_imx_setupxfer(struct spi_device *spi,
 
 static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx)
 {
-	struct spi_master *master = spi_imx->bitbang.master;
+	struct spi_controller *controller = spi_imx->bitbang.master;
 
-	if (master->dma_rx) {
-		dma_release_channel(master->dma_rx);
-		master->dma_rx = NULL;
+	if (controller->dma_rx) {
+		dma_release_channel(controller->dma_rx);
+		controller->dma_rx = NULL;
 	}
 
-	if (master->dma_tx) {
-		dma_release_channel(master->dma_tx);
-		master->dma_tx = NULL;
+	if (controller->dma_tx) {
+		dma_release_channel(controller->dma_tx);
+		controller->dma_tx = NULL;
 	}
 }
 
 static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
-			     struct spi_master *master)
+			     struct spi_controller *controller)
 {
 	int ret;
 
 	spi_imx->wml = spi_imx->devtype_data->fifo_size / 2;
 
 	/* Prepare for TX DMA: */
-	master->dma_tx = dma_request_chan(dev, "tx");
-	if (IS_ERR(master->dma_tx)) {
-		ret = PTR_ERR(master->dma_tx);
+	controller->dma_tx = dma_request_chan(dev, "tx");
+	if (IS_ERR(controller->dma_tx)) {
+		ret = PTR_ERR(controller->dma_tx);
 		dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret);
-		master->dma_tx = NULL;
+		controller->dma_tx = NULL;
 		goto err;
 	}
 
 	/* Prepare for RX : */
-	master->dma_rx = dma_request_chan(dev, "rx");
-	if (IS_ERR(master->dma_rx)) {
-		ret = PTR_ERR(master->dma_rx);
+	controller->dma_rx = dma_request_chan(dev, "rx");
+	if (IS_ERR(controller->dma_rx)) {
+		ret = PTR_ERR(controller->dma_rx);
 		dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret);
-		master->dma_rx = NULL;
+		controller->dma_rx = NULL;
 		goto err;
 	}
 
 	init_completion(&spi_imx->dma_rx_completion);
 	init_completion(&spi_imx->dma_tx_completion);
-	master->can_dma = spi_imx_can_dma;
-	master->max_dma_len = MAX_SDMA_BD_BYTES;
-	spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
-					 SPI_MASTER_MUST_TX;
+	controller->can_dma = spi_imx_can_dma;
+	controller->max_dma_len = MAX_SDMA_BD_BYTES;
+	spi_imx->bitbang.master->flags = SPI_CONTROLLER_MUST_RX |
+					 SPI_CONTROLLER_MUST_TX;
 
 	return 0;
 err:
@@ -1348,7 +1348,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	struct dma_async_tx_descriptor *desc_tx, *desc_rx;
 	unsigned long transfer_timeout;
 	unsigned long timeout;
-	struct spi_master *master = spi_imx->bitbang.master;
+	struct spi_controller *controller = spi_imx->bitbang.master;
 	struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
 	struct scatterlist *last_sg = sg_last(rx->sgl, rx->nents);
 	unsigned int bytes_per_word, i;
@@ -1366,7 +1366,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 
 	spi_imx->wml =  i;
 
-	ret = spi_imx_dma_configure(master);
+	ret = spi_imx_dma_configure(controller);
 	if (ret)
 		goto dma_failure_no_start;
 
@@ -1381,7 +1381,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	 * The TX DMA setup starts the transfer, so make sure RX is configured
 	 * before TX.
 	 */
-	desc_rx = dmaengine_prep_slave_sg(master->dma_rx,
+	desc_rx = dmaengine_prep_slave_sg(controller->dma_rx,
 				rx->sgl, rx->nents, DMA_DEV_TO_MEM,
 				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc_rx) {
@@ -1393,14 +1393,14 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	desc_rx->callback_param = (void *)spi_imx;
 	dmaengine_submit(desc_rx);
 	reinit_completion(&spi_imx->dma_rx_completion);
-	dma_async_issue_pending(master->dma_rx);
+	dma_async_issue_pending(controller->dma_rx);
 
-	desc_tx = dmaengine_prep_slave_sg(master->dma_tx,
+	desc_tx = dmaengine_prep_slave_sg(controller->dma_tx,
 				tx->sgl, tx->nents, DMA_MEM_TO_DEV,
 				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc_tx) {
-		dmaengine_terminate_all(master->dma_tx);
-		dmaengine_terminate_all(master->dma_rx);
+		dmaengine_terminate_all(controller->dma_tx);
+		dmaengine_terminate_all(controller->dma_rx);
 		return -EINVAL;
 	}
 
@@ -1408,7 +1408,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	desc_tx->callback_param = (void *)spi_imx;
 	dmaengine_submit(desc_tx);
 	reinit_completion(&spi_imx->dma_tx_completion);
-	dma_async_issue_pending(master->dma_tx);
+	dma_async_issue_pending(controller->dma_tx);
 
 	transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
 
@@ -1417,17 +1417,17 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 						transfer_timeout);
 	if (!timeout) {
 		dev_err(spi_imx->dev, "I/O Error in DMA TX\n");
-		dmaengine_terminate_all(master->dma_tx);
-		dmaengine_terminate_all(master->dma_rx);
+		dmaengine_terminate_all(controller->dma_tx);
+		dmaengine_terminate_all(controller->dma_rx);
 		return -ETIMEDOUT;
 	}
 
 	timeout = wait_for_completion_timeout(&spi_imx->dma_rx_completion,
 					      transfer_timeout);
 	if (!timeout) {
-		dev_err(&master->dev, "I/O Error in DMA RX\n");
+		dev_err(&controller->dev, "I/O Error in DMA RX\n");
 		spi_imx->devtype_data->reset(spi_imx);
-		dmaengine_terminate_all(master->dma_rx);
+		dmaengine_terminate_all(controller->dma_rx);
 		return -ETIMEDOUT;
 	}
 
@@ -1441,7 +1441,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 static int spi_imx_pio_transfer(struct spi_device *spi,
 				struct spi_transfer *transfer)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 	unsigned long transfer_timeout;
 	unsigned long timeout;
 
@@ -1473,7 +1473,7 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 				      struct spi_transfer *transfer)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 	int ret = transfer->len;
 
 	if (is_imx53_ecspi(spi_imx) &&
@@ -1517,7 +1517,7 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 static int spi_imx_transfer(struct spi_device *spi,
 				struct spi_transfer *transfer)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 
 	transfer->effective_speed_hz = spi_imx->spi_bus_clk;
 
@@ -1547,9 +1547,9 @@ static void spi_imx_cleanup(struct spi_device *spi)
 }
 
 static int
-spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
+spi_imx_prepare_message(struct spi_controller *controller, struct spi_message *msg)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 	int ret;
 
 	ret = pm_runtime_get_sync(spi_imx->dev);
@@ -1569,18 +1569,18 @@ spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
 }
 
 static int
-spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg)
+spi_imx_unprepare_message(struct spi_controller *controller, struct spi_message *msg)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 
 	pm_runtime_mark_last_busy(spi_imx->dev);
 	pm_runtime_put_autosuspend(spi_imx->dev);
 	return 0;
 }
 
-static int spi_imx_slave_abort(struct spi_master *master)
+static int spi_imx_slave_abort(struct spi_controller *controller)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 
 	spi_imx->slave_aborted = true;
 	complete(&spi_imx->xfer_done);
@@ -1591,7 +1591,7 @@ static int spi_imx_slave_abort(struct spi_master *master)
 static int spi_imx_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	struct spi_master *master;
+	struct spi_controller *controller;
 	struct spi_imx_data *spi_imx;
 	struct resource *res;
 	int ret, irq, spi_drctl;
@@ -1603,12 +1603,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 	slave_mode = devtype_data->has_slavemode &&
 			of_property_read_bool(np, "spi-slave");
 	if (slave_mode)
-		master = spi_alloc_slave(&pdev->dev,
-					 sizeof(struct spi_imx_data));
+		controller = spi_alloc_slave(&pdev->dev,
+					     sizeof(struct spi_imx_data));
 	else
-		master = spi_alloc_master(&pdev->dev,
-					  sizeof(struct spi_imx_data));
-	if (!master)
+		controller = spi_alloc_master(&pdev->dev,
+					      sizeof(struct spi_imx_data));
+	if (!controller)
 		return -ENOMEM;
 
 	ret = of_property_read_u32(np, "fsl,spi-rdy-drctl", &spi_drctl);
@@ -1617,14 +1617,14 @@ static int spi_imx_probe(struct platform_device *pdev)
 		spi_drctl = 0;
 	}
 
-	platform_set_drvdata(pdev, master);
+	platform_set_drvdata(pdev, controller);
 
-	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
-	master->bus_num = np ? -1 : pdev->id;
-	master->use_gpio_descriptors = true;
+	controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
+	controller->bus_num = np ? -1 : pdev->id;
+	controller->use_gpio_descriptors = true;
 
-	spi_imx = spi_master_get_devdata(master);
-	spi_imx->bitbang.master = master;
+	spi_imx = spi_controller_get_devdata(controller);
+	spi_imx->bitbang.master = controller;
 	spi_imx->dev = &pdev->dev;
 	spi_imx->slave_mode = slave_mode;
 
@@ -1637,9 +1637,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 	 * board files have <= 3 chip selects.
 	 */
 	if (!device_property_read_u32(&pdev->dev, "num-cs", &val))
-		master->num_chipselect = val;
+		controller->num_chipselect = val;
 	else
-		master->num_chipselect = 3;
+		controller->num_chipselect = 3;
 
 	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
 	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
@@ -1670,38 +1670,38 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(spi_imx->base)) {
 		ret = PTR_ERR(spi_imx->base);
-		goto out_master_put;
+		goto out_controller_put;
 	}
 	spi_imx->base_phys = res->start;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		ret = irq;
-		goto out_master_put;
+		goto out_controller_put;
 	}
 
 	ret = devm_request_irq(&pdev->dev, irq, spi_imx_isr, 0,
 			       dev_name(&pdev->dev), spi_imx);
 	if (ret) {
 		dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret);
-		goto out_master_put;
+		goto out_controller_put;
 	}
 
 	spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(spi_imx->clk_ipg)) {
 		ret = PTR_ERR(spi_imx->clk_ipg);
-		goto out_master_put;
+		goto out_controller_put;
 	}
 
 	spi_imx->clk_per = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(spi_imx->clk_per)) {
 		ret = PTR_ERR(spi_imx->clk_per);
-		goto out_master_put;
+		goto out_controller_put;
 	}
 
 	ret = clk_prepare_enable(spi_imx->clk_per);
 	if (ret)
-		goto out_master_put;
+		goto out_controller_put;
 
 	ret = clk_prepare_enable(spi_imx->clk_ipg);
 	if (ret)
@@ -1719,7 +1719,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 	 * if validated on other chips.
 	 */
 	if (spi_imx->devtype_data->has_dmamode) {
-		ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master);
+		ret = spi_imx_sdma_init(&pdev->dev, spi_imx, controller);
 		if (ret == -EPROBE_DEFER)
 			goto out_runtime_pm_put;
 
@@ -1732,7 +1732,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 
 	spi_imx->devtype_data->intctrl(spi_imx, 0);
 
-	master->dev.of_node = pdev->dev.of_node;
+	controller->dev.of_node = pdev->dev.of_node;
 	ret = spi_bitbang_start(&spi_imx->bitbang);
 	if (ret) {
 		dev_err_probe(&pdev->dev, ret, "bitbang start failed\n");
@@ -1755,16 +1755,16 @@ static int spi_imx_probe(struct platform_device *pdev)
 	clk_disable_unprepare(spi_imx->clk_ipg);
 out_put_per:
 	clk_disable_unprepare(spi_imx->clk_per);
-out_master_put:
-	spi_master_put(master);
+out_controller_put:
+	spi_controller_put(controller);
 
 	return ret;
 }
 
 static int spi_imx_remove(struct platform_device *pdev)
 {
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_controller *controller = platform_get_drvdata(pdev);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 	int ret;
 
 	spi_bitbang_stop(&spi_imx->bitbang);
@@ -1783,18 +1783,18 @@ static int spi_imx_remove(struct platform_device *pdev)
 	pm_runtime_disable(spi_imx->dev);
 
 	spi_imx_sdma_exit(spi_imx);
-	spi_master_put(master);
+	spi_controller_put(controller);
 
 	return 0;
 }
 
 static int __maybe_unused spi_imx_runtime_resume(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
+	struct spi_controller *controller = dev_get_drvdata(dev);
 	struct spi_imx_data *spi_imx;
 	int ret;
 
-	spi_imx = spi_master_get_devdata(master);
+	spi_imx = spi_controller_get_devdata(controller);
 
 	ret = clk_prepare_enable(spi_imx->clk_per);
 	if (ret)
@@ -1811,10 +1811,10 @@ static int __maybe_unused spi_imx_runtime_resume(struct device *dev)
 
 static int __maybe_unused spi_imx_runtime_suspend(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
+	struct spi_controller *controller = dev_get_drvdata(dev);
 	struct spi_imx_data *spi_imx;
 
-	spi_imx = spi_master_get_devdata(master);
+	spi_imx = spi_controller_get_devdata(controller);
 
 	clk_disable_unprepare(spi_imx->clk_per);
 	clk_disable_unprepare(spi_imx->clk_ipg);
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 6/9] spi: spi-imx: complete conversion from master -> controller
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

With patch:
| 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"")
the SPI "master" was generalized to "controller". This patch completed
the conversion of the spi-imx driver by replacing the remaining
occurrences of master to controller.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 162 +++++++++++++++++++++---------------------
 1 file changed, 81 insertions(+), 81 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index e817cf95eea6..bfce856f56bf 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -225,15 +225,15 @@ static int spi_imx_bytes_per_word(const int bits_per_word)
 		return 4;
 }
 
-static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
+static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device *spi,
 			 struct spi_transfer *transfer)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 
-	if (!use_dma || master->fallback)
+	if (!use_dma || controller->fallback)
 		return false;
 
-	if (!master->dma_rx)
+	if (!controller->dma_rx)
 		return false;
 
 	if (spi_imx->slave_mode)
@@ -1152,12 +1152,12 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int spi_imx_dma_configure(struct spi_master *master)
+static int spi_imx_dma_configure(struct spi_controller *controller)
 {
 	int ret;
 	enum dma_slave_buswidth buswidth;
 	struct dma_slave_config rx = {}, tx = {};
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 
 	switch (spi_imx_bytes_per_word(spi_imx->bits_per_word)) {
 	case 4:
@@ -1177,7 +1177,7 @@ static int spi_imx_dma_configure(struct spi_master *master)
 	tx.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
 	tx.dst_addr_width = buswidth;
 	tx.dst_maxburst = spi_imx->wml;
-	ret = dmaengine_slave_config(master->dma_tx, &tx);
+	ret = dmaengine_slave_config(controller->dma_tx, &tx);
 	if (ret) {
 		dev_err(spi_imx->dev, "TX dma configuration failed with %d\n", ret);
 		return ret;
@@ -1187,7 +1187,7 @@ static int spi_imx_dma_configure(struct spi_master *master)
 	rx.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
 	rx.src_addr_width = buswidth;
 	rx.src_maxburst = spi_imx->wml;
-	ret = dmaengine_slave_config(master->dma_rx, &rx);
+	ret = dmaengine_slave_config(controller->dma_rx, &rx);
 	if (ret) {
 		dev_err(spi_imx->dev, "RX dma configuration failed with %d\n", ret);
 		return ret;
@@ -1199,7 +1199,7 @@ static int spi_imx_dma_configure(struct spi_master *master)
 static int spi_imx_setupxfer(struct spi_device *spi,
 				 struct spi_transfer *t)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 
 	if (!t)
 		return 0;
@@ -1263,50 +1263,50 @@ static int spi_imx_setupxfer(struct spi_device *spi,
 
 static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx)
 {
-	struct spi_master *master = spi_imx->bitbang.master;
+	struct spi_controller *controller = spi_imx->bitbang.master;
 
-	if (master->dma_rx) {
-		dma_release_channel(master->dma_rx);
-		master->dma_rx = NULL;
+	if (controller->dma_rx) {
+		dma_release_channel(controller->dma_rx);
+		controller->dma_rx = NULL;
 	}
 
-	if (master->dma_tx) {
-		dma_release_channel(master->dma_tx);
-		master->dma_tx = NULL;
+	if (controller->dma_tx) {
+		dma_release_channel(controller->dma_tx);
+		controller->dma_tx = NULL;
 	}
 }
 
 static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
-			     struct spi_master *master)
+			     struct spi_controller *controller)
 {
 	int ret;
 
 	spi_imx->wml = spi_imx->devtype_data->fifo_size / 2;
 
 	/* Prepare for TX DMA: */
-	master->dma_tx = dma_request_chan(dev, "tx");
-	if (IS_ERR(master->dma_tx)) {
-		ret = PTR_ERR(master->dma_tx);
+	controller->dma_tx = dma_request_chan(dev, "tx");
+	if (IS_ERR(controller->dma_tx)) {
+		ret = PTR_ERR(controller->dma_tx);
 		dev_dbg(dev, "can't get the TX DMA channel, error %d!\n", ret);
-		master->dma_tx = NULL;
+		controller->dma_tx = NULL;
 		goto err;
 	}
 
 	/* Prepare for RX : */
-	master->dma_rx = dma_request_chan(dev, "rx");
-	if (IS_ERR(master->dma_rx)) {
-		ret = PTR_ERR(master->dma_rx);
+	controller->dma_rx = dma_request_chan(dev, "rx");
+	if (IS_ERR(controller->dma_rx)) {
+		ret = PTR_ERR(controller->dma_rx);
 		dev_dbg(dev, "can't get the RX DMA channel, error %d\n", ret);
-		master->dma_rx = NULL;
+		controller->dma_rx = NULL;
 		goto err;
 	}
 
 	init_completion(&spi_imx->dma_rx_completion);
 	init_completion(&spi_imx->dma_tx_completion);
-	master->can_dma = spi_imx_can_dma;
-	master->max_dma_len = MAX_SDMA_BD_BYTES;
-	spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
-					 SPI_MASTER_MUST_TX;
+	controller->can_dma = spi_imx_can_dma;
+	controller->max_dma_len = MAX_SDMA_BD_BYTES;
+	spi_imx->bitbang.master->flags = SPI_CONTROLLER_MUST_RX |
+					 SPI_CONTROLLER_MUST_TX;
 
 	return 0;
 err:
@@ -1348,7 +1348,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	struct dma_async_tx_descriptor *desc_tx, *desc_rx;
 	unsigned long transfer_timeout;
 	unsigned long timeout;
-	struct spi_master *master = spi_imx->bitbang.master;
+	struct spi_controller *controller = spi_imx->bitbang.master;
 	struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
 	struct scatterlist *last_sg = sg_last(rx->sgl, rx->nents);
 	unsigned int bytes_per_word, i;
@@ -1366,7 +1366,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 
 	spi_imx->wml =  i;
 
-	ret = spi_imx_dma_configure(master);
+	ret = spi_imx_dma_configure(controller);
 	if (ret)
 		goto dma_failure_no_start;
 
@@ -1381,7 +1381,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	 * The TX DMA setup starts the transfer, so make sure RX is configured
 	 * before TX.
 	 */
-	desc_rx = dmaengine_prep_slave_sg(master->dma_rx,
+	desc_rx = dmaengine_prep_slave_sg(controller->dma_rx,
 				rx->sgl, rx->nents, DMA_DEV_TO_MEM,
 				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc_rx) {
@@ -1393,14 +1393,14 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	desc_rx->callback_param = (void *)spi_imx;
 	dmaengine_submit(desc_rx);
 	reinit_completion(&spi_imx->dma_rx_completion);
-	dma_async_issue_pending(master->dma_rx);
+	dma_async_issue_pending(controller->dma_rx);
 
-	desc_tx = dmaengine_prep_slave_sg(master->dma_tx,
+	desc_tx = dmaengine_prep_slave_sg(controller->dma_tx,
 				tx->sgl, tx->nents, DMA_MEM_TO_DEV,
 				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc_tx) {
-		dmaengine_terminate_all(master->dma_tx);
-		dmaengine_terminate_all(master->dma_rx);
+		dmaengine_terminate_all(controller->dma_tx);
+		dmaengine_terminate_all(controller->dma_rx);
 		return -EINVAL;
 	}
 
@@ -1408,7 +1408,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	desc_tx->callback_param = (void *)spi_imx;
 	dmaengine_submit(desc_tx);
 	reinit_completion(&spi_imx->dma_tx_completion);
-	dma_async_issue_pending(master->dma_tx);
+	dma_async_issue_pending(controller->dma_tx);
 
 	transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
 
@@ -1417,17 +1417,17 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 						transfer_timeout);
 	if (!timeout) {
 		dev_err(spi_imx->dev, "I/O Error in DMA TX\n");
-		dmaengine_terminate_all(master->dma_tx);
-		dmaengine_terminate_all(master->dma_rx);
+		dmaengine_terminate_all(controller->dma_tx);
+		dmaengine_terminate_all(controller->dma_rx);
 		return -ETIMEDOUT;
 	}
 
 	timeout = wait_for_completion_timeout(&spi_imx->dma_rx_completion,
 					      transfer_timeout);
 	if (!timeout) {
-		dev_err(&master->dev, "I/O Error in DMA RX\n");
+		dev_err(&controller->dev, "I/O Error in DMA RX\n");
 		spi_imx->devtype_data->reset(spi_imx);
-		dmaengine_terminate_all(master->dma_rx);
+		dmaengine_terminate_all(controller->dma_rx);
 		return -ETIMEDOUT;
 	}
 
@@ -1441,7 +1441,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 static int spi_imx_pio_transfer(struct spi_device *spi,
 				struct spi_transfer *transfer)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 	unsigned long transfer_timeout;
 	unsigned long timeout;
 
@@ -1473,7 +1473,7 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 				      struct spi_transfer *transfer)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 	int ret = transfer->len;
 
 	if (is_imx53_ecspi(spi_imx) &&
@@ -1517,7 +1517,7 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 static int spi_imx_transfer(struct spi_device *spi,
 				struct spi_transfer *transfer)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 
 	transfer->effective_speed_hz = spi_imx->spi_bus_clk;
 
@@ -1547,9 +1547,9 @@ static void spi_imx_cleanup(struct spi_device *spi)
 }
 
 static int
-spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
+spi_imx_prepare_message(struct spi_controller *controller, struct spi_message *msg)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 	int ret;
 
 	ret = pm_runtime_get_sync(spi_imx->dev);
@@ -1569,18 +1569,18 @@ spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
 }
 
 static int
-spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg)
+spi_imx_unprepare_message(struct spi_controller *controller, struct spi_message *msg)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 
 	pm_runtime_mark_last_busy(spi_imx->dev);
 	pm_runtime_put_autosuspend(spi_imx->dev);
 	return 0;
 }
 
-static int spi_imx_slave_abort(struct spi_master *master)
+static int spi_imx_slave_abort(struct spi_controller *controller)
 {
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 
 	spi_imx->slave_aborted = true;
 	complete(&spi_imx->xfer_done);
@@ -1591,7 +1591,7 @@ static int spi_imx_slave_abort(struct spi_master *master)
 static int spi_imx_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	struct spi_master *master;
+	struct spi_controller *controller;
 	struct spi_imx_data *spi_imx;
 	struct resource *res;
 	int ret, irq, spi_drctl;
@@ -1603,12 +1603,12 @@ static int spi_imx_probe(struct platform_device *pdev)
 	slave_mode = devtype_data->has_slavemode &&
 			of_property_read_bool(np, "spi-slave");
 	if (slave_mode)
-		master = spi_alloc_slave(&pdev->dev,
-					 sizeof(struct spi_imx_data));
+		controller = spi_alloc_slave(&pdev->dev,
+					     sizeof(struct spi_imx_data));
 	else
-		master = spi_alloc_master(&pdev->dev,
-					  sizeof(struct spi_imx_data));
-	if (!master)
+		controller = spi_alloc_master(&pdev->dev,
+					      sizeof(struct spi_imx_data));
+	if (!controller)
 		return -ENOMEM;
 
 	ret = of_property_read_u32(np, "fsl,spi-rdy-drctl", &spi_drctl);
@@ -1617,14 +1617,14 @@ static int spi_imx_probe(struct platform_device *pdev)
 		spi_drctl = 0;
 	}
 
-	platform_set_drvdata(pdev, master);
+	platform_set_drvdata(pdev, controller);
 
-	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
-	master->bus_num = np ? -1 : pdev->id;
-	master->use_gpio_descriptors = true;
+	controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
+	controller->bus_num = np ? -1 : pdev->id;
+	controller->use_gpio_descriptors = true;
 
-	spi_imx = spi_master_get_devdata(master);
-	spi_imx->bitbang.master = master;
+	spi_imx = spi_controller_get_devdata(controller);
+	spi_imx->bitbang.master = controller;
 	spi_imx->dev = &pdev->dev;
 	spi_imx->slave_mode = slave_mode;
 
@@ -1637,9 +1637,9 @@ static int spi_imx_probe(struct platform_device *pdev)
 	 * board files have <= 3 chip selects.
 	 */
 	if (!device_property_read_u32(&pdev->dev, "num-cs", &val))
-		master->num_chipselect = val;
+		controller->num_chipselect = val;
 	else
-		master->num_chipselect = 3;
+		controller->num_chipselect = 3;
 
 	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
 	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
@@ -1670,38 +1670,38 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(spi_imx->base)) {
 		ret = PTR_ERR(spi_imx->base);
-		goto out_master_put;
+		goto out_controller_put;
 	}
 	spi_imx->base_phys = res->start;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		ret = irq;
-		goto out_master_put;
+		goto out_controller_put;
 	}
 
 	ret = devm_request_irq(&pdev->dev, irq, spi_imx_isr, 0,
 			       dev_name(&pdev->dev), spi_imx);
 	if (ret) {
 		dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret);
-		goto out_master_put;
+		goto out_controller_put;
 	}
 
 	spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(spi_imx->clk_ipg)) {
 		ret = PTR_ERR(spi_imx->clk_ipg);
-		goto out_master_put;
+		goto out_controller_put;
 	}
 
 	spi_imx->clk_per = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(spi_imx->clk_per)) {
 		ret = PTR_ERR(spi_imx->clk_per);
-		goto out_master_put;
+		goto out_controller_put;
 	}
 
 	ret = clk_prepare_enable(spi_imx->clk_per);
 	if (ret)
-		goto out_master_put;
+		goto out_controller_put;
 
 	ret = clk_prepare_enable(spi_imx->clk_ipg);
 	if (ret)
@@ -1719,7 +1719,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 	 * if validated on other chips.
 	 */
 	if (spi_imx->devtype_data->has_dmamode) {
-		ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master);
+		ret = spi_imx_sdma_init(&pdev->dev, spi_imx, controller);
 		if (ret == -EPROBE_DEFER)
 			goto out_runtime_pm_put;
 
@@ -1732,7 +1732,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 
 	spi_imx->devtype_data->intctrl(spi_imx, 0);
 
-	master->dev.of_node = pdev->dev.of_node;
+	controller->dev.of_node = pdev->dev.of_node;
 	ret = spi_bitbang_start(&spi_imx->bitbang);
 	if (ret) {
 		dev_err_probe(&pdev->dev, ret, "bitbang start failed\n");
@@ -1755,16 +1755,16 @@ static int spi_imx_probe(struct platform_device *pdev)
 	clk_disable_unprepare(spi_imx->clk_ipg);
 out_put_per:
 	clk_disable_unprepare(spi_imx->clk_per);
-out_master_put:
-	spi_master_put(master);
+out_controller_put:
+	spi_controller_put(controller);
 
 	return ret;
 }
 
 static int spi_imx_remove(struct platform_device *pdev)
 {
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	struct spi_controller *controller = platform_get_drvdata(pdev);
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 	int ret;
 
 	spi_bitbang_stop(&spi_imx->bitbang);
@@ -1783,18 +1783,18 @@ static int spi_imx_remove(struct platform_device *pdev)
 	pm_runtime_disable(spi_imx->dev);
 
 	spi_imx_sdma_exit(spi_imx);
-	spi_master_put(master);
+	spi_controller_put(controller);
 
 	return 0;
 }
 
 static int __maybe_unused spi_imx_runtime_resume(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
+	struct spi_controller *controller = dev_get_drvdata(dev);
 	struct spi_imx_data *spi_imx;
 	int ret;
 
-	spi_imx = spi_master_get_devdata(master);
+	spi_imx = spi_controller_get_devdata(controller);
 
 	ret = clk_prepare_enable(spi_imx->clk_per);
 	if (ret)
@@ -1811,10 +1811,10 @@ static int __maybe_unused spi_imx_runtime_resume(struct device *dev)
 
 static int __maybe_unused spi_imx_runtime_suspend(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
+	struct spi_controller *controller = dev_get_drvdata(dev);
 	struct spi_imx_data *spi_imx;
 
-	spi_imx = spi_master_get_devdata(master);
+	spi_imx = spi_controller_get_devdata(controller);
 
 	clk_disable_unprepare(spi_imx->clk_per);
 	clk_disable_unprepare(spi_imx->clk_ipg);
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 7/9] spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel,
	Marc Kleine-Budde, David Jander

There's no need to embed the struct spi_bitbang into our private
data (struct spi_imx_data), the spi core is flexible enough, so that
we only need a pointer to the allocated struct spi_controller.

This is also a preparation patch to add PIO based polling support to
the driver.

Co-developed-by: David Jander <david@protonic.nl>
Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 56 +++++++++++++++++++++----------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index bfce856f56bf..ec6758e032ff 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -18,7 +18,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
 #include <linux/types.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -86,7 +85,7 @@ struct spi_imx_devtype_data {
 };
 
 struct spi_imx_data {
-	struct spi_bitbang bitbang;
+	struct spi_controller *controller;
 	struct device *dev;
 
 	struct completion xfer_done;
@@ -584,7 +583,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
 	 * the SPI communication as the device on the other end would consider
 	 * the change of SCLK polarity as a clock tick already.
 	 *
-	 * Because spi_imx->spi_bus_clk is only set in bitbang prepare_message
+	 * Because spi_imx->spi_bus_clk is only set in prepare_message
 	 * callback, iterate over all the transfers in spi_message, find the
 	 * one with lowest bus frequency, and use that bus frequency for the
 	 * delay calculation. In case all transfers have speed_hz == 0, then
@@ -1245,7 +1244,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
 		spi_imx->dynamic_burst = 0;
 	}
 
-	if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
+	if (spi_imx_can_dma(spi_imx->controller, spi, t))
 		spi_imx->usedma = true;
 	else
 		spi_imx->usedma = false;
@@ -1263,7 +1262,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
 
 static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx)
 {
-	struct spi_controller *controller = spi_imx->bitbang.master;
+	struct spi_controller *controller = spi_imx->controller;
 
 	if (controller->dma_rx) {
 		dma_release_channel(controller->dma_rx);
@@ -1305,7 +1304,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
 	init_completion(&spi_imx->dma_tx_completion);
 	controller->can_dma = spi_imx_can_dma;
 	controller->max_dma_len = MAX_SDMA_BD_BYTES;
-	spi_imx->bitbang.master->flags = SPI_CONTROLLER_MUST_RX |
+	spi_imx->controller->flags = SPI_CONTROLLER_MUST_RX |
 					 SPI_CONTROLLER_MUST_TX;
 
 	return 0;
@@ -1348,7 +1347,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	struct dma_async_tx_descriptor *desc_tx, *desc_rx;
 	unsigned long transfer_timeout;
 	unsigned long timeout;
-	struct spi_controller *controller = spi_imx->bitbang.master;
+	struct spi_controller *controller = spi_imx->controller;
 	struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
 	struct scatterlist *last_sg = sg_last(rx->sgl, rx->nents);
 	unsigned int bytes_per_word, i;
@@ -1431,7 +1430,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 		return -ETIMEDOUT;
 	}
 
-	return transfer->len;
+	return 0;
 /* fallback to pio */
 dma_failure_no_start:
 	transfer->error |= SPI_TRANS_FAIL_NO_START;
@@ -1467,14 +1466,14 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 		return -ETIMEDOUT;
 	}
 
-	return transfer->len;
+	return 0;
 }
 
 static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 				      struct spi_transfer *transfer)
 {
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
-	int ret = transfer->len;
+	int ret = 0;
 
 	if (is_imx53_ecspi(spi_imx) &&
 	    transfer->len > MX53_MAX_TRANSFER_BYTES) {
@@ -1514,11 +1513,13 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 	return ret;
 }
 
-static int spi_imx_transfer(struct spi_device *spi,
+static int spi_imx_transfer_one(struct spi_controller *controller,
+				struct spi_device *spi,
 				struct spi_transfer *transfer)
 {
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 
+	spi_imx_setupxfer(spi, transfer);
 	transfer->effective_speed_hz = spi_imx->spi_bus_clk;
 
 	/* flush rxfifo before transfer */
@@ -1624,7 +1625,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 	controller->use_gpio_descriptors = true;
 
 	spi_imx = spi_controller_get_devdata(controller);
-	spi_imx->bitbang.master = controller;
+	spi_imx->controller = controller;
 	spi_imx->dev = &pdev->dev;
 	spi_imx->slave_mode = slave_mode;
 
@@ -1641,17 +1642,17 @@ static int spi_imx_probe(struct platform_device *pdev)
 	else
 		controller->num_chipselect = 3;
 
-	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
-	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
-	spi_imx->bitbang.master->setup = spi_imx_setup;
-	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
-	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
-	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
-	spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
-	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
+	spi_imx->controller->transfer_one = spi_imx_transfer_one;
+	spi_imx->controller->setup = spi_imx_setup;
+	spi_imx->controller->cleanup = spi_imx_cleanup;
+	spi_imx->controller->prepare_message = spi_imx_prepare_message;
+	spi_imx->controller->unprepare_message = spi_imx_unprepare_message;
+	spi_imx->controller->slave_abort = spi_imx_slave_abort;
+	spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
+
 	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
 	    is_imx53_ecspi(spi_imx))
-		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
+		spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY;
 
 	if (is_imx51_ecspi(spi_imx) &&
 	    device_property_read_u32(&pdev->dev, "cs-gpios", NULL))
@@ -1660,7 +1661,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 		 * setting the burst length to the word size. This is
 		 * considerably faster than manually controlling the CS.
 		 */
-		spi_imx->bitbang.master->mode_bits |= SPI_CS_WORD;
+		spi_imx->controller->mode_bits |= SPI_CS_WORD;
 
 	spi_imx->spi_drctl = spi_drctl;
 
@@ -1733,10 +1734,10 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->devtype_data->intctrl(spi_imx, 0);
 
 	controller->dev.of_node = pdev->dev.of_node;
-	ret = spi_bitbang_start(&spi_imx->bitbang);
+	ret = spi_register_controller(controller);
 	if (ret) {
-		dev_err_probe(&pdev->dev, ret, "bitbang start failed\n");
-		goto out_bitbang_start;
+		dev_err_probe(&pdev->dev, ret, "register controller failed\n");
+		goto out_register_controller;
 	}
 
 	pm_runtime_mark_last_busy(spi_imx->dev);
@@ -1744,7 +1745,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 
 	return ret;
 
-out_bitbang_start:
+out_register_controller:
 	if (spi_imx->devtype_data->has_dmamode)
 		spi_imx_sdma_exit(spi_imx);
 out_runtime_pm_put:
@@ -1767,7 +1768,7 @@ static int spi_imx_remove(struct platform_device *pdev)
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 	int ret;
 
-	spi_bitbang_stop(&spi_imx->bitbang);
+	spi_unregister_controller(controller);
 
 	ret = pm_runtime_get_sync(spi_imx->dev);
 	if (ret < 0) {
@@ -1783,7 +1784,6 @@ static int spi_imx_remove(struct platform_device *pdev)
 	pm_runtime_disable(spi_imx->dev);
 
 	spi_imx_sdma_exit(spi_imx);
-	spi_controller_put(controller);
 
 	return 0;
 }
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 7/9] spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel,
	Marc Kleine-Budde, David Jander

There's no need to embed the struct spi_bitbang into our private
data (struct spi_imx_data), the spi core is flexible enough, so that
we only need a pointer to the allocated struct spi_controller.

This is also a preparation patch to add PIO based polling support to
the driver.

Co-developed-by: David Jander <david@protonic.nl>
Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 56 +++++++++++++++++++++----------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index bfce856f56bf..ec6758e032ff 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -18,7 +18,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
 #include <linux/types.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -86,7 +85,7 @@ struct spi_imx_devtype_data {
 };
 
 struct spi_imx_data {
-	struct spi_bitbang bitbang;
+	struct spi_controller *controller;
 	struct device *dev;
 
 	struct completion xfer_done;
@@ -584,7 +583,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
 	 * the SPI communication as the device on the other end would consider
 	 * the change of SCLK polarity as a clock tick already.
 	 *
-	 * Because spi_imx->spi_bus_clk is only set in bitbang prepare_message
+	 * Because spi_imx->spi_bus_clk is only set in prepare_message
 	 * callback, iterate over all the transfers in spi_message, find the
 	 * one with lowest bus frequency, and use that bus frequency for the
 	 * delay calculation. In case all transfers have speed_hz == 0, then
@@ -1245,7 +1244,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
 		spi_imx->dynamic_burst = 0;
 	}
 
-	if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
+	if (spi_imx_can_dma(spi_imx->controller, spi, t))
 		spi_imx->usedma = true;
 	else
 		spi_imx->usedma = false;
@@ -1263,7 +1262,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
 
 static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx)
 {
-	struct spi_controller *controller = spi_imx->bitbang.master;
+	struct spi_controller *controller = spi_imx->controller;
 
 	if (controller->dma_rx) {
 		dma_release_channel(controller->dma_rx);
@@ -1305,7 +1304,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
 	init_completion(&spi_imx->dma_tx_completion);
 	controller->can_dma = spi_imx_can_dma;
 	controller->max_dma_len = MAX_SDMA_BD_BYTES;
-	spi_imx->bitbang.master->flags = SPI_CONTROLLER_MUST_RX |
+	spi_imx->controller->flags = SPI_CONTROLLER_MUST_RX |
 					 SPI_CONTROLLER_MUST_TX;
 
 	return 0;
@@ -1348,7 +1347,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 	struct dma_async_tx_descriptor *desc_tx, *desc_rx;
 	unsigned long transfer_timeout;
 	unsigned long timeout;
-	struct spi_controller *controller = spi_imx->bitbang.master;
+	struct spi_controller *controller = spi_imx->controller;
 	struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
 	struct scatterlist *last_sg = sg_last(rx->sgl, rx->nents);
 	unsigned int bytes_per_word, i;
@@ -1431,7 +1430,7 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
 		return -ETIMEDOUT;
 	}
 
-	return transfer->len;
+	return 0;
 /* fallback to pio */
 dma_failure_no_start:
 	transfer->error |= SPI_TRANS_FAIL_NO_START;
@@ -1467,14 +1466,14 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 		return -ETIMEDOUT;
 	}
 
-	return transfer->len;
+	return 0;
 }
 
 static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 				      struct spi_transfer *transfer)
 {
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
-	int ret = transfer->len;
+	int ret = 0;
 
 	if (is_imx53_ecspi(spi_imx) &&
 	    transfer->len > MX53_MAX_TRANSFER_BYTES) {
@@ -1514,11 +1513,13 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 	return ret;
 }
 
-static int spi_imx_transfer(struct spi_device *spi,
+static int spi_imx_transfer_one(struct spi_controller *controller,
+				struct spi_device *spi,
 				struct spi_transfer *transfer)
 {
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
 
+	spi_imx_setupxfer(spi, transfer);
 	transfer->effective_speed_hz = spi_imx->spi_bus_clk;
 
 	/* flush rxfifo before transfer */
@@ -1624,7 +1625,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 	controller->use_gpio_descriptors = true;
 
 	spi_imx = spi_controller_get_devdata(controller);
-	spi_imx->bitbang.master = controller;
+	spi_imx->controller = controller;
 	spi_imx->dev = &pdev->dev;
 	spi_imx->slave_mode = slave_mode;
 
@@ -1641,17 +1642,17 @@ static int spi_imx_probe(struct platform_device *pdev)
 	else
 		controller->num_chipselect = 3;
 
-	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
-	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
-	spi_imx->bitbang.master->setup = spi_imx_setup;
-	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
-	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
-	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
-	spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
-	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
+	spi_imx->controller->transfer_one = spi_imx_transfer_one;
+	spi_imx->controller->setup = spi_imx_setup;
+	spi_imx->controller->cleanup = spi_imx_cleanup;
+	spi_imx->controller->prepare_message = spi_imx_prepare_message;
+	spi_imx->controller->unprepare_message = spi_imx_unprepare_message;
+	spi_imx->controller->slave_abort = spi_imx_slave_abort;
+	spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
+
 	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
 	    is_imx53_ecspi(spi_imx))
-		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
+		spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY;
 
 	if (is_imx51_ecspi(spi_imx) &&
 	    device_property_read_u32(&pdev->dev, "cs-gpios", NULL))
@@ -1660,7 +1661,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 		 * setting the burst length to the word size. This is
 		 * considerably faster than manually controlling the CS.
 		 */
-		spi_imx->bitbang.master->mode_bits |= SPI_CS_WORD;
+		spi_imx->controller->mode_bits |= SPI_CS_WORD;
 
 	spi_imx->spi_drctl = spi_drctl;
 
@@ -1733,10 +1734,10 @@ static int spi_imx_probe(struct platform_device *pdev)
 	spi_imx->devtype_data->intctrl(spi_imx, 0);
 
 	controller->dev.of_node = pdev->dev.of_node;
-	ret = spi_bitbang_start(&spi_imx->bitbang);
+	ret = spi_register_controller(controller);
 	if (ret) {
-		dev_err_probe(&pdev->dev, ret, "bitbang start failed\n");
-		goto out_bitbang_start;
+		dev_err_probe(&pdev->dev, ret, "register controller failed\n");
+		goto out_register_controller;
 	}
 
 	pm_runtime_mark_last_busy(spi_imx->dev);
@@ -1744,7 +1745,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 
 	return ret;
 
-out_bitbang_start:
+out_register_controller:
 	if (spi_imx->devtype_data->has_dmamode)
 		spi_imx_sdma_exit(spi_imx);
 out_runtime_pm_put:
@@ -1767,7 +1768,7 @@ static int spi_imx_remove(struct platform_device *pdev)
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller);
 	int ret;
 
-	spi_bitbang_stop(&spi_imx->bitbang);
+	spi_unregister_controller(controller);
 
 	ret = pm_runtime_get_sync(spi_imx->dev);
 	if (ret < 0) {
@@ -1783,7 +1784,6 @@ static int spi_imx_remove(struct platform_device *pdev)
 	pm_runtime_disable(spi_imx->dev);
 
 	spi_imx_sdma_exit(spi_imx);
-	spi_controller_put(controller);
 
 	return 0;
 }
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 8/9] spi: spi-imx: add PIO polling support
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel,
	Marc Kleine-Budde, David Jander

The driver supports several modes, one of them is PIO/IRQ
"spi_imx_pio_transfer()". The data is exchanged with the IP core using
PIO, an IRQ is setup to signal empty/full FIFOs and the end of the
transfer. The IRQ and scheduling overhead for short transfers is
significant. Using polling instead of IRQs can be beneficial to reduce
the overall CPU load, especially on small transfer workloads.

On an imx6 single core, a given RX workload of the mcp251xfd driver
results in 40% CPU load. Using polling mode reduces the CPU load to
30%.

This patch adds PIO polling support to the driver. For transfers with
a duration of less than 30 µs the polling mode instead of IRQ based
PIO mode is used. 30 µs seems to be a good compromise, which is used
the by the SPI drivers for the raspberry Pi (spi-bcm2835,
spi-bcm2835), too.

Co-developed-by: David Jander <david@protonic.nl>
Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 66 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index ec6758e032ff..798a5182b849 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -31,6 +31,12 @@ static bool use_dma = true;
 module_param(use_dma, bool, 0644);
 MODULE_PARM_DESC(use_dma, "Enable usage of DMA when available (default)");
 
+/* define polling limits */
+static unsigned int polling_limit_us = 30;
+module_param(polling_limit_us, uint, 0664);
+MODULE_PARM_DESC(polling_limit_us,
+		 "time in us to run a transfer in polling mode\n");
+
 #define MXC_RPM_TIMEOUT		2000 /* 2000ms */
 
 #define MXC_CSPIRXDATA		0x00
@@ -1469,6 +1475,54 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 	return 0;
 }
 
+static int spi_imx_poll_transfer(struct spi_device *spi,
+				 struct spi_transfer *transfer)
+{
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
+	unsigned long timeout;
+
+	spi_imx->tx_buf = transfer->tx_buf;
+	spi_imx->rx_buf = transfer->rx_buf;
+	spi_imx->count = transfer->len;
+	spi_imx->txfifo = 0;
+	spi_imx->remainder = 0;
+
+	/* fill in the fifo before timeout calculations if we are
+	 * interrupted here, then the data is getting transferred by
+	 * the HW while we are interrupted
+	 */
+	spi_imx_push(spi_imx);
+
+	timeout = spi_imx_calculate_timeout(spi_imx, transfer->len) + jiffies;
+	while (spi_imx->txfifo) {
+		/* RX */
+		while (spi_imx->txfifo &&
+		       spi_imx->devtype_data->rx_available(spi_imx)) {
+			spi_imx->rx(spi_imx);
+			spi_imx->txfifo--;
+		}
+
+		/* TX */
+		if (spi_imx->count) {
+			spi_imx_push(spi_imx);
+			continue;
+		}
+
+		if (spi_imx->txfifo &&
+		    time_after(jiffies, timeout)) {
+
+			dev_err_ratelimited(&spi->dev,
+					    "timeout period reached: jiffies: %lu- falling back to interrupt mode\n",
+					    jiffies - timeout);
+
+			/* fall back to interrupt mode */
+			return spi_imx_pio_transfer(spi, transfer);
+		}
+	}
+
+	return 0;
+}
+
 static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 				      struct spi_transfer *transfer)
 {
@@ -1518,6 +1572,7 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
 				struct spi_transfer *transfer)
 {
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
+	unsigned long hz_per_byte, byte_limit;
 
 	spi_imx_setupxfer(spi, transfer);
 	transfer->effective_speed_hz = spi_imx->spi_bus_clk;
@@ -1529,6 +1584,17 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
 	if (spi_imx->slave_mode)
 		return spi_imx_pio_transfer_slave(spi, transfer);
 
+	/*
+	 * Calculate the estimated time in us the transfer runs. Find
+	 * the number of Hz per byte per polling limit.
+	 */
+	hz_per_byte = polling_limit_us ? ((8 + 4) * USEC_PER_SEC) / polling_limit_us : 0;
+	byte_limit = hz_per_byte ? transfer->effective_speed_hz / hz_per_byte : 1;
+
+	/* run in polling mode for short transfers */
+	if (transfer->len < byte_limit)
+		return spi_imx_poll_transfer(spi, transfer);
+
 	if (spi_imx->usedma)
 		return spi_imx_dma_transfer(spi_imx, transfer);
 
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 8/9] spi: spi-imx: add PIO polling support
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel,
	Marc Kleine-Budde, David Jander

The driver supports several modes, one of them is PIO/IRQ
"spi_imx_pio_transfer()". The data is exchanged with the IP core using
PIO, an IRQ is setup to signal empty/full FIFOs and the end of the
transfer. The IRQ and scheduling overhead for short transfers is
significant. Using polling instead of IRQs can be beneficial to reduce
the overall CPU load, especially on small transfer workloads.

On an imx6 single core, a given RX workload of the mcp251xfd driver
results in 40% CPU load. Using polling mode reduces the CPU load to
30%.

This patch adds PIO polling support to the driver. For transfers with
a duration of less than 30 µs the polling mode instead of IRQ based
PIO mode is used. 30 µs seems to be a good compromise, which is used
the by the SPI drivers for the raspberry Pi (spi-bcm2835,
spi-bcm2835), too.

Co-developed-by: David Jander <david@protonic.nl>
Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 66 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index ec6758e032ff..798a5182b849 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -31,6 +31,12 @@ static bool use_dma = true;
 module_param(use_dma, bool, 0644);
 MODULE_PARM_DESC(use_dma, "Enable usage of DMA when available (default)");
 
+/* define polling limits */
+static unsigned int polling_limit_us = 30;
+module_param(polling_limit_us, uint, 0664);
+MODULE_PARM_DESC(polling_limit_us,
+		 "time in us to run a transfer in polling mode\n");
+
 #define MXC_RPM_TIMEOUT		2000 /* 2000ms */
 
 #define MXC_CSPIRXDATA		0x00
@@ -1469,6 +1475,54 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 	return 0;
 }
 
+static int spi_imx_poll_transfer(struct spi_device *spi,
+				 struct spi_transfer *transfer)
+{
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
+	unsigned long timeout;
+
+	spi_imx->tx_buf = transfer->tx_buf;
+	spi_imx->rx_buf = transfer->rx_buf;
+	spi_imx->count = transfer->len;
+	spi_imx->txfifo = 0;
+	spi_imx->remainder = 0;
+
+	/* fill in the fifo before timeout calculations if we are
+	 * interrupted here, then the data is getting transferred by
+	 * the HW while we are interrupted
+	 */
+	spi_imx_push(spi_imx);
+
+	timeout = spi_imx_calculate_timeout(spi_imx, transfer->len) + jiffies;
+	while (spi_imx->txfifo) {
+		/* RX */
+		while (spi_imx->txfifo &&
+		       spi_imx->devtype_data->rx_available(spi_imx)) {
+			spi_imx->rx(spi_imx);
+			spi_imx->txfifo--;
+		}
+
+		/* TX */
+		if (spi_imx->count) {
+			spi_imx_push(spi_imx);
+			continue;
+		}
+
+		if (spi_imx->txfifo &&
+		    time_after(jiffies, timeout)) {
+
+			dev_err_ratelimited(&spi->dev,
+					    "timeout period reached: jiffies: %lu- falling back to interrupt mode\n",
+					    jiffies - timeout);
+
+			/* fall back to interrupt mode */
+			return spi_imx_pio_transfer(spi, transfer);
+		}
+	}
+
+	return 0;
+}
+
 static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 				      struct spi_transfer *transfer)
 {
@@ -1518,6 +1572,7 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
 				struct spi_transfer *transfer)
 {
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
+	unsigned long hz_per_byte, byte_limit;
 
 	spi_imx_setupxfer(spi, transfer);
 	transfer->effective_speed_hz = spi_imx->spi_bus_clk;
@@ -1529,6 +1584,17 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
 	if (spi_imx->slave_mode)
 		return spi_imx_pio_transfer_slave(spi, transfer);
 
+	/*
+	 * Calculate the estimated time in us the transfer runs. Find
+	 * the number of Hz per byte per polling limit.
+	 */
+	hz_per_byte = polling_limit_us ? ((8 + 4) * USEC_PER_SEC) / polling_limit_us : 0;
+	byte_limit = hz_per_byte ? transfer->effective_speed_hz / hz_per_byte : 1;
+
+	/* run in polling mode for short transfers */
+	if (transfer->len < byte_limit)
+		return spi_imx_poll_transfer(spi, transfer);
+
 	if (spi_imx->usedma)
 		return spi_imx_dma_transfer(spi_imx, transfer);
 
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 9/9] spi: spi-imx: mx51_ecspi_prepare_message(): skip writing MX51_ECSPI_CONFIG register if unchanged
  2022-05-02 16:52 ` Marc Kleine-Budde
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

In mx51_ecspi_prepare_message() the MX51_ECSPI_CONFIG register is
setup for the current spi_message. After writing the register, there
is a delay to ensure that the changes hit the hardware.

This patch checks if the register MX51_ECSPI_CONFIG actually needs to
be changed. If the register content is unchanged the function is left
early, skipping the write to the hardware and the delay. This leads to
a small, but measurable performance increase. For a given workload
with small transfers on an imx6 single core the CPU load decreases
from 30% to ~27%.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 798a5182b849..addfed56f1d4 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -519,6 +519,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
 	u32 min_speed_hz = ~0U;
 	u32 testreg, delay;
 	u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
+	u32 current_cfg = cfg;
 
 	/* set Master or Slave mode */
 	if (spi_imx->slave_mode)
@@ -576,6 +577,9 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
 	else
 		cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
 
+	if (cfg == current_cfg)
+		return 0;
+
 	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
 	/*
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 9/9] spi: spi-imx: mx51_ecspi_prepare_message(): skip writing MX51_ECSPI_CONFIG register if unchanged
@ 2022-05-02 16:52   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:52 UTC (permalink / raw)
  To: linux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel, Marc Kleine-Budde

In mx51_ecspi_prepare_message() the MX51_ECSPI_CONFIG register is
setup for the current spi_message. After writing the register, there
is a delay to ensure that the changes hit the hardware.

This patch checks if the register MX51_ECSPI_CONFIG actually needs to
be changed. If the register content is unchanged the function is left
early, skipping the write to the hardware and the delay. This leads to
a small, but measurable performance increase. For a given workload
with small transfers on an imx6 single core the CPU load decreases
from 30% to ~27%.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 798a5182b849..addfed56f1d4 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -519,6 +519,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
 	u32 min_speed_hz = ~0U;
 	u32 testreg, delay;
 	u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
+	u32 current_cfg = cfg;
 
 	/* set Master or Slave mode */
 	if (spi_imx->slave_mode)
@@ -576,6 +577,9 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
 	else
 		cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select);
 
+	if (cfg == current_cfg)
+		return 0;
+
 	writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
 
 	/*
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [RFC 7/9] spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller
  2022-05-02 16:52   ` Marc Kleine-Budde
@ 2022-05-02 17:14     ` Baruch Siach
  -1 siblings, 0 replies; 25+ messages in thread
From: Baruch Siach @ 2022-05-02 17:14 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: linux-spi, Fabio Estevam, Marek Vasut, kernel, linux-imx,
	Mark Brown, David Jander, linux-arm-kernel

Hi Marc,

On Mon, May 02 2022, Marc Kleine-Budde wrote:

> There's no need to embed the struct spi_bitbang into our private
> data (struct spi_imx_data), the spi core is flexible enough, so that
> we only need a pointer to the allocated struct spi_controller.
>
> This is also a preparation patch to add PIO based polling support to
> the driver.
>
> Co-developed-by: David Jander <david@protonic.nl>
> Signed-off-by: David Jander <david@protonic.nl>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

[...]

> @@ -1641,17 +1642,17 @@ static int spi_imx_probe(struct platform_device *pdev)
>  	else
>  		controller->num_chipselect = 3;
>  
> -	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
> -	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
> -	spi_imx->bitbang.master->setup = spi_imx_setup;
> -	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
> -	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
> -	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
> -	spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
> -	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
> +	spi_imx->controller->transfer_one = spi_imx_transfer_one;
> +	spi_imx->controller->setup = spi_imx_setup;
> +	spi_imx->controller->cleanup = spi_imx_cleanup;
> +	spi_imx->controller->prepare_message = spi_imx_prepare_message;
> +	spi_imx->controller->unprepare_message = spi_imx_unprepare_message;
> +	spi_imx->controller->slave_abort = spi_imx_slave_abort;
> +	spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
> +
>  	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
>  	    is_imx53_ecspi(spi_imx))
> -		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
> +		spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY;
>  
>  	if (is_imx51_ecspi(spi_imx) &&
>  	    device_property_read_u32(&pdev->dev, "cs-gpios", NULL))

This hunk conflicts with commit 79422ed9bd7f ("spi: spi-imx: add support
for SPI_RX_CPHA_FLIP") in Mark's for-5.19 branch. That commit also adds
another reference to bitbang.master.

baruch

-- 
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch@tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il -

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 7/9] spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller
@ 2022-05-02 17:14     ` Baruch Siach
  0 siblings, 0 replies; 25+ messages in thread
From: Baruch Siach @ 2022-05-02 17:14 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: linux-spi, Fabio Estevam, Marek Vasut, kernel, linux-imx,
	Mark Brown, David Jander, linux-arm-kernel

Hi Marc,

On Mon, May 02 2022, Marc Kleine-Budde wrote:

> There's no need to embed the struct spi_bitbang into our private
> data (struct spi_imx_data), the spi core is flexible enough, so that
> we only need a pointer to the allocated struct spi_controller.
>
> This is also a preparation patch to add PIO based polling support to
> the driver.
>
> Co-developed-by: David Jander <david@protonic.nl>
> Signed-off-by: David Jander <david@protonic.nl>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

[...]

> @@ -1641,17 +1642,17 @@ static int spi_imx_probe(struct platform_device *pdev)
>  	else
>  		controller->num_chipselect = 3;
>  
> -	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
> -	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
> -	spi_imx->bitbang.master->setup = spi_imx_setup;
> -	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
> -	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
> -	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
> -	spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
> -	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
> +	spi_imx->controller->transfer_one = spi_imx_transfer_one;
> +	spi_imx->controller->setup = spi_imx_setup;
> +	spi_imx->controller->cleanup = spi_imx_cleanup;
> +	spi_imx->controller->prepare_message = spi_imx_prepare_message;
> +	spi_imx->controller->unprepare_message = spi_imx_unprepare_message;
> +	spi_imx->controller->slave_abort = spi_imx_slave_abort;
> +	spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
> +
>  	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
>  	    is_imx53_ecspi(spi_imx))
> -		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
> +		spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY;
>  
>  	if (is_imx51_ecspi(spi_imx) &&
>  	    device_property_read_u32(&pdev->dev, "cs-gpios", NULL))

This hunk conflicts with commit 79422ed9bd7f ("spi: spi-imx: add support
for SPI_RX_CPHA_FLIP") in Mark's for-5.19 branch. That commit also adds
another reference to bitbang.master.

baruch

-- 
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch@tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il -

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 7/9] spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller
  2022-05-02 17:14     ` Baruch Siach
@ 2022-05-02 17:33       ` Marc Kleine-Budde
  -1 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 17:33 UTC (permalink / raw)
  To: Baruch Siach
  Cc: linux-spi, Fabio Estevam, Marek Vasut, kernel, linux-imx,
	Mark Brown, David Jander, linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 2639 bytes --]

On 02.05.2022 20:14:28, Baruch Siach wrote:
> Hi Marc,
> 
> On Mon, May 02 2022, Marc Kleine-Budde wrote:
> 
> > There's no need to embed the struct spi_bitbang into our private
> > data (struct spi_imx_data), the spi core is flexible enough, so that
> > we only need a pointer to the allocated struct spi_controller.
> >
> > This is also a preparation patch to add PIO based polling support to
> > the driver.
> >
> > Co-developed-by: David Jander <david@protonic.nl>
> > Signed-off-by: David Jander <david@protonic.nl>
> > Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> 
> [...]
> 
> > @@ -1641,17 +1642,17 @@ static int spi_imx_probe(struct platform_device *pdev)
> >  	else
> >  		controller->num_chipselect = 3;
> >  
> > -	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
> > -	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
> > -	spi_imx->bitbang.master->setup = spi_imx_setup;
> > -	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
> > -	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
> > -	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
> > -	spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
> > -	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
> > +	spi_imx->controller->transfer_one = spi_imx_transfer_one;
> > +	spi_imx->controller->setup = spi_imx_setup;
> > +	spi_imx->controller->cleanup = spi_imx_cleanup;
> > +	spi_imx->controller->prepare_message = spi_imx_prepare_message;
> > +	spi_imx->controller->unprepare_message = spi_imx_unprepare_message;
> > +	spi_imx->controller->slave_abort = spi_imx_slave_abort;
> > +	spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
> > +
> >  	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
> >  	    is_imx53_ecspi(spi_imx))
> > -		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
> > +		spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY;
> >  
> >  	if (is_imx51_ecspi(spi_imx) &&
> >  	    device_property_read_u32(&pdev->dev, "cs-gpios", NULL))
> 
> This hunk conflicts with commit 79422ed9bd7f ("spi: spi-imx: add support
> for SPI_RX_CPHA_FLIP") in Mark's for-5.19 branch. That commit also adds
> another reference to bitbang.master.

Will rebase to broonie/spi.git for-5.19.

Thanks,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 7/9] spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller
@ 2022-05-02 17:33       ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 17:33 UTC (permalink / raw)
  To: Baruch Siach
  Cc: linux-spi, Fabio Estevam, Marek Vasut, kernel, linux-imx,
	Mark Brown, David Jander, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 2639 bytes --]

On 02.05.2022 20:14:28, Baruch Siach wrote:
> Hi Marc,
> 
> On Mon, May 02 2022, Marc Kleine-Budde wrote:
> 
> > There's no need to embed the struct spi_bitbang into our private
> > data (struct spi_imx_data), the spi core is flexible enough, so that
> > we only need a pointer to the allocated struct spi_controller.
> >
> > This is also a preparation patch to add PIO based polling support to
> > the driver.
> >
> > Co-developed-by: David Jander <david@protonic.nl>
> > Signed-off-by: David Jander <david@protonic.nl>
> > Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> 
> [...]
> 
> > @@ -1641,17 +1642,17 @@ static int spi_imx_probe(struct platform_device *pdev)
> >  	else
> >  		controller->num_chipselect = 3;
> >  
> > -	spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
> > -	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
> > -	spi_imx->bitbang.master->setup = spi_imx_setup;
> > -	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
> > -	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
> > -	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
> > -	spi_imx->bitbang.master->slave_abort = spi_imx_slave_abort;
> > -	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
> > +	spi_imx->controller->transfer_one = spi_imx_transfer_one;
> > +	spi_imx->controller->setup = spi_imx_setup;
> > +	spi_imx->controller->cleanup = spi_imx_cleanup;
> > +	spi_imx->controller->prepare_message = spi_imx_prepare_message;
> > +	spi_imx->controller->unprepare_message = spi_imx_unprepare_message;
> > +	spi_imx->controller->slave_abort = spi_imx_slave_abort;
> > +	spi_imx->controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS;
> > +
> >  	if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx) ||
> >  	    is_imx53_ecspi(spi_imx))
> > -		spi_imx->bitbang.master->mode_bits |= SPI_LOOP | SPI_READY;
> > +		spi_imx->controller->mode_bits |= SPI_LOOP | SPI_READY;
> >  
> >  	if (is_imx51_ecspi(spi_imx) &&
> >  	    device_property_read_u32(&pdev->dev, "cs-gpios", NULL))
> 
> This hunk conflicts with commit 79422ed9bd7f ("spi: spi-imx: add support
> for SPI_RX_CPHA_FLIP") in Mark's for-5.19 branch. That commit also adds
> another reference to bitbang.master.

Will rebase to broonie/spi.git for-5.19.

Thanks,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [RFC 8/9] spi: spi-imx: add PIO polling support
  2022-05-02 16:49 [RFC 1/9] spi: spi-imx: cleanups and performance improvements Marc Kleine-Budde
@ 2022-05-02 16:49 ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-05-02 16:49 UTC (permalink / raw)
  To: inux-spi, Fabio Estevam, Marek Vasut
  Cc: kernel, linux-imx, Mark Brown, linux-arm-kernel,
	Marc Kleine-Budde, David Jander

The driver supports several modes, one of them is PIO/IRQ
"spi_imx_pio_transfer()". The data is exchanged with the IP core using
PIO, an IRQ is setup to signal empty/full FIFOs and the end of the
transfer. The IRQ and scheduling overhead for short transfers is
significant. Using polling instead of IRQs can be beneficial to reduce
the overall CPU load, especially on small transfer workloads.

On an imx6 single core, a given RX workload of the mcp251xfd driver
results in 40% CPU load. Using polling mode reduces the CPU load to
30%.

This patch adds PIO polling support to the driver. For transfers with
a duration of less than 30 µs the polling mode instead of IRQ based
PIO mode is used. 30 µs seems to be a good compromise, which is used
the by the SPI drivers for the raspberry Pi (spi-bcm2835,
spi-bcm2835), too.

Co-developed-by: David Jander <david@protonic.nl>
Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/spi/spi-imx.c | 66 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index ec6758e032ff..798a5182b849 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -31,6 +31,12 @@ static bool use_dma = true;
 module_param(use_dma, bool, 0644);
 MODULE_PARM_DESC(use_dma, "Enable usage of DMA when available (default)");
 
+/* define polling limits */
+static unsigned int polling_limit_us = 30;
+module_param(polling_limit_us, uint, 0664);
+MODULE_PARM_DESC(polling_limit_us,
+		 "time in us to run a transfer in polling mode\n");
+
 #define MXC_RPM_TIMEOUT		2000 /* 2000ms */
 
 #define MXC_CSPIRXDATA		0x00
@@ -1469,6 +1475,54 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 	return 0;
 }
 
+static int spi_imx_poll_transfer(struct spi_device *spi,
+				 struct spi_transfer *transfer)
+{
+	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
+	unsigned long timeout;
+
+	spi_imx->tx_buf = transfer->tx_buf;
+	spi_imx->rx_buf = transfer->rx_buf;
+	spi_imx->count = transfer->len;
+	spi_imx->txfifo = 0;
+	spi_imx->remainder = 0;
+
+	/* fill in the fifo before timeout calculations if we are
+	 * interrupted here, then the data is getting transferred by
+	 * the HW while we are interrupted
+	 */
+	spi_imx_push(spi_imx);
+
+	timeout = spi_imx_calculate_timeout(spi_imx, transfer->len) + jiffies;
+	while (spi_imx->txfifo) {
+		/* RX */
+		while (spi_imx->txfifo &&
+		       spi_imx->devtype_data->rx_available(spi_imx)) {
+			spi_imx->rx(spi_imx);
+			spi_imx->txfifo--;
+		}
+
+		/* TX */
+		if (spi_imx->count) {
+			spi_imx_push(spi_imx);
+			continue;
+		}
+
+		if (spi_imx->txfifo &&
+		    time_after(jiffies, timeout)) {
+
+			dev_err_ratelimited(&spi->dev,
+					    "timeout period reached: jiffies: %lu- falling back to interrupt mode\n",
+					    jiffies - timeout);
+
+			/* fall back to interrupt mode */
+			return spi_imx_pio_transfer(spi, transfer);
+		}
+	}
+
+	return 0;
+}
+
 static int spi_imx_pio_transfer_slave(struct spi_device *spi,
 				      struct spi_transfer *transfer)
 {
@@ -1518,6 +1572,7 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
 				struct spi_transfer *transfer)
 {
 	struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller);
+	unsigned long hz_per_byte, byte_limit;
 
 	spi_imx_setupxfer(spi, transfer);
 	transfer->effective_speed_hz = spi_imx->spi_bus_clk;
@@ -1529,6 +1584,17 @@ static int spi_imx_transfer_one(struct spi_controller *controller,
 	if (spi_imx->slave_mode)
 		return spi_imx_pio_transfer_slave(spi, transfer);
 
+	/*
+	 * Calculate the estimated time in us the transfer runs. Find
+	 * the number of Hz per byte per polling limit.
+	 */
+	hz_per_byte = polling_limit_us ? ((8 + 4) * USEC_PER_SEC) / polling_limit_us : 0;
+	byte_limit = hz_per_byte ? transfer->effective_speed_hz / hz_per_byte : 1;
+
+	/* run in polling mode for short transfers */
+	if (transfer->len < byte_limit)
+		return spi_imx_poll_transfer(spi, transfer);
+
 	if (spi_imx->usedma)
 		return spi_imx_dma_transfer(spi_imx, transfer);
 
-- 
2.35.1



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2022-05-02 17:34 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-02 16:52 [RFC 0/9] spi: spi-imx: cleanups and performance improvements Marc Kleine-Budde
2022-05-02 16:52 ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 1/9] spi: spi-imx: fix sparse warning: add identifier name to function definition Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 2/9] spi: spi-imx: avoid unnecessary line continuations Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 3/9] spi: spi-imx: mx51_ecspi_intctrl(): prefer 'unsigned int' to bare use of 'unsigned' Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 4/9] spi: spi-imx: spi_imx_buf_rx_swap_u32(): fix sparse warning Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 5/9] spi: spi-imx: spi_imx_buf_rx_swap_u32(): replace open coded swahw32() Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 6/9] spi: spi-imx: complete conversion from master -> controller Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 7/9] spi: spi-imx: replace struct spi_imx_data::bitbang by pointer to struct spi_controller Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
2022-05-02 17:14   ` Baruch Siach
2022-05-02 17:14     ` Baruch Siach
2022-05-02 17:33     ` Marc Kleine-Budde
2022-05-02 17:33       ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 8/9] spi: spi-imx: add PIO polling support Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
2022-05-02 16:52 ` [RFC 9/9] spi: spi-imx: mx51_ecspi_prepare_message(): skip writing MX51_ECSPI_CONFIG register if unchanged Marc Kleine-Budde
2022-05-02 16:52   ` Marc Kleine-Budde
  -- strict thread matches above, loose matches on Subject: below --
2022-05-02 16:49 [RFC 1/9] spi: spi-imx: cleanups and performance improvements Marc Kleine-Budde
2022-05-02 16:49 ` [RFC 8/9] spi: spi-imx: add PIO polling support Marc Kleine-Budde

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.