]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'spi/topic/rspi' into spi-pdata
authorMark Brown <broonie@linaro.org>
Thu, 29 Aug 2013 12:59:05 +0000 (13:59 +0100)
committerMark Brown <broonie@linaro.org>
Thu, 29 Aug 2013 12:59:05 +0000 (13:59 +0100)
Conflicts:
drivers/spi/spi-rspi.c

32 files changed:
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-altera.c
drivers/spi/spi-ath79.c
drivers/spi/spi-au1550.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bfin-sport.c
drivers/spi/spi-bfin-v3.c [new file with mode: 0644]
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-davinci.c
drivers/spi/spi-ep93xx.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-fsl-lib.c
drivers/spi/spi-fsl-spi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mpc52xx-psc.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-oc-tiny.c
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-pl022.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c24xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-sh-sci.c
drivers/spi/spi-sirf.c
drivers/spi/spi-ti-ssp.c
drivers/spi/spi-tle62x0.c
drivers/spi/spi-xilinx.c

index 89cbbabaff44c66771efc3f26b18e9b4565a4cc3..e31bf77ab2594122eb3bbdf3393834c3915cd0a4 100644 (file)
@@ -88,10 +88,17 @@ config SPI_BCM2835
 
 config SPI_BFIN5XX
        tristate "SPI controller driver for ADI Blackfin5xx"
-       depends on BLACKFIN
+       depends on BLACKFIN && !BF60x
        help
          This is the SPI controller master driver for Blackfin 5xx processor.
 
+config SPI_BFIN_V3
+       tristate "SPI controller v3 for Blackfin"
+       depends on BF60x
+       help
+         This is the SPI controller v3 master driver
+         found on Blackfin 60x processor.
+
 config SPI_BFIN_SPORT
        tristate "SPI bus via Blackfin SPORT"
        depends on BLACKFIN
index 33f9c09561e799051fb257f53f6161961cb734e7..7c4170263cd8db4bcb5bb126b33de16b34cc2cd0 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550)              += spi-au1550.o
 obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
 obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN_V3)               += spi-bfin-v3.o
 obj-$(CONFIG_SPI_BFIN_SPORT)           += spi-bfin-sport.o
 obj-$(CONFIG_SPI_BITBANG)              += spi-bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)            += spi-butterfly.o
