From patchwork Mon Feb 1 06:44:23 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vignesh Raghavendra X-Patchwork-Id: 8176351 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 767DB9F3CD for ; Mon, 1 Feb 2016 06:47:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6F0CD20412 for ; Mon, 1 Feb 2016 06:47:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 51914203ED for ; Mon, 1 Feb 2016 06:47:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752320AbcBAGqr (ORCPT ); Mon, 1 Feb 2016 01:46:47 -0500 Received: from arroyo.ext.ti.com ([192.94.94.40]:48106 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751307AbcBAGqq (ORCPT ); Mon, 1 Feb 2016 01:46:46 -0500 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id u116jlRL017184; Mon, 1 Feb 2016 00:45:47 -0600 Received: from DLEE70.ent.ti.com (dlemailx.itg.ti.com [157.170.170.113]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id u116jl7j020087; Mon, 1 Feb 2016 00:45:47 -0600 Received: from dflp33.itg.ti.com (10.64.6.16) by DLEE70.ent.ti.com (157.170.170.113) with Microsoft SMTP Server id 14.3.224.2; Mon, 1 Feb 2016 00:45:47 -0600 Received: from uda0132425.apr.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp33.itg.ti.com (8.14.3/8.13.8) with ESMTP id u116je4a022829; Mon, 1 Feb 2016 00:45:44 -0600 From: Vignesh R To: Brian Norris , Mark Brown CC: Russell King , , David Woodhouse , , , , , Vignesh R Subject: [RESEND][PATCH v5 1/3] spi: introduce accelerated read support for spi flash devices Date: Mon, 1 Feb 2016 12:14:23 +0530 Message-ID: <1454309065-11493-2-git-send-email-vigneshr@ti.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1454309065-11493-1-git-send-email-vigneshr@ti.com> References: <1454309065-11493-1-git-send-email-vigneshr@ti.com> MIME-Version: 1.0 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In addition to providing direct access to SPI bus, some spi controller hardwares (like ti-qspi) provide special port (like memory mapped port) that are optimized to improve SPI flash read performance. This means the controller can automatically send the SPI signals required to read data from the SPI flash device. For this, SPI controller needs to know flash specific information like read command to use, dummy bytes and address width. Introduce spi_flash_read() interface to support accelerated read over SPI flash devices. SPI master drivers can implement this callback to support interfaces such as memory mapped read etc. m25p80 flash driver and other flash drivers can call this make use of such interfaces. The interface should only be used with SPI flashes and cannot be used with other SPI devices. Signed-off-by: Vignesh R --- Resend v5: Rebased on top of v4.5-rc1 v5: No changes. drivers/spi/spi.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 47eff8012a77..dcc6f6e92668 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1152,6 +1152,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) } } + mutex_lock(&master->bus_lock_mutex); trace_spi_message_start(master->cur_msg); if (master->prepare_message) { @@ -1161,6 +1162,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) "failed to prepare message: %d\n", ret); master->cur_msg->status = ret; spi_finalize_current_message(master); + mutex_unlock(&master->bus_lock_mutex); return; } master->cur_msg_prepared = true; @@ -1170,6 +1172,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { master->cur_msg->status = ret; spi_finalize_current_message(master); + mutex_unlock(&master->bus_lock_mutex); return; } @@ -1177,8 +1180,10 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) if (ret) { dev_err(&master->dev, "failed to transfer one message from queue\n"); + mutex_unlock(&master->bus_lock_mutex); return; } + mutex_unlock(&master->bus_lock_mutex); } /** @@ -2351,6 +2356,46 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) EXPORT_SYMBOL_GPL(spi_async_locked); +int spi_flash_read(struct spi_device *spi, + struct spi_flash_read_message *msg) + +{ + struct spi_master *master = spi->master; + int ret; + + if ((msg->opcode_nbits == SPI_NBITS_DUAL || + msg->addr_nbits == SPI_NBITS_DUAL) && + !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD))) + return -EINVAL; + if ((msg->opcode_nbits == SPI_NBITS_QUAD || + msg->addr_nbits == SPI_NBITS_QUAD) && + !(spi->mode & SPI_TX_QUAD)) + return -EINVAL; + if (msg->data_nbits == SPI_NBITS_DUAL && + !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD))) + return -EINVAL; + if (msg->data_nbits == SPI_NBITS_QUAD && + !(spi->mode & SPI_RX_QUAD)) + return -EINVAL; + + if (master->auto_runtime_pm) { + ret = pm_runtime_get_sync(master->dev.parent); + if (ret < 0) { + dev_err(&master->dev, "Failed to power device: %d\n", + ret); + return ret; + } + } + mutex_lock(&master->bus_lock_mutex); + ret = master->spi_flash_read(spi, msg); + mutex_unlock(&master->bus_lock_mutex); + if (master->auto_runtime_pm) + pm_runtime_put(master->dev.parent); + + return ret; +} +EXPORT_SYMBOL_GPL(spi_flash_read); + /*-------------------------------------------------------------------------*/ /* Utility methods for SPI master protocol drivers, layered on diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 53be3a4c60cb..ba0dee9d05a3 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -25,6 +25,7 @@ struct dma_chan; struct spi_master; struct spi_transfer; +struct spi_flash_read_message; /* * INTERFACES between SPI master-side drivers and SPI infrastructure. @@ -361,6 +362,8 @@ 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(). + * @spi_flash_read: to support spi-controller hardwares that provide + * accelerated interface to read from flash devices. * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS * number. Any individual value may be -ENOENT for CS lines that * are not GPIOs (driven by the SPI controller itself). @@ -513,6 +516,8 @@ struct spi_master { struct spi_message *message); int (*unprepare_message)(struct spi_master *master, struct spi_message *message); + int (*spi_flash_read)(struct spi_device *spi, + struct spi_flash_read_message *msg); /* * These hooks are for drivers that use a generic implementation @@ -1019,6 +1024,42 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) return be16_to_cpu(result); } +/** + * struct spi_flash_read_message - flash specific information for + * spi-masters that provide accelerated flash read interfaces + * @buf: buffer to read data + * @from: offset within the flash from where data is to be read + * @len: length of data to be read + * @retlen: actual length of data read + * @read_opcode: read_opcode to be used to communicate with flash + * @addr_width: number of address bytes + * @dummy_bytes: number of dummy bytes + * @opcode_nbits: number of lines to send opcode + * @addr_nbits: number of lines to send address + * @data_nbits: number of lines for data + */ +struct spi_flash_read_message { + void *buf; + loff_t from; + size_t len; + size_t retlen; + u8 read_opcode; + u8 addr_width; + u8 dummy_bytes; + u8 opcode_nbits; + u8 addr_nbits; + u8 data_nbits; +}; + +/* SPI core interface for flash read support */ +static inline bool spi_flash_read_supported(struct spi_device *spi) +{ + return spi->master->spi_flash_read ? true : false; +} + +int spi_flash_read(struct spi_device *spi, + struct spi_flash_read_message *msg); + /*---------------------------------------------------------------------------*/ /*