]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
spi/fsl-dspi: Convert to use regmap and add big-endian support
authorChao Fu <B44548@freescale.com>
Wed, 12 Feb 2014 07:29:05 +0000 (15:29 +0800)
committerMark Brown <broonie@linaro.org>
Sun, 16 Feb 2014 01:15:23 +0000 (09:15 +0800)
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 <b44548@freescale.com>
Reviewed-by: Xiubo Li <Li.Xiubo@freescale.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
drivers/spi/Kconfig
drivers/spi/spi-fsl-dspi.c

index a1fb3035a42bebf683e25bf4012a539fe8092a50..5376de40f10b562ba218651433be71508e4c560b 100644 (file)
@@ -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 {
index ba9310bc9acb7449a91ccb59b8f7de5c09c5801d..00e951045aac7416def47a634a2da37940d34c11 100644 (file)
@@ -270,6 +270,7 @@ config SPI_FSL_SPI
 config SPI_FSL_DSPI
        tristate "Freescale DSPI controller"
        select SPI_BITBANG
+       select REGMAP_MMIO
        depends on SOC_VF610 || COMPILE_TEST
        help
          This enables support for the Freescale DSPI controller in master
index ec79f726672a14f7644810101afe59e82322976c..fb16575d233ffe1d812e9524d43a8f8c091a459b 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/io.h>
@@ -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");