index 81b9adb6e766bdae0b0f6c9de4836ecfaffc490a..e53caac13aec06f836640ad0bd6f5f8f317a694f 100644 (file)
@@ -217,7 +217,7 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
 
 static int altera_spi_probe(struct platform_device *pdev)
 {
-       struct altera_spi_platform_data *platp = pdev->dev.platform_data;
+       struct altera_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
        struct altera_spi *hw;
        struct spi_master *master;
        struct resource *res;
index 0e06407a4670b14ac1ea7b40024f9092df5d0443..37bad952ab38a649ea86eedc52ac6e3df1b9a133 100644 (file)
@@ -221,7 +221,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
        sp = spi_master_get_devdata(master);
        platform_set_drvdata(pdev, sp);
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
 
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
        master->setup = ath79_spi_setup;
index e1965553ab799b7c77cdf8a5fe8e18b727bb7c05..1d00d9b397dde39dc585c2c99d7be47cbb50607e 100644 (file)
@@ -776,7 +776,7 @@ static int au1550_spi_probe(struct platform_device *pdev)
        hw = spi_master_get_devdata(master);
 
        hw->master = spi_master_get(master);
-       hw->pdata = pdev->dev.platform_data;
+       hw->pdata = dev_get_platdata(&pdev->dev);
        hw->dev = &pdev->dev;
 
        if (hw->pdata == NULL) {
index 9fd7a39b8029e2d630161a278879965f5abb9407..f2b548f5ae99f623ebc1d8dc9cc228b8cf78d811 100644 (file)
@@ -353,7 +353,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 {
        struct resource *r;
        struct device *dev = &pdev->dev;
-       struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data;
+       struct bcm63xx_spi_pdata *pdata = dev_get_platdata(&pdev->dev);
        int irq;
        struct spi_master *master;
        struct clk *clk;
@@ -480,8 +480,7 @@ static int bcm63xx_spi_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int bcm63xx_spi_suspend(struct device *dev)
 {
-       struct spi_master *master =
-                       platform_get_drvdata(to_platform_device(dev));
+       struct spi_master *master = dev_get_drvdata(dev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
        spi_master_suspend(master);
@@ -493,8 +492,7 @@ static int bcm63xx_spi_suspend(struct device *dev)
 
 static int bcm63xx_spi_resume(struct device *dev)
 {
-       struct spi_master *master =
-                       platform_get_drvdata(to_platform_device(dev));
+       struct spi_master *master = dev_get_drvdata(dev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
        clk_prepare_enable(bs->clk);
index 07ec597f9732cb3a7324d39f02747ad1979b601a..91921b5f58171fcd8de5faf0d33099f8fc490f2f 100644 (file)
@@ -756,7 +756,7 @@ static int bfin_sport_spi_probe(struct platform_device *pdev)
        struct bfin_sport_spi_master_data *drv_data;
        int status;
 
-       platform_info = dev->platform_data;
+       platform_info = dev_get_platdata(dev);
 
        /* Allocate master with space for drv_data */
        master = spi_alloc_master(dev, sizeof(*master) + 16);
diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c
new file mode 100644 (file)
index 0000000..35f2db7
--- /dev/null
@@ -0,0 +1,971 @@
+/*
+ * Analog Devices SPI3 controller driver
+ *
+ * Copyright (c) 2013 Analog Devices Inc.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+
+#include <asm/bfin_spi3.h>
+#include <asm/cacheflush.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+enum bfin_spi_state {
+       START_STATE,
+       RUNNING_STATE,
+       DONE_STATE,
+       ERROR_STATE
+};
+
+struct bfin_spi_master;
+
+struct bfin_spi_transfer_ops {
+       void (*write) (struct bfin_spi_master *);
+       void (*read) (struct bfin_spi_master *);
+       void (*duplex) (struct bfin_spi_master *);
+};
+
+/* runtime info for spi master */
+struct bfin_spi_master {
+       /* SPI framework hookup */
+       struct spi_master *master;
+
+       /* Regs base of SPI controller */
+       struct bfin_spi_regs __iomem *regs;
+
+       /* Pin request list */
+       u16 *pin_req;
+
+       /* Message Transfer pump */
+       struct tasklet_struct pump_transfers;
+
+       /* Current message transfer state info */
+       struct spi_message *cur_msg;
+       struct spi_transfer *cur_transfer;
+       struct bfin_spi_device *cur_chip;
+       unsigned transfer_len;
+
+       /* transfer buffer */
+       void *tx;
+       void *tx_end;
+       void *rx;
+       void *rx_end;
+
+       /* dma info */
+       unsigned int tx_dma;
+       unsigned int rx_dma;
+       dma_addr_t tx_dma_addr;
+       dma_addr_t rx_dma_addr;
+       unsigned long dummy_buffer; /* used in unidirectional transfer */
+       unsigned long tx_dma_size;
+       unsigned long rx_dma_size;
+       int tx_num;
+       int rx_num;
+
+       /* store register value for suspend/resume */
+       u32 control;
+       u32 ssel;
+
+       unsigned long sclk;
+       enum bfin_spi_state state;
+
+       const struct bfin_spi_transfer_ops *ops;
+};
+
+struct bfin_spi_device {
+       u32 control;
+       u32 clock;
+       u32 ssel;
+
+       u8 cs;
+       u16 cs_chg_udelay; /* Some devices require > 255usec delay */
+       u32 cs_gpio;
+       u32 tx_dummy_val; /* tx value for rx only transfer */
+       bool enable_dma;
+       const struct bfin_spi_transfer_ops *ops;
+};
+
+static void bfin_spi_enable(struct bfin_spi_master *drv_data)
+{
+       bfin_write_or(&drv_data->regs->control, SPI_CTL_EN);
+}
+
+static void bfin_spi_disable(struct bfin_spi_master *drv_data)
+{
+       bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN);
+}
+
+/* Caculate the SPI_CLOCK register value based on input HZ */
+static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz)
+{
+       u32 spi_clock = sclk / speed_hz;
+
+       if (spi_clock)
+               spi_clock--;
+       return spi_clock;
+}
+
+static int bfin_spi_flush(struct bfin_spi_master *drv_data)
+{
+       unsigned long limit = loops_per_jiffy << 1;
+
+       /* wait for stop and clear stat */
+       while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit)
+               cpu_relax();
+
+       bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+
+       return limit;
+}
+
+/* Chip select operation functions for cs_change flag */
+static void bfin_spi_cs_active(struct bfin_spi_master *drv_data, struct bfin_spi_device *chip)
+{
+       if (likely(chip->cs < MAX_CTRL_CS))
+               bfin_write_and(&drv_data->regs->ssel, ~chip->ssel);
+       else
+               gpio_set_value(chip->cs_gpio, 0);
+}
+
+static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data,
+                               struct bfin_spi_device *chip)
+{
+       if (likely(chip->cs < MAX_CTRL_CS))
+               bfin_write_or(&drv_data->regs->ssel, chip->ssel);
+       else
+               gpio_set_value(chip->cs_gpio, 1);
+
+       /* Move delay here for consistency */
+       if (chip->cs_chg_udelay)
+               udelay(chip->cs_chg_udelay);
+}
+
+/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */
+static inline void bfin_spi_cs_enable(struct bfin_spi_master *drv_data,
+                                       struct bfin_spi_device *chip)
+{
+       if (chip->cs < MAX_CTRL_CS)
+               bfin_write_or(&drv_data->regs->ssel, chip->ssel >> 8);
+}
+
+static inline void bfin_spi_cs_disable(struct bfin_spi_master *drv_data,
+                                       struct bfin_spi_device *chip)
+{
+       if (chip->cs < MAX_CTRL_CS)
+               bfin_write_and(&drv_data->regs->ssel, ~(chip->ssel >> 8));
+}
+
+/* stop controller and re-config current chip*/
+static void bfin_spi_restore_state(struct bfin_spi_master *drv_data)
+{
+       struct bfin_spi_device *chip = drv_data->cur_chip;
+
+       /* Clear status and disable clock */
+       bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+       bfin_write(&drv_data->regs->rx_control, 0x0);
+       bfin_write(&drv_data->regs->tx_control, 0x0);
+       bfin_spi_disable(drv_data);
+
+       SSYNC();
+
+       /* Load the registers */
+       bfin_write(&drv_data->regs->control, chip->control);
+       bfin_write(&drv_data->regs->clock, chip->clock);
+
+       bfin_spi_enable(drv_data);
+       drv_data->tx_num = drv_data->rx_num = 0;
+       /* we always choose tx transfer initiate */
+       bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN);
+       bfin_write(&drv_data->regs->tx_control,
+                       SPI_TXCTL_TEN | SPI_TXCTL_TTI);
+       bfin_spi_cs_active(drv_data, chip);
+}
+
+/* discard invalid rx data and empty rfifo */
+static inline void dummy_read(struct bfin_spi_master *drv_data)
+{
+       while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_RFE))
+               bfin_read(&drv_data->regs->rfifo);
+}
+
+static void bfin_spi_u8_write(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->tx < drv_data->tx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++)));
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static void bfin_spi_u8_read(struct bfin_spi_master *drv_data)
+{
+       u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, tx_val);
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static void bfin_spi_u8_duplex(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++)));
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = {
+       .write  = bfin_spi_u8_write,
+       .read   = bfin_spi_u8_read,
+       .duplex = bfin_spi_u8_duplex,
+};
+
+static void bfin_spi_u16_write(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->tx < drv_data->tx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx));
+               drv_data->tx += 2;
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static void bfin_spi_u16_read(struct bfin_spi_master *drv_data)
+{
+       u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, tx_val);
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+               drv_data->rx += 2;
+       }
+}
+
+static void bfin_spi_u16_duplex(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx));
+               drv_data->tx += 2;
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+               drv_data->rx += 2;
+       }
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = {
+       .write  = bfin_spi_u16_write,
+       .read   = bfin_spi_u16_read,
+       .duplex = bfin_spi_u16_duplex,
+};
+
+static void bfin_spi_u32_write(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->tx < drv_data->tx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx));
+               drv_data->tx += 4;
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               bfin_read(&drv_data->regs->rfifo);
+       }
+}
+
+static void bfin_spi_u32_read(struct bfin_spi_master *drv_data)
+{
+       u32 tx_val = drv_data->cur_chip->tx_dummy_val;
+
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, tx_val);
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+               drv_data->rx += 4;
+       }
+}
+
+static void bfin_spi_u32_duplex(struct bfin_spi_master *drv_data)
+{
+       dummy_read(drv_data);
+       while (drv_data->rx < drv_data->rx_end) {
+               bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx));
+               drv_data->tx += 4;
+               while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)
+                       cpu_relax();
+               *(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo);
+               drv_data->rx += 4;
+       }
+}
+
+static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = {
+       .write  = bfin_spi_u32_write,
+       .read   = bfin_spi_u32_read,
+       .duplex = bfin_spi_u32_duplex,
+};
+
+
+/* test if there is more transfer to be done */
+static void bfin_spi_next_transfer(struct bfin_spi_master *drv)
+{
+       struct spi_message *msg = drv->cur_msg;
+       struct spi_transfer *t = drv->cur_transfer;
+
+       /* Move to next transfer */
+       if (t->transfer_list.next != &msg->transfers) {
+               drv->cur_transfer = list_entry(t->transfer_list.next,
+                              struct spi_transfer, transfer_list);
+               drv->state = RUNNING_STATE;
+       } else {
+               drv->state = DONE_STATE;
+               drv->cur_transfer = NULL;
+       }
+}
+
+static void bfin_spi_giveback(struct bfin_spi_master *drv_data)
+{
+       struct bfin_spi_device *chip = drv_data->cur_chip;
+
+       bfin_spi_cs_deactive(drv_data, chip);
+       spi_finalize_current_message(drv_data->master);
+}
+
+static int bfin_spi_setup_transfer(struct bfin_spi_master *drv)
+{
+       struct spi_transfer *t = drv->cur_transfer;
+       u32 cr, cr_width;
+
+       if (t->tx_buf) {
+               drv->tx = (void *)t->tx_buf;
+               drv->tx_end = drv->tx + t->len;
+       } else {
+               drv->tx = NULL;
+       }
+
+       if (t->rx_buf) {
+               drv->rx = t->rx_buf;
+               drv->rx_end = drv->rx + t->len;
+       } else {
+               drv->rx = NULL;
+       }
+
+       drv->transfer_len = t->len;
+
+       /* bits per word setup */
+       switch (t->bits_per_word) {
+       case 8:
+               cr_width = SPI_CTL_SIZE08;
+               drv->ops = &bfin_bfin_spi_transfer_ops_u8;
+               break;
+       case 16:
+               cr_width = SPI_CTL_SIZE16;
+               drv->ops = &bfin_bfin_spi_transfer_ops_u16;
+               break;
+       case 32:
+               cr_width = SPI_CTL_SIZE32;
+               drv->ops = &bfin_bfin_spi_transfer_ops_u32;
+               break;
+       default:
+               return -EINVAL;
+       }
+       cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE;
+       cr |= cr_width;
+       bfin_write(&drv->regs->control, cr);
+
+       /* speed setup */
+       bfin_write(&drv->regs->clock,
+                       hz_to_spi_clock(drv->sclk, t->speed_hz));
+       return 0;
+}
+
+static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data)
+{
+       struct spi_transfer *t = drv_data->cur_transfer;
+       struct spi_message *msg = drv_data->cur_msg;
+       struct bfin_spi_device *chip = drv_data->cur_chip;
+       u32 dma_config;
+       unsigned long word_count, word_size;
+       void *tx_buf, *rx_buf;
+
+       switch (t->bits_per_word) {
+       case 8:
+               dma_config = WDSIZE_8 | PSIZE_8;
+               word_count = drv_data->transfer_len;
+               word_size = 1;
+               break;
+       case 16:
+               dma_config = WDSIZE_16 | PSIZE_16;
+               word_count = drv_data->transfer_len / 2;
+               word_size = 2;
+               break;
+       default:
+               dma_config = WDSIZE_32 | PSIZE_32;
+               word_count = drv_data->transfer_len / 4;
+               word_size = 4;
+               break;
+       }
+
+       if (!drv_data->rx) {
+               tx_buf = drv_data->tx;
+               rx_buf = &drv_data->dummy_buffer;
+               drv_data->tx_dma_size = drv_data->transfer_len;
+               drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer);
+               set_dma_x_modify(drv_data->tx_dma, word_size);
+               set_dma_x_modify(drv_data->rx_dma, 0);
+       } else if (!drv_data->tx) {
+               drv_data->dummy_buffer = chip->tx_dummy_val;
+               tx_buf = &drv_data->dummy_buffer;
+               rx_buf = drv_data->rx;
+               drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer);
+               drv_data->rx_dma_size = drv_data->transfer_len;
+               set_dma_x_modify(drv_data->tx_dma, 0);
+               set_dma_x_modify(drv_data->rx_dma, word_size);
+       } else {
+               tx_buf = drv_data->tx;
+               rx_buf = drv_data->rx;
+               drv_data->tx_dma_size = drv_data->rx_dma_size
+                                       = drv_data->transfer_len;
+               set_dma_x_modify(drv_data->tx_dma, word_size);
+               set_dma_x_modify(drv_data->rx_dma, word_size);
+       }
+
+       drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev,
+                               (void *)tx_buf,
+                               drv_data->tx_dma_size,
+                               DMA_TO_DEVICE);
+       if (dma_mapping_error(&msg->spi->dev,
+                               drv_data->tx_dma_addr))
+               return -ENOMEM;
+
+       drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev,
+                               (void *)rx_buf,
+                               drv_data->rx_dma_size,
+                               DMA_FROM_DEVICE);
+       if (dma_mapping_error(&msg->spi->dev,
+                               drv_data->rx_dma_addr)) {
+               dma_unmap_single(&msg->spi->dev,
+                               drv_data->tx_dma_addr,
+                               drv_data->tx_dma_size,
+                               DMA_TO_DEVICE);
+               return -ENOMEM;
+       }
+
+       dummy_read(drv_data);
+       set_dma_x_count(drv_data->tx_dma, word_count);
+       set_dma_x_count(drv_data->rx_dma, word_count);
+       set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr);
+       set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr);
+       dma_config |= DMAFLOW_STOP | RESTART | DI_EN;
+       set_dma_config(drv_data->tx_dma, dma_config);
+       set_dma_config(drv_data->rx_dma, dma_config | WNR);
+       enable_dma(drv_data->tx_dma);
+       enable_dma(drv_data->rx_dma);
+       SSYNC();
+
+       bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE);
+       SSYNC();
+       bfin_write(&drv_data->regs->tx_control,
+                       SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF);
+
+       return 0;
+}
+
+static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data)
+{
+       struct spi_message *msg = drv_data->cur_msg;
+
+       if (!drv_data->rx) {
+               /* write only half duplex */
+               drv_data->ops->write(drv_data);
+               if (drv_data->tx != drv_data->tx_end)
+                       return -EIO;
+       } else if (!drv_data->tx) {
+               /* read only half duplex */
+               drv_data->ops->read(drv_data);
+               if (drv_data->rx != drv_data->rx_end)
+                       return -EIO;
+       } else {
+               /* full duplex mode */
+               drv_data->ops->duplex(drv_data);
+               if (drv_data->tx != drv_data->tx_end)
+                       return -EIO;
+       }
+
+       if (!bfin_spi_flush(drv_data))
+               return -EIO;
+       msg->actual_length += drv_data->transfer_len;
+       tasklet_schedule(&drv_data->pump_transfers);
+       return 0;
+}
+
+static void bfin_spi_pump_transfers(unsigned long data)
+{
+       struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data;
+       struct spi_message *msg = NULL;
+       struct spi_transfer *t = NULL;
+       struct bfin_spi_device *chip = NULL;
+       int ret;
+
+       /* Get current state information */
+       msg = drv_data->cur_msg;
+       t = drv_data->cur_transfer;
+       chip = drv_data->cur_chip;
+
+       /* Handle for abort */
+       if (drv_data->state == ERROR_STATE) {
+               msg->status = -EIO;
+               bfin_spi_giveback(drv_data);
+               return;
+       }
+
+       if (drv_data->state == RUNNING_STATE) {
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
+               if (t->cs_change)
+                       bfin_spi_cs_deactive(drv_data, chip);
+               bfin_spi_next_transfer(drv_data);
+               t = drv_data->cur_transfer;
+       }
+       /* Handle end of message */
+       if (drv_data->state == DONE_STATE) {
+               msg->status = 0;
+               bfin_spi_giveback(drv_data);
+               return;
+       }
+
+       if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) {
+               /* Schedule next transfer tasklet */
+               tasklet_schedule(&drv_data->pump_transfers);
+               return;
+       }
+
+       ret = bfin_spi_setup_transfer(drv_data);
+       if (ret) {
+               msg->status = ret;
+               bfin_spi_giveback(drv_data);
+       }
+
+       bfin_write(&drv_data->regs->status, 0xFFFFFFFF);
+       bfin_spi_cs_active(drv_data, chip);
+       drv_data->state = RUNNING_STATE;
+
+       if (chip->enable_dma)
+               ret = bfin_spi_dma_xfer(drv_data);
+       else
+               ret = bfin_spi_pio_xfer(drv_data);
+       if (ret) {
+               msg->status = ret;
+               bfin_spi_giveback(drv_data);
+       }
+}
+
+static int bfin_spi_transfer_one_message(struct spi_master *master,
+                                       struct spi_message *m)
+{
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+       drv_data->cur_msg = m;
+       drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+       bfin_spi_restore_state(drv_data);
+
+       drv_data->state = START_STATE;
+       drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+                                           struct spi_transfer, transfer_list);
+
+       tasklet_schedule(&drv_data->pump_transfers);
+       return 0;
+}
+
+#define MAX_SPI_SSEL   7
+
+static const u16 ssel[][MAX_SPI_SSEL] = {
+       {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
+       P_SPI0_SSEL4, P_SPI0_SSEL5,
+       P_SPI0_SSEL6, P_SPI0_SSEL7},
+
+       {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3,
+       P_SPI1_SSEL4, P_SPI1_SSEL5,
+       P_SPI1_SSEL6, P_SPI1_SSEL7},
+
+       {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3,
+       P_SPI2_SSEL4, P_SPI2_SSEL5,
+       P_SPI2_SSEL6, P_SPI2_SSEL7},
+};
+
+static int bfin_spi_setup(struct spi_device *spi)
+{
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master);
+       struct bfin_spi_device *chip = spi_get_ctldata(spi);
+       u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE;
+       int ret = -EINVAL;
+
+       if (!chip) {
+               struct bfin_spi3_chip *chip_info = spi->controller_data;
+
+               chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+               if (!chip) {
+                       dev_err(&spi->dev, "can not allocate chip data\n");
+                       return -ENOMEM;
+               }
+               if (chip_info) {
+                       if (chip_info->control & ~bfin_ctl_reg) {
+                               dev_err(&spi->dev,
+                                       "do not set bits that the SPI framework manages\n");
+                               goto error;
+                       }
+                       chip->control = chip_info->control;
+                       chip->cs_chg_udelay = chip_info->cs_chg_udelay;
+                       chip->tx_dummy_val = chip_info->tx_dummy_val;
+                       chip->enable_dma = chip_info->enable_dma;
+               }
+               chip->cs = spi->chip_select;
+               if (chip->cs < MAX_CTRL_CS) {
+                       chip->ssel = (1 << chip->cs) << 8;
+                       ret = peripheral_request(ssel[spi->master->bus_num]
+                                       [chip->cs-1], dev_name(&spi->dev));
+                       if (ret) {
+                               dev_err(&spi->dev, "peripheral_request() error\n");
+                               goto error;
+                       }
+               } else {
+                       chip->cs_gpio = chip->cs - MAX_CTRL_CS;
+                       ret = gpio_request_one(chip->cs_gpio, GPIOF_OUT_INIT_HIGH,
+                                               dev_name(&spi->dev));
+                       if (ret) {
+                               dev_err(&spi->dev, "gpio_request_one() error\n");
+                               goto error;
+                       }
+               }
+               spi_set_ctldata(spi, chip);
+       }
+
+       /* force a default base state */
+       chip->control &= bfin_ctl_reg;
+
+       if (spi->mode & SPI_CPOL)
+               chip->control |= SPI_CTL_CPOL;
+       if (spi->mode & SPI_CPHA)
+               chip->control |= SPI_CTL_CPHA;
+       if (spi->mode & SPI_LSB_FIRST)
+               chip->control |= SPI_CTL_LSBF;
+       chip->control |= SPI_CTL_MSTR;
+       /* we choose software to controll cs */
+       chip->control &= ~SPI_CTL_ASSEL;
+
+       chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz);
+
+       bfin_spi_cs_enable(drv_data, chip);
+       bfin_spi_cs_deactive(drv_data, chip);
+
+       return 0;
+error:
+       if (chip) {
+               kfree(chip);
+               spi_set_ctldata(spi, NULL);
+       }
+
+       return ret;
+}
+
+static void bfin_spi_cleanup(struct spi_device *spi)
+{
+       struct bfin_spi_device *chip = spi_get_ctldata(spi);
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master);
+
+       if (!chip)
+               return;
+
+       if (chip->cs < MAX_CTRL_CS) {
+               peripheral_free(ssel[spi->master->bus_num]
+                                       [chip->cs-1]);
+               bfin_spi_cs_disable(drv_data, chip);
+       } else {
+               gpio_free(chip->cs_gpio);
+       }
+
+       kfree(chip);
+       spi_set_ctldata(spi, NULL);
+}
+
+static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id)
+{
+       struct bfin_spi_master *drv_data = dev_id;
+       u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma);
+
+       clear_dma_irqstat(drv_data->tx_dma);
+       if (dma_stat & DMA_DONE) {
+               drv_data->tx_num++;
+       } else {
+               dev_err(&drv_data->master->dev,
+                               "spi tx dma error: %d\n", dma_stat);
+               if (drv_data->tx)
+                       drv_data->state = ERROR_STATE;
+       }
+       bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id)
+{
+       struct bfin_spi_master *drv_data = dev_id;
+       struct spi_message *msg = drv_data->cur_msg;
+       u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma);
+
+       clear_dma_irqstat(drv_data->rx_dma);
+       if (dma_stat & DMA_DONE) {
+               drv_data->rx_num++;
+               /* we may fail on tx dma */
+               if (drv_data->state != ERROR_STATE)
+                       msg->actual_length += drv_data->transfer_len;
+       } else {
+               drv_data->state = ERROR_STATE;
+               dev_err(&drv_data->master->dev,
+                               "spi rx dma error: %d\n", dma_stat);
+       }
+       bfin_write(&drv_data->regs->tx_control, 0);
+       bfin_write(&drv_data->regs->rx_control, 0);
+       if (drv_data->rx_num != drv_data->tx_num)
+               dev_dbg(&drv_data->master->dev,
+                               "dma interrupt missing: tx=%d,rx=%d\n",
+                               drv_data->tx_num, drv_data->rx_num);
+       tasklet_schedule(&drv_data->pump_transfers);
+       return IRQ_HANDLED;
+}
+
+static int bfin_spi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct bfin_spi3_master *info = dev_get_platdata(dev);
+       struct spi_master *master;
+       struct bfin_spi_master *drv_data;
+       struct resource *mem, *res;
+       unsigned int tx_dma, rx_dma;
+       unsigned long sclk;
+       int ret;
+
+       if (!info) {
+               dev_err(dev, "platform data missing!\n");
+               return -ENODEV;
+       }
+
+       sclk = get_sclk1();
+       if (!sclk) {
+               dev_err(dev, "can not get sclk1\n");
+               return -ENXIO;
+       }
+
+       /* get register base and tx/rx dma */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(dev, "can not get register base\n");
+               return -ENXIO;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(dev, "can not get tx dma resource\n");
+               return -ENXIO;
+       }
+       tx_dma = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!res) {
+               dev_err(dev, "can not get rx dma resource\n");
+               return -ENXIO;
+       }
+       rx_dma = res->start;
+
+       /* allocate master with space for drv_data */
+       master = spi_alloc_master(dev, sizeof(*drv_data));
+       if (!master) {
+               dev_err(dev, "can not alloc spi_master\n");
+               return -ENOMEM;
+       }
+       platform_set_drvdata(pdev, master);
+
+       /* the mode bits supported by this driver */
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+
+       master->bus_num = pdev->id;
+       master->num_chipselect = info->num_chipselect;
+       master->cleanup = bfin_spi_cleanup;
+       master->setup = bfin_spi_setup;
+       master->transfer_one_message = bfin_spi_transfer_one_message;
+       master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1);
+
+       drv_data = spi_master_get_devdata(master);
+       drv_data->master = master;
+       drv_data->tx_dma = tx_dma;
+       drv_data->rx_dma = rx_dma;
+       drv_data->pin_req = info->pin_req;
+       drv_data->sclk = sclk;
+
+       drv_data->regs = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(drv_data->regs)) {
+               ret = PTR_ERR(drv_data->regs);
+               goto err_put_master;
+       }
+
+       /* request tx and rx dma */
+       ret = request_dma(tx_dma, "SPI_TX_DMA");
+       if (ret) {
+               dev_err(dev, "can not request SPI TX DMA channel\n");
+               goto err_put_master;
+       }
+       set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data);
+
+       ret = request_dma(rx_dma, "SPI_RX_DMA");
+       if (ret) {
+               dev_err(dev, "can not request SPI RX DMA channel\n");
+               goto err_free_tx_dma;
+       }
+       set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data);
+
+       /* request CLK, MOSI and MISO */
+       ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3");
+       if (ret < 0) {
+               dev_err(dev, "can not request spi pins\n");
+               goto err_free_rx_dma;
+       }
+
+       bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA);
+       bfin_write(&drv_data->regs->ssel, 0x0000FE00);
+       bfin_write(&drv_data->regs->delay, 0x0);
+
+       tasklet_init(&drv_data->pump_transfers,
+                       bfin_spi_pump_transfers, (unsigned long)drv_data);
+       /* register with the SPI framework */
+       ret = spi_register_master(master);
+       if (ret) {
+               dev_err(dev, "can not  register spi master\n");
+               goto err_free_peripheral;
+       }
+
+       return ret;
+
+err_free_peripheral:
+       peripheral_free_list(drv_data->pin_req);
+err_free_rx_dma:
+       free_dma(rx_dma);
+err_free_tx_dma:
+       free_dma(tx_dma);
+err_put_master:
+       spi_master_put(master);
+
+       return ret;
+}
+
+static int bfin_spi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+       bfin_spi_disable(drv_data);
+
+       peripheral_free_list(drv_data->pin_req);
+       free_dma(drv_data->rx_dma);
+       free_dma(drv_data->tx_dma);
+
+       spi_unregister_master(drv_data->master);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_spi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+
+       spi_master_suspend(master);
+
+       drv_data->control = bfin_read(&drv_data->regs->control);
+       drv_data->ssel = bfin_read(&drv_data->regs->ssel);
+
+       bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA);
+       bfin_write(&drv_data->regs->ssel, 0x0000FE00);
+       dma_disable_irq(drv_data->rx_dma);
+       dma_disable_irq(drv_data->tx_dma);
+
+       return 0;
+}
+
+static int bfin_spi_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bfin_spi_master *drv_data = spi_master_get_devdata(master);
+       int ret = 0;
+
+       /* bootrom may modify spi and dma status when resume in spi boot mode */
+       disable_dma(drv_data->rx_dma);
+
+       dma_enable_irq(drv_data->rx_dma);
+       dma_enable_irq(drv_data->tx_dma);
+       bfin_write(&drv_data->regs->control, drv_data->control);
+       bfin_write(&drv_data->regs->ssel, drv_data->ssel);
+
+       ret = spi_master_resume(master);
+       if (ret) {
+               free_dma(drv_data->rx_dma);
+               free_dma(drv_data->tx_dma);
+       }
+
+       return ret;
+}
+#endif
+static const struct dev_pm_ops bfin_spi_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume)
+};
+
+MODULE_ALIAS("platform:bfin-spi3");
+static struct platform_driver bfin_spi_driver = {
+       .driver = {
+               .name   = "bfin-spi3",
+               .owner  = THIS_MODULE,
+               .pm     = &bfin_spi_pm_ops,
+       },
+       .remove         = bfin_spi_remove,
+};
+
+module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe);
+
+MODULE_DESCRIPTION("Analog Devices SPI3 controller driver");
+MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
+MODULE_LICENSE("GPL v2");
index 59a73424419c8935c3428fea06247c08ced2d614..45bdf73d6868e62d0efd5c16296d359400d05b17 100644 (file)
@@ -1271,7 +1271,7 @@ static int bfin_spi_probe(struct platform_device *pdev)
        struct resource *res;
        int status = 0;
 
