Add support for registering SPI slave controllers using the existing SPI master framework: - SPI slave controllers must set the SPI_MASTER_IS_SLAVE flag in spi_master.flags, - The "cs-gpios" property is ignored, - The bus is described in DT as having a single slave node, "reg" and "spi-max-frequency" properties are ignored. >From the point of view of an SPI slave protocol handler, an SPI slave controller looks exactly like an ordinary SPI master controller. Signed-off-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx> --- Should we rename spi_master to spi_controller? --- drivers/spi/Kconfig | 14 +++++++++++++- drivers/spi/Makefile | 2 ++ drivers/spi/spi.c | 39 ++++++++++++++++++++++++--------------- include/linux/spi/spi.h | 5 +++-- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 4b931ec8d90b610f..00e990d91a715c0e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -736,6 +736,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 diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 3c74d003535bb9fb..71d02939080fb747 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -97,3 +97,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 diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 77e6e45951f4c5e1..6ea32255d6d9e780 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1462,6 +1462,7 @@ err_init_queue: static struct spi_device * of_register_spi_device(struct spi_master *master, struct device_node *nc) { + bool slave = master->flags & SPI_MASTER_IS_SLAVE; struct spi_device *spi; int rc; u32 value; @@ -1485,13 +1486,16 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc) } /* 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); - goto err_out; + if (!slave) { + 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); + goto err_out; + } + spi->chip_select = value; } - spi->chip_select = value; /* Mode (clock phase/polarity/etc.) */ if (of_find_property(nc, "spi-cpha", NULL)) @@ -1543,13 +1547,16 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc) } /* Device speed */ - rc = of_property_read_u32(nc, "spi-max-frequency", &value); - if (rc) { - dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n", - nc->full_name, rc); - goto err_out; + if (!slave) { + rc = of_property_read_u32(nc, "spi-max-frequency", &value); + if (rc) { + dev_err(&master->dev, + "%s has no valid 'spi-max-frequency' property (%d)\n", + nc->full_name, rc); + goto err_out; + } + spi->max_speed_hz = value; } - spi->max_speed_hz = value; /* Store a pointer to the node in the device structure */ of_node_get(nc); @@ -1779,7 +1786,7 @@ static int of_spi_register_master(struct spi_master *master) int nb, i, *cs; struct device_node *np = master->dev.of_node; - if (!np) + if (!np || master->flags & SPI_MASTER_IS_SLAVE) return 0; nb = of_gpio_named_count(np, "cs-gpios"); @@ -1885,8 +1892,10 @@ 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", + master->flags & SPI_MASTER_IS_SLAVE ? "slave" + : "master", + dev_name(&master->dev), dynamic ? " (dynamic)" : ""); /* If we're using a queued driver, start the queue */ if (master->transfer) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 1f03483f61e5714b..0fbebaa7d93990a4 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -28,8 +28,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 handers, + * and SPI infrastructure. */ extern struct bus_type spi_bus_type; @@ -439,6 +439,7 @@ struct spi_master { #define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ #define SPI_MASTER_MUST_RX BIT(3) /* requires rx */ #define SPI_MASTER_MUST_TX BIT(4) /* requires tx */ +#define SPI_MASTER_IS_SLAVE BIT(5) /* SPI slave controller */ /* * on some hardware transfer size may be constrained -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-spi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html