Add support to parse and setup the common OF properties. The parsing is
quite confusing since the kernel driver API decided to use a u16 for the
value. I kept it this way to be closer to the Linux code.

This prepares the core for the upcoming core based message handling.

Signed-off-by: Marco Felsch <[email protected]>
---
Changelog:
v2:
 - no changes

 drivers/spi/spi.c | 25 +++++++++++++++++++++++++
 include/spi/spi.h | 22 ++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index c239de9d8549..e8a0b1b84be5 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -70,6 +70,9 @@ struct spi_device *spi_new_device(struct spi_controller *ctrl,
                proxy->cs_gpiod = ctrl->cs_gpiods[chip->chip_select];
        proxy->max_speed_hz = chip->max_speed_hz;
        proxy->mode = chip->mode;
+       proxy->cs_setup = chip->cs_setup;
+       proxy->cs_hold = chip->cs_hold;
+       proxy->cs_inactive = chip->cs_inactive;
        proxy->bits_per_word = chip->bits_per_word ? chip->bits_per_word : 8;
        proxy->dev.platform_data = chip->platform_data;
        proxy->dev.bus = &spi_bus;
@@ -111,6 +114,22 @@ struct spi_device *spi_new_device(struct spi_controller 
*ctrl,
 }
 EXPORT_SYMBOL(spi_new_device);
 
+static void of_spi_parse_dt_cs_delay(struct device_node *nc,
+                                    struct spi_delay *delay, const char *prop)
+{
+       u32 value;
+
+       if (!of_property_read_u32(nc, prop, &value)) {
+               if (value > U16_MAX) {
+                       delay->value = DIV_ROUND_UP(value, 1000);
+                       delay->unit = SPI_DELAY_UNIT_USECS;
+               } else {
+                       delay->value = value;
+                       delay->unit = SPI_DELAY_UNIT_NSECS;
+               }
+       }
+}
+
 static void spi_of_register_slaves(struct spi_controller *ctrl)
 {
        struct device_node *n;
@@ -145,6 +164,12 @@ static void spi_of_register_slaves(struct spi_controller 
*ctrl)
                        chip.mode |= SPI_3WIRE;
                of_property_read_u32(n, "spi-max-frequency",
                                &chip.max_speed_hz);
+
+               /* Device CS delays */
+               of_spi_parse_dt_cs_delay(n, &chip.cs_setup, 
"spi-cs-setup-delay-ns");
+               of_spi_parse_dt_cs_delay(n, &chip.cs_hold, 
"spi-cs-hold-delay-ns");
+               of_spi_parse_dt_cs_delay(n, &chip.cs_inactive, 
"spi-cs-inactive-delay-ns");
+
                reg = of_find_property(n, "reg", NULL);
                if (!reg)
                        continue;
diff --git a/include/spi/spi.h b/include/spi/spi.h
index d643b83a7dbb..2061a44134d0 100644
--- a/include/spi/spi.h
+++ b/include/spi/spi.h
@@ -13,6 +13,19 @@
 struct spi_controller_mem_ops;
 struct spi_message;
 
+/**
+ * struct spi_delay - SPI delay information
+ * @value: Value for the delay
+ * @unit: Unit for the delay
+ */
+struct spi_delay {
+#define SPI_DELAY_UNIT_USECS   0
+#define SPI_DELAY_UNIT_NSECS   1
+#define SPI_DELAY_UNIT_SCK     2
+       u16     value;
+       u8      unit;
+};
+
 struct spi_board_info {
        char    *name;
        int     max_speed_hz;
@@ -26,6 +39,11 @@ struct spi_board_info {
        u8      bits_per_word;
        void    *platform_data;
        struct device_node *device_node;
+
+       /* CS delays */
+       struct spi_delay        cs_setup;
+       struct spi_delay        cs_hold;
+       struct spi_delay        cs_inactive;
 };
 
 /**
@@ -101,6 +119,10 @@ struct spi_device {
        void                    *controller_data;
        const char              *modalias;
        struct gpio_desc        *cs_gpiod;      /* Chip select gpio desc */
+       /* CS delays */
+       struct spi_delay        cs_setup;
+       struct spi_delay        cs_hold;
+       struct spi_delay        cs_inactive;
 
        /*
         * likely need more hooks for more protocol options affecting how
-- 
2.39.5


Reply via email to