spi-imx: Add mx25 support
[pandora-kernel.git] / drivers / spi / spi_imx.c
index b1f530f..4c9b133 100644 (file)
@@ -44,6 +44,9 @@
 #define MXC_CSPIINT            0x0c
 #define MXC_RESET              0x1c
 
+#define MX3_CSPISTAT           0x14
+#define MX3_CSPISTAT_RR                (1 << 3)
+
 /* generic defines to abstract from the different register layouts */
 #define MXC_INT_RR     (1 << 0) /* Receive data ready interrupt */
 #define MXC_INT_TE     (1 << 1) /* Transmit FIFO empty interrupt */
@@ -205,7 +208,7 @@ static int mx31_config(struct spi_imx_data *spi_imx,
 
        if (cpu_is_mx31())
                reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT;
-       else if (cpu_is_mx35()) {
+       else if (cpu_is_mx25() || cpu_is_mx35()) {
                reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT;
                reg |= MX31_CSPICTRL_SSCTL;
        }
@@ -219,7 +222,7 @@ static int mx31_config(struct spi_imx_data *spi_imx,
        if (config->cs < 0) {
                if (cpu_is_mx31())
                        reg |= (config->cs + 32) << MX31_CSPICTRL_CS_SHIFT;
-               else if (cpu_is_mx35())
+               else if (cpu_is_mx25() || cpu_is_mx35())
                        reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT;
        }
 
@@ -354,43 +357,14 @@ static int mx1_rx_available(struct spi_imx_data *spi_imx)
 static void spi_imx_chipselect(struct spi_device *spi, int is_active)
 {
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
-       unsigned int cs = 0;
        int gpio = spi_imx->chipselect[spi->chip_select];
-       struct spi_imx_config config;
-
-       if (spi->mode & SPI_CS_HIGH)
-               cs = 1;
+       int active = is_active != BITBANG_CS_INACTIVE;
+       int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);
 
-       if (is_active == BITBANG_CS_INACTIVE) {
-               if (gpio >= 0)
-                       gpio_set_value(gpio, !cs);
+       if (gpio < 0)
                return;
-       }
-
-       config.bpw = spi->bits_per_word;
-       config.speed_hz = spi->max_speed_hz;
-       config.mode = spi->mode;
-       config.cs = spi_imx->chipselect[spi->chip_select];
-
-       spi_imx->config(spi_imx, &config);
-
-       /* Initialize the functions for transfer */
-       if (config.bpw <= 8) {
-               spi_imx->rx = spi_imx_buf_rx_u8;
-               spi_imx->tx = spi_imx_buf_tx_u8;
-       } else if (config.bpw <= 16) {
-               spi_imx->rx = spi_imx_buf_rx_u16;
-               spi_imx->tx = spi_imx_buf_tx_u16;
-       } else if (config.bpw <= 32) {
-               spi_imx->rx = spi_imx_buf_rx_u32;
-               spi_imx->tx = spi_imx_buf_tx_u32;
-       } else
-               BUG();
 
-       if (gpio >= 0)
-               gpio_set_value(gpio, cs);
-
-       return;
+       gpio_set_value(gpio, dev_is_lowactive ^ active);
 }
 
 static void spi_imx_push(struct spi_imx_data *spi_imx)
@@ -442,6 +416,27 @@ static int spi_imx_setupxfer(struct spi_device *spi,
        config.bpw = t ? t->bits_per_word : spi->bits_per_word;
        config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
        config.mode = spi->mode;
+       config.cs = spi_imx->chipselect[spi->chip_select];
+
+       if (!config.speed_hz)
+               config.speed_hz = spi->max_speed_hz;
+       if (!config.bpw)
+               config.bpw = spi->bits_per_word;
+       if (!config.speed_hz)
+               config.speed_hz = spi->max_speed_hz;
+
+       /* Initialize the functions for transfer */
+       if (config.bpw <= 8) {
+               spi_imx->rx = spi_imx_buf_rx_u8;
+               spi_imx->tx = spi_imx_buf_tx_u8;
+       } else if (config.bpw <= 16) {
+               spi_imx->rx = spi_imx_buf_rx_u16;
+               spi_imx->tx = spi_imx_buf_tx_u16;
+       } else if (config.bpw <= 32) {
+               spi_imx->rx = spi_imx_buf_rx_u32;
+               spi_imx->tx = spi_imx_buf_tx_u32;
+       } else
+               BUG();
 
        spi_imx->config(spi_imx, &config);
 
@@ -471,12 +466,15 @@ static int spi_imx_transfer(struct spi_device *spi,
 
 static int spi_imx_setup(struct spi_device *spi)
 {
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
+       struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+       int gpio = spi_imx->chipselect[spi->chip_select];
 
        pr_debug("%s: mode %d, %u bpw, %d hz\n", __func__,
                 spi->mode, spi->bits_per_word, spi->max_speed_hz);
 
+       if (gpio >= 0)
+               gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+
        spi_imx_chipselect(spi, BITBANG_CS_INACTIVE);
 
        return 0;
@@ -518,14 +516,14 @@ static int __init spi_imx_probe(struct platform_device *pdev)
                        continue;
                ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
                if (ret) {
-                       i--;
-                       while (i > 0)
+                       while (i > 0) {
+                               i--;
                                if (spi_imx->chipselect[i] >= 0)
-                                       gpio_free(spi_imx->chipselect[i--]);
-                       dev_err(&pdev->dev, "can't get cs gpios");
+                                       gpio_free(spi_imx->chipselect[i]);
+                       }
+                       dev_err(&pdev->dev, "can't get cs gpios\n");
                        goto out_master_put;
                }
-               gpio_direction_output(spi_imx->chipselect[i], 1);
        }
 
        spi_imx->bitbang.chipselect = spi_imx_chipselect;
@@ -533,6 +531,7 @@ static int __init spi_imx_probe(struct platform_device *pdev)
        spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
        spi_imx->bitbang.master->setup = spi_imx_setup;
        spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
+       spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
        init_completion(&spi_imx->xfer_done);
 
@@ -556,7 +555,7 @@ static int __init spi_imx_probe(struct platform_device *pdev)
        }
 
        spi_imx->irq = platform_get_irq(pdev, 0);
-       if (!spi_imx->irq) {
+       if (spi_imx->irq <= 0) {
                ret = -EINVAL;
                goto out_iounmap;
        }
@@ -567,7 +566,7 @@ static int __init spi_imx_probe(struct platform_device *pdev)
                goto out_iounmap;
        }
 
-       if (cpu_is_mx31() || cpu_is_mx35()) {
+       if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) {
                spi_imx->intctrl = mx31_intctrl;
                spi_imx->config = mx31_config;
                spi_imx->trigger = mx31_trigger;
@@ -595,9 +594,14 @@ static int __init spi_imx_probe(struct platform_device *pdev)
        clk_enable(spi_imx->clk);
        spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
 
-       if (!cpu_is_mx31() || !cpu_is_mx35())
+       if (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
                writel(1, spi_imx->base + MXC_RESET);
 
+       /* drain receive buffer */
+       if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
+               while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
+                       readl(spi_imx->base + MXC_CSPIRXDATA);
+
        spi_imx->intctrl(spi_imx, 0);
 
        ret = spi_bitbang_start(&spi_imx->bitbang);