spi: core: Add support for registering SPI slave controllers
authorGeert Uytterhoeven <geert+renesas@glider.be>
Mon, 22 May 2017 13:11:41 +0000 (15:11 +0200)
committerMark Brown <broonie@kernel.org>
Fri, 26 May 2017 12:11:00 +0000 (13:11 +0100)
Add support for registering SPI slave controllers using the existing SPI
master framework:
  - SPI slave controllers must use spi_alloc_slave() instead of
    spi_alloc_master(), and should provide an additional callback
    "slave_abort" to abort an ongoing SPI transfer request,
  - SPI slave controllers are added to a new "spi_slave" device class,
  - SPI slave handlers can be bound to the SPI slave device represented
    by an SPI slave controller using a DT child node named "slave",
  - Alternatively, (un)binding an SPI slave handler to the SPI slave
    device represented by an SPI slave controller can be done by
    (un)registering the slave device through a sysfs virtual file named
    "slave".

From the point of view of an SPI slave protocol handler, an SPI slave
controller looks almost like an ordinary SPI master controller. The only
exception is that a transfer request will block on the remote SPI
master, and may be cancelled using spi_slave_abort().

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi.c
include/linux/spi/spi.h

index 1761c9004fc1149e8552b86525613e93c2b49cf4..df8ddec24b5d7e88c5c42170f6d94c4bf531907b 100644 (file)
@@ -784,6 +784,18 @@ config SPI_TLE62X0
 
 endif # SPI_MASTER
 
-# (slave support would go here)
+#
+# SLAVE side ... listening to other SPI masters
+#
+
+config SPI_SLAVE
+       bool "SPI slave protocol handlers"
+       help
+         If your system has a slave-capable SPI controller, you can enable
+         slave protocol handlers.
+
+if SPI_SLAVE
+
+endif # SPI_SLAVE
 
 endif # SPI
index b375a7a892160b76b5bf62a7f66f86484f300ed1..e50852c6fcb87d8b0871b0df0c39da80484836fb 100644 (file)
@@ -105,3 +105,5 @@ obj-$(CONFIG_SPI_XILINX)            += spi-xilinx.o
 obj-$(CONFIG_SPI_XLP)                  += spi-xlp.o
 obj-$(CONFIG_SPI_XTENSA_XTFPGA)                += spi-xtensa-xtfpga.o
 obj-$(CONFIG_SPI_ZYNQMP_GQSPI)         += spi-zynqmp-gqspi.o
+
+# SPI slave protocol handlers
index 89254a55eb2e78c44e2a2c27bc693d9af623662b..6a8280bdc7a87a3443e65bae1f8013626b9f027e 100644 (file)
@@ -1535,15 +1535,6 @@ static int of_spi_parse_dt(struct spi_master *master, struct spi_device *spi,
        u32 value;
        int rc;
 
-       /* Device address */
-       rc = of_property_read_u32(nc, "reg", &value);
-       if (rc) {
-               dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
-                       nc->full_name, rc);
-               return rc;
-       }
-       spi->chip_select = value;
-
        /* Mode (clock phase/polarity/etc.) */
        if (of_find_property(nc, "spi-cpha", NULL))
                spi->mode |= SPI_CPHA;
@@ -1593,6 +1584,24 @@ static int of_spi_parse_dt(struct spi_master *master, struct spi_device *spi,
                }
        }
 
