[PATCH 06/12] spi: add support to handle cs-gpios
Marco Felsch
m.felsch at pengutronix.de
Fri Nov 15 11:57:41 PST 2024
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 at 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
More information about the barebox
mailing list