Module: xenomai-3
Branch: wip/drivers
Commit: f2d77932c737e31a3c2abce81ba00436a60ed1f6
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=f2d77932c737e31a3c2abce81ba00436a60ed1f6

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue Jun 28 09:58:10 2016 +0200

drivers/spi: enable GPIO-based chip select

---

 kernel/drivers/spi/spi-device.c |   38 +++++++++++++++++++++-----------------
 kernel/drivers/spi/spi-device.h |    1 +
 kernel/drivers/spi/spi-master.c |   18 ++++++++++++++++--
 3 files changed, 38 insertions(+), 19 deletions(-)

diff --git a/kernel/drivers/spi/spi-device.c b/kernel/drivers/spi/spi-device.c
index 62482b2..08cf9b0 100644
--- a/kernel/drivers/spi/spi-device.c
+++ b/kernel/drivers/spi/spi-device.c
@@ -43,22 +43,14 @@ int rtdm_spi_add_remote_slave(struct rtdm_spi_remote_slave 
*slave,
        slave->config.speed_hz = spi->max_speed_hz;
        slave->config.mode = spi->mode;
        slave->master = master;
-       mutex_init(&slave->ctl_lock);
        
        dev = &slave->dev;
        dev->driver = &master->driver;
        dev->label = kasprintf(GFP_KERNEL, "%s/slave%d.%%d",
                               dev_name(&kmaster->dev),
                               kmaster->bus_num);
-       if (dev->label == NULL) {
-               ret = -ENOMEM;
-               goto fail_label;
-       }
-
-       dev->device_data = master;
-       ret = rtdm_dev_register(dev);
-       if (ret)
-               goto fail_register;
+       if (dev->label == NULL)
+               return -ENOMEM;
 
        if (gpio_is_valid(spi->cs_gpio))
                slave->cs_gpio = spi->cs_gpio;
@@ -68,21 +60,30 @@ int rtdm_spi_add_remote_slave(struct rtdm_spi_remote_slave 
*slave,
                        slave->cs_gpio = kmaster->cs_gpios[spi->chip_select];
        }
 
-       if (gpio_is_valid(slave->cs_gpio))
-               dev_dbg(slave_to_kdev(slave), "using CS GPIO%d\n",
-                       slave->cs_gpio);
+       if (gpio_is_valid(slave->cs_gpio)) {
+               ret = gpio_request(slave->cs_gpio, dev->label);
+               if (ret)
+                       goto fail;
+               slave->cs_gpiod = gpio_to_desc(slave->cs_gpio);
+               if (slave->cs_gpiod == NULL)
+                       goto fail;
+       }
+       
+       mutex_init(&slave->ctl_lock);
+
+       dev->device_data = master;
+       ret = rtdm_dev_register(dev);
+       if (ret)
+               goto fail;
 
        rtdm_lock_get_irqsave(&master->lock, c);
        list_add_tail(&slave->next, &master->slaves);
        rtdm_lock_put_irqrestore(&master->lock, c);
 
        return 0;
-
-fail_register:
+fail:
        kfree(dev->label);
 
-fail_label:
-
        return ret;
 }
 EXPORT_SYMBOL_GPL(rtdm_spi_add_remote_slave);
@@ -93,6 +94,9 @@ void rtdm_spi_remove_remote_slave(struct 
rtdm_spi_remote_slave *slave)
        struct rtdm_device *dev;
        rtdm_lockctx_t c;
        
+       if (gpio_is_valid(slave->cs_gpio))
+               gpio_free(slave->cs_gpio);
+
        mutex_destroy(&slave->ctl_lock);
        rtdm_lock_get_irqsave(&master->lock, c);
        list_del(&slave->next);
diff --git a/kernel/drivers/spi/spi-device.h b/kernel/drivers/spi/spi-device.h
index fcfca90..ee43c38 100644
--- a/kernel/drivers/spi/spi-device.h
+++ b/kernel/drivers/spi/spi-device.h
@@ -30,6 +30,7 @@ struct rtdm_spi_master;
 struct rtdm_spi_remote_slave {
        u8 chip_select;
        int cs_gpio;
+       struct gpio_desc *cs_gpiod;
        struct rtdm_device dev;
        struct list_head next;
        struct rtdm_spi_config config;
diff --git a/kernel/drivers/spi/spi-master.c b/kernel/drivers/spi/spi-master.c
index 132a3b9..fe2ee40 100644
--- a/kernel/drivers/spi/spi-master.c
+++ b/kernel/drivers/spi/spi-master.c
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/err.h>
 #include <linux/spi/spi.h>
+#include <linux/gpio.h>
 #include "spi-master.h"
 
 static inline
@@ -105,6 +106,7 @@ static int do_chip_select(struct rtdm_spi_remote_slave 
*slave)
 {                              /* master->bus_lock held */
        struct rtdm_spi_master *master = slave->master;
        rtdm_lockctx_t c;
+       int state;
 
        if (slave->config.speed_hz == 0)
                return -EINVAL; /* Setup is missing. */
@@ -113,7 +115,11 @@ static int do_chip_select(struct rtdm_spi_remote_slave 
*slave)
        rtdm_lock_get_irqsave(&master->lock, c);
        
        if (master->cs != slave) {
-               master->ops->chip_select(slave, true);
+               if (gpio_is_valid(slave->cs_gpio)) {
+                       state = !!(slave->config.mode & SPI_CS_HIGH);
+                       gpiod_set_raw_value(slave->cs_gpiod, state);
+               } else
+                       master->ops->chip_select(slave, true);
                master->cs = slave;
        }
 
@@ -126,10 +132,18 @@ static void do_chip_deselect(struct rtdm_spi_remote_slave 
*slave)
 {                              /* master->bus_lock held */
        struct rtdm_spi_master *master = slave->master;
        rtdm_lockctx_t c;
+       int state;
 
        rtdm_lock_get_irqsave(&master->lock, c);
-       master->ops->chip_select(slave, false);
+
+       if (gpio_is_valid(slave->cs_gpio)) {
+               state = !(slave->config.mode & SPI_CS_HIGH);
+               gpiod_set_raw_value(slave->cs_gpiod, state);
+       } else
+               master->ops->chip_select(slave, false);
+
        master->cs = NULL;
+
        rtdm_lock_put_irqrestore(&master->lock, c);
 }
 


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
https://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to