+       if (spi_controller_is_slave(master)) {
+               if (strcmp(nc->name, "slave")) {
+                       dev_err(&master->dev, "%s is not called 'slave'\n",
+                               nc->full_name);
+                       return -EINVAL;
+               }
+               return 0;
+       }
+
+       /* Device address */
+       rc = of_property_read_u32(nc, "reg", &value);
+       if (rc) {
+               dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
+                       nc->full_name, rc);
+               return rc;
+       }
+       spi->chip_select = value;
+
        /* Device speed */
        rc = of_property_read_u32(nc, "spi-max-frequency", &value);
        if (rc) {
@@ -1658,8 +1667,8 @@ err_out:
  * of_register_spi_devices() - Register child devices onto the SPI bus
  * @master:    Pointer to spi_master device
  *
- * Registers an spi_device for each child node of master node which has a 'reg'
- * property.
+ * Registers an spi_device for each child node of controller node which
+ * represents a valid SPI slave.
  */
 static void of_register_spi_devices(struct spi_master *master)
 {
@@ -1828,28 +1837,129 @@ static struct class spi_master_class = {
        .dev_groups     = spi_master_groups,
 };
 
+#ifdef CONFIG_SPI_SLAVE
+/**
+ * spi_slave_abort - abort the ongoing transfer request on an SPI slave
+ *                  controller
+ * @spi: device used for the current transfer
+ */
+int spi_slave_abort(struct spi_device *spi)
+{
+       struct spi_master *master = spi->master;
+
+       if (spi_controller_is_slave(master) && master->slave_abort)
+               return master->slave_abort(master);
+
+       return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(spi_slave_abort);
+
+static int match_true(struct device *dev, void *data)
+{
+       return 1;
+}
+
+static ssize_t spi_slave_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct spi_master *ctlr = container_of(dev, struct spi_master, dev);
+       struct device *child;
+
+       child = device_find_child(&ctlr->dev, NULL, match_true);
+       return sprintf(buf, "%s\n",
+                      child ? to_spi_device(child)->modalias : NULL);
+}
+
+static ssize_t spi_slave_store(struct device *dev,
+                              struct device_attribute *attr, const char *buf,
+                              size_t count)
+{
+       struct spi_master *ctlr = container_of(dev, struct spi_master, dev);
+       struct spi_device *spi;
+       struct device *child;
+       char name[32];
+       int rc;
+
+       rc = sscanf(buf, "%31s", name);
+       if (rc != 1 || !name[0])
+               return -EINVAL;
+
+       child = device_find_child(&ctlr->dev, NULL, match_true);
+       if (child) {
+               /* Remove registered slave */
+               device_unregister(child);
+               put_device(child);
+       }
+
+       if (strcmp(name, "(null)")) {
+               /* Register new slave */
+               spi = spi_alloc_device(ctlr);
+               if (!spi)
+                       return -ENOMEM;
+
+               strlcpy(spi->modalias, name, sizeof(spi->modalias));
+
+               rc = spi_add_device(spi);
+               if (rc) {
+                       spi_dev_put(spi);
+                       return rc;
+               }
+       }
+
+       return count;
+}
+
+static DEVICE_ATTR(slave, 0644, spi_slave_show, spi_slave_store);
+
+static struct attribute *spi_slave_attrs[] = {
+       &dev_attr_slave.attr,
+       NULL,
+};
+
+static const struct attribute_group spi_slave_group = {
+       .attrs = spi_slave_attrs,
+};
+
+static const struct attribute_group *spi_slave_groups[] = {
+       &spi_master_statistics_group,
+       &spi_slave_group,
+       NULL,
+};
+
+static struct class spi_slave_class = {
+       .name           = "spi_slave",
+       .owner          = THIS_MODULE,
+       .dev_release    = spi_master_release,
+       .dev_groups     = spi_slave_groups,
+};
+#else
+extern struct class spi_slave_class;   /* dummy */
+#endif
 
 /**
- * spi_alloc_master - allocate SPI master controller
+ * __spi_alloc_controller - allocate an SPI master or slave controller
  * @dev: the controller, possibly using the platform_bus
  * @size: how much zeroed driver-private data to allocate; the pointer to this
  *     memory is in the driver_data field of the returned device,
  *     accessible with spi_master_get_devdata().
+ * @slave: flag indicating whether to allocate an SPI master (false) or SPI
+ *     slave (true) controller
  * Context: can sleep
  *
- * This call is used only by SPI master controller drivers, which are the
+ * This call is used only by SPI controller drivers, which are the
  * only ones directly touching chip registers.  It's how they allocate
  * an spi_master structure, prior to calling spi_register_master().
  *
  * This must be called from context that can sleep.
  *
- * The caller is responsible for assigning the bus number and initializing
- * the master's methods before calling spi_register_master(); and (after errors
+ * The caller is responsible for assigning the bus number and initializing the
+ * controller's methods before calling spi_register_master(); and (after errors
  * adding the device) calling spi_master_put() to prevent a memory leak.
  *
- * Return: the SPI master structure on success, else NULL.
+ * Return: the SPI controller structure on success, else NULL.
  */
-struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
+struct spi_master *__spi_alloc_controller(struct device *dev,
+                                         unsigned int size, bool slave)
 {
        struct spi_master       *master;
 
@@ -1863,14 +1973,18 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
        device_initialize(&master->dev);
        master->bus_num = -1;
        master->num_chipselect = 1;
-       master->dev.class = &spi_master_class;
+       master->slave = slave;
+       if (IS_ENABLED(CONFIG_SPI_SLAVE) && slave)
+               master->dev.class = &spi_slave_class;
+       else
+               master->dev.class = &spi_master_class;
        master->dev.parent = dev;
        pm_suspend_ignore_children(&master->dev, true);
        spi_master_set_devdata(master, &master[1]);
 
        return master;
 }
-EXPORT_SYMBOL_GPL(spi_alloc_master);
+EXPORT_SYMBOL_GPL(__spi_alloc_controller);
 
 #ifdef CONFIG_OF
 static int of_spi_register_master(struct spi_master *master)
@@ -1946,9 +2060,11 @@ int spi_register_master(struct spi_master *master)
        if (!dev)
                return -ENODEV;
 
-       status = of_spi_register_master(master);
-       if (status)
-               return status;
+       if (!spi_controller_is_slave(master)) {
+               status = of_spi_register_master(master);
+               if (status)
+                       return status;
+       }
 
        /* even if it's just one always-selected device, there must
         * be at least one chipselect
@@ -1985,8 +2101,9 @@ int spi_register_master(struct spi_master *master)
        status = device_add(&master->dev);
        if (status < 0)
                goto done;
-       dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
-                       dynamic ? " (dynamic)" : "");
+       dev_dbg(dev, "registered %s %s%s\n",
+                       spi_controller_is_slave(master) ? "slave" : "master",
+                       dev_name(&master->dev), dynamic ? " (dynamic)" : "");
 
        /* If we're using a queued driver, start the queue */
        if (master->transfer)
@@ -3159,6 +3276,9 @@ static struct spi_master *of_find_spi_master_by_node(struct device_node *node)
 
        dev = class_find_device(&spi_master_class, NULL, node,
                                __spi_of_master_match);
+       if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE))
+               dev = class_find_device(&spi_slave_class, NULL, node,
+                                       __spi_of_master_match);
        if (!dev)
                return NULL;
 
