Module: xenomai-3 Branch: master Commit: 0f85395e3228ea30523d21a50ee9a0e5d0dfe82c URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=0f85395e3228ea30523d21a50ee9a0e5d0dfe82c
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