spi: spi_bfin5xx: fix probe() sequencing
[safe/jmp/linux-2.6] / drivers / spi / spi_bfin5xx.c
index ce4692c..a4bf3af 100644 (file)
@@ -1,37 +1,11 @@
 /*
- * File:       drivers/spi/bfin5xx_spi.c
- * Maintainer:
- *             Bryan Wu <bryan.wu@analog.com>
- * Original Author:
- *             Luke Yang (Analog Devices Inc.)
- *
- * Created:    March. 10th 2006
- * Description:        SPI controller driver for Blackfin BF5xx
- * Bugs:       Enter bugs at http://blackfin.uclinux.org/
- *
- * Modified:
- *     March 10, 2006  bfin5xx_spi.c Created. (Luke Yang)
- *      August 7, 2006  added full duplex mode (Axel Weiss & Luke Yang)
- *      July  17, 2007  add support for BF54x SPI0 controller (Bryan Wu)
- *      July  30, 2007  add platfrom_resource interface to support multi-port
- *                      SPI controller (Bryan Wu)
+ * Blackfin On-Chip SPI Driver
  *
  * Copyright 2004-2007 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 as published by
- * the Free Software Foundation ;  either version 2, or (at your option)
- * any later version.
+ * Enter bugs at http://blackfin.uclinux.org/
  *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program ;  see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/init.h>
@@ -278,16 +252,16 @@ static void u8_writer(struct driver_data *drv_data)
        dev_dbg(&drv_data->pdev->dev,
                "cr8-s is 0x%x\n", read_STAT(drv_data));
 
-       /* poll for SPI completion before start */
-       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-               cpu_relax();
-
        while (drv_data->tx < drv_data->tx_end) {
                write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
                while (read_STAT(drv_data) & BIT_STAT_TXS)
                        cpu_relax();
                ++drv_data->tx;
        }
+
+       /* poll for SPI completion before return */
+       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+               cpu_relax();
 }
 
 static void u8_cs_chg_writer(struct driver_data *drv_data)
@@ -358,14 +332,10 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)
 
 static void u8_duplex(struct driver_data *drv_data)
 {
-       /* poll for SPI completion before start */
-       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-               cpu_relax();
-
        /* in duplex mode, clk is triggered by writing of TDBR */
        while (drv_data->rx < drv_data->rx_end) {
                write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-               while (read_STAT(drv_data) & BIT_STAT_TXS)
+               while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
                        cpu_relax();
                while (!(read_STAT(drv_data) & BIT_STAT_RXS))
                        cpu_relax();
@@ -402,32 +372,30 @@ static void u16_writer(struct driver_data *drv_data)
        dev_dbg(&drv_data->pdev->dev,
                "cr16 is 0x%x\n", read_STAT(drv_data));
 
-       /* poll for SPI completion before start */
-       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-               cpu_relax();
-
        while (drv_data->tx < drv_data->tx_end) {
                write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
                while ((read_STAT(drv_data) & BIT_STAT_TXS))
                        cpu_relax();
                drv_data->tx += 2;
        }
+
+       /* poll for SPI completion before return */
+       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+               cpu_relax();
 }
 
 static void u16_cs_chg_writer(struct driver_data *drv_data)
 {
        struct chip_data *chip = drv_data->cur_chip;
 
-       /* poll for SPI completion before start */
-       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-               cpu_relax();
-
        while (drv_data->tx < drv_data->tx_end) {
                cs_active(drv_data, chip);
 
                write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
                while ((read_STAT(drv_data) & BIT_STAT_TXS))
                        cpu_relax();
+               while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+                       cpu_relax();
 
                cs_deactive(drv_data, chip);
 
@@ -495,14 +463,10 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
 
 static void u16_duplex(struct driver_data *drv_data)
 {
-       /* poll for SPI completion before start */
-       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-               cpu_relax();
-
        /* in duplex mode, clk is triggered by writing of TDBR */
        while (drv_data->tx < drv_data->tx_end) {
                write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-               while (read_STAT(drv_data) & BIT_STAT_TXS)
+               while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
                        cpu_relax();
                while (!(read_STAT(drv_data) & BIT_STAT_RXS))
                        cpu_relax();
@@ -516,15 +480,11 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
 {
        struct chip_data *chip = drv_data->cur_chip;
 
-       /* poll for SPI completion before start */
-       while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-               cpu_relax();
-
        while (drv_data->tx < drv_data->tx_end) {
                cs_active(drv_data, chip);
 
                write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-               while (read_STAT(drv_data) & BIT_STAT_TXS)
+               while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
                        cpu_relax();
                while (!(read_STAT(drv_data) & BIT_STAT_RXS))
                        cpu_relax();
@@ -753,8 +713,8 @@ static void pump_transfers(unsigned long data)
        } else {
                drv_data->len = transfer->len;
        }
-       dev_dbg(&drv_data->pdev->dev, "transfer: ",
-               "drv_data->write is %p, chip->write is %p, null_wr is %p\n",
+       dev_dbg(&drv_data->pdev->dev,
+               "transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n",
                drv_data->write, chip->write, null_writer);
 
        /* speed and width has been set on per message */
@@ -1334,6 +1294,12 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
                goto out_error_queue_alloc;
        }
 
+       status = peripheral_request_list(drv_data->pin_req, DRV_NAME);
+       if (status != 0) {
+               dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
+               goto out_error_queue_alloc;
+       }
+
        /* Register with the SPI framework */
        platform_set_drvdata(pdev, drv_data);
        status = spi_register_master(master);
@@ -1342,12 +1308,6 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
                goto out_error_queue_alloc;
        }
 
-       status = peripheral_request_list(drv_data->pin_req, DRV_NAME);
-       if (status != 0) {
-               dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
-               goto out_error;
-       }
-
        dev_info(dev, "%s, Version %s, regs_base@%p, dma channel@%d\n",
                DRV_DESC, DRV_VERSION, drv_data->regs_base,
                drv_data->dma_channel);