/*
- * 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>
#define DRV_NAME "bfin-spi"
#define DRV_AUTHOR "Bryan Wu, Luke Yang"
-#define DRV_DESC "Blackfin BF5xx on-chip SPI Contoller Driver"
+#define DRV_DESC "Blackfin BF5xx on-chip SPI Controller Driver"
#define DRV_VERSION "1.0"
MODULE_AUTHOR(DRV_AUTHOR);
struct spi_master *master;
/* Regs base of SPI controller */
- u32 regs_base;
+ void __iomem *regs_base;
+
+ /* Pin request list */
+ u16 *pin_req;
/* BFIN hookup */
struct bfin5xx_spi_master *master_info;
u8 enable_dma;
u8 bits_per_word; /* 8 or 16 */
u8 cs_change_per_word;
- u8 cs_chg_udelay;
+ u16 cs_chg_udelay; /* Some devices require > 255usec delay */
void (*write) (struct driver_data *);
void (*read) (struct driver_data *);
void (*duplex) (struct driver_data *);
/* wait for stop and clear stat */
while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && limit--)
- continue;
+ cpu_relax();
write_STAT(drv_data, BIT_STAT_CLR);
flag |= (chip->flag << 8);
write_FLAG(drv_data, flag);
+
+ /* Move delay here for consistency */
+ if (chip->cs_chg_udelay)
+ udelay(chip->cs_chg_udelay);
}
#define MAX_SPI_SSEL 7
/* stop controller and re-config current chip*/
-static int restore_state(struct driver_data *drv_data)
+static void restore_state(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
- int ret = 0;
/* Clear status and disable clock */
write_STAT(drv_data, BIT_STAT_CLR);
dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
/* Load the registers */
- cs_deactive(drv_data, chip);
- write_BAUD(drv_data, chip->baud);
- chip->ctl_reg &= (~BIT_CTL_TIMOD);
- chip->ctl_reg |= (chip->width << 8);
write_CTRL(drv_data, chip->ctl_reg);
+ write_BAUD(drv_data, chip->baud);
bfin_spi_enable(drv_data);
-
- if (ret)
- dev_dbg(&drv_data->pdev->dev,
- ": request chip select number %d failed\n",
- chip->chip_select_num);
-
- return ret;
+ cs_active(drv_data, chip);
}
/* used to kick off transfer in rx mode */
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(drv_data, 0);
while ((read_STAT(drv_data) & BIT_STAT_TXS))
- continue;
+ cpu_relax();
drv_data->tx += n_bytes;
}
}
while (drv_data->rx < drv_data->rx_end) {
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
dummy_read(drv_data);
drv_data->rx += n_bytes;
}
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))
- continue;
-
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
while (read_STAT(drv_data) & BIT_STAT_TXS)
- continue;
+ 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)
{
struct chip_data *chip = drv_data->cur_chip;
- /* poll for SPI completion before start */
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
-
while (drv_data->tx < drv_data->tx_end) {
cs_active(drv_data, chip);
write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
while (read_STAT(drv_data) & BIT_STAT_TXS)
- continue;
+ cpu_relax();
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ cpu_relax();
+
cs_deactive(drv_data, chip);
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
++drv_data->tx;
}
}
/* poll for SPI completion before start */
while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
+ cpu_relax();
/* clear TDBR buffer before read(else it will be shifted out) */
write_TDBR(drv_data, 0xFFFF);
while (drv_data->rx < drv_data->rx_end - 1) {
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
++drv_data->rx;
}
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u8 *) (drv_data->rx) = read_SHAW(drv_data);
++drv_data->rx;
}
{
struct chip_data *chip = drv_data->cur_chip;
- /* poll for SPI completion before start */
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
-
- /* clear TDBR buffer before read(else it will be shifted out) */
- write_TDBR(drv_data, 0xFFFF);
+ while (drv_data->rx < drv_data->rx_end) {
+ cs_active(drv_data, chip);
+ read_RDBR(drv_data); /* kick off */
- cs_active(drv_data, chip);
- dummy_read(drv_data);
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
+ cpu_relax();
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ cpu_relax();
- while (drv_data->rx < drv_data->rx_end - 1) {
+ *(u8 *) (drv_data->rx) = read_SHAW(drv_data);
cs_deactive(drv_data, chip);
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
-
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
- cs_active(drv_data, chip);
- *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
++drv_data->rx;
}
- cs_deactive(drv_data, chip);
-
- while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
- *(u8 *) (drv_data->rx) = read_SHAW(drv_data);
- ++drv_data->rx;
}
static void u8_duplex(struct driver_data *drv_data)
{
- /* poll for SPI completion before start */
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
-
/* 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)
- continue;
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ cpu_relax();
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
++drv_data->rx;
++drv_data->tx;
{
struct chip_data *chip = drv_data->cur_chip;
- /* poll for SPI completion before start */
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
-
while (drv_data->rx < drv_data->rx_end) {
cs_active(drv_data, chip);
write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
- while (read_STAT(drv_data) & BIT_STAT_TXS)
- continue;
+
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ cpu_relax();
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+
cs_deactive(drv_data, chip);
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
++drv_data->rx;
++drv_data->tx;
}
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))
- continue;
-
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
while ((read_STAT(drv_data) & BIT_STAT_TXS))
- continue;
+ 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))
- continue;
-
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))
- continue;
+ cpu_relax();
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ cpu_relax();
+
cs_deactive(drv_data, chip);
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
drv_data->tx += 2;
}
}
/* poll for SPI completion before start */
while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
+ cpu_relax();
/* clear TDBR buffer before read(else it will be shifted out) */
write_TDBR(drv_data, 0xFFFF);
while (drv_data->rx < (drv_data->rx_end - 2)) {
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
drv_data->rx += 2;
}
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u16 *) (drv_data->rx) = read_SHAW(drv_data);
drv_data->rx += 2;
}
/* poll for SPI completion before start */
while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
+ cpu_relax();
/* clear TDBR buffer before read(else it will be shifted out) */
write_TDBR(drv_data, 0xFFFF);
cs_active(drv_data, chip);
dummy_read(drv_data);
- while (drv_data->rx < drv_data->rx_end) {
+ while (drv_data->rx < drv_data->rx_end - 2) {
cs_deactive(drv_data, chip);
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
-
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
cs_active(drv_data, chip);
*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
drv_data->rx += 2;
cs_deactive(drv_data, chip);
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u16 *) (drv_data->rx) = read_SHAW(drv_data);
drv_data->rx += 2;
}
static void u16_duplex(struct driver_data *drv_data)
{
- /* poll for SPI completion before start */
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
-
/* 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)
- continue;
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ cpu_relax();
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
drv_data->rx += 2;
drv_data->tx += 2;
{
struct chip_data *chip = drv_data->cur_chip;
- /* poll for SPI completion before start */
- while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
-
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)
- continue;
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+ cpu_relax();
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
- continue;
+ cpu_relax();
*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+
cs_deactive(drv_data, chip);
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
drv_data->rx += 2;
drv_data->tx += 2;
}
static irqreturn_t dma_irq_handler(int irq, void *dev_id)
{
- struct driver_data *drv_data = (struct driver_data *)dev_id;
+ struct driver_data *drv_data = dev_id;
struct chip_data *chip = drv_data->cur_chip;
struct spi_message *msg = drv_data->cur_msg;
/* Wait for DMA to complete */
while (get_dma_curr_irqstat(drv_data->dma_channel) & DMA_RUN)
- continue;
+ cpu_relax();
/*
* wait for the last transaction shifted out. HRM states:
if (drv_data->tx != NULL) {
while ((read_STAT(drv_data) & TXS) ||
(read_STAT(drv_data) & TXS))
- continue;
+ cpu_relax();
}
while (!(read_STAT(drv_data) & SPIF))
- continue;
+ cpu_relax();
msg->actual_length += drv_data->len_in_bytes;
message = drv_data->cur_msg;
transfer = drv_data->cur_transfer;
chip = drv_data->cur_chip;
+
/*
* if msg is error or done, report it back using complete() callback
*/
drv_data->len_in_bytes = transfer->len;
drv_data->cs_change = transfer->cs_change;
- width = chip->width;
+ /* Bits per word setup */
+ switch (transfer->bits_per_word) {
+ case 8:
+ drv_data->n_bytes = 1;
+ width = CFG_SPI_WORDSIZE8;
+ drv_data->read = chip->cs_change_per_word ?
+ u8_cs_chg_reader : u8_reader;
+ drv_data->write = chip->cs_change_per_word ?
+ u8_cs_chg_writer : u8_writer;
+ drv_data->duplex = chip->cs_change_per_word ?
+ u8_cs_chg_duplex : u8_duplex;
+ break;
+
+ case 16:
+ drv_data->n_bytes = 2;
+ width = CFG_SPI_WORDSIZE16;
+ drv_data->read = chip->cs_change_per_word ?
+ u16_cs_chg_reader : u16_reader;
+ drv_data->write = chip->cs_change_per_word ?
+ u16_cs_chg_writer : u16_writer;
+ drv_data->duplex = chip->cs_change_per_word ?
+ u16_cs_chg_duplex : u16_duplex;
+ break;
+
+ default:
+ /* No change, the same as default setting */
+ drv_data->n_bytes = chip->n_bytes;
+ width = chip->width;
+ drv_data->write = drv_data->tx ? chip->write : null_writer;
+ drv_data->read = drv_data->rx ? chip->read : null_reader;
+ drv_data->duplex = chip->duplex ? chip->duplex : null_writer;
+ break;
+ }
+ cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
+ cr |= (width << 8);
+ write_CTRL(drv_data, cr);
+
if (width == CFG_SPI_WORDSIZE16) {
drv_data->len = (transfer->len) >> 1;
} else {
drv_data->len = transfer->len;
}
- drv_data->write = drv_data->tx ? chip->write : null_writer;
- drv_data->read = drv_data->rx ? chip->read : null_reader;
- drv_data->duplex = chip->duplex ? chip->duplex : null_writer;
- 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 */
message->state = RUNNING_STATE;
dma_config = 0;
+ /* Speed setup (surely valid because already checked) */
+ if (transfer->speed_hz)
+ write_BAUD(drv_data, hz_to_spi_baud(transfer->speed_hz));
+ else
+ write_BAUD(drv_data, chip->baud);
+
write_STAT(drv_data, BIT_STAT_CLR);
cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
cs_active(drv_data, chip);
disable_dma(drv_data->dma_channel);
clear_dma_irqstat(drv_data->dma_channel);
+ bfin_spi_disable(drv_data);
/* config dma channel */
dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
/* poll for SPI completion before start */
while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
- continue;
+ cpu_relax();
/* dirty hack for autobuffer DMA mode */
if (drv_data->tx_dma == 0xFFFF) {
dev_dbg(&drv_data->pdev->dev,
"doing autobuffer DMA out.\n");
- /* set SPI transfer mode */
- write_CTRL(drv_data, (cr | CFG_SPI_DMAWRITE));
-
/* no irq in autobuffer mode */
dma_config =
(DMAFLOW_AUTO | RESTART | dma_width | DI_EN);
(unsigned long)drv_data->tx);
enable_dma(drv_data->dma_channel);
- /* just return here, there can only be one transfer in this mode */
+ /* start SPI transfer */
+ write_CTRL(drv_data,
+ (cr | CFG_SPI_DMAWRITE | BIT_CTL_ENABLE));
+
+ /* just return here, there can only be one transfer
+ * in this mode
+ */
message->status = 0;
giveback(drv_data);
return;
/* set transfer mode, and enable SPI */
dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n");
- /* set SPI transfer mode */
- write_CTRL(drv_data, (cr | CFG_SPI_DMAREAD));
-
/* clear tx reg soformer data is not shifted out */
write_TDBR(drv_data, 0xFFFF);
(unsigned long)drv_data->rx);
enable_dma(drv_data->dma_channel);
+ /* start SPI transfer */
+ write_CTRL(drv_data,
+ (cr | CFG_SPI_DMAREAD | BIT_CTL_ENABLE));
+
} else if (drv_data->tx != NULL) {
dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");
- /* set SPI transfer mode */
- write_CTRL(drv_data, (cr | CFG_SPI_DMAWRITE));
-
/* start dma */
dma_enable_irq(drv_data->dma_channel);
dma_config = (RESTART | dma_width | DI_EN);
set_dma_start_addr(drv_data->dma_channel,
(unsigned long)drv_data->tx);
enable_dma(drv_data->dma_channel);
+
+ /* start SPI transfer */
+ write_CTRL(drv_data,
+ (cr | CFG_SPI_DMAWRITE | BIT_CTL_ENABLE));
}
} else {
/* IO mode write then read */
/* Setup the SSP using the per chip configuration */
drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
- if (restore_state(drv_data)) {
- spin_unlock_irqrestore(&drv_data->lock, flags);
- return;
- };
+ restore_state(drv_data);
list_del_init(&drv_data->cur_msg->queue);
if ((chip->chip_select_num > 0)
&& (chip->chip_select_num <= spi->master->num_chipselect))
peripheral_request(ssel[spi->master->bus_num]
- [chip->chip_select_num-1], DRV_NAME);
+ [chip->chip_select_num-1], spi->modalias);
+
+ cs_deactive(drv_data, chip);
return 0;
}
return 0;
}
-static int setup_pin_mux(int action, int bus_num)
-{
-
- u16 pin_req[3][4] = {
- {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
- {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
- {P_SPI2_SCK, P_SPI2_MISO, P_SPI2_MOSI, 0},
- };
-
- if (action) {
- if (peripheral_request_list(pin_req[bus_num], DRV_NAME))
- return -EFAULT;
- } else {
- peripheral_free_list(pin_req[bus_num]);
- }
-
- return 0;
-}
-
static int __init bfin5xx_spi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
drv_data->master = master;
drv_data->master_info = platform_info;
drv_data->pdev = pdev;
+ drv_data->pin_req = platform_info->pin_req;
master->bus_num = pdev->id;
master->num_chipselect = platform_info->num_chipselect;
goto out_error_get_res;
}
- drv_data->regs_base = (u32) ioremap(res->start,
- (res->end - res->start + 1));
- if (!drv_data->regs_base) {
+ drv_data->regs_base = ioremap(res->start, (res->end - res->start + 1));
+ if (drv_data->regs_base == NULL) {
dev_err(dev, "Cannot map IO\n");
status = -ENXIO;
goto out_error_ioremap;
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);
goto out_error_queue_alloc;
}
- if (setup_pin_mux(1, master->bus_num)) {
- dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
- goto out_error;
- }
-
- dev_info(dev, "%s, Version %s, regs_base@0x%08x, dma channel@%d\n",
+ 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);
return status;
iounmap((void *) drv_data->regs_base);
out_error_ioremap:
out_error_get_res:
-out_error:
spi_master_put(master);
return status;
/* Disconnect from the SPI framework */
spi_unregister_master(drv_data->master);
- setup_pin_mux(0, drv_data->master->bus_num);
+ peripheral_free_list(drv_data->pin_req);
/* Prevent double remove */
platform_set_drvdata(pdev, NULL);
#define bfin5xx_spi_resume NULL
#endif /* CONFIG_PM */
-MODULE_ALIAS("bfin-spi-master"); /* for platform bus hotplug */
+MODULE_ALIAS("platform:bfin-spi");
static struct platform_driver bfin5xx_spi_driver = {
.driver = {
.name = DRV_NAME,