mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Marco Felsch <m.felsch@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH 06/12] spi: add support to handle cs-gpios
Date: Fri, 15 Nov 2024 20:57:41 +0100	[thread overview]
Message-ID: <20241115195747.997164-6-m.felsch@pengutronix.de> (raw)
In-Reply-To: <20241115195747.997164-1-m.felsch@pengutronix.de>

At the moment all drivers have to parse the cs-gpios on their own and
have to implement the mapping. By this commit we add the support to
handle this within the core and if there is a valid CS GPIO for a device
we assign it accordingly.

Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
---
 drivers/spi/spi.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++
 include/spi/spi.h |  9 +++++++
 2 files changed, 75 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 36d0653a191c..c239de9d8549 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -8,6 +8,8 @@
  */
 
 #include <common.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
 #include <linux/spi/spi-mem.h>
 #include <spi/spi.h>
 #include <xfuncs.h>
@@ -64,6 +66,8 @@ struct spi_device *spi_new_device(struct spi_controller *ctrl,
 	proxy = xzalloc(sizeof *proxy);
 	proxy->master = ctrl;
 	proxy->chip_select = chip->chip_select;
+	if (ctrl->cs_gpiods)
+		proxy->cs_gpiod = ctrl->cs_gpiods[chip->chip_select];
 	proxy->max_speed_hz = chip->max_speed_hz;
 	proxy->mode = chip->mode;
 	proxy->bits_per_word = chip->bits_per_word ? chip->bits_per_word : 8;
@@ -215,6 +219,62 @@ static void scan_boardinfo(struct spi_controller *ctrl)
 	}
 }
 
+/**
+ * spi_get_gpio_descs() - grab chip select GPIOs for the master
+ * @ctlr: The SPI master to grab GPIO descriptors for
+ */
+static int spi_get_gpio_descs(struct spi_controller *ctlr)
+{
+	int nb, i;
+	struct gpio_desc **cs;
+	struct device *dev = ctlr->dev;
+
+	nb = gpiod_count(dev, "cs");
+	if (nb < 0) {
+		/* No GPIOs at all is fine, else return the error */
+		if (nb == -ENOENT)
+			return 0;
+		return nb;
+	}
+
+	ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect);
+
+	cs = devm_kcalloc(dev, ctlr->num_chipselect, sizeof(*cs),
+			  GFP_KERNEL);
+	if (!cs)
+		return -ENOMEM;
+	ctlr->cs_gpiods = cs;
+
+	for (i = 0; i < nb; i++) {
+		/*
+		 * Most chipselects are active low, the inverted
+		 * semantics are handled by special quirks in gpiolib,
+		 * so initializing them GPIOD_OUT_LOW here means
+		 * "unasserted", in most cases this will drive the physical
+		 * line high.
+		 */
+		cs[i] = gpiod_get_index_optional(dev, "cs", i, GPIOD_OUT_LOW);
+		if (IS_ERR(cs[i]))
+			return PTR_ERR(cs[i]);
+
+		if (cs[i]) {
+			/*
+			 * If we find a CS GPIO, name it after the device and
+			 * chip select line.
+			 */
+			char *gpioname;
+
+			gpioname = basprintf("%s CS%d", dev_name(dev), i);
+			if (!gpioname)
+				return -ENOMEM;
+			gpiod_set_consumer_name(cs[i], gpioname);
+			free(gpioname);
+		}
+	}
+
+	return 0;
+}
+
 static int spi_controller_check_ops(struct spi_controller *ctlr)
 {
 	/*
@@ -285,6 +345,12 @@ int spi_register_controller(struct spi_controller *ctrl)
 	if (ctrl->bus_num < 0)
 		ctrl->bus_num = dyn_bus_id--;
 
+	if (ctrl->use_gpio_descriptors) {
+		status = spi_get_gpio_descs(ctrl);
+		if (status)
+			return status;
+	}
+
 	list_add_tail(&ctrl->list, &spi_controller_list);
 
 	spi_of_register_slaves(ctrl);
diff --git a/include/spi/spi.h b/include/spi/spi.h
index 9261d508befd..53d6bd32e025 100644
--- a/include/spi/spi.h
+++ b/include/spi/spi.h
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
+#include <linux/gpio/consumer.h>
 
 struct spi_controller_mem_ops;
 struct spi_message;
@@ -99,6 +100,7 @@ struct spi_device {
 	void			*controller_state;
 	void			*controller_data;
 	const char		*modalias;
+	struct gpio_desc	*cs_gpiod;	/* Chip select gpio desc */
 
 	/*
 	 * likely need more hooks for more protocol options affecting how
@@ -156,6 +158,9 @@ static inline void spi_set_ctldata(struct spi_device *spi, void *state)
  *	the device whose settings are being modified.
  * @transfer: adds a message to the controller's transfer queue.
  * @cleanup: frees controller-specific state
+ * @cs_gpiods: Array of GPIO descriptors to use as chip select lines; one per CS
+ *	number. Any individual value may be NULL for CS lines that
+ *	are not GPIOs (driven by the SPI controller itself).
  * @list: link with the global spi_controller list
  *
  * Each SPI controller can communicate with one or more @spi_device
@@ -233,6 +238,10 @@ struct spi_controller {
 	/* called on release() to free memory provided by spi_controller */
 	void			(*cleanup)(struct spi_device *spi);
 
+	/* GPIO chip select */
+	struct gpio_desc	**cs_gpiods;
+	bool			use_gpio_descriptors;
+
 	struct list_head list;
 };
 
-- 
2.39.5




  parent reply	other threads:[~2024-11-15 19:58 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-15 19:57 [PATCH 01/12] spi: cosmetic style fixes Marco Felsch
2024-11-15 19:57 ` [PATCH 02/12] spi: fix spi_message init during __spi_validate Marco Felsch
2024-11-15 19:57 ` [PATCH 03/12] spi: add spi_{set,get}_ctldata accessors Marco Felsch
2024-11-15 19:57 ` [PATCH 04/12] gpiolib: add support for gpiod_get_index and gpiod_get_index_optional Marco Felsch
2024-11-15 19:57 ` [PATCH 05/12] gpiolib: add support for gpiod_set_consumer_name Marco Felsch
2024-11-15 19:57 ` Marco Felsch [this message]
2024-11-15 19:57 ` [PATCH 07/12] spi: add support to setup spi-cs-{setup,hold,inactive}-delay-ns Marco Felsch
2024-11-15 19:57 ` [PATCH 08/12] spi: allow reporting the effectivly used speed_hz for a transfer Marco Felsch
2024-11-15 19:57 ` [PATCH 09/12] spi: import spi_controller::flags Marco Felsch
2024-11-15 19:57 ` [PATCH 10/12] spi: add support for spi_controller::set_cs_timing Marco Felsch
2024-11-15 19:57 ` [PATCH 11/12] spi: Provide common spi_message processing loop Marco Felsch
2024-11-15 19:57 ` [PATCH 12/12] spi: add support for BCM2835 SPI controller Marco Felsch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241115195747.997164-6-m.felsch@pengutronix.de \
    --to=m.felsch@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox