From patchwork Tue Feb 11 05:48:16 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chao Fu X-Patchwork-Id: 3625011 X-Patchwork-Delegate: broonie@sirena.org.uk 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.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7877F9F382 for ; Tue, 11 Feb 2014 06:50:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6FBB2201FB for ; Tue, 11 Feb 2014 06:50:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 51A8C201F7 for ; Tue, 11 Feb 2014 06:50:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750809AbaBKGuw (ORCPT ); Tue, 11 Feb 2014 01:50:52 -0500 Received: from am1ehsobe006.messaging.microsoft.com ([213.199.154.209]:21501 "EHLO am1outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750803AbaBKGuv (ORCPT ); Tue, 11 Feb 2014 01:50:51 -0500 Received: from mail80-am1-R.bigfish.com (10.3.201.238) by AM1EHSOBE020.bigfish.com (10.3.207.142) with Microsoft SMTP Server id 14.1.225.22; Tue, 11 Feb 2014 06:50:49 +0000 Received: from mail80-am1 (localhost [127.0.0.1]) by mail80-am1-R.bigfish.com (Postfix) with ESMTP id C30863A0242; Tue, 11 Feb 2014 06:50:49 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 1 X-BigFish: VS1(zzzz1f42h2148h208ch1ee6h1de0h1fdah2073h2146h1202h1e76h2189h1d1ah1d2ah21bch1fc6hzd2iz1de098h8275bh1de097hz2dh2a8h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1b2fh2222h224fh1fb3h1d0ch1d2eh1d3fh1dc1h1dfeh1dffh1e23h1fe8h1ff5h2218h2216h226dh22d0h24afh2327h2336h2438h2461h2487h24d7h2516h2545h255eh1155h) Received: from mail80-am1 (localhost.localdomain [127.0.0.1]) by mail80-am1 (MessageSwitch) id 1392101447518059_26118; Tue, 11 Feb 2014 06:50:47 +0000 (UTC) Received: from AM1EHSMHS001.bigfish.com (unknown [10.3.201.226]) by mail80-am1.bigfish.com (Postfix) with ESMTP id 688B560050; Tue, 11 Feb 2014 06:50:47 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by AM1EHSMHS001.bigfish.com (10.3.207.101) with Microsoft SMTP Server (TLS) id 14.16.227.3; Tue, 11 Feb 2014 06:50:47 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-001.039d.mgd.msft.net (10.84.1.13) with Microsoft SMTP Server (TLS) id 14.3.158.2; Tue, 11 Feb 2014 06:50:42 +0000 Received: from rock.am.freescale.net (rock.ap.freescale.net [10.193.20.106]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id s1B6ocd2019325; Mon, 10 Feb 2014 23:50:39 -0700 From: Chao Fu To: , CC: , , Chao Fu , Chao Fu Subject: [PATCH v3 1/2] spi:fsl-dspi:convert to use regmap and big-endian supports Date: Tue, 11 Feb 2014 13:48:16 +0800 Message-ID: <1392097697-14919-1-git-send-email-b44548@freescale.com> X-Mailer: git-send-email 1.8.0 MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% X-FOPE-CONNECTOR: Id%0$Dn%FREESCALE.MAIL.ONMICROSOFT.COM$RO%1$TLS%0$FQDN%$TlsDn% Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY, UNRESOLVED_TEMPLATE 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 From: Chao Fu Freescale DSPI module will have two endianess in different platform, but ARM is little endian. So when DSPI in big endian, core in little endian, readl and writel can not adjust R/W register in this condition. This patch will remove general readl/writel, and import regmap mechanism. Data endian will be transfered in regmap APIs. Documents: dspi add bool "big-endian" in dts node if DSPI module work in big endian. Signed-off-by: Chao Fu --- Change in v3: Remove readl and wrirel, and import regmap mechanism to R/W module registers. Change in v2: Make dspi_readx dspi_writex as inline functions. Modify the issue of indentation in function is_double_byte_mode. Add description about big endian in bindings document. .../devicetree/bindings/spi/spi-fsl-dspi.txt | 2 + drivers/spi/spi-fsl-dspi.c | 80 ++++++++++++++-------- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt index a1fb303..5376de4 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt @@ -10,6 +10,7 @@ Required properties: - pinctrl-names: must contain a "default" entry. - spi-num-chipselects : the number of the chipselect signals. - bus-num : the slave chip chipselect signal number. +- big-endian : if DSPI modudle is big endian, the bool will be set in node. Example: dspi0@4002c000 { @@ -24,6 +25,7 @@ dspi0@4002c000 { bus-num = <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_dspi0_1>; + big-endian; status = "okay"; sflash: at26df081a@0 { diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index ec79f72..fb16575 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -108,7 +109,7 @@ struct fsl_dspi { struct spi_bitbang bitbang; struct platform_device *pdev; - void __iomem *base; + struct regmap *regmap; int irq; struct clk *clk; @@ -129,18 +130,11 @@ struct fsl_dspi { static inline int is_double_byte_mode(struct fsl_dspi *dspi) { - return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK) - == SPI_FRAME_BITS(8)) ? 0 : 1; -} + unsigned int val; -static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits) -{ - u32 temp; + regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val); - temp = readl(dspi->base + SPI_CTAR(dspi->cs)); - temp &= ~SPI_FRAME_BITS_MASK; - temp |= SPI_FRAME_BITS(bits); - writel(temp, dspi->base + SPI_CTAR(dspi->cs)); + return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1; } static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, @@ -188,7 +182,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) */ if (tx_word && (dspi->len == 1)) { dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; - set_bit_mode(dspi, 8); + regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), + SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); tx_word = 0; } @@ -238,7 +233,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */ } - writel(dspi_pushr, dspi->base + SPI_PUSHR); + regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); + tx_count++; } @@ -253,17 +249,23 @@ static int dspi_transfer_read(struct fsl_dspi *dspi) while ((dspi->rx < dspi->rx_end) && (rx_count < DSPI_FIFO_SIZE)) { if (rx_word) { + unsigned int val; + if ((dspi->rx_end - dspi->rx) == 1) break; - d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); + regmap_read(dspi->regmap, SPI_POPR, &val); + d = SPI_POPR_RXDATA(val); if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) *(u16 *)dspi->rx = d; dspi->rx += 2; } else { - d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); + unsigned int val; + + regmap_read(dspi->regmap, SPI_POPR, &val); + d = SPI_POPR_RXDATA(val); if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) *(u8 *)dspi->rx = d; dspi->rx++; @@ -295,13 +297,13 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) if (!dspi->tx) dspi->dataflags |= TRAN_STATE_TX_VOID; - writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR); - writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs)); - writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER); + regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val); + regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val); + regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); if (t->speed_hz) - writel(dspi->cur_chip->ctar_val, - dspi->base + SPI_CTAR(dspi->cs)); + regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), + dspi->cur_chip->ctar_val); dspi_transfer_write(dspi); @@ -315,7 +317,9 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) static void dspi_chipselect(struct spi_device *spi, int value) { struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); - u32 pushr = readl(dspi->base + SPI_PUSHR); + unsigned int pushr; + + regmap_read(dspi->regmap, SPI_PUSHR, &pushr); switch (value) { case BITBANG_CS_ACTIVE: @@ -326,7 +330,7 @@ static void dspi_chipselect(struct spi_device *spi, int value) break; } - writel(pushr, dspi->base + SPI_PUSHR); + regmap_write(dspi->regmap, SPI_PUSHR, pushr); } static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) @@ -382,13 +386,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) { struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; - writel(SPI_SR_EOQF, dspi->base + SPI_SR); + regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); dspi_transfer_read(dspi); if (!dspi->len) { if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) - set_bit_mode(dspi, 16); + regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), + SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); + dspi->waitflags = 1; wake_up_interruptible(&dspi->waitq); } else { @@ -435,12 +441,20 @@ static const struct dev_pm_ops dspi_pm = { SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume) }; +static struct regmap_config dspi_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x88, +}; + static int dspi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spi_master *master; struct fsl_dspi *dspi; struct resource *res; + void __iomem *base; int ret = 0, cs_num, bus_num; master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); @@ -475,12 +489,24 @@ static int dspi_probe(struct platform_device *pdev) master->bus_num = bus_num; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dspi->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(dspi->base)) { - ret = PTR_ERR(dspi->base); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + ret = PTR_ERR(base); goto out_master_put; } + dspi_regmap_config.lock_arg = dspi; + dspi_regmap_config.val_format_endian = + of_property_read_bool(np, "big-endian") + ? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT; + dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base, + &dspi_regmap_config); + if (IS_ERR(dspi->regmap)) { + dev_err(&pdev->dev, "failed to init regmap: %ld\n", + PTR_ERR(dspi->regmap)); + return PTR_ERR(dspi->regmap); + } + dspi->irq = platform_get_irq(pdev, 0); if (dspi->irq < 0) { dev_err(&pdev->dev, "can't get platform irq\n");