From patchwork Thu Apr 13 12:14:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wang, Jiada" X-Patchwork-Id: 9679313 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0048260383 for ; Thu, 13 Apr 2017 12:15:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E3F3628652 for ; Thu, 13 Apr 2017 12:15:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D8E0B2865A; Thu, 13 Apr 2017 12:15:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 00A6E28652 for ; Thu, 13 Apr 2017 12:15:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=tmiHVuQ+9nRriOUIyNnJXaMmG4hpo7BNdpFBThv/JwU=; b=kdKoQFV4Glz7eM 8F+OiL7AAsGOCY52zRZBCZL7u9wyvSinAAGROQhBZ/6rTIlI8l8qoyzaPaSGzWzqM7AF9ibm6LGWg 2EIrLbiwOscu9mqWnrYxJTyM22Gii33Iwr+wB020It2QRcoXVOCBDbn0zYfMdCv4mgomO7x9sjynU iOsNIVWknIXKgyQ70soEJgaNt41v950SSS/X00uHV7OubuVDYWydLYXvmfjTQHwZJPVnNGpgkIqAZ xYRWRDbP1jZ+0HVrPYCl1rL9bb40jH7083jMraq2c8tIfqEZ5tNcL4HsTxZLQlUZbDNxfb6kvd48d NF2p4RRpaZPm80ChqBTw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cydex-0003gC-Iz; Thu, 13 Apr 2017 12:15:35 +0000 Received: from relay1.mentorg.com ([192.94.38.131]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cydeM-0001h6-GZ for linux-arm-kernel@lists.infradead.org; Thu, 13 Apr 2017 12:15:01 +0000 Received: from nat-ies.mentorg.com ([192.94.31.2] helo=SVR-IES-FEM-02.mgc.mentorg.com) by relay1.mentorg.com with esmtp id 1cyddz-0001uw-Uy from Jiada_Wang@mentor.com ; Thu, 13 Apr 2017 05:14:36 -0700 Received: from ubuntu.localdomain (137.202.0.76) by SVR-IES-FEM-02.mgc.mentorg.com (137.202.0.106) with Microsoft SMTP Server id 14.3.224.2; Thu, 13 Apr 2017 13:14:34 +0100 From: To: , , , , , Subject: [PATCH RFC 1/5] spi: core: add support to work in Slave mode Date: Thu, 13 Apr 2017 05:14:00 -0700 Message-ID: <1492085644-4195-2-git-send-email-jiada_wang@mentor.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1492085644-4195-1-git-send-email-jiada_wang@mentor.com> References: <1492085644-4195-1-git-send-email-jiada_wang@mentor.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170413_051458_580827_941E8DC1 X-CRM114-Status: GOOD ( 26.15 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jiada Wang , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Jiada Wang Add support for SPI bus controller to work in slave mode using the existing SPI master framework. - SPI device on SPI bus controller with 'spi-slave' property declared in DT node represents SPI controller itself to work as a slave device and listening to external SPI master devices - when SPI bus controller works in slave mode, 'chip_select' and 'max_speed_hz' are not required. - SPI slave mode continue to use 'struct spi_master' Signed-off-by: Jiada Wang --- Documentation/devicetree/bindings/spi/spi-bus.txt | 27 ++++++++++++++--------- Documentation/spi/spi-summary | 19 +++++++++++----- drivers/spi/Kconfig | 14 +++++++++++- drivers/spi/spi.c | 23 ++++++++++++++++++- include/linux/spi/spi.h | 15 +++++++++++++ 5 files changed, 80 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt index 4b1d6e7..96e93ba 100644 --- a/Documentation/devicetree/bindings/spi/spi-bus.txt +++ b/Documentation/devicetree/bindings/spi/spi-bus.txt @@ -1,17 +1,20 @@ 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 can work either in master mode or in slave mode, based on the +child node on it. -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. + 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 @@ -43,10 +46,11 @@ 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. +- reg - (required, master mode only) 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-max-frequency - (required, master mode only) 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 @@ -63,6 +67,9 @@ contain the following properties. 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 - (optional) Empty property indicating SPI bus controller + itself works in slave mode to interface with external master + devices. 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 diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary index d1824b3..4c2ceaa 100644 --- a/Documentation/spi/spi-summary +++ b/Documentation/spi/spi-summary @@ -62,9 +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? --------------------------------------- @@ -154,9 +153,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 @@ -168,12 +166,21 @@ shows up in sysfs in several locations: /sys/devices/.../CTLR/spiB.C ... spi_device on bus "B", chipselect C, accessed through CTLR. + /sys/devices/.../CTLR/spiB-slv ... SPI bus "B" controller itself as a + spi_device works in slave mode, accessed through CTRL. + /sys/bus/spi/devices/spiB.C ... symlink to that physical .../CTLR/spiB.C device + /sys/bus/spi/devices/spiB-slv ... symlink to that physical + .../CTLR/spiB-slv device + /sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver that should be used with this device (for hotplug/coldplug) + /sys/devices/.../CTLR/spiB-slv/modalias ... identifies the driver + that should be used with this device (for hotplug/coldplug) + /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices /sys/class/spi_master/spiB ... symlink (or actual device node) to diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 25ae7f2e..1096c7d 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -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 diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 90b5b2e..3af26e2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -475,6 +475,12 @@ static void spi_dev_set_name(struct spi_device *spi) return; } + if (spi->slave_mode) { + dev_set_name(&spi->dev, "%s-slv", + dev_name(&spi->master->dev)); + return; + } + dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev), spi->chip_select); } @@ -484,6 +490,9 @@ static int spi_dev_check(struct device *dev, void *data) struct spi_device *spi = to_spi_device(dev); struct spi_device *new_spi = data; + if (spi->slave_mode) + return 0; + if (spi->master == new_spi->master && spi->chip_select == new_spi->chip_select) return -EBUSY; @@ -523,6 +532,9 @@ int spi_add_device(struct spi_device *spi) */ mutex_lock(&spi_add_lock); + if (spi->slave_mode) + goto setup_spi; + status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check); if (status) { dev_err(dev, "chipselect %d already in use\n", @@ -533,6 +545,7 @@ int spi_add_device(struct spi_device *spi) if (master->cs_gpios) spi->cs_gpio = master->cs_gpios[spi->chip_select]; +setup_spi: /* Drivers may modify this initial i/o setup, but will * normally rely on the device being setup. Devices * using SPI_CS_HIGH can't coexist well otherwise... @@ -1511,6 +1524,14 @@ static int of_spi_parse_dt(struct spi_master *master, struct spi_device *spi, u32 value; int rc; + if (of_find_property(nc, "spi-slave", NULL)) { + if (!spi_controller_has_slavemode(master)) + return -EINVAL; + + spi->slave_mode = 1; + return 0; + } + /* Device address */ rc = of_property_read_u32(nc, "reg", &value); if (rc) { @@ -1961,7 +1982,7 @@ 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), + dev_dbg(dev, "registered controller %s%s\n", dev_name(&master->dev), dynamic ? " (dynamic)" : ""); /* If we're using a queued driver, start the queue */ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 75c6bd0..bb81425 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -115,6 +115,8 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, * This may be changed by the device's driver, or left at the * default (0) indicating protocol words are eight bit bytes. * The spi_transfer.bits_per_word can override this for each transfer. + * @slave_mode: indicates whether SPI controller works in master mode + * or slave mode to transfer data with external spi devices. * @irq: Negative, or the number passed to request_irq() to receive * interrupts from this device. * @controller_state: Controller's runtime state @@ -144,6 +146,7 @@ struct spi_device { u8 chip_select; u8 bits_per_word; u16 mode; + u8 slave_mode; #define SPI_CPHA 0x01 /* clock phase */ #define SPI_CPOL 0x02 /* clock polarity */ #define SPI_MODE_0 (0|0) /* (original MicroWire) */ @@ -372,6 +375,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * transfer_one callback. * @handle_err: the subsystem calls the driver to handle an error that occurs * in the generic implementation of transfer_one_message(). + * @has_slavemode: checks whether SPI Controller supports slave mode or not. * @unprepare_message: undo any work done by prepare_message(). * @spi_flash_read: to support spi-controller hardwares that provide * accelerated interface to read from flash devices. @@ -549,6 +553,7 @@ struct spi_master { struct spi_transfer *transfer); void (*handle_err)(struct spi_master *master, struct spi_message *message); + bool (*has_slavemode)(struct spi_master *master); /* gpio chip select */ int *cs_gpios; @@ -590,6 +595,16 @@ static inline void spi_master_put(struct spi_master *master) put_device(&master->dev); } + +static inline bool spi_controller_has_slavemode(struct spi_master *master) +{ +#ifdef CONFIG_SPI_SLAVE + if (master->has_slavemode) + return master->has_slavemode(master); +#endif + return false; +} + /* 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);