linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] spi: mt7621: allow GPIO chip select lines
@ 2024-03-15  1:57 Justin Swartz
  2024-03-15 14:45 ` Mark Brown
  0 siblings, 1 reply; 10+ messages in thread
From: Justin Swartz @ 2024-03-15  1:57 UTC (permalink / raw)
  To: Mark Brown, Matthias Brugger, AngeloGioacchino Del Regno
  Cc: Justin Swartz, linux-spi, linux-kernel, linux-arm-kernel, linux-mediatek

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 recalulcate
num_chipselect to account for the GPIO descriptors that
it should have populated in the cs_gpiod array member.

Add the mt7621_spi_set_cs_gpio() function to control the
logical state of a GPIO chip select line, agnostic of the
electrical line state and activation polarity.

Add the mt7621_spi_cleanup() function to ensure that every
GPIO chip select will be deactivated when no longer in use.

Extend mt7621_spi_setup() so that if an SPI device is
associated with a GPIO chip select, its chip select line
will be deactivated before use.

Rename mt7621_spi_set_cs() to mt7621_spi_set_native_cs(),
and redefine mt7621_spi_set_cs() to determine whether:

  to call mt7621_spi_set_cs_gpio(), in the case of the
  passed SPI device being associated with a GPIO chip
  select line,

  or to call mt7621_spi_set_set_native_cs() instead.

Modify mt7621_transfer_one_message() to take into account
that mt7621_spi_set_cs() now returns an int and should use
the returned value for spi_message status indication if a
failure related to GPIO access has occured.

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

See Documentation/devicetree/bindings/spi/spi-controller.yaml
for information about cs-gpios semantics.

Example:

&spi0 {
	cs-gpios = <0>, <0>,
	           <&gpio 18 GPIO_ACTIVE_LOW>,   /* WDT_RST_N */
	           <&gpio 19 GPIO_ACTIVE_HIGH>;  /* PERST_N   */
	status = "ok";

	...

	spidev@2 {
		compatible = "defective,by-design";
		reg = <2>;
		spi-max-frequency = <16000000>;
	};

	spidev@3 {
		compatible = "defective,by-design";
		reg = <3>;
		spi-cs-high;
		spi-max-frequency = <16000000>;
	};
}; 	 

 drivers/spi/spi-mt7621.c | 46 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c
index 4e9053d03..87e164c86 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,7 +77,19 @@ 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 int mt7621_spi_set_cs_gpio(struct spi_device *spi, int enable)
+{
+	struct gpio_desc *gpiod = spi_get_csgpiod(spi, 0);
+	int cs = spi_get_chipselect(spi, 0);
+	int status = gpiod_direction_output(gpiod, enable);
+
+	if (status)
+		dev_err(&spi->dev, "set_gpio: failed to set CS%d", cs);
+
+	return status;
+}
+
+static void mt7621_spi_set_native_cs(struct spi_device *spi, int enable)
 {
 	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
 	int cs = spi_get_chipselect(spi, 0);
@@ -99,6 +113,15 @@ static void mt7621_spi_set_cs(struct spi_device *spi, int enable)
 	mt7621_spi_write(rs, MT7621_SPI_POLAR, polar);
 }
 
+static int mt7621_spi_set_cs(struct spi_device *spi, int enable)
+{
+	if (spi_is_csgpiod(spi))
+		return mt7621_spi_set_cs_gpio(spi, enable);
+
+	mt7621_spi_set_native_cs(spi,enable);
+	return 0;
+}
+
 static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed)
 {
 	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi);
@@ -266,7 +289,9 @@ static int mt7621_spi_transfer_one_message(struct spi_controller *host,
 	}
 
 	/* Assert CS */
-	mt7621_spi_set_cs(spi, 1);
+	status = mt7621_spi_set_cs(spi, 1);
+	if (status)
+		goto msg_done;
 
 	m->actual_length = 0;
 	list_for_each_entry(t, &m->transfers, transfer_list) {
@@ -290,7 +315,7 @@ static int mt7621_spi_transfer_one_message(struct spi_controller *host,
 
 	/* Flush data and deassert CS */
 	mt7621_spi_flush(rs);
-	mt7621_spi_set_cs(spi, 0);
+	status = mt7621_spi_set_cs(spi, 0);
 
 msg_done:
 	m->status = status;
@@ -313,9 +338,18 @@ static int mt7621_spi_setup(struct spi_device *spi)
 		return -EINVAL;
 	}
 
+	if (spi_is_csgpiod(spi))
+		return mt7621_spi_set_cs_gpio(spi, 0);
+
 	return 0;
 }
 
+static void mt7621_spi_cleanup(struct spi_device *spi)
+{
+	if (spi_is_csgpiod(spi))
+		mt7621_spi_set_cs_gpio(spi, 0);
+}
+
 static const struct of_device_id mt7621_spi_match[] = {
 	{ .compatible = "ralink,mt7621-spi" },
 	{},
@@ -353,10 +387,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->cleanup = mt7621_spi_cleanup;
 	host->transfer_one_message = mt7621_spi_transfer_one_message;
 	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 = host->max_native_cs;
+	host->use_gpio_descriptors = true;
 
 	dev_set_drvdata(&pdev->dev, host);
 
-- 


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

* Re: [PATCH] spi: mt7621: allow GPIO chip select lines
  2024-03-15  1:57 [PATCH] spi: mt7621: allow GPIO chip select lines Justin Swartz
@ 2024-03-15 14:45 ` Mark Brown
  2024-03-15 16:23   ` Justin Swartz
  0 siblings, 1 reply; 10+ messages in thread
From: Mark Brown @ 2024-03-15 14:45 UTC (permalink / raw)
  To: Justin Swartz
  Cc: Matthias Brugger, AngeloGioacchino Del Regno, linux-spi,
	linux-kernel, linux-arm-kernel, linux-mediatek

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

On Fri, Mar 15, 2024 at 03:57:07AM +0200, Justin Swartz wrote:

> Add the mt7621_spi_set_cs_gpio() function to control the
> logical state of a GPIO chip select line, agnostic of the
> electrical line state and activation polarity.

The core should handle GPIO chip selects for you?

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

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

* Re: [PATCH] spi: mt7621: allow GPIO chip select lines
  2024-03-15 14:45 ` Mark Brown
