diff mbox series

spi: mt7621: allow GPIO chip select lines

Message ID 20240316005917.20526-1-justin.swartz@risingedge.co.za
State New
Headers show
Series spi: mt7621: allow GPIO chip select lines | expand

Commit Message

Justin Swartz March 16, 2024, 12:59 a.m. UTC
Extract a magic number, from mt7621_spi_probe(), used to
declare the number of chip select lines (which co-incides
with the native chip select count of 2) to a macro.

Use the newly defined MT7621_NATIVE_CS_COUNT macro to
instead populate both the spi_controller's max_native_cs
and num_chipselect members.

Declare that the spi_controller should use_gpio_descriptors
if present in the device properties (such as those declared
in the cs-gpio property of a "ralink,mt7621-spi" compatible
device-tree node) so that the SPI core will recalculcate
num_chipselect to account for the GPIO descriptors that
it should have populated in the cs_gpiod array member.

Remove the assignment of mt7621_spi_transfer_one_message()
to the spi_controller's transfer_one_message hook.

Refactor the mt7621_spi_transfer_one_message() logic into
mt7621_spi_prepare_message() and mt7621_spi_transfer_one()
and assign both to the spi_controller's prepare_message
and transfer_one hooks respectively.

Migrate the call mt7621_spi_transfer_one_message() made to
mt7621_spi_flush() just before chip select deactivation,
to the end of mt7621_spi_write_half_duplex() to ensure
that any pending data is shifted out of MOSI before the SPI
core deactivates the chip select line.

As chip select activation is now taken care of by the SPI
core, due to the use of the transfer_one hook instead of
transfer_one_message, the calls to mt7621_spi_set_cs()
from mt7621_spi_transfer_one_message() have fallen away.

And although the SPI core will handle activation for GPIO
chip select lines behind the scenes, it requires a callback
to allow the driver to perform controller-specific
operations to control its native chip select lines.

Rename mt7621_spi_set_cs() to mt7621_spi_set_native_cs()
and make sure that it takes into account the activation
polarity of the chip select line it's acting upon, as the
passed enable parameter represents the desired line level
and not the desired activation state, and then assign
mt7621_set_cs() to the spi_controller's set_cs hook.

Signed-off-by: Justin Swartz <justin.swartz@risingedge.co.za>
---

Changes from v1 to v2:

  Mark Brown recommended using the transfer_one hook
  approach, so I did.


 drivers/spi/spi-mt7621.c | 95 +++++++++++++++++++---------------------
 1 file changed, 45 insertions(+), 50 deletions(-)

--

Comments

Justin Swartz March 16, 2024, 1:01 a.m. UTC | #1
Please ignore this patch. It was accidentally sent without
"v2" nor --in-reply-to=...


