Loading Documentation/devicetree/bindings/spi/spi-bus.txt +45 −31 Original line number Diff line number Diff line SPI (Serial Peripheral Interface) busses SPI busses can be described with a node for the SPI master device and a set of child nodes for each SPI slave on the bus. For this discussion, it is assumed that the system's SPI controller is in SPI master mode. This binding does not describe SPI controllers in slave mode. SPI busses can be described with a node for the SPI controller device and a set of child nodes for each SPI slave on the bus. The system's SPI controller may be described for use in SPI master mode or in SPI slave mode, but not for both at the same time. The SPI master node requires the following properties: The SPI controller node requires the following properties: - compatible - Name of SPI bus controller following generic names recommended practice. In master mode, the SPI controller node requires the following additional properties: - #address-cells - number of cells required to define a chip select address on the SPI bus. - #size-cells - should be zero. - compatible - name of SPI bus controller following generic names recommended practice. In slave mode, the SPI controller node requires one additional property: - spi-slave - Empty property. No other properties are required in the SPI bus node. It is assumed that a driver for an SPI bus device will understand that it is an SPI bus. However, the binding does not attempt to define the specific method for Loading @@ -21,7 +27,7 @@ assumption that board specific platform code will be used to manage chip selects. Individual drivers can define additional properties to support describing the chip select layout. Optional properties: Optional properties (master mode only): - cs-gpios - gpios chip select. - num-cs - total number of chipselects. Loading @@ -41,28 +47,36 @@ cs1 : native cs2 : &gpio1 1 0 cs3 : &gpio1 2 0 SPI slave nodes must be children of the SPI master node and can contain the following properties. - reg - (required) chip select address of device. - compatible - (required) name of SPI device following generic names recommended practice. - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz. - spi-cpol - (optional) Empty property indicating device requires inverse clock polarity (CPOL) mode. - spi-cpha - (optional) Empty property indicating device requires shifted clock phase (CPHA) mode. - spi-cs-high - (optional) Empty property indicating device requires chip select active high. - spi-3wire - (optional) Empty property indicating device requires 3-wire mode. - spi-lsb-first - (optional) Empty property indicating device requires LSB first mode. - spi-tx-bus-width - (optional) The bus width (number of data wires) that is used for MOSI. Defaults to 1 if not present. - spi-rx-bus-width - (optional) The bus width (number of data wires) that is used for MISO. Defaults to 1 if not present. - spi-rx-delay-us - (optional) Microsecond delay after a read transfer. - spi-tx-delay-us - (optional) Microsecond delay after a write transfer. SPI slave nodes must be children of the SPI controller node. In master mode, one or more slave nodes (up to the number of chip selects) can be present. Required properties are: - compatible - Name of SPI device following generic names recommended practice. - reg - Chip select address of device. - spi-max-frequency - Maximum SPI clocking speed of device in Hz. In slave mode, the (single) slave node is optional. If present, it must be called "slave". Required properties are: - compatible - Name of SPI device following generic names recommended practice. All slave nodes can contain the following optional properties: - spi-cpol - Empty property indicating device requires inverse clock polarity (CPOL) mode. - spi-cpha - Empty property indicating device requires shifted clock phase (CPHA) mode. - spi-cs-high - Empty property indicating device requires chip select active high. - spi-3wire - Empty property indicating device requires 3-wire mode. - spi-lsb-first - Empty property indicating device requires LSB first mode. - spi-tx-bus-width - The bus width (number of data wires) that is used for MOSI. Defaults to 1 if not present. - spi-rx-bus-width - The bus width (number of data wires) that is used for MISO. Defaults to 1 if not present. - spi-rx-delay-us - Microsecond delay after a read transfer. - spi-tx-delay-us - Microsecond delay after a write transfer. Some SPI controllers and devices support Dual and Quad SPI transfer mode. It allows data in the SPI system to be transferred using 2 wires (DUAL) or 4 Loading Documentation/spi/spi-summary +20 −7 Original line number Diff line number Diff line Loading @@ -62,8 +62,8 @@ chips described as using "three wire" signaling: SCK, data, nCSx. (That data line is sometimes called MOMI or SISO.) Microcontrollers often support both master and slave sides of the SPI protocol. This document (and Linux) currently only supports the master side of SPI interactions. protocol. This document (and Linux) supports both the master and slave sides of SPI interactions. Who uses it? On what kinds of systems? Loading Loading @@ -154,9 +154,8 @@ control audio interfaces, present touchscreen sensors as input interfaces, or monitor temperature and voltage levels during industrial processing. And those might all be sharing the same controller driver. A "struct spi_device" encapsulates the master-side interface between those two types of driver. At this writing, Linux has no slave side programming interface. A "struct spi_device" encapsulates the controller-side interface between those two types of drivers. There is a minimal core of SPI programming interfaces, focussing on using the driver model to connect controller and protocol drivers using Loading @@ -177,10 +176,24 @@ shows up in sysfs in several locations: /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices /sys/class/spi_master/spiB ... symlink (or actual device node) to a logical node which could hold class related state for the controller managing bus "B". All spiB.* devices share one a logical node which could hold class related state for the SPI master controller managing bus "B". All spiB.* devices share one physical SPI bus segment, with SCLK, MOSI, and MISO. /sys/devices/.../CTLR/slave ... virtual file for (un)registering the slave device for an SPI slave controller. Writing the driver name of an SPI slave handler to this file registers the slave device; writing "(null)" unregisters the slave device. Reading from this file shows the name of the slave device ("(null)" if not registered). /sys/class/spi_slave/spiB ... symlink (or actual device node) to a logical node which could hold class related state for the SPI slave controller on bus "B". When registered, a single spiB.* device is present here, possible sharing the physical SPI bus segment with other SPI slave devices. Note that the actual location of the controller's class state depends on whether you enabled CONFIG_SYSFS_DEPRECATED or not. At this time, the only class-specific state is the bus number ("B" in "spiB"), so Loading drivers/spi/Kconfig +25 −1 Original line number Diff line number Diff line Loading @@ -785,6 +785,30 @@ 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 config SPI_SLAVE_TIME tristate "SPI slave handler reporting boot up time" help SPI slave handler responding with the time of reception of the last SPI message. config SPI_SLAVE_SYSTEM_CONTROL tristate "SPI slave handler controlling system state" help SPI slave handler to allow remote control of system reboot, power off, halt, and suspend. endif # SPI_SLAVE endif # SPI drivers/spi/Makefile +4 −0 Original line number Diff line number Diff line Loading @@ -105,3 +105,7 @@ 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 obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o obj-$(CONFIG_SPI_SLAVE_SYSTEM_CONTROL) += spi-slave-system-control.o drivers/spi/spi-slave-system-control.c 0 → 100644 +154 −0 Original line number Diff line number Diff line /* * SPI slave handler controlling system state * * This SPI slave handler allows remote control of system reboot, power off, * halt, and suspend. * * Copyright (C) 2016-2017 Glider bvba * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Usage (assuming /dev/spidev2.0 corresponds to the SPI master on the remote * system): * * # reboot='\x7c\x50' * # poweroff='\x71\x3f' * # halt='\x38\x76' * # suspend='\x1b\x1b' * # spidev_test -D /dev/spidev2.0 -p $suspend # or $reboot, $poweroff, $halt */ #include <linux/completion.h> #include <linux/module.h> #include <linux/reboot.h> #include <linux/suspend.h> #include <linux/spi/spi.h> /* * The numbers are chosen to display something human-readable on two 7-segment * displays connected to two 74HC595 shift registers */ #define CMD_REBOOT 0x7c50 /* rb */ #define CMD_POWEROFF 0x713f /* OF */ #define CMD_HALT 0x3876 /* HL */ #define CMD_SUSPEND 0x1b1b /* ZZ */ struct spi_slave_system_control_priv { struct spi_device *spi; struct completion finished; struct spi_transfer xfer; struct spi_message msg; __be16 cmd; }; static int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv); static void spi_slave_system_control_complete(void *arg) { struct spi_slave_system_control_priv *priv = arg; u16 cmd; int ret; if (priv->msg.status) goto terminate; cmd = be16_to_cpu(priv->cmd); switch (cmd) { case CMD_REBOOT: dev_info(&priv->spi->dev, "Rebooting system...\n"); kernel_restart(NULL); case CMD_POWEROFF: dev_info(&priv->spi->dev, "Powering off system...\n"); kernel_power_off(); break; case CMD_HALT: dev_info(&priv->spi->dev, "Halting system...\n"); kernel_halt(); break; case CMD_SUSPEND: dev_info(&priv->spi->dev, "Suspending system...\n"); pm_suspend(PM_SUSPEND_MEM); break; default: dev_warn(&priv->spi->dev, "Unknown command 0x%x\n", cmd); break; } ret = spi_slave_system_control_submit(priv); if (ret) goto terminate; return; terminate: dev_info(&priv->spi->dev, "Terminating\n"); complete(&priv->finished); } static int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv) { int ret; spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1); priv->msg.complete = spi_slave_system_control_complete; priv->msg.context = priv; ret = spi_async(priv->spi, &priv->msg); if (ret) dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret); return ret; } static int spi_slave_system_control_probe(struct spi_device *spi) { struct spi_slave_system_control_priv *priv; int ret; priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->spi = spi; init_completion(&priv->finished); priv->xfer.rx_buf = &priv->cmd; priv->xfer.len = sizeof(priv->cmd); ret = spi_slave_system_control_submit(priv); if (ret) return ret; spi_set_drvdata(spi, priv); return 0; } static int spi_slave_system_control_remove(struct spi_device *spi) { struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi); spi_slave_abort(spi); wait_for_completion(&priv->finished); return 0; } static struct spi_driver spi_slave_system_control_driver = { .driver = { .name = "spi-slave-system-control", }, .probe = spi_slave_system_control_probe, .remove = spi_slave_system_control_remove, }; module_spi_driver(spi_slave_system_control_driver); MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>"); MODULE_DESCRIPTION("SPI slave handler controlling system state"); MODULE_LICENSE("GPL v2"); Loading
Documentation/devicetree/bindings/spi/spi-bus.txt +45 −31 Original line number Diff line number Diff line SPI (Serial Peripheral Interface) busses SPI busses can be described with a node for the SPI master device and a set of child nodes for each SPI slave on the bus. For this discussion, it is assumed that the system's SPI controller is in SPI master mode. This binding does not describe SPI controllers in slave mode. SPI busses can be described with a node for the SPI controller device and a set of child nodes for each SPI slave on the bus. The system's SPI controller may be described for use in SPI master mode or in SPI slave mode, but not for both at the same time. The SPI master node requires the following properties: The SPI controller node requires the following properties: - compatible - Name of SPI bus controller following generic names recommended practice. In master mode, the SPI controller node requires the following additional properties: - #address-cells - number of cells required to define a chip select address on the SPI bus. - #size-cells - should be zero. - compatible - name of SPI bus controller following generic names recommended practice. In slave mode, the SPI controller node requires one additional property: - spi-slave - Empty property. No other properties are required in the SPI bus node. It is assumed that a driver for an SPI bus device will understand that it is an SPI bus. However, the binding does not attempt to define the specific method for Loading @@ -21,7 +27,7 @@ assumption that board specific platform code will be used to manage chip selects. Individual drivers can define additional properties to support describing the chip select layout. Optional properties: Optional properties (master mode only): - cs-gpios - gpios chip select. - num-cs - total number of chipselects. Loading @@ -41,28 +47,36 @@ cs1 : native cs2 : &gpio1 1 0 cs3 : &gpio1 2 0 SPI slave nodes must be children of the SPI master node and can contain the following properties. - reg - (required) chip select address of device. - compatible - (required) name of SPI device following generic names recommended practice. - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz. - spi-cpol - (optional) Empty property indicating device requires inverse clock polarity (CPOL) mode. - spi-cpha - (optional) Empty property indicating device requires shifted clock phase (CPHA) mode. - spi-cs-high - (optional) Empty property indicating device requires chip select active high. - spi-3wire - (optional) Empty property indicating device requires 3-wire mode. - spi-lsb-first - (optional) Empty property indicating device requires LSB first mode. - spi-tx-bus-width - (optional) The bus width (number of data wires) that is used for MOSI. Defaults to 1 if not present. - spi-rx-bus-width - (optional) The bus width (number of data wires) that is used for MISO. Defaults to 1 if not present. - spi-rx-delay-us - (optional) Microsecond delay after a read transfer. - spi-tx-delay-us - (optional) Microsecond delay after a write transfer. SPI slave nodes must be children of the SPI controller node. In master mode, one or more slave nodes (up to the number of chip selects) can be present. Required properties are: - compatible - Name of SPI device following generic names recommended practice. - reg - Chip select address of device. - spi-max-frequency - Maximum SPI clocking speed of device in Hz. In slave mode, the (single) slave node is optional. If present, it must be called "slave". Required properties are: - compatible - Name of SPI device following generic names recommended practice. All slave nodes can contain the following optional properties: - spi-cpol - Empty property indicating device requires inverse clock polarity (CPOL) mode. - spi-cpha - Empty property indicating device requires shifted clock phase (CPHA) mode. - spi-cs-high - Empty property indicating device requires chip select active high. - spi-3wire - Empty property indicating device requires 3-wire mode. - spi-lsb-first - Empty property indicating device requires LSB first mode. - spi-tx-bus-width - The bus width (number of data wires) that is used for MOSI. Defaults to 1 if not present. - spi-rx-bus-width - The bus width (number of data wires) that is used for MISO. Defaults to 1 if not present. - spi-rx-delay-us - Microsecond delay after a read transfer. - spi-tx-delay-us - Microsecond delay after a write transfer. Some SPI controllers and devices support Dual and Quad SPI transfer mode. It allows data in the SPI system to be transferred using 2 wires (DUAL) or 4 Loading
Documentation/spi/spi-summary +20 −7 Original line number Diff line number Diff line Loading @@ -62,8 +62,8 @@ chips described as using "three wire" signaling: SCK, data, nCSx. (That data line is sometimes called MOMI or SISO.) Microcontrollers often support both master and slave sides of the SPI protocol. This document (and Linux) currently only supports the master side of SPI interactions. protocol. This document (and Linux) supports both the master and slave sides of SPI interactions. Who uses it? On what kinds of systems? Loading Loading @@ -154,9 +154,8 @@ control audio interfaces, present touchscreen sensors as input interfaces, or monitor temperature and voltage levels during industrial processing. And those might all be sharing the same controller driver. A "struct spi_device" encapsulates the master-side interface between those two types of driver. At this writing, Linux has no slave side programming interface. A "struct spi_device" encapsulates the controller-side interface between those two types of drivers. There is a minimal core of SPI programming interfaces, focussing on using the driver model to connect controller and protocol drivers using Loading @@ -177,10 +176,24 @@ shows up in sysfs in several locations: /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices /sys/class/spi_master/spiB ... symlink (or actual device node) to a logical node which could hold class related state for the controller managing bus "B". All spiB.* devices share one a logical node which could hold class related state for the SPI master controller managing bus "B". All spiB.* devices share one physical SPI bus segment, with SCLK, MOSI, and MISO. /sys/devices/.../CTLR/slave ... virtual file for (un)registering the slave device for an SPI slave controller. Writing the driver name of an SPI slave handler to this file registers the slave device; writing "(null)" unregisters the slave device. Reading from this file shows the name of the slave device ("(null)" if not registered). /sys/class/spi_slave/spiB ... symlink (or actual device node) to a logical node which could hold class related state for the SPI slave controller on bus "B". When registered, a single spiB.* device is present here, possible sharing the physical SPI bus segment with other SPI slave devices. Note that the actual location of the controller's class state depends on whether you enabled CONFIG_SYSFS_DEPRECATED or not. At this time, the only class-specific state is the bus number ("B" in "spiB"), so Loading
drivers/spi/Kconfig +25 −1 Original line number Diff line number Diff line Loading @@ -785,6 +785,30 @@ 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 config SPI_SLAVE_TIME tristate "SPI slave handler reporting boot up time" help SPI slave handler responding with the time of reception of the last SPI message. config SPI_SLAVE_SYSTEM_CONTROL tristate "SPI slave handler controlling system state" help SPI slave handler to allow remote control of system reboot, power off, halt, and suspend. endif # SPI_SLAVE endif # SPI
drivers/spi/Makefile +4 −0 Original line number Diff line number Diff line Loading @@ -105,3 +105,7 @@ 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 obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o obj-$(CONFIG_SPI_SLAVE_SYSTEM_CONTROL) += spi-slave-system-control.o
drivers/spi/spi-slave-system-control.c 0 → 100644 +154 −0 Original line number Diff line number Diff line /* * SPI slave handler controlling system state * * This SPI slave handler allows remote control of system reboot, power off, * halt, and suspend. * * Copyright (C) 2016-2017 Glider bvba * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Usage (assuming /dev/spidev2.0 corresponds to the SPI master on the remote * system): * * # reboot='\x7c\x50' * # poweroff='\x71\x3f' * # halt='\x38\x76' * # suspend='\x1b\x1b' * # spidev_test -D /dev/spidev2.0 -p $suspend # or $reboot, $poweroff, $halt */ #include <linux/completion.h> #include <linux/module.h> #include <linux/reboot.h> #include <linux/suspend.h> #include <linux/spi/spi.h> /* * The numbers are chosen to display something human-readable on two 7-segment * displays connected to two 74HC595 shift registers */ #define CMD_REBOOT 0x7c50 /* rb */ #define CMD_POWEROFF 0x713f /* OF */ #define CMD_HALT 0x3876 /* HL */ #define CMD_SUSPEND 0x1b1b /* ZZ */ struct spi_slave_system_control_priv { struct spi_device *spi; struct completion finished; struct spi_transfer xfer; struct spi_message msg; __be16 cmd; }; static int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv); static void spi_slave_system_control_complete(void *arg) { struct spi_slave_system_control_priv *priv = arg; u16 cmd; int ret; if (priv->msg.status) goto terminate; cmd = be16_to_cpu(priv->cmd); switch (cmd) { case CMD_REBOOT: dev_info(&priv->spi->dev, "Rebooting system...\n"); kernel_restart(NULL); case CMD_POWEROFF: dev_info(&priv->spi->dev, "Powering off system...\n"); kernel_power_off(); break; case CMD_HALT: dev_info(&priv->spi->dev, "Halting system...\n"); kernel_halt(); break; case CMD_SUSPEND: dev_info(&priv->spi->dev, "Suspending system...\n"); pm_suspend(PM_SUSPEND_MEM); break; default: dev_warn(&priv->spi->dev, "Unknown command 0x%x\n", cmd); break; } ret = spi_slave_system_control_submit(priv); if (ret) goto terminate; return; terminate: dev_info(&priv->spi->dev, "Terminating\n"); complete(&priv->finished); } static int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv) { int ret; spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1); priv->msg.complete = spi_slave_system_control_complete; priv->msg.context = priv; ret = spi_async(priv->spi, &priv->msg); if (ret) dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret); return ret; } static int spi_slave_system_control_probe(struct spi_device *spi) { struct spi_slave_system_control_priv *priv; int ret; priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->spi = spi; init_completion(&priv->finished); priv->xfer.rx_buf = &priv->cmd; priv->xfer.len = sizeof(priv->cmd); ret = spi_slave_system_control_submit(priv); if (ret) return ret; spi_set_drvdata(spi, priv); return 0; } static int spi_slave_system_control_remove(struct spi_device *spi) { struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi); spi_slave_abort(spi); wait_for_completion(&priv->finished); return 0; } static struct spi_driver spi_slave_system_control_driver = { .driver = { .name = "spi-slave-system-control", }, .probe = spi_slave_system_control_probe, .remove = spi_slave_system_control_remove, }; module_spi_driver(spi_slave_system_control_driver); MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>"); MODULE_DESCRIPTION("SPI slave handler controlling system state"); MODULE_LICENSE("GPL v2");