@ 2024-03-15 16:23   ` Justin Swartz
  2024-03-15 17:47     ` Mark Brown
  0 siblings, 1 reply; 10+ messages in thread
From: Justin Swartz @ 2024-03-15 16:23 UTC (permalink / raw)
  To: Mark Brown
  Cc: Matthias Brugger, AngeloGioacchino Del Regno, linux-spi,
	linux-kernel, linux-arm-kernel, linux-mediatek

On 2024-03-15 16:45, Mark Brown wrote:
> On Fri, Mar 15, 2024 at 03:57:07AM +0200, Justin Swartz wrote:
> 
>> Add the mt7621_spi_set_cs_gpio() function to control the
>> logical state of a GPIO chip select line, agnostic of the
>> electrical line state and activation polarity.
> 
> The core should handle GPIO chip selects for you?

As far as I can tell, it doesn't - at least as far the state
of spi-mt7621.c is concerned prior to the patch, plus kernel
configuration choices, device tree definition, and other
factors I might not be taking into account.

But maybe I'm doing something wrong, or perhaps have a
misconfiguration somewhere. So, if you're able to point out
something I've done incorrectly, it would be appreciated.

To attempt to confirm if the core will handle my desired
GPIO chip select lines without explicit state toggling,
I tried to set the value of use_gpio_descriptors to true,
without any other modifications to spi-mt7621.c as of
commit 90d35da658da8cff0d4ecbb5113f5fac9d00eb72:

[... Sorry if my tabs decide to be spaces instead ...]

---%---
--- a/drivers/spi/spi-mt7621.c
+++ b/drivers/spi/spi-mt7621.c
@@ -357,6 +357,7 @@ static int mt7621_spi_probe(struct platform_device 
*pdev)
         host->bits_per_word_mask = SPI_BPW_MASK(8);
         host->dev.of_node = pdev->dev.of_node;
         host->num_chipselect = 2;
+       host->use_gpio_descriptors = true;

         dev_set_drvdata(&pdev->dev, host);
---%---

I use a smallish program to write(2) a few bytes from
stdin to an spidev node.

---%---
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>

static int      Device      = -1;
static uint32_t Mode        = 0;
static uint32_t BitsPerWord = 8;
static uint32_t MaxSpeed    = 100000;

#define BUFFER_SIZE 4096
static uint8_t  Buffer[BUFFER_SIZE];

static int  openDevice(char *);
static void closeDevice(void);
static int  transmit(void);