On 2024-03-16 02:59, Justin Swartz wrote:
> Extract a magic number, from mt7621_spi_probe(), used to
> declare the number of chip select lines (which co-incides
> with the native chip select count of 2) to a macro.
> 
> Use the newly defined MT7621_NATIVE_CS_COUNT macro to
> instead populate both the spi_controller's max_native_cs
> and num_chipselect members.
> 
> Declare that the spi_controller should use_gpio_descriptors
> if present in the device properties (such as those declared
> in the cs-gpio property of a "ralink,mt7621-spi" compatible
> device-tree node) so that the SPI core will recalculcate
> num_chipselect to account for the GPIO descriptors that
> it should have populated in the cs_gpiod array member.
> 
> Remove the assignment of mt7621_spi_transfer_one_message()
> to the spi_controller's transfer_one_message hook.
> 
> Refactor the mt7621_spi_transfer_one_message() logic into
> mt7621_spi_prepare_message() and mt7621_spi_transfer_one()
> and assign both to the spi_controller's prepare_message
> and transfer_one hooks respectively.
> 
> Migrate the call mt7621_spi_transfer_one_message() made to
> mt7621_spi_flush() just before chip select deactivation,
> to the end of mt7621_spi_write_half_duplex() to ensure
> that any pending data is shifted out of MOSI before the SPI
> core deactivates the chip select line.
> 
> As chip select activation is now taken care of by the SPI
> core, due to the use of the transfer_one hook instead of
> transfer_one_message, the calls to mt7621_spi_set_cs()
> from mt7621_spi_transfer_one_message() have fallen away.
> 
> And although the SPI core will handle activation for GPIO
> chip select lines behind the scenes, it requires a callback
> to allow the driver to perform controller-specific
> operations to control its native chip select lines.
> 
> Rename mt7621_spi_set_cs() to mt7621_spi_set_native_cs()
> and make sure that it takes into account the activation
> polarity of the chip select line it's acting upon, as the
> passed enable parameter represents the desired line level
> and not the desired activation state, and then assign
> mt7621_set_cs() to the spi_controller's set_cs hook.
> 
> Signed-off-by: Justin Swartz <justin.swartz@risingedge.co.za>
> ---
> 
> Changes from v1 to v2:
> 
>   Mark Brown recommended using the transfer_one hook
>   approach, so I did.
> 
> 
>  drivers/spi/spi-mt7621.c | 95 +++++++++++++++++++---------------------
>  1 file changed, 45 insertions(+), 50 deletions(-)
> 
> diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c
> index 4e9053d03..3770b8e09 100644
> --- a/drivers/spi/spi-mt7621.c
> +++ b/drivers/spi/spi-mt7621.c
> @@ -52,6 +52,8 @@
>  #define MT7621_CPOL		BIT(4)
>  #define MT7621_LSB_FIRST	BIT(3)
> 
> +#define MT7621_NATIVE_CS_COUNT	2
> +
>  struct mt7621_spi {
>  	struct spi_controller	*host;
>  	void __iomem		*base;
> @@ -75,10 +77,11 @@ static inline void mt7621_spi_write(struct
> mt7621_spi *rs, u32 reg, u32 val)
>  	iowrite32(val, rs->base + reg);
>  }
> 
> -static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
> +static void mt7621_spi_set_native_cs(struct spi_device *spi, bool 
> enable)
>  {
>  	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
>  	int cs = spi_get_chipselect(spi, 0);
> +	bool active = spi->mode & SPI_CS_HIGH ? enable : !enable;
>  	u32 polar = 0;
>  	u32 host;
> 
> @@ -94,7 +97,7 @@ static void mt7621_spi_set_cs(struct spi_device
> *spi, int enable)
> 
>  	rs->pending_write = 0;
> 
> -	if (enable)
> +	if (active)
>  		polar = BIT(cs);
>  	mt7621_spi_write(rs, MT7621_SPI_POLAR, polar);
>  }
> @@ -154,6 +157,23 @@ static inline int
> mt7621_spi_wait_till_ready(struct mt7621_spi *rs)
>  	return -ETIMEDOUT;
>  }
> 
> +static int mt7621_spi_prepare_message(struct spi_controller *host,
> +				      struct spi_message *m)
> +{
> +	struct mt7621_spi *rs = spi_controller_get_devdata(host);
> +	struct spi_device *spi = m->spi;
> +	unsigned int speed = spi->max_speed_hz;
> +	struct spi_transfer *t = NULL;
> +
> +	mt7621_spi_wait_till_ready(rs);
> +
> +	list_for_each_entry(t, &m->transfers, transfer_list)
> +		if (t->speed_hz < speed)
> +			speed = t->speed_hz;
> +
> +	return mt7621_spi_prepare(spi, speed);
> +}
> +
>  static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs,
>  					int rx_len, u8 *buf)
>  {
> @@ -243,59 +263,30 @@ static void mt7621_spi_write_half_duplex(struct
> mt7621_spi *rs,
>  	}
> 
>  	rs->pending_write = len;
> +	mt7621_spi_flush(rs);
>  }
> 
> -static int mt7621_spi_transfer_one_message(struct spi_controller 
> *host,
> -					   struct spi_message *m)
> +static int mt7621_spi_transfer_one(struct spi_controller *host,
> +				   struct spi_device *spi,
> +				   struct spi_transfer *t)
>  {
>  	struct mt7621_spi *rs = spi_controller_get_devdata(host);
> -	struct spi_device *spi = m->spi;
> -	unsigned int speed = spi->max_speed_hz;
> -	struct spi_transfer *t = NULL;
> -	int status = 0;
> -
> -	mt7621_spi_wait_till_ready(rs);
> 
> -	list_for_each_entry(t, &m->transfers, transfer_list)
> -		if (t->speed_hz < speed)
> -			speed = t->speed_hz;
> -
> -	if (mt7621_spi_prepare(spi, speed)) {
> -		status = -EIO;
> -		goto msg_done;
> -	}
> -
> -	/* Assert CS */
> -	mt7621_spi_set_cs(spi, 1);
> -
> -	m->actual_length = 0;
> -	list_for_each_entry(t, &m->transfers, transfer_list) {
> -		if ((t->rx_buf) && (t->tx_buf)) {
> -			/*
> -			 * This controller will shift some extra data out
> -			 * of spi_opcode if (mosi_bit_cnt > 0) &&
> -			 * (cmd_bit_cnt == 0). So the claimed full-duplex
> -			 * support is broken since we have no way to read
> -			 * the MISO value during that bit.
> -			 */
> -			status = -EIO;
> -			goto msg_done;
> -		} else if (t->rx_buf) {
> -			mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf);
> -		} else if (t->tx_buf) {
> -			mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf);
> -		}
> -		m->actual_length += t->len;
> +	if ((t->rx_buf) && (t->tx_buf)) {
> +		/*
> +		 * This controller will shift some extra data out
> +		 * of spi_opcode if (mosi_bit_cnt > 0) &&
> +		 * (cmd_bit_cnt == 0). So the claimed full-duplex
> +		 * support is broken since we have no way to read
> +		 * the MISO value during that bit.
> +		 */
> +		return -EIO;
> +	} else if (t->rx_buf) {
> +		mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf);
> +	} else if (t->tx_buf) {
> +		mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf);
>  	}
> 
> -	/* Flush data and deassert CS */
> -	mt7621_spi_flush(rs);
> -	mt7621_spi_set_cs(spi, 0);
> -
> -msg_done:
> -	m->status = status;
> -	spi_finalize_current_message(host);
> -
>  	return 0;
>  }
> 
> @@ -353,10 +344,14 @@ static int mt7621_spi_probe(struct 
> platform_device *pdev)
>  	host->mode_bits = SPI_LSB_FIRST;
>  	host->flags = SPI_CONTROLLER_HALF_DUPLEX;
>  	host->setup = mt7621_spi_setup;
> -	host->transfer_one_message = mt7621_spi_transfer_one_message;
> +	host->prepare_message = mt7621_spi_prepare_message;
> +	host->set_cs = mt7621_spi_set_native_cs;
> +	host->transfer_one = mt7621_spi_transfer_one;
>  	host->bits_per_word_mask = SPI_BPW_MASK(8);
>  	host->dev.of_node = pdev->dev.of_node;
> -	host->num_chipselect = 2;
> +	host->max_native_cs = MT7621_NATIVE_CS_COUNT;
> +	host->num_chipselect = MT7621_NATIVE_CS_COUNT;
> +	host->use_gpio_descriptors = true;
> 
>  	dev_set_drvdata(&pdev->dev, host);
Mark Brown March 16, 2024, 1:11 a.m. UTC | #2
On Sat, Mar 16, 2024 at 03:01:02AM +0200, Justin Swartz wrote:

