From patchwork Wed Jun 22 13:42:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Geert Uytterhoeven X-Patchwork-Id: 9193001 X-Patchwork-Delegate: geert@linux-m68k.org 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 0A12E60756 for ; Wed, 22 Jun 2016 13:44:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F0175283FD for ; Wed, 22 Jun 2016 13:44:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E3BBC28406; Wed, 22 Jun 2016 13:44:21 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2EB4528409 for ; Wed, 22 Jun 2016 13:44:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752169AbcFVNnh (ORCPT ); Wed, 22 Jun 2016 09:43:37 -0400 Received: from michel.telenet-ops.be ([195.130.137.88]:42051 "EHLO michel.telenet-ops.be" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752600AbcFVNmS (ORCPT ); Wed, 22 Jun 2016 09:42:18 -0400 Received: from ayla.of.borg ([84.195.107.21]) by michel.telenet-ops.be with bizsmtp id 9piD1t01G0TjorY06piDiJ; Wed, 22 Jun 2016 15:42:16 +0200 Received: from ramsan.of.borg ([192.168.97.29] helo=ramsan) by ayla.of.borg with esmtp (Exim 4.82) (envelope-from ) id 1bFiQ1-0005Rs-Hh; Wed, 22 Jun 2016 15:42:13 +0200 Received: from geert by ramsan with local (Exim 4.82) (envelope-from ) id 1bFiQ2-00016U-6x; Wed, 22 Jun 2016 15:42:14 +0200 From: Geert Uytterhoeven To: Mark Brown Cc: Rob Herring , Mark Rutland , Magnus Damm , Hisashi Nakamura , Hiromitsu Yamasaki , linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-kernel@vger.kernel.org, Geert Uytterhoeven Subject: [PATCH/RFC 3/6] spi: sh-msiof: Add slave mode support Date: Wed, 22 Jun 2016 15:42:06 +0200 Message-Id: <1466602929-4191-4-git-send-email-geert+renesas@glider.be> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1466602929-4191-1-git-send-email-geert+renesas@glider.be> References: <1466602929-4191-1-git-send-email-geert+renesas@glider.be> Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Hisashi Nakamura Add slave mode support to the MSIOF driver. For now this only supports the transmission of messages with a size that is known in advance. Signed-off-by: Hisashi Nakamura Signed-off-by: Hiromitsu Yamasaki [geert: Timeout handling cleanup, spi core integration, rewording] Signed-off-by: Geert Uytterhoeven --- drivers/spi/spi-sh-msiof.c | 52 ++++++++++++++++++++++++++++++++++---------- include/linux/spi/sh_msiof.h | 6 +++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 0f83ad1d5a5858dd..afde3fe12bce844f 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -3,6 +3,7 @@ * * Copyright (c) 2009 Magnus Damm * Copyright (C) 2014 Glider bvba + * Copyright (C) 2014 Renesas Electronics Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -33,7 +34,6 @@ #include - struct sh_msiof_chipdata { u16 tx_fifo_size; u16 rx_fifo_size; @@ -334,7 +334,10 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, tmp |= !cs_high << MDR1_SYNCAC_SHIFT; tmp |= lsb_first << MDR1_BITLSB_SHIFT; tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); - sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON); + if (p->master->flags & SPI_MASTER_IS_SLAVE) + sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); + else + sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON); if (p->master->flags & SPI_MASTER_MUST_TX) { /* These bits are reserved if RX needs TX */ tmp &= ~0x0000ffff; @@ -561,17 +564,19 @@ static int sh_msiof_prepare_message(struct spi_master *master, static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) { - int ret; + bool slave = p->master->flags & SPI_MASTER_IS_SLAVE; + int ret = 0; /* setup clock and rx/tx signals */ - ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE); + if (!slave) + ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE); if (rx_buf && !ret) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_RXE); if (!ret) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TXE); /* start by setting frame bit */ - if (!ret) + if (!ret && !slave) ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE); return ret; @@ -579,15 +584,17 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) { - int ret; + bool slave = p->master->flags & SPI_MASTER_IS_SLAVE; + int ret = 0; /* shut down frame, rx/tx and clock signals */ - ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0); + if (!slave) + ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0); if (!ret) ret = sh_msiof_modify_ctr_wait(p, CTR_TXE, 0); if (rx_buf && !ret) ret = sh_msiof_modify_ctr_wait(p, CTR_RXE, 0); - if (!ret) + if (!ret && !slave) ret = sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0); return ret; @@ -633,7 +640,11 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, } /* wait for tx fifo to be emptied / rx fifo to be filled */ - if (!wait_for_completion_timeout(&p->done, HZ)) { + if (p->master->flags & SPI_MASTER_IS_SLAVE) + ret = !wait_for_completion_interruptible(&p->done); + else + ret = wait_for_completion_timeout(&p->done, HZ); + if (!ret) { dev_err(&p->pdev->dev, "PIO timeout\n"); ret = -ETIMEDOUT; goto stop_reset; @@ -743,7 +754,11 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, } /* wait for tx fifo to be emptied / rx fifo to be filled */ - if (!wait_for_completion_timeout(&p->done, HZ)) { + if (p->master->flags & SPI_MASTER_IS_SLAVE) + ret = !wait_for_completion_interruptible(&p->done); + else + ret = wait_for_completion_timeout(&p->done, HZ); + if (!ret) { dev_err(&p->pdev->dev, "DMA timeout\n"); ret = -ETIMEDOUT; goto stop_reset; @@ -840,7 +855,8 @@ static int sh_msiof_transfer_one(struct spi_master *master, int ret; /* setup clocks (clock already enabled in chipselect()) */ - sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz); + if (!(p->master->flags & SPI_MASTER_IS_SLAVE)) + sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz); while (master->dma_tx && len > 15) { /* @@ -986,14 +1002,24 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) { struct sh_msiof_spi_info *info; struct device_node *np = dev->of_node; + struct device_node *slave; u32 num_cs = 1; info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL); if (!info) return NULL; + slave = of_get_child_by_name(np, "slave"); + if (slave) { + info->mode = MSIOF_SPI_SLAVE; + of_node_put(slave); + } else { + info->mode = MSIOF_SPI_MASTER; + } + /* Parse the MSIOF properties */ - of_property_read_u32(np, "num-cs", &num_cs); + if (info->mode == MSIOF_SPI_MASTER) + of_property_read_u32(np, "num-cs", &num_cs); of_property_read_u32(np, "renesas,tx-fifo-size", &info->tx_fifo_override); of_property_read_u32(np, "renesas,rx-fifo-size", @@ -1228,6 +1254,8 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE; master->flags = chipdata->master_flags; + if (p->info->mode == MSIOF_SPI_SLAVE) + master->flags |= SPI_MASTER_IS_SLAVE; master->bus_num = pdev->id; master->dev.of_node = pdev->dev.of_node; master->num_chipselect = p->info->num_chipselect; diff --git a/include/linux/spi/sh_msiof.h b/include/linux/spi/sh_msiof.h index b087a85f5f72a351..f74b581f242f8c43 100644 --- a/include/linux/spi/sh_msiof.h +++ b/include/linux/spi/sh_msiof.h @@ -1,10 +1,16 @@ #ifndef __SPI_SH_MSIOF_H__ #define __SPI_SH_MSIOF_H__ +enum { + MSIOF_SPI_MASTER, + MSIOF_SPI_SLAVE, +}; + struct sh_msiof_spi_info { int tx_fifo_override; int rx_fifo_override; u16 num_chipselect; + int mode; unsigned int dma_tx_id; unsigned int dma_rx_id; u32 dtdl;