From patchwork Thu Aug 28 06:53:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 4794731 Return-Path: X-Original-To: patchwork-ltsi-dev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 61D76C0338 for ; Thu, 28 Aug 2014 07:34:22 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 53BD22016C for ; Thu, 28 Aug 2014 07:34:21 +0000 (UTC) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3A5EF20109 for ; Thu, 28 Aug 2014 07:34:20 +0000 (UTC) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id EBCD2E3A; Thu, 28 Aug 2014 07:20:33 +0000 (UTC) X-Original-To: ltsi-dev@lists.linuxfoundation.org Delivered-To: ltsi-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 09381BD7 for ; Thu, 28 Aug 2014 07:20:31 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from kirsty.vergenet.net (kirsty.vergenet.net [202.4.237.240]) by smtp1.linuxfoundation.org (Postfix) with ESMTP id 1BD1D1F9D0 for ; Thu, 28 Aug 2014 07:20:30 +0000 (UTC) Received: from ayumi.isobedori.kobe.vergenet.net (p4222-ipbfp1605kobeminato.hyogo.ocn.ne.jp [114.154.95.222]) by kirsty.vergenet.net (Postfix) with ESMTP id AA18B2671A1; Thu, 28 Aug 2014 17:07:40 +1000 (EST) Received: by ayumi.isobedori.kobe.vergenet.net (Postfix, from userid 7100) id 3C368EDEAE7; Thu, 28 Aug 2014 16:07:39 +0900 (JST) From: Simon Horman To: ltsi-dev@lists.linuxfoundation.org Date: Thu, 28 Aug 2014 15:53:38 +0900 Message-Id: <1409209620-24487-93-git-send-email-horms+renesas@verge.net.au> X-Mailer: git-send-email 2.0.1 In-Reply-To: <1409209620-24487-1-git-send-email-horms+renesas@verge.net.au> References: <1409209620-24487-1-git-send-email-horms+renesas@verge.net.au> X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 Cc: Magnus Damm Subject: [LTSI-dev] [PATCH LTSI-3.14 092/894] spi: rspi: Add support for RSPI on RZ/A1H X-BeenThere: ltsi-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: "A list to discuss patches, development, and other things related to the LTSI project" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ltsi-dev-bounces@lists.linuxfoundation.org Errors-To: ltsi-dev-bounces@lists.linuxfoundation.org X-Virus-Scanned: ClamAV using ClamSMTP From: Geert Uytterhoeven Add support for the RSPI variant in the RZ/A1H (r7s72100) SoC. Main differences with RSPI on SH are: - Lack of TX only mode, hence we always have to use full duplex transfers, - The Data Register must be accessed used 8-bit operations. RSPI on RZ is matched using the new "rspi-rz" platform device name. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown (cherry picked from commit 862d357f84f009fdcba22be8d6a2f82ff80ab740) Signed-off-by: Simon Horman --- drivers/spi/spi-rspi.c | 101 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 92 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index d2ade5e..0c75569 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -47,7 +47,7 @@ #define RSPI_SPCKD 0x0c /* Clock Delay Register */ #define RSPI_SSLND 0x0d /* Slave Select Negation Delay Register */ #define RSPI_SPND 0x0e /* Next-Access Delay Register */ -#define RSPI_SPCR2 0x0f /* Control Register 2 */ +#define RSPI_SPCR2 0x0f /* Control Register 2 (SH only) */ #define RSPI_SPCMD0 0x10 /* Command Register 0 */ #define RSPI_SPCMD1 0x12 /* Command Register 1 */ #define RSPI_SPCMD2 0x14 /* Command Register 2 */ @@ -56,10 +56,12 @@ #define RSPI_SPCMD5 0x1a /* Command Register 5 */ #define RSPI_SPCMD6 0x1c /* Command Register 6 */ #define RSPI_SPCMD7 0x1e /* Command Register 7 */ + +/* RSPI on RZ only */ #define RSPI_SPBFCR 0x20 /* Buffer Control Register */ #define RSPI_SPBFDR 0x22 /* Buffer Data Count Setting Register */ -/*qspi only */ +/* QSPI only */ #define QSPI_SPBFCR 0x18 /* Buffer Control Register */ #define QSPI_SPBDCR 0x1a /* Buffer Data Count Register */ #define QSPI_SPBMUL0 0x1c /* Transfer Data Length Multiplier Setting Register 0 */ @@ -102,7 +104,7 @@ #define SPSR_PERF 0x08 /* Parity Error Flag */ #define SPSR_MODF 0x04 /* Mode Fault Error Flag */ #define SPSR_IDLNF 0x02 /* RSPI Idle Flag */ -#define SPSR_OVRF 0x01 /* Overrun Error Flag */ +#define SPSR_OVRF 0x01 /* Overrun Error Flag (RSPI only) */ /* SPSCR - Sequence Control Register */ #define SPSCR_SPSLN_MASK 0x07 /* Sequence Length Specification */ @@ -119,13 +121,13 @@ #define SPDCR_SPLWORD SPDCR_SPLW1 #define SPDCR_SPLBYTE SPDCR_SPLW0 #define SPDCR_SPLW 0x20 /* Access Width Specification (SH) */ -#define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select */ +#define SPDCR_SPRDTD 0x10 /* Receive Transmit Data Select (SH) */ #define SPDCR_SLSEL1 0x08 #define SPDCR_SLSEL0 0x04 -#define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select */ +#define SPDCR_SLSEL_MASK 0x0c /* SSL1 Output Select (SH) */ #define SPDCR_SPFC1 0x02 #define SPDCR_SPFC0 0x01 -#define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) */ +#define SPDCR_SPFC_MASK 0x03 /* Frame Count Setting (1-4) (SH) */ /* SPCKD - Clock Delay Register */ #define SPCKD_SCKDL_MASK 0x07 /* Clock Delay Setting (1-8) */ @@ -168,8 +170,8 @@ #define SPCMD_CPHA 0x0001 /* Clock Phase Setting */ /* SPBFCR - Buffer Control Register */ -#define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset (qspi only) */ -#define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset (qspi only) */ +#define SPBFCR_TXRST 0x80 /* Transmit Buffer Data Reset */ +#define SPBFCR_RXRST 0x40 /* Receive Buffer Data Reset */ #define SPBFCR_TXTRG_MASK 0x30 /* Transmit Buffer Data Triggering Number */ #define SPBFCR_RXTRG_MASK 0x07 /* Receive Buffer Data Triggering Number */ @@ -244,7 +246,7 @@ struct spi_ops { }; /* - * functions for RSPI + * functions for RSPI on legacy SH */ static int rspi_set_config_register(struct rspi_data *rspi, int access_size) { @@ -280,6 +282,39 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size) } /* + * functions for RSPI on RZ + */ +static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size) +{ + int spbr; + + /* Sets output mode */ + rspi_write8(rspi, 0x00, RSPI_SPPCR); + + /* Sets transfer bit rate */ + spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1; + rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR); + + /* Disable dummy transmission, set byte access */ + rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR); + rspi->byte_access = 1; + + /* Sets RSPCK, SSL, next-access delay value */ + rspi_write8(rspi, 0x00, RSPI_SPCKD); + rspi_write8(rspi, 0x00, RSPI_SSLND); + rspi_write8(rspi, 0x00, RSPI_SPND); + + /* Sets SPCMD */ + rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); + rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); + + /* Sets RSPI mode */ + rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR); + + return 0; +} + +/* * functions for QSPI */ static int qspi_set_config_register(struct rspi_data *rspi, int access_size) @@ -520,6 +555,13 @@ static void rspi_receive_init(const struct rspi_data *rspi) RSPI_SPSR); } +static void rspi_rz_receive_init(const struct rspi_data *rspi) +{ + rspi_receive_init(rspi); + rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, RSPI_SPBFCR); + rspi_write8(rspi, 0, RSPI_SPBFCR); +} + static void qspi_receive_init(const struct rspi_data *rspi) { u8 spsr; @@ -706,6 +748,41 @@ static int rspi_transfer_one(struct spi_master *master, struct spi_device *spi, return 0; } +static int rspi_rz_transfer_out_in(struct rspi_data *rspi, + struct spi_transfer *xfer) +{ + int remain = xfer->len, ret; + const u8 *tx_buf = xfer->tx_buf; + u8 *rx_buf = xfer->rx_buf; + u8 data; + + rspi_rz_receive_init(rspi); + + while (remain > 0) { + data = tx_buf ? *tx_buf++ : DUMMY_DATA; + ret = rspi_data_out_in(rspi, data); + if (ret < 0) + return ret; + if (rx_buf) + *rx_buf++ = ret; + remain--; + } + + /* Wait for the last transmission */ + rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE); + + return 0; +} + +static int rspi_rz_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct rspi_data *rspi = spi_master_get_devdata(master); + + return rspi_rz_transfer_out_in(rspi, xfer); +} + static int qspi_transfer_out_in(struct rspi_data *rspi, struct spi_transfer *xfer) { @@ -1041,6 +1118,11 @@ static struct spi_ops rspi_ops = { .transfer_one = rspi_transfer_one, }; +static struct spi_ops rspi_rz_ops = { + .set_config_register = rspi_rz_set_config_register, + .transfer_one = rspi_rz_transfer_one, +}; + static struct spi_ops qspi_ops = { .set_config_register = qspi_set_config_register, .transfer_one = qspi_transfer_one, @@ -1048,6 +1130,7 @@ static struct spi_ops qspi_ops = { static struct platform_device_id spi_driver_ids[] = { { "rspi", (kernel_ulong_t)&rspi_ops }, + { "rspi-rz", (kernel_ulong_t)&rspi_rz_ops }, { "qspi", (kernel_ulong_t)&qspi_ops }, {}, };