> Please ignore this patch. It was accidentally sent without
> "v2" nor --in-reply-to=...

The --in-reply-to should be avoided:

Please don't send new patches in reply to old patches or serieses, this
makes it harder for both people and tools to understand what is going
on - it can bury things in mailboxes and make it difficult to keep track
of what current patches are, both for the new patches and the old ones.
Justin Swartz March 16, 2024, 1:15 a.m. UTC | #3
On 2024-03-16 03:11, Mark Brown wrote:
> On Sat, Mar 16, 2024 at 03:01:02AM +0200, Justin Swartz wrote:
> 
>> Please ignore this patch. It was accidentally sent without
>> "v2" nor --in-reply-to=...
> 
> The --in-reply-to should be avoided:
> 
> Please don't send new patches in reply to old patches or serieses, this
> makes it harder for both people and tools to understand what is going
> on - it can bury things in mailboxes and make it difficult to keep 
> track
> of what current patches are, both for the new patches and the old ones.

Thanks, I'll do that next time - already sent v2 in the wrong manner.
diff mbox series

Patch

diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c
index 4e9053d03..3770b8e09 100644
--- a/drivers/spi/spi-mt7621.c
+++ b/drivers/spi/spi-mt7621.c
@@ -52,6 +52,8 @@ 
 #define MT7621_CPOL		BIT(4)
 #define MT7621_LSB_FIRST	BIT(3)
 
+#define MT7621_NATIVE_CS_COUNT	2
+
 struct mt7621_spi {
 	struct spi_controller	*host;
 	void __iomem		*base;
@@ -75,10 +77,11 @@  static inline void mt7621_spi_write(struct mt7621_spi *rs, u32 reg, u32 val)
 	iowrite32(val, rs->base + reg);
 }
 
-static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
+static void mt7621_spi_set_native_cs(struct spi_device *spi, bool enable)
 {
 	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
 	int cs = spi_get_chipselect(spi, 0);
+	bool active = spi->mode & SPI_CS_HIGH ? enable : !enable;
 	u32 polar = 0;
 	u32 host;
 
@@ -94,7 +97,7 @@  static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
 
 	rs->pending_write = 0;
 
-	if (enable)
+	if (active)
 		polar = BIT(cs);
 	mt7621_spi_write(rs, MT7621_SPI_POLAR, polar);
 }