int main(int argc, char *argv[])
{
         if (argc != 2) {
                 puts("usage: spiw SPI-DEVICE");
                 return EXIT_FAILURE;
         }

         atexit(closeDevice);

         if (openDevice(argv[1]) == -1)
                 return EXIT_FAILURE;

         while (!feof(stdin))
                 if (transmit() == -1)
                         return EXIT_FAILURE;

         return EXIT_SUCCESS;
}

static int openDevice(char *filename)
{
         Device = open(filename, O_RDWR);

         if (Device == -1)
                 return -1;

         if (ioctl(Device, SPI_IOC_WR_MODE32, &Mode) == -1)
                 return -1;

         if (ioctl(Device, SPI_IOC_WR_BITS_PER_WORD, &BitsPerWord) == -1)
                 return -1;

         if (ioctl(Device, SPI_IOC_WR_MAX_SPEED_HZ, &MaxSpeed) == -1)
                 return -1;

         return 0;
}

static void closeDevice(void)
{
         if (Device != -1)
                 close(Device);
}

static int transmit(void)
{
         size_t length = fread(Buffer, 1, sizeof(Buffer), stdin);

         if (ferror(stdin))
                 return -1;

         return write(Device, Buffer, length);
}
---%---

If I send write some data to a device associated with one
of the GPIO chip selects while watching the signals on the
SPI bus, I can see the expected transitions on SCLK and MOSI
but there isn't any change on the expected CS line, nor any
others:

~ # printf "\x41" | /tmp/spiw /dev/spidev0.2


A rough diagram, to show that although 'A' was sent, the
chip select wasn't activated:

       ______________________________________________________
CS2

                __    __    __    __    __    __    __    __
SCLK  ________|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |

       ________    _____                               ______
MOSI          |__|     |_____________________________|
                      :                                   :
                :     :     :     :     :     :     :     :
                0     1     0     0     0     0     0     1


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

* Re: [PATCH] spi: mt7621: allow GPIO chip select lines
  2024-03-15 16:23   ` Justin Swartz
@ 2024-03-15 17:47     ` Mark Brown
  2024-03-15 20:21       ` Justin Swartz
  0 siblings, 1 reply; 10+ messages in thread
From: Mark Brown @ 2024-03-15 17:47 UTC (permalink / raw)
  To: Justin Swartz
  Cc: Matthias Brugger, AngeloGioacchino Del Regno, linux-spi,
	linux-kernel, linux-arm-kernel, linux-mediatek

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

On Fri, Mar 15, 2024 at 06:23:09PM +0200, Justin Swartz wrote:
> On 2024-03-15 16:45, Mark Brown wrote:

> > The core should handle GPIO chip selects for you?

> As far as I can tell, it doesn't - at least as far the state
> of spi-mt7621.c is concerned prior to the patch, plus kernel
> configuration choices, device tree definition, and other
> factors I might not be taking into account.

> But maybe I'm doing something wrong, or perhaps have a
> misconfiguration somewhere. So, if you're able to point out
> something I've done incorrectly, it would be appreciated.

Look at other drivers that support GPIO chip selects?

> To attempt to confirm if the core will handle my desired
> GPIO chip select lines without explicit state toggling,
> I tried to set the value of use_gpio_descriptors to true,
> without any other modifications to spi-mt7621.c as of
> commit 90d35da658da8cff0d4ecbb5113f5fac9d00eb72:

Please include human readable descriptions of things like commits and
issues being discussed in e-mail in your mails, this makes them much
easier for humans to read especially when they have no internet access.
I do frequently catch up on my mail on flights or while otherwise
travelling so this is even more pressing for me than just being about
making things a bit easier to read.

The core needs to know that the GPIO chip selects are there but once it
knows that they're there things like setting the chip select should just
work.

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

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

* Re: [PATCH] spi: mt7621: allow GPIO chip select lines
  2024-03-15 17:47     ` Mark Brown
@ 2024-03-15 20:21       ` Justin Swartz
  2024-03-15 20:41         ` Mark Brown
  0 siblings, 1 reply; 10+ messages in thread
From: Justin Swartz @ 2024-03-15 20:21 UTC (permalink / raw)
  To: Mark Brown
  Cc: Matthias Brugger, AngeloGioacchino Del Regno, linux-spi,
	linux-kernel, linux-arm-kernel, linux-mediatek