@@ -3240,6 +3360,9 @@ static struct spi_master *acpi_spi_find_master_by_adev(struct acpi_device *adev)
 
        dev = class_find_device(&spi_master_class, NULL, adev,
                                spi_acpi_master_match);
+       if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE))
+               dev = class_find_device(&spi_slave_class, NULL, adev,
+                                       spi_acpi_master_match);
        if (!dev)
                return NULL;
 
@@ -3312,6 +3435,12 @@ static int __init spi_init(void)
        if (status < 0)
                goto err2;
 
+       if (IS_ENABLED(CONFIG_SPI_SLAVE)) {
+               status = class_register(&spi_slave_class);
+               if (status < 0)
+                       goto err3;
+       }
+
        if (IS_ENABLED(CONFIG_OF_DYNAMIC))
                WARN_ON(of_reconfig_notifier_register(&spi_of_notifier));
        if (IS_ENABLED(CONFIG_ACPI))
@@ -3319,6 +3448,8 @@ static int __init spi_init(void)
 
        return 0;
 
+err3:
+       class_unregister(&spi_master_class);
 err2:
        bus_unregister(&spi_bus_type);
 err1:
index 935bd2854ff19b2ab64e6d3786bc4ab53f7bc59c..0a78745e5766451e276caaa8da9b36531a2f17f3 100644 (file)
@@ -29,8 +29,8 @@ struct spi_transfer;
 struct spi_flash_read_message;
 
 /*
- * INTERFACES between SPI master-side drivers and SPI infrastructure.
- * (There's no SPI slave support for Linux yet...)
+ * INTERFACES between SPI master-side drivers and SPI slave protocol handlers,
+ * and SPI infrastructure.
  */
 extern struct bus_type spi_bus_type;
 