-       platform_info = dev->platform_data;
+       platform_info = dev_get_platdata(dev);
 
        /* Allocate master with space for drv_data */
        master = spi_alloc_master(dev, sizeof(*drv_data));
index 0631b9d4a5de7eb70d9e15fa3f701b9f8bb59c70..8e07928cadb33f7a2ae325d2e00ca0e00cce381c 100644 (file)
@@ -400,7 +400,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
        struct mcfqspi_platform_data *pdata;
        int status;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                dev_dbg(&pdev->dev, "platform data is missing\n");
                return -ENOENT;
@@ -558,7 +558,7 @@ static int mcfqspi_resume(struct device *dev)
 #ifdef CONFIG_PM_RUNTIME
 static int mcfqspi_runtime_suspend(struct device *dev)
 {
-       struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
+       struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
 
        clk_disable(mcfqspi->clk);
 
@@ -567,7 +567,7 @@ static int mcfqspi_runtime_suspend(struct device *dev)
 
 static int mcfqspi_runtime_resume(struct device *dev)
 {
-       struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
+       struct mcfqspi *mcfqspi = dev_get_drvdata(dev);
 
        clk_enable(mcfqspi->clk);
 
index 222d3e37fc283b95dc5932570c1dec874cec78e2..5cd6398e970e5a9e9774307694775d5ccbefb48a 100644 (file)
@@ -872,8 +872,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
                goto free_master;
        }
 
-       if (pdev->dev.platform_data) {
-               pdata = pdev->dev.platform_data;
+       if (dev_get_platdata(&pdev->dev)) {
+               pdata = dev_get_platdata(&pdev->dev);
                dspi->pdata = *pdata;
        } else {
                /* update dspi pdata with that from the DT */
index cad30b8a1d71cb7b573879ae21814c49758419a3..50831c837677fe7a6028a2b6e0f3161f11daf764 100644 (file)
@@ -1022,7 +1022,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
        int irq;
        int error;
 
-       info = pdev->dev.platform_data;
+       info = dev_get_platdata(&pdev->dev);
 
        master = spi_alloc_master(&pdev->dev, sizeof(*espi));
        if (!master) {
index 6a74d7848d93febe8ccb2007fa5af63c46de4ea1..b8f1103fe28ee63a4d5209f5f88466fdc84255af 100644 (file)
@@ -584,7 +584,7 @@ static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
 static struct spi_master * fsl_espi_probe(struct device *dev,
                struct resource *mem, unsigned int irq)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct spi_master *master;
        struct mpc8xxx_spi *mpc8xxx_spi;
        struct fsl_espi_reg *reg_base;
@@ -665,7 +665,7 @@ err:
 static int of_fsl_espi_get_chipselects(struct device *dev)
 {
        struct device_node *np = dev->of_node;
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        const u32 *prop;
        int len;
 
index e947f2d1b2f5a0814f03e561bd389c4b70030127..0b75f26158abbf00b5c781585a28a82e70a31eff 100644 (file)
@@ -122,7 +122,7 @@ const char *mpc8xxx_spi_strmode(unsigned int flags)
 int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
                        unsigned int irq)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct spi_master *master;
        struct mpc8xxx_spi *mpc8xxx_spi;
        int ret = 0;
index 41e89c3e3edcdd7c1b60b90345afaf6933f5e6c2..bbc94294891cb054b0e35dfe21eb47b38a3d5cb2 100644 (file)
@@ -574,7 +574,7 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on)
 
 static void fsl_spi_grlib_probe(struct device *dev)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct spi_master *master = dev_get_drvdata(dev);
        struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
        struct fsl_spi_reg *reg_base = mpc8xxx_spi->reg_base;
@@ -600,7 +600,7 @@ static void fsl_spi_grlib_probe(struct device *dev)
 static struct spi_master * fsl_spi_probe(struct device *dev,
                struct resource *mem, unsigned int irq)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct spi_master *master;
        struct mpc8xxx_spi *mpc8xxx_spi;
        struct fsl_spi_reg *reg_base;
@@ -700,7 +700,8 @@ err:
 static void fsl_spi_cs_control(struct spi_device *spi, bool on)
 {
        struct device *dev = spi->dev.parent->parent;
-       struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+       struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
        u16 cs = spi->chip_select;
        int gpio = pinfo->gpios[cs];
        bool alow = pinfo->alow_flags[cs];
@@ -711,7 +712,7 @@ static void fsl_spi_cs_control(struct spi_device *spi, bool on)
 static int of_fsl_spi_get_chipselects(struct device *dev)
 {
        struct device_node *np = dev->of_node;
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
        int ngpios;
        int i = 0;
@@ -790,7 +791,7 @@ err_alloc_flags:
 
 static int of_fsl_spi_free_chipselects(struct device *dev)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
        int i;
 
@@ -889,7 +890,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
        int irq;
        struct spi_master *master;
 
-       if (!pdev->dev.platform_data)
+       if (!dev_get_platdata(&pdev->dev))
                return -EINVAL;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index a54524cf42cc42689726547818fc55a33e3a1a94..68b69fec13a911cc2ec859ab3b40e5f0ff3f27a6 100644 (file)
@@ -420,7 +420,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
        if (status > 0)
                use_of = 1;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
 #ifdef GENERIC_BITBANG
        if (!pdata || !pdata->num_chipselect)
                return -ENODEV;
@@ -506,7 +506,7 @@ static int spi_gpio_remove(struct platform_device *pdev)
        int                             status;
 
        spi_gpio = platform_get_drvdata(pdev);
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
 
        /* stop() unregisters child devices too */
        status = spi_bitbang_stop(&spi_gpio->bitbang);
index 29fce6af5145f13a7a0dadd212f1626937ac3885..de0976cf0ae2b24531e4accd1f042c889e55a814 100644 (file)
@@ -474,7 +474,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
                                              u32 size, unsigned int irq,
                                              s16 bus_num)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct mpc512x_psc_spi *mps;
        struct spi_master *master;
        int ret;
index fed0571d4decb0fb131890a3101dd5150c3c4aa7..6e925dc3439682344def5508f53d2ec6ec9175d6 100644 (file)
@@ -366,7 +366,7 @@ static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
 static int mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
                                u32 size, unsigned int irq, s16 bus_num)
 {
-       struct fsl_spi_platform_data *pdata = dev->platform_data;
+       struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
        struct mpc52xx_psc_spi *mps;
        struct spi_master *master;
        int ret;
index 150d85453c27d2c2d5347402113cc52547180db4..e19a3074ac53358e6f9ff75631e2ce2fa9978e0a 100644 (file)
@@ -361,7 +361,7 @@ static int nuc900_spi_probe(struct platform_device *pdev)
 
        hw = spi_master_get_devdata(master);
        hw->master = spi_master_get(master);
-       hw->pdata  = pdev->dev.platform_data;
+       hw->pdata  = dev_get_platdata(&pdev->dev);
        hw->dev = &pdev->dev;
 
        if (hw->pdata == NULL) {
index 58deb79d046be444cbb0392e4f17583e8d99ee8d..8de5056c4ade4e561662222e496cb5b8b6bc1695 100644 (file)
@@ -285,7 +285,7 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
 
 static int tiny_spi_probe(struct platform_device *pdev)
 {
-       struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
+       struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev);
        struct tiny_spi *hw;
        struct spi_master *master;
        struct resource *res;
index ee25670f8cfd127341fff7ddc16562a7e512507d..b0e1d88f1635e66e63afd82ce95d108a4e03746c 100644 (file)
@@ -512,7 +512,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev)
         * You should allocate this with ioremap() before initializing
         * the SPI.
         */
-       spi100k->base = (void __iomem *) pdev->dev.platform_data;
+       spi100k->base = (void __iomem *)dev_get_platdata(&pdev->dev);
 
        INIT_WORK(&spi100k->work, omap1_spi100k_work);
 
index 5994039758debd91acd7fa1bd238cf3e85a8b790..fc190a5a0badd03d9037bd04986f247c500049fe 100644 (file)
@@ -1340,7 +1340,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
                if (of_get_property(node, "ti,pindir-d0-out-d1-in", NULL))
                        mcspi->pin_dir = MCSPI_PINDIR_D0_OUT_D1_IN;
        } else {
-               pdata = pdev->dev.platform_data;
+               pdata = dev_get_platdata(&pdev->dev);
                master->num_chipselect = pdata->num_cs;
                if (pdev->id != -1)
                        master->bus_num = pdev->id;
index abef061fb84af1537afde292373604be6d1e85b1..4b564b74c99c7a16b7e4fb2074a587143b5fe3dc 100644 (file)
@@ -2091,7 +2091,8 @@ pl022_platform_data_dt_get(struct device *dev)
 static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
 {
        struct device *dev = &adev->dev;
-       struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
+       struct pl022_ssp_controller *platform_info =
+                       dev_get_platdata(&adev->dev);
        struct spi_master *master;
        struct pl022 *pl022 = NULL;     /*Data for this driver */
        struct device_node *np = adev->dev.of_node;
index 00c32320dce87c0adb66eca0eef65e9d2c417e2c..57de139f76dcc8a08f984f85e089b130dc11aa1a 100644 (file)
@@ -666,8 +666,8 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
 static int rspi_request_dma(struct rspi_data *rspi,
                                      struct platform_device *pdev)
 {
+       struct rspi_plat_data *rspi_pd = dev_get_platdata(&pdev->dev);
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
        dma_cap_mask_t mask;
        struct dma_slave_config cfg;
        int ret;
index 68910b3101525e88bf9fcf675f7755ef5d790a04..ce318d95a6ee8cb619d80f4a74ede5c377b024f4 100644 (file)
@@ -525,7 +525,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
        memset(hw, 0, sizeof(struct s3c24xx_spi));
 
        hw->master = spi_master_get(master);
-       hw->pdata = pdata = pdev->dev.platform_data;
+       hw->pdata = pdata = dev_get_platdata(&pdev->dev);
        hw->dev = &pdev->dev;
 
        if (pdata == NULL) {
@@ -690,7 +690,7 @@ static int s3c24xx_spi_remove(struct platform_device *dev)
 
 static int s3c24xx_spi_suspend(struct device *dev)
 {
-       struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
+       struct s3c24xx_spi *hw = dev_get_drvdata(dev);
 
        if (hw->pdata && hw->pdata->gpio_setup)
                hw->pdata->gpio_setup(hw->pdata, 0);
@@ -701,7 +701,7 @@ static int s3c24xx_spi_suspend(struct device *dev)
 
 static int s3c24xx_spi_resume(struct device *dev)
 {
-       struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev));
+       struct s3c24xx_spi *hw = dev_get_drvdata(dev);
 
        s3c24xx_spi_initialsetup(hw);
        return 0;
index 63e2070c6c14aa8e39a64a850248e07a38546708..2465d6d35b068fa5158073a515ca562973ffc239 100644 (file)
@@ -1275,7 +1275,7 @@ static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
 #else
 static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
 {
-       return dev->platform_data;
+       return dev_get_platdata(dev);
 }
 #endif
 
@@ -1300,7 +1300,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
        struct resource *mem_res;
        struct resource *res;
        struct s3c64xx_spi_driver_data *sdd;
-       struct s3c64xx_spi_info *sci = pdev->dev.platform_data;
+       struct s3c64xx_spi_info *sci = dev_get_platdata(&pdev->dev);
        struct spi_master *master;
        int ret, irq;
        char clk_name[16];
index 2bc5a6b86300bfdd2896332832a8a1058cd28e8d..cbc7f2216c16383346bd3ed3d52518980300b360 100644 (file)
@@ -645,7 +645,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        if (pdev->dev.of_node)
                p->info = sh_msiof_spi_parse_dt(&pdev->dev);
        else
-               p->info = pdev->dev.platform_data;
+               p->info = dev_get_platdata(&pdev->dev);
 
        if (!p->info) {
                dev_err(&pdev->dev, "failed to obtain device info\n");
index 097e506042bee82762e729d48cd515bc62b9146b..8eefeb6007dfef67f8bcb5f8c6ad87ed5b3c68c8 100644 (file)
@@ -130,7 +130,7 @@ static int sh_sci_spi_probe(struct platform_device *dev)
        sp = spi_master_get_devdata(master);
 
        platform_set_drvdata(dev, sp);
-       sp->info = dev->dev.platform_data;
+       sp->info = dev_get_platdata(&dev->dev);
 
        /* setup spi bitbang adaptor */
        sp->bitbang.master = spi_master_get(master);
index fc20bcfd90c30dd7bf90faa9eb4cd8785822b38e..fc5081ab3677b94df8fc3c4133228f5c83371dbe 100644 (file)
@@ -599,8 +599,7 @@ static int  spi_sirfsoc_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int spi_sirfsoc_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct spi_master *master = platform_get_drvdata(pdev);
+       struct spi_master *master = dev_get_drvdata(dev);
        struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
 
        clk_disable(sspi->clk);
@@ -609,8 +608,7 @@ static int spi_sirfsoc_suspend(struct device *dev)
 
 static int spi_sirfsoc_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct spi_master *master = platform_get_drvdata(pdev);
+       struct spi_master *master = dev_get_drvdata(dev);
        struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
 
        clk_enable(sspi->clk);
index 10606fcc6efc81bca1fb63cd696cf393290253c1..7d20e121e4c1dfb521d6cf110f3eba7e870d00d5 100644 (file)
@@ -283,7 +283,7 @@ static int ti_ssp_spi_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        int error = 0;
 
-       pdata = dev->platform_data;
+       pdata = dev_get_platdata(dev);
        if (!pdata) {
                dev_err(dev, "platform data not found\n");
                return -EINVAL;
index 6b0874d782ed7aa1c9cd569637500e12a1d74dd1..b5a70e3fecb77ba50e5630dffe5b6493ede4744d 100644 (file)
@@ -247,7 +247,7 @@ static int tle62x0_probe(struct spi_device *spi)
        int ptr;
        int ret;
 
-       pdata = spi->dev.platform_data;
+       pdata = dev_get_platdata(&spi->dev);
        if (pdata == NULL) {
                dev_err(&spi->dev, "no device data specified\n");
                return -EINVAL;
index 09a9428525934e2e56732e89202680102295dd9b..08ea84a6eb3283418484d4012298271ec6ab77ae 100644 (file)
@@ -80,10 +80,9 @@ struct xilinx_spi {
        /* bitbang has to be first */
        struct spi_bitbang bitbang;
        struct completion done;
-       struct resource mem; /* phys mem */
        void __iomem    *regs;  /* virt. address of the control registers */
 
-       u32             irq;
+       int             irq;
 
        u8 *rx_ptr;             /* pointer in the Tx buffer */
        const u8 *tx_ptr;       /* pointer in the Rx buffer */
@@ -355,17 +354,34 @@ static const struct of_device_id xilinx_spi_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
 
-struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
-       u32 irq, s16 bus_num, int num_cs, int bits_per_word)
+static int xilinx_spi_probe(struct platform_device *pdev)
 {
-       struct spi_master *master;
        struct xilinx_spi *xspi;
-       int ret;
+       struct xspi_platform_data *pdata;
+       struct resource *res;
+       int ret, num_cs = 0, bits_per_word = 8;
+       struct spi_master *master;
        u32 tmp;
+       u8 i;
+
+       pdata = dev_get_platdata(&pdev->dev);
+       if (pdata) {
+               num_cs = pdata->num_chipselect;
+               bits_per_word = pdata->bits_per_word;
+       } else {
+               of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits",
+                                         &num_cs);
+       }
 
-       master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
+       if (!num_cs) {
+               dev_err(&pdev->dev,
+                       "Missing slave select configuration data\n");
+               return -EINVAL;
+       }
+
+       master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi));
        if (!master)
-               return NULL;
+               return -ENODEV;
 
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA;
@@ -378,22 +394,16 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
        xspi->bitbang.master->setup = xilinx_spi_setup;
        init_completion(&xspi->done);
 
-       if (!request_mem_region(mem->start, resource_size(mem),
-               XILINX_SPI_NAME))
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       xspi->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(xspi->regs)) {
+               ret = PTR_ERR(xspi->regs);
                goto put_master;
-
-       xspi->regs = ioremap(mem->start, resource_size(mem));
-       if (xspi->regs == NULL) {
-               dev_warn(dev, "ioremap failure\n");
-               goto map_failed;
        }
 
-       master->bus_num = bus_num;
+       master->bus_num = pdev->dev.id;
        master->num_chipselect = num_cs;
-       master->dev.of_node = dev->of_node;
-
-       xspi->mem = *mem;
-       xspi->irq = irq;
+       master->dev.of_node = pdev->dev.of_node;
 
        /*
         * Detect endianess on the IP via loop bit in CR. Detection
@@ -423,113 +433,63 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
        } else if (xspi->bits_per_word == 32) {
                xspi->tx_fn = xspi_tx32;
                xspi->rx_fn = xspi_rx32;
-       } else
-               goto unmap_io;
-
+       } else {
+               ret = -EINVAL;
+               goto put_master;
+       }
 
        /* SPI controller initializations */
        xspi_init_hw(xspi);
 
+       xspi->irq = platform_get_irq(pdev, 0);
+       if (xspi->irq < 0) {
+               ret = xspi->irq;
+               goto put_master;
+       }
+
        /* Register for SPI Interrupt */
-       ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+       ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0,
+                              dev_name(&pdev->dev), xspi);
        if (ret)
-               goto unmap_io;
+               goto put_master;
 
        ret = spi_bitbang_start(&xspi->bitbang);
        if (ret) {
-               dev_err(dev, "spi_bitbang_start FAILED\n");
-               goto free_irq;
-       }
-
-       dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
-               (unsigned long long)mem->start, xspi->regs, xspi->irq);
-       return master;
-
-free_irq:
-       free_irq(xspi->irq, xspi);
-unmap_io:
-       iounmap(xspi->regs);
-map_failed:
-       release_mem_region(mem->start, resource_size(mem));
-put_master:
-       spi_master_put(master);
-       return NULL;
-}
-EXPORT_SYMBOL(xilinx_spi_init);
-
-void xilinx_spi_deinit(struct spi_master *master)
-{
-       struct xilinx_spi *xspi;
-
-       xspi = spi_master_get_devdata(master);
-
-       spi_bitbang_stop(&xspi->bitbang);
-       free_irq(xspi->irq, xspi);
-       iounmap(xspi->regs);
-
-       release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
-       spi_master_put(xspi->bitbang.master);
-}
-EXPORT_SYMBOL(xilinx_spi_deinit);
-
-static int xilinx_spi_probe(struct platform_device *dev)
-{
-       struct xspi_platform_data *pdata;
-       struct resource *r;
-       int irq, num_cs = 0, bits_per_word = 8;
-       struct spi_master *master;
-       u8 i;
-
-       pdata = dev->dev.platform_data;
-       if (pdata) {
-               num_cs = pdata->num_chipselect;
-               bits_per_word = pdata->bits_per_word;
-       }
-
-#ifdef CONFIG_OF
-       if (dev->dev.of_node) {
-               const __be32 *prop;
-               int len;
-
-               /* number of slave select bits is required */
-               prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits",
-                                      &len);
-               if (prop && len >= sizeof(*prop))
-                       num_cs = __be32_to_cpup(prop);
-       }
-#endif
-
-       if (!num_cs) {
-               dev_err(&dev->dev, "Missing slave select configuration data\n");
-               return -EINVAL;
+               dev_err(&pdev->dev, "spi_bitbang_start FAILED\n");
+               goto put_master;
        }
 
-
-       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!r)
-               return -ENODEV;
-
-       irq = platform_get_irq(dev, 0);
-       if (irq < 0)
-               return -ENXIO;
-
-       master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs,
-                                bits_per_word);
-       if (!master)
-               return -ENODEV;
+       dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n",
+               (unsigned long long)res->start, xspi->regs, xspi->irq);
 
        if (pdata) {
                for (i = 0; i < pdata->num_devices; i++)
                        spi_new_device(master, pdata->devices + i);
        }
 
-       platform_set_drvdata(dev, master);
+       platform_set_drvdata(pdev, master);
        return 0;
+
+put_master:
+       spi_master_put(master);
+
+       return ret;
 }
 
-static int xilinx_spi_remove(struct platform_device *dev)
+static int xilinx_spi_remove(struct platform_device *pdev)
 {
-       xilinx_spi_deinit(platform_get_drvdata(dev));
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct xilinx_spi *xspi = spi_master_get_devdata(master);
+       void __iomem *regs_base = xspi->regs;
+
+       spi_bitbang_stop(&xspi->bitbang);
+
+       /* Disable all the interrupts just in case */
+       xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
+       /* Disable the global IPIF interrupt */
+       xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET);
+
+       spi_master_put(xspi->bitbang.master);
 
        return 0;
 }