On 2024-03-15 19:47, Mark Brown wrote:
> On Fri, Mar 15, 2024 at 06:23:09PM +0200, Justin Swartz wrote:
>> On 2024-03-15 16:45, Mark Brown wrote:
> 
>> > The core should handle GPIO chip selects for you?
> 
>> As far as I can tell, it doesn't - at least as far the state
>> of spi-mt7621.c is concerned prior to the patch, plus kernel
>> configuration choices, device tree definition, and other
>> factors I might not be taking into account.
> 
>> But maybe I'm doing something wrong, or perhaps have a
>> misconfiguration somewhere. So, if you're able to point out
>> something I've done incorrectly, it would be appreciated.
> 
> Look at other drivers that support GPIO chip selects?

Of the 43 drivers (of drivers/spi/*.c) that setup the
spi_controller's use_gpio_descriptors as true:

   39 drivers use the transfer_one hook, and
    4 drivers use the transfer_one_message hook.

Drivers that use the transfer_one hook benefit from the core
taking care of chip selection on their behalf.

Drivers that use the transfer_one_message hook handle chip
selection on their own, within the function they've pointed
the hook at.

There's comment prior to the declaration of the spi_controller
structure (in include/linux/spi/spi.h) that says the following
about the transfer_one* hooks (beginning at line 493):

  *                    Note: transfer_one and transfer_one_message are 
mutually
  *                    exclusive; when both are set, the generic 
subsystem does
  *                    not call your transfer_one callback.

Considering spi-mt7621.c was implemented using the
transfer_one_message() hook, I'd assumed that it made more
sense to take the approach of determining whether a chip
select was native or GPIO, and then calling a function that
is responsible only for the control over a single type of
chip select to ensure that I was not influencing the previous
native chip select logic in any drastic manner.

To me that seems less intrusive, and allows less room for
potential breakage for existing users of this driver (who
are native chip select users only), than the outright
refactoring of the mt7621_spi_transfer_one_message() function
into an mt7621_spi_transfer_one() function instead.

Based on reading (some of) drivers/spi/spi.c and looking at
cflow-generated callgraph of drivers/spi/spi.c, to determine
where spi_set_cs() and any gpiod_* functions are called,
I believe that only the transfer_one() hook approach leads
to SPI core control of the GPIO chip select lines - via the
core's own spi_transfer_one_message().


>> To attempt to confirm if the core will handle my desired
>> GPIO chip select lines without explicit state toggling,
>> I tried to set the value of use_gpio_descriptors to true,
>> without any other modifications to spi-mt7621.c as of
>> commit 90d35da658da8cff0d4ecbb5113f5fac9d00eb72:
> 
> Please include human readable descriptions of things like commits and
> issues being discussed in e-mail in your mails, this makes them much
> easier for humans to read especially when they have no internet access.
> I do frequently catch up on my mail on flights or while otherwise
> travelling so this is even more pressing for me than just being about
> making things a bit easier to read.

I understand that. The unlabelled commit was:

$ git log | grep -A5 90d35da658da8cff0d4ecbb5113f5fac9d00eb72
commit 90d35da658da8cff0d4ecbb5113f5fac9d00eb72
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Sun Mar 3 13:02:52 2024 -0800

     Linux 6.8-rc7


> The core needs to know that the GPIO chip selects are there but once it
> knows that they're there things like setting the chip select should 
> just
> work.

This seems to be true for transfer_one() hookers only.

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

* Re: [PATCH] spi: mt7621: allow GPIO chip select lines
  2024-03-15 20:21       ` Justin Swartz
@ 2024-03-15 20:41         ` Mark Brown
  2024-03-16  1:03           ` [PATCH v2] " Justin Swartz
  0 siblings, 1 reply; 10+ messages in thread
From: Mark Brown @ 2024-03-15 20:41 UTC (permalink / raw)
  To: Justin Swartz
  Cc: Matthias Brugger, AngeloGioacchino Del Regno, linux-spi,
	linux-kernel, linux-arm-kernel, linux-mediatek

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

On Fri, Mar 15, 2024 at 10:21:53PM +0200, Justin Swartz wrote:
> On 2024-03-15 19:47, Mark Brown wrote:

> > Look at other drivers that support GPIO chip selects?

> Of the 43 drivers (of drivers/spi/*.c) that setup the
> spi_controller's use_gpio_descriptors as true:

>   39 drivers use the transfer_one hook, and
>    4 drivers use the transfer_one_message hook.

> Drivers that use the transfer_one hook benefit from the core
> taking care of chip selection on their behalf.

> Drivers that use the transfer_one_message hook handle chip
> selection on their own, within the function they've pointed
> the hook at.

Oh, this is an old school driver.  Glancing at the code I can't see any
particular reason why it's not using transfer_one(), you should just
convert the driver to that which will reduce the open coding and just
generally improve functionality.  You could add a callback to flush the
write FIFO or add that into the write function, I'm not sure if there's
a meaningful performance benefit there.

> Considering spi-mt7621.c was implemented using the
> transfer_one_message() hook, I'd assumed that it made more

I think it's just old and based on having gone through staging likely
based on even older BSP code.

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

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

* [PATCH v2] spi: mt7621: allow GPIO chip select lines
  2024-03-15 20:41         ` Mark Brown
@ 2024-03-16  1:03           ` Justin Swartz
  2024-03-18 10:16             ` AngeloGioacchino Del Regno
  2024-03-25 17:44             ` Mark Brown
  0 siblings, 2 replies; 10+ messages in thread
From: Justin Swartz @ 2024-03-16  1:03 UTC (permalink / raw)
  To: Mark Brown, Matthias Brugger, AngeloGioacchino Del Regno
  Cc: Justin Swartz, linux-spi, linux-kernel, linux-arm-kernel, linux-mediatek

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);
 
-- 


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

* Re: [PATCH v2] spi: mt7621: allow GPIO chip select lines
  2024-03-16  1:03           ` [PATCH v2] " Justin Swartz
@ 2024-03-18 10:16             ` AngeloGioacchino Del Regno
  2024-03-18 11:06               ` Justin Swartz
  2024-03-25 17:44             ` Mark Brown
  1 sibling, 1 reply; 10+ messages in thread
From: AngeloGioacchino Del Regno @ 2024-03-18 10:16 UTC (permalink / raw)
  To: Justin Swartz, Mark Brown, Matthias Brugger
  Cc: linux-spi, linux-kernel, linux-arm-kernel, linux-mediatek

Il 16/03/24 02:03, Justin Swartz ha scritto:
> 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>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>



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

* Re: [PATCH v2] spi: mt7621: allow GPIO chip select lines
  2024-03-18 10:16             ` AngeloGioacchino Del Regno
@ 2024-03-18 11:06               ` Justin Swartz
  0 siblings, 0 replies; 10+ messages in thread
From: Justin Swartz @ 2024-03-18 11:06 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: Mark Brown, Matthias Brugger, linux-spi, linux-kernel,
	linux-arm-kernel, linux-mediatek

On 2024-03-18 12:16, AngeloGioacchino Del Regno wrote:
> Il 16/03/24 02:03, Justin Swartz ha scritto:
>> 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>
> 
> Reviewed-by: AngeloGioacchino Del Regno
> <angelogioacchino.delregno@collabora.com>

Thank you very much for the review.

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

* Re: [PATCH v2] spi: mt7621: allow GPIO chip select lines
  2024-03-16  1:03           ` [PATCH v2] " Justin Swartz
  2024-03-18 10:16             ` AngeloGioacchino Del Regno
@ 2024-03-25 17:44             ` Mark Brown
  1 sibling, 0 replies; 10+ messages in thread
From: Mark Brown @ 2024-03-25 17:44 UTC (permalink / raw)
  To: Matthias Brugger, AngeloGioacchino Del Regno, Justin Swartz
  Cc: linux-spi, linux-kernel, linux-arm-kernel, linux-mediatek

On Sat, 16 Mar 2024 03:03:01 +0200, 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.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: mt7621: allow GPIO chip select lines
      commit: 2a741cd6ec5899cec054ae27120f490ad57bc6bb

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark


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

end of thread, other threads:[~2024-03-25 17:44 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-15  1:57 [PATCH] spi: mt7621: allow GPIO chip select lines Justin Swartz
2024-03-15 14:45 ` Mark Brown
2024-03-15 16:23   ` Justin Swartz
2024-03-15 17:47     ` Mark Brown
2024-03-15 20:21       ` Justin Swartz
2024-03-15 20:41         ` Mark Brown
2024-03-16  1:03           ` [PATCH v2] " Justin Swartz
2024-03-18 10:16             ` AngeloGioacchino Del Regno
2024-03-18 11:06               ` Justin Swartz
2024-03-25 17:44             ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).