@@ -311,6 +311,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @min_speed_hz: Lowest supported transfer speed
  * @max_speed_hz: Highest supported transfer speed
  * @flags: other constraints relevant to this driver
+ * @slave: indicates that this is an SPI slave controller
  * @max_transfer_size: function that returns the max transfer size for
  *     a &spi_device; may be %NULL, so the default %SIZE_MAX will be used.
  * @max_message_size: function that returns the max message size for
@@ -374,6 +375,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @handle_err: the subsystem calls the driver to handle an error that occurs
  *             in the generic implementation of transfer_one_message().
  * @unprepare_message: undo any work done by prepare_message().
+ * @slave_abort: abort the ongoing transfer request on an SPI slave controller
  * @spi_flash_read: to support spi-controller hardwares that provide
  *                  accelerated interface to read from flash devices.
  * @spi_flash_can_dma: analogous to can_dma() interface, but for
@@ -447,6 +449,9 @@ struct spi_master {
 #define SPI_MASTER_MUST_TX      BIT(4)         /* requires tx */
 #define SPI_MASTER_GPIO_SS      BIT(5)         /* GPIO CS must select slave */
 
+       /* flag indicating this is an SPI slave controller */
+       bool                    slave;
+
        /*
         * on some hardware transfer / message size may be constrained
         * the limit may depend on device transfer settings
@@ -539,6 +544,7 @@ struct spi_master {
                               struct spi_message *message);
        int (*unprepare_message)(struct spi_master *master,
                                 struct spi_message *message);
+       int (*slave_abort)(struct spi_master *spi);
        int (*spi_flash_read)(struct  spi_device *spi,
                              struct spi_flash_read_message *msg);
        bool (*spi_flash_can_dma)(struct spi_device *spi,
@@ -595,6 +601,11 @@ static inline void spi_master_put(struct spi_master *master)
                put_device(&master->dev);
 }
 
+static inline bool spi_controller_is_slave(struct spi_master *ctlr)
+{
+       return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->slave;
+}
+
 /* PM calls that need to be issued by the driver */
 extern int spi_master_suspend(struct spi_master *master);
 extern int spi_master_resume(struct spi_master *master);
@@ -605,8 +616,23 @@ extern void spi_finalize_current_message(struct spi_master *master);
 extern void spi_finalize_current_transfer(struct spi_master *master);
 
 /* the spi driver core manages memory for the spi_master classdev */
-extern struct spi_master *
-spi_alloc_master(struct device *host, unsigned size);
+extern struct spi_master *__spi_alloc_controller(struct device *host,
+                                                unsigned int size, bool slave);
+
+static inline struct spi_master *spi_alloc_master(struct device *host,
+                                                 unsigned int size)
+{
+       return __spi_alloc_controller(host, size, false);
+}
+
+static inline struct spi_master *spi_alloc_slave(struct device *host,
+                                                unsigned int size)
+{
+       if (!IS_ENABLED(CONFIG_SPI_SLAVE))
+               return NULL;
+
+       return __spi_alloc_controller(host, size, true);
+}
 
 extern int spi_register_master(struct spi_master *master);
 extern int devm_spi_register_master(struct device *dev,
@@ -912,6 +938,7 @@ extern int spi_setup(struct spi_device *spi);
 extern int spi_async(struct spi_device *spi, struct spi_message *message);
 extern int spi_async_locked(struct spi_device *spi,
                            struct spi_message *message);
+extern int spi_slave_abort(struct spi_device *spi);
 
 static inline size_t
 spi_max_message_size(struct spi_device *spi)