@@ -154,6 +157,23 @@  static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs)
 	return -ETIMEDOUT;
 }
 
+static int mt7621_spi_prepare_message(struct spi_controller *host,
+				      struct spi_message *m)
+{
+	struct mt7621_spi *rs = spi_controller_get_devdata(host);
+	struct spi_device *spi = m->spi;
+	unsigned int speed = spi->max_speed_hz;
+	struct spi_transfer *t = NULL;
+
+	mt7621_spi_wait_till_ready(rs);
+
+	list_for_each_entry(t, &m->transfers, transfer_list)
+		if (t->speed_hz < speed)
+			speed = t->speed_hz;
+
+	return mt7621_spi_prepare(spi, speed);
+}
+
 static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs,
 					int rx_len, u8 *buf)
 {
@@ -243,59 +263,30 @@  static void mt7621_spi_write_half_duplex(struct mt7621_spi *rs,
 	}
 
 	rs->pending_write = len;
+	mt7621_spi_flush(rs);
 }
 
-static int mt7621_spi_transfer_one_message(struct spi_controller *host,
-					   struct spi_message *m)
+static int mt7621_spi_transfer_one(struct spi_controller *host,
+				   struct spi_device *spi,
+				   struct spi_transfer *t)
 {
 	struct mt7621_spi *rs = spi_controller_get_devdata(host);
-	struct spi_device *spi = m->spi;
-	unsigned int speed = spi->max_speed_hz;
-	struct spi_transfer *t = NULL;
-	int status = 0;
-
-	mt7621_spi_wait_till_ready(rs);
 
-	list_for_each_entry(t, &m->transfers, transfer_list)
-		if (t->speed_hz < speed)
-			speed = t->speed_hz;
-
-	if (mt7621_spi_prepare(spi, speed)) {
-		status = -EIO;
-		goto msg_done;
-	}
-
-	/* Assert CS */
-	mt7621_spi_set_cs(spi, 1);
-
-	m->actual_length = 0;
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if ((t->rx_buf) && (t->tx_buf)) {
-			/*
-			 * This controller will shift some extra data out
-			 * of spi_opcode if (mosi_bit_cnt > 0) &&
-			 * (cmd_bit_cnt == 0). So the claimed full-duplex
-			 * support is broken since we have no way to read
-			 * the MISO value during that bit.
-			 */
-			status = -EIO;
-			goto msg_done;
-		} else if (t->rx_buf) {
-			mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf);
-		} else if (t->tx_buf) {
-			mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf);
-		}
-		m->actual_length += t->len;
+	if ((t->rx_buf) && (t->tx_buf)) {
+		/*
+		 * This controller will shift some extra data out
+		 * of spi_opcode if (mosi_bit_cnt > 0) &&
+		 * (cmd_bit_cnt == 0). So the claimed full-duplex
+		 * support is broken since we have no way to read
+		 * the MISO value during that bit.
+		 */
+		return -EIO;
+	} else if (t->rx_buf) {
+		mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf);
+	} else if (t->tx_buf) {
+		mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf);
 	}
 
-	/* Flush data and deassert CS */
-	mt7621_spi_flush(rs);
-	mt7621_spi_set_cs(spi, 0);
-
-msg_done:
-	m->status = status;
-	spi_finalize_current_message(host);
-
 	return 0;
 }
 
@@ -353,10 +344,14 @@  static int mt7621_spi_probe(struct platform_device *pdev)
 	host->mode_bits = SPI_LSB_FIRST;
 	host->flags = SPI_CONTROLLER_HALF_DUPLEX;
 	host->setup = mt7621_spi_setup;
-	host->transfer_one_message = mt7621_spi_transfer_one_message;
+	host->prepare_message = mt7621_spi_prepare_message;
+	host->set_cs = mt7621_spi_set_native_cs;
+	host->transfer_one = mt7621_spi_transfer_one;
 	host->bits_per_word_mask = SPI_BPW_MASK(8);
 	host->dev.of_node = pdev->dev.of_node;
-	host->num_chipselect = 2;
+	host->max_native_cs = MT7621_NATIVE_CS_COUNT;
+	host->num_chipselect = MT7621_NATIVE_CS_COUNT;
+	host->use_gpio_descriptors = true;
 
 	dev_set_drvdata(&pdev->dev, host);