netns xfrm: fix "ip xfrm state|policy count" misreport
[safe/jmp/linux-2.6] / drivers / spi / spi_imx.c
index b91a5a8..1893f1e 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,7 @@ 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;
@@ -450,6 +425,19 @@ static int spi_imx_setupxfer(struct spi_device *spi,
        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);
 
        return 0;
@@ -481,9 +469,6 @@ static int spi_imx_setup(struct spi_device *spi)
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
        int gpio = spi_imx->chipselect[spi->chip_select];
 
-       if (!spi->bits_per_word)
-               spi->bits_per_word = 8;
-
        pr_debug("%s: mode %d, %u bpw, %d hz\n", __func__,
                 spi->mode, spi->bits_per_word, spi->max_speed_hz);
 
@@ -499,7 +484,7 @@ static void spi_imx_cleanup(struct spi_device *spi)
 {
 }
 
-static int __init spi_imx_probe(struct platform_device *pdev)
+static int __devinit spi_imx_probe(struct platform_device *pdev)
 {
        struct spi_imx_master *mxc_platform_info;
        struct spi_master *master;
@@ -507,7 +492,7 @@ static int __init spi_imx_probe(struct platform_device *pdev)
        struct resource *res;
        int i, ret;
 
-       mxc_platform_info = (struct spi_imx_master *)pdev->dev.platform_data;
+       mxc_platform_info = dev_get_platdata(&pdev->dev);
        if (!mxc_platform_info) {
                dev_err(&pdev->dev, "can't get the platform data\n");
                return -EINVAL;
@@ -531,11 +516,12 @@ 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;
                }
        }
@@ -545,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);
 
@@ -568,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;
        }
@@ -579,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;
@@ -607,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);
@@ -642,7 +634,7 @@ out_master_put:
        return ret;
 }
 
-static int __exit spi_imx_remove(struct platform_device *pdev)
+static int __devexit spi_imx_remove(struct platform_device *pdev)
 {
        struct spi_master *master = platform_get_drvdata(pdev);
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -676,7 +668,7 @@ static struct platform_driver spi_imx_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = spi_imx_probe,
-       .remove = __exit_p(spi_imx_remove),
+       .remove = __devexit_p(spi_imx_remove),
 };
 
 static int __init spi_imx_init(void)