2007-10-12 03:05:34

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 00/10] Blackfin SPI driver updates for 2.6.24


- add BF54x support
- add multi SPI ports support
- fixup some bugs


2007-10-12 03:06:05

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 03/10] Blackfin SPI driver: add error handing

- add error handling in SPI bus driver with selecting clients
- use proper defines to access Blackfin MMRs
- remove useless SSYNCs

Signed-off-by: Michael Hennerich <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 107 +++++++++++++++++++--------------------------
1 files changed, 45 insertions(+), 62 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 8041b89..2f46283 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -59,10 +59,9 @@ MODULE_LICENSE("GPL");

#define DEFINE_SPI_REG(reg, off) \
static inline u16 read_##reg(void) \
- { return *(volatile unsigned short*)(SPI0_REGBASE + off); } \
+ { return bfin_read16(SPI0_REGBASE + off); } \
static inline void write_##reg(u16 v) \
- {*(volatile unsigned short*)(SPI0_REGBASE + off) = v;\
- SSYNC();}
+ {bfin_write16(SPI0_REGBASE + off, v); }

DEFINE_SPI_REG(CTRL, 0x00)
DEFINE_SPI_REG(FLAG, 0x04)
@@ -145,7 +144,6 @@ static void bfin_spi_enable(struct driver_data *drv_data)

cr = read_CTRL();
write_CTRL(cr | BIT_CTL_ENABLE);
- SSYNC();
}

static void bfin_spi_disable(struct driver_data *drv_data)
@@ -154,7 +152,6 @@ static void bfin_spi_disable(struct driver_data *drv_data)

cr = read_CTRL();
write_CTRL(cr & (~BIT_CTL_ENABLE));
- SSYNC();
}

/* Caculate the SPI_BAUD register value based on input HZ */
@@ -182,52 +179,44 @@ static int flush(struct driver_data *drv_data)
return limit;
}

+#define MAX_SPI0_SSEL 7
+
/* stop controller and re-config current chip*/
-static void restore_state(struct driver_data *drv_data)
+static int restore_state(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
+ int ret = 0;
+ u16 ssel[MAX_SPI0_SSEL] = {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
+ P_SPI0_SSEL4, P_SPI0_SSEL5,
+ P_SPI0_SSEL6, P_SPI0_SSEL7,};

/* Clear status and disable clock */
write_STAT(BIT_STAT_CLR);
bfin_spi_disable(drv_data);
dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");

+ /* Load the registers */
+ write_CTRL(chip->ctl_reg);
+ write_BAUD(chip->baud);
+ write_FLAG(chip->flag);
+
if (!chip->chip_select_requested) {
+ int i = chip->chip_select_num;

- dev_dbg(&drv_data->pdev->dev,
- "chip select number is %d\n", chip->chip_select_num);
-
- switch (chip->chip_select_num) {
- case 1:
- peripheral_request(P_SPI0_SSEL1, DRV_NAME);
- break;
- case 2:
- peripheral_request(P_SPI0_SSEL2, DRV_NAME);
- break;
- case 3:
- peripheral_request(P_SPI0_SSEL3, DRV_NAME);
- break;
- case 4:
- peripheral_request(P_SPI0_SSEL4, DRV_NAME);
- break;
- case 5:
- peripheral_request(P_SPI0_SSEL5, DRV_NAME);
- break;
- case 6:
- peripheral_request(P_SPI0_SSEL6, DRV_NAME);
- break;
- case 7:
- peripheral_request(P_SPI0_SSEL7, DRV_NAME);
- break;
- }
+ dev_dbg(&drv_data->pdev->dev, "chip select number is %d\n", i);
+
+ if ((i > 0) && (i <= MAX_SPI0_SSEL))
+ ret = peripheral_request(ssel[i-1], DRV_NAME);

chip->chip_select_requested = 1;
}

- /* Load the registers */
- write_CTRL(chip->ctl_reg);
- write_BAUD(chip->baud);
- write_FLAG(chip->flag);
+ if (ret)
+ dev_dbg(&drv_data->pdev->dev,
+ ": request chip select number %d failed\n",
+ chip->chip_select_num);
+
+ return ret;
}

/* used to kick off transfer in rx mode */
@@ -285,7 +274,6 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)

while (drv_data->tx < drv_data->tx_end) {
write_FLAG(chip->flag);
- SSYNC();

write_TDBR(*(u8 *) (drv_data->tx));
while (read_STAT() & BIT_STAT_TXS)
@@ -293,13 +281,13 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)
while (!(read_STAT() & BIT_STAT_SPIF))
continue;
write_FLAG(0xFF00 | chip->flag);
- SSYNC();
+
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
++drv_data->tx;
}
write_FLAG(0xFF00);
- SSYNC();
+
}

static void u8_reader(struct driver_data *drv_data)
@@ -331,7 +319,6 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)

while (drv_data->rx < drv_data->rx_end) {
write_FLAG(chip->flag);
- SSYNC();

read_RDBR(); /* kick off */
while (!(read_STAT() & BIT_STAT_RXS))
@@ -340,13 +327,13 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)
continue;
*(u8 *) (drv_data->rx) = read_SHAW();
write_FLAG(0xFF00 | chip->flag);
- SSYNC();
+
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
++drv_data->rx;
}
write_FLAG(0xFF00);
- SSYNC();
+
}

static void u8_duplex(struct driver_data *drv_data)
@@ -370,7 +357,7 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)

while (drv_data->rx < drv_data->rx_end) {
write_FLAG(chip->flag);
- SSYNC();
+

write_TDBR(*(u8 *) (drv_data->tx));
while (!(read_STAT() & BIT_STAT_SPIF))
@@ -379,14 +366,14 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
continue;
*(u8 *) (drv_data->rx) = read_RDBR();
write_FLAG(0xFF00 | chip->flag);
- SSYNC();
+
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
++drv_data->rx;
++drv_data->tx;
}
write_FLAG(0xFF00);
- SSYNC();
+
}

static void u16_writer(struct driver_data *drv_data)
@@ -412,7 +399,6 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)

while (drv_data->tx < drv_data->tx_end) {
write_FLAG(chip->flag);
- SSYNC();

write_TDBR(*(u16 *) (drv_data->tx));
while ((read_STAT() & BIT_STAT_TXS))
@@ -420,13 +406,12 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)
while (!(read_STAT() & BIT_STAT_SPIF))
continue;
write_FLAG(0xFF00 | chip->flag);
- SSYNC();
+
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
drv_data->tx += 2;
}
write_FLAG(0xFF00);
- SSYNC();
}

static void u16_reader(struct driver_data *drv_data)
@@ -454,7 +439,6 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)

while (drv_data->rx < drv_data->rx_end) {
write_FLAG(chip->flag);
- SSYNC();

read_RDBR(); /* kick off */
while (!(read_STAT() & BIT_STAT_RXS))
@@ -463,13 +447,12 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
continue;
*(u16 *) (drv_data->rx) = read_SHAW();
write_FLAG(0xFF00 | chip->flag);
- SSYNC();
+
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
drv_data->rx += 2;
}
write_FLAG(0xFF00);
- SSYNC();
}

static void u16_duplex(struct driver_data *drv_data)
@@ -493,7 +476,6 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)

while (drv_data->tx < drv_data->tx_end) {
write_FLAG(chip->flag);
- SSYNC();

write_TDBR(*(u16 *) (drv_data->tx));
while (!(read_STAT() & BIT_STAT_SPIF))
@@ -502,14 +484,13 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
continue;
*(u16 *) (drv_data->rx) = read_RDBR();
write_FLAG(0xFF00 | chip->flag);
- SSYNC();
+
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
drv_data->rx += 2;
drv_data->tx += 2;
}
write_FLAG(0xFF00);
- SSYNC();
}

/* test if ther is more transfer to be done */
@@ -811,7 +792,6 @@ static void pump_transfers(unsigned long data)
"IO duplex: cr is 0x%x\n", cr);

write_CTRL(cr);
- SSYNC();

drv_data->duplex(drv_data);

@@ -826,7 +806,6 @@ static void pump_transfers(unsigned long data)
"IO write: cr is 0x%x\n", cr);

write_CTRL(cr);
- SSYNC();

drv_data->write(drv_data);

@@ -841,7 +820,6 @@ static void pump_transfers(unsigned long data)
"IO read: cr is 0x%x\n", cr);

write_CTRL(cr);
- SSYNC();

drv_data->read(drv_data);
if (drv_data->rx != drv_data->rx_end)
@@ -890,6 +868,14 @@ static void pump_messages(struct work_struct *work)
/* Extract head of queue */
drv_data->cur_msg = list_entry(drv_data->queue.next,
struct spi_message, queue);
+
+ /* 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;
+ };
+
list_del_init(&drv_data->cur_msg->queue);

/* Initial message state */
@@ -897,13 +883,10 @@ static void pump_messages(struct work_struct *work)
drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
struct spi_transfer, transfer_list);

- /* Setup the SSP using the per chip configuration */
- drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
- restore_state(drv_data);
dev_dbg(&drv_data->pdev->dev,
"got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
- drv_data->cur_chip->baud, drv_data->cur_chip->flag,
- drv_data->cur_chip->ctl_reg);
+ drv_data->cur_chip->baud, drv_data->cur_chip->flag,
+ drv_data->cur_chip->ctl_reg);

dev_dbg(&drv_data->pdev->dev,
"the first transfer len is %d\n",
--
1.5.3.4

2007-10-12 03:06:32

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 01/10] Blackfin SPI driver: Initial supporting BF54x in SPI driver

- support BF54x SPI0
- clean up some code
- will support multiports in the future

Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 130 +++++++++++------------
include/asm-blackfin/mach-bf548/defBF54x_base.h | 17 +++
2 files changed, 80 insertions(+), 67 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index f540ed7..2992ada 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1,17 +1,20 @@
/*
- * File: drivers/spi/bfin5xx_spi.c
- * Based on: N/A
- * Author: Luke Yang (Analog Devices Inc.)
+ * File: drivers/spi/bfin5xx_spi.c
+ * Maintainer:
+ * Bryan Wu <[email protected]>
+ * Original Author:
+ * Luke Yang (Analog Devices Inc.)
*
- * Created: March. 10th 2006
- * Description: SPI controller driver for Blackfin 5xx
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ * 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)
*
- * Copyright 2004-2006 Analog Devices Inc.
+ * 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
@@ -31,28 +34,27 @@

#include <linux/init.h>
#include <linux/module.h>
+#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/io.h>
#include <linux/ioport.h>
+#include <linux/irq.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
#include <linux/workqueue.h>
-#include <linux/errno.h>
-#include <linux/delay.h>

-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
#include <asm/dma.h>
-
+#include <asm/portmux.h>
#include <asm/bfin5xx_spi.h>

-MODULE_AUTHOR("Luke Yang");
-MODULE_DESCRIPTION("Blackfin 5xx SPI Contoller");
+MODULE_AUTHOR("Bryan Wu, Luke Yang");
+MODULE_DESCRIPTION("Blackfin BF5xx SPI Contoller Driver");
MODULE_LICENSE("GPL");

+#define DRV_NAME "bfin-spi-master"
#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)

#define DEFINE_SPI_REG(reg, off) \
@@ -125,6 +127,7 @@ struct chip_data {
u16 flag;

u8 chip_select_num;
+ u8 chip_select_requested;
u8 n_bytes;
u8 width; /* 0 or 1 */
u8 enable_dma;
@@ -189,53 +192,37 @@ static void restore_state(struct driver_data *drv_data)
bfin_spi_disable(drv_data);
dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");

-#if defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537)
- dev_dbg(&drv_data->pdev->dev,
- "chip select number is %d\n", chip->chip_select_num);
-
- switch (chip->chip_select_num) {
- case 1:
- bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3c00);
- SSYNC();
- break;
-
- case 2:
- case 3:
- bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJSE_SPI);
- SSYNC();
- bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800);
- SSYNC();
- break;
-
- case 4:
- bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS4E_SPI);
- SSYNC();
- bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3840);
- SSYNC();
- break;
+ if (!chip->chip_select_requested) {

- case 5:
- bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS5E_SPI);
- SSYNC();
- bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3820);
- SSYNC();
- break;
+ dev_dbg(&drv_data->pdev->dev,
+ "chip select number is %d\n", chip->chip_select_num);

- case 6:
- bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS6E_SPI);
- SSYNC();
- bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3810);
- SSYNC();
- break;
+ switch (chip->chip_select_num) {
+ case 1:
+ peripheral_request(P_SPI0_SSEL1, DRV_NAME);
+ break;
+ case 2:
+ peripheral_request(P_SPI0_SSEL2, DRV_NAME);
+ break;
+ case 3:
+ peripheral_request(P_SPI0_SSEL3, DRV_NAME);
+ break;
+ case 4:
+ peripheral_request(P_SPI0_SSEL4, DRV_NAME);
+ break;
+ case 5:
+ peripheral_request(P_SPI0_SSEL5, DRV_NAME);
+ break;
+ case 6:
+ peripheral_request(P_SPI0_SSEL6, DRV_NAME);
+ break;
+ case 7:
+ peripheral_request(P_SPI0_SSEL7, DRV_NAME);
+ break;
+ }

- case 7:
- bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJCE_SPI);
- SSYNC();
- bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800);
- SSYNC();
- break;
+ chip->chip_select_requested = 1;
}
-#endif

/* Load the registers */
write_CTRL(chip->ctl_reg);
@@ -278,7 +265,7 @@ static void null_reader(struct driver_data *drv_data)

static void u8_writer(struct driver_data *drv_data)
{
- dev_dbg(&drv_data->pdev->dev,
+ dev_dbg(&drv_data->pdev->dev,
"cr8-s is 0x%x\n", read_STAT());
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(*(u8 *) (drv_data->tx));
@@ -317,7 +304,7 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)

static void u8_reader(struct driver_data *drv_data)
{
- dev_dbg(&drv_data->pdev->dev,
+ dev_dbg(&drv_data->pdev->dev,
"cr-8 is 0x%x\n", read_STAT());

/* clear TDBR buffer before read(else it will be shifted out) */
@@ -404,7 +391,7 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)

static void u16_writer(struct driver_data *drv_data)
{
- dev_dbg(&drv_data->pdev->dev,
+ dev_dbg(&drv_data->pdev->dev,
"cr16 is 0x%x\n", read_STAT());

while (drv_data->tx < drv_data->tx_end) {
@@ -817,7 +804,7 @@ static void pump_transfers(unsigned long data)
/* full duplex mode */
BUG_ON((drv_data->tx_end - drv_data->tx) !=
(drv_data->rx_end - drv_data->rx));
- cr = (read_CTRL() & (~BIT_CTL_TIMOD));
+ cr = (read_CTRL() & (~BIT_CTL_TIMOD));
cr |= CFG_SPI_WRITE | (width << 8) |
(CFG_SPI_ENABLE << 14);
dev_dbg(&drv_data->pdev->dev,
@@ -835,7 +822,7 @@ static void pump_transfers(unsigned long data)
cr = (read_CTRL() & (~BIT_CTL_TIMOD));
cr |= CFG_SPI_WRITE | (width << 8) |
(CFG_SPI_ENABLE << 14);
- dev_dbg(&drv_data->pdev->dev,
+ dev_dbg(&drv_data->pdev->dev,
"IO write: cr is 0x%x\n", cr);

write_CTRL(cr);
@@ -850,7 +837,7 @@ static void pump_transfers(unsigned long data)
cr = (read_CTRL() & (~BIT_CTL_TIMOD));
cr |= CFG_SPI_READ | (width << 8) |
(CFG_SPI_ENABLE << 14);
- dev_dbg(&drv_data->pdev->dev,
+ dev_dbg(&drv_data->pdev->dev,
"IO read: cr is 0x%x\n", cr);

write_CTRL(cr);
@@ -862,7 +849,7 @@ static void pump_transfers(unsigned long data)
}

if (!tranf_success) {
- dev_dbg(&drv_data->pdev->dev,
+ dev_dbg(&drv_data->pdev->dev,
"IO write error!\n");
message->state = ERROR_STATE;
} else {
@@ -917,8 +904,8 @@ static void pump_messages(struct work_struct *work)
"got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
drv_data->cur_chip->baud, drv_data->cur_chip->flag,
drv_data->cur_chip->ctl_reg);
-
- dev_dbg(&drv_data->pdev->dev,
+
+ dev_dbg(&drv_data->pdev->dev,
"the first transfer len is %d\n",
drv_data->cur_transfer->len);

@@ -1194,6 +1181,15 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can not alloc spi_master\n");
return -ENOMEM;
}
+
+ if (peripheral_request(P_SPI0_SCK, DRV_NAME) ||
+ peripheral_request(P_SPI0_MISO, DRV_NAME) ||
+ peripheral_request(P_SPI0_MOSI, DRV_NAME) ) {
+
+ dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
+ goto out_error_queue_alloc;
+ }
+
drv_data = spi_master_get_devdata(master);
drv_data->master = master;
drv_data->master_info = platform_info;
diff --git a/include/asm-blackfin/mach-bf548/defBF54x_base.h b/include/asm-blackfin/mach-bf548/defBF54x_base.h
index 895ddd4..56f0a76 100644
--- a/include/asm-blackfin/mach-bf548/defBF54x_base.h
+++ b/include/asm-blackfin/mach-bf548/defBF54x_base.h
@@ -1637,8 +1637,25 @@
#define RESTART 0x20 /* Work Unit Transitions */
#define DI_SEL 0x40 /* Data Interrupt Timing Select */
#define DI_EN 0x80 /* Data Interrupt Enable */
+
#define NDSIZE 0xf00 /* Flex Descriptor Size */
+#define NDSIZE_0 0x0000 /* Next Descriptor Size = 0 (Stop/Autobuffer) */
+#define NDSIZE_1 0x0100 /* Next Descriptor Size = 1 */
+#define NDSIZE_2 0x0200 /* Next Descriptor Size = 2 */
+#define NDSIZE_3 0x0300 /* Next Descriptor Size = 3 */
+#define NDSIZE_4 0x0400 /* Next Descriptor Size = 4 */
+#define NDSIZE_5 0x0500 /* Next Descriptor Size = 5 */
+#define NDSIZE_6 0x0600 /* Next Descriptor Size = 6 */
+#define NDSIZE_7 0x0700 /* Next Descriptor Size = 7 */
+#define NDSIZE_8 0x0800 /* Next Descriptor Size = 8 */
+#define NDSIZE_9 0x0900 /* Next Descriptor Size = 9 */
+
#define DMAFLOW 0xf000 /* Next Operation */
+#define DMAFLOW_STOP 0x0000 /* Stop Mode */
+#define DMAFLOW_AUTO 0x1000 /* Autobuffer Mode */
+#define DMAFLOW_ARRAY 0x4000 /* Descriptor Array Mode */
+#define DMAFLOW_SMALL 0x6000 /* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE 0x7000 /* Large Model Descriptor List Mode */

/* Bit masks for DMAx_IRQ_STATUS, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */

--
1.5.3.4

2007-10-12 03:06:58

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 04/10] Blackfin SPI driver: Blackfin SPI driver does not respect the per-transfer cs_change field

Add cs_active/cs_deactive functions and try to catch the cs_change flag.

Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 76 ++++++++++++++++++++++++++++++++-------------
1 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 2f46283..7093065 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -115,6 +115,7 @@ struct driver_data {
size_t rx_map_len;
size_t tx_map_len;
u8 n_bytes;
+ int cs_change;
void (*write) (struct driver_data *);
void (*read) (struct driver_data *);
void (*duplex) (struct driver_data *);
@@ -179,6 +180,26 @@ static int flush(struct driver_data *drv_data)
return limit;
}

+/* Chip select operation functions for cs_change flag */
+static void cs_active(struct chip_data *chip)
+{
+ u16 flag = read_FLAG();
+
+ flag |= chip->flag;
+ flag &= ~(chip->flag << 8);
+
+ write_FLAG(flag);
+}
+
+static void cs_deactive(struct chip_data *chip)
+{
+ u16 flag = read_FLAG();
+
+ flag |= (chip->flag << 8);
+
+ write_FLAG(flag);
+}
+
#define MAX_SPI0_SSEL 7

/* stop controller and re-config current chip*/
@@ -198,7 +219,7 @@ static int restore_state(struct driver_data *drv_data)
/* Load the registers */
write_CTRL(chip->ctl_reg);
write_BAUD(chip->baud);
- write_FLAG(chip->flag);
+ cs_active(chip);

if (!chip->chip_select_requested) {
int i = chip->chip_select_num;
@@ -273,20 +294,20 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)
struct chip_data *chip = drv_data->cur_chip;

while (drv_data->tx < drv_data->tx_end) {
- write_FLAG(chip->flag);
+ cs_active(chip);

write_TDBR(*(u8 *) (drv_data->tx));
while (read_STAT() & BIT_STAT_TXS)
continue;
while (!(read_STAT() & BIT_STAT_SPIF))
continue;
- write_FLAG(0xFF00 | chip->flag);
+ cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
++drv_data->tx;
}
- write_FLAG(0xFF00);
+ cs_deactive(chip);

}

@@ -318,7 +339,7 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)
struct chip_data *chip = drv_data->cur_chip;

while (drv_data->rx < drv_data->rx_end) {
- write_FLAG(chip->flag);
+ cs_active(chip);

read_RDBR(); /* kick off */
while (!(read_STAT() & BIT_STAT_RXS))
@@ -326,13 +347,13 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)
while (!(read_STAT() & BIT_STAT_SPIF))
continue;
*(u8 *) (drv_data->rx) = read_SHAW();
- write_FLAG(0xFF00 | chip->flag);
+ cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
++drv_data->rx;
}
- write_FLAG(0xFF00);
+ cs_deactive(chip);

}

@@ -356,7 +377,7 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
struct chip_data *chip = drv_data->cur_chip;

while (drv_data->rx < drv_data->rx_end) {
- write_FLAG(chip->flag);
+ cs_active(chip);


write_TDBR(*(u8 *) (drv_data->tx));
@@ -365,15 +386,14 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
while (!(read_STAT() & BIT_STAT_RXS))
continue;
*(u8 *) (drv_data->rx) = read_RDBR();
- write_FLAG(0xFF00 | chip->flag);
+ cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
++drv_data->rx;
++drv_data->tx;
}
- write_FLAG(0xFF00);
-
+ cs_deactive(chip);
}

static void u16_writer(struct driver_data *drv_data)
@@ -398,20 +418,20 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)
struct chip_data *chip = drv_data->cur_chip;

while (drv_data->tx < drv_data->tx_end) {
- write_FLAG(chip->flag);
+ cs_active(chip);

write_TDBR(*(u16 *) (drv_data->tx));
while ((read_STAT() & BIT_STAT_TXS))
continue;
while (!(read_STAT() & BIT_STAT_SPIF))
continue;
- write_FLAG(0xFF00 | chip->flag);
+ cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
drv_data->tx += 2;
}
- write_FLAG(0xFF00);
+ cs_deactive(chip);
}

static void u16_reader(struct driver_data *drv_data)
@@ -438,7 +458,7 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
struct chip_data *chip = drv_data->cur_chip;

while (drv_data->rx < drv_data->rx_end) {
- write_FLAG(chip->flag);
+ cs_active(chip);

read_RDBR(); /* kick off */
while (!(read_STAT() & BIT_STAT_RXS))
@@ -446,13 +466,13 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
while (!(read_STAT() & BIT_STAT_SPIF))
continue;
*(u16 *) (drv_data->rx) = read_SHAW();
- write_FLAG(0xFF00 | chip->flag);
+ cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
drv_data->rx += 2;
}
- write_FLAG(0xFF00);
+ cs_deactive(chip);
}

static void u16_duplex(struct driver_data *drv_data)
@@ -475,7 +495,7 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
struct chip_data *chip = drv_data->cur_chip;

while (drv_data->tx < drv_data->tx_end) {
- write_FLAG(chip->flag);
+ cs_active(chip);

write_TDBR(*(u16 *) (drv_data->tx));
while (!(read_STAT() & BIT_STAT_SPIF))
@@ -483,14 +503,14 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
while (!(read_STAT() & BIT_STAT_RXS))
continue;
*(u16 *) (drv_data->rx) = read_RDBR();
- write_FLAG(0xFF00 | chip->flag);
+ cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
drv_data->rx += 2;
drv_data->tx += 2;
}
- write_FLAG(0xFF00);
+ cs_deactive(chip);
}

/* test if ther is more transfer to be done */
@@ -515,6 +535,7 @@ static void *next_transfer(struct driver_data *drv_data)
*/
static void giveback(struct driver_data *drv_data)
{
+ struct chip_data *chip = drv_data->cur_chip;
struct spi_transfer *last_transfer;
unsigned long flags;
struct spi_message *msg;
@@ -534,10 +555,13 @@ static void giveback(struct driver_data *drv_data)

/* disable chip select signal. And not stop spi in autobuffer mode */
if (drv_data->tx_dma != 0xFFFF) {
- write_FLAG(0xFF00);
+ cs_deactive(chip);
bfin_spi_disable(drv_data);
}

+ if (!drv_data->cs_change)
+ cs_deactive(chip);
+
if (msg->complete)
msg->complete(msg->context);
}
@@ -546,6 +570,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
{
struct driver_data *drv_data = (struct driver_data *)dev_id;
struct spi_message *msg = drv_data->cur_msg;
+ struct chip_data *chip = drv_data->cur_chip;

dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n");
clear_dma_irqstat(CH_SPI);
@@ -573,6 +598,9 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)

msg->actual_length += drv_data->len_in_bytes;

+ if (drv_data->cs_change)
+ cs_deactive(chip);
+
/* Move to next transfer */
msg->state = next_transfer(drv_data);

@@ -659,6 +687,7 @@ static void pump_transfers(unsigned long data)
drv_data->rx_dma = transfer->rx_dma;
drv_data->tx_dma = transfer->tx_dma;
drv_data->len_in_bytes = transfer->len;
+ drv_data->cs_change = transfer->cs_change;

width = chip->width;
if (width == CFG_SPI_WORDSIZE16) {
@@ -683,7 +712,7 @@ static void pump_transfers(unsigned long data)
} else {
write_BAUD(chip->baud);
}
- write_FLAG(chip->flag);
+ cs_active(chip);

dev_dbg(&drv_data->pdev->dev,
"now pumping a transfer: width is %d, len is %d\n",
@@ -834,6 +863,9 @@ static void pump_transfers(unsigned long data)
/* Update total byte transfered */
message->actual_length += drv_data->len;

+ if (drv_data->cs_change)
+ cs_deactive(chip);
+
/* Move to next transfer of this msg */
message->state = next_transfer(drv_data);
}
--
1.5.3.4

2007-10-12 03:07:30

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 05/10] Blackfin SPI driver: prevent people from setting bits in ctl_reg

From: Mike Frysinger <[email protected]>

Prevent people from setting bits in ctl_reg that the SPI
framework already handles, hopefully we can one day drop
ctl_reg completely

Signed-off-by: Mike Frysinger <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 7093065..1a83656 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -996,6 +996,16 @@ static int setup(struct spi_device *spi)

/* chip_info isn't always needed */
if (chip_info) {
+ /* Make sure people stop trying to set fields via ctl_reg when they
+ * should actually be using common SPI framework. Currently we let
+ * through: WOM EMISO PSSE GM SZ TIMOD. Not sure if a user actually
+ * needs/uses any of these, but let's assume (for now) they do.
+ */
+ if (chip_info->ctl_reg & (SPE | MSTR | CPOL | CPHA | LSBF | SIZE)) {
+ dev_err(&spi->dev, "do not set bits in ctl_reg that the SPI framework provides\n");
+ return -EINVAL;
+ }
+
chip->enable_dma = chip_info->enable_dma != 0
&& drv_data->master_info->enable_dma;
chip->ctl_reg = chip_info->ctl_reg;
--
1.5.3.4

2007-10-12 03:08:10

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 06/10] Blackfin SPI driver: update spi driver to support multi-ports

update spi driver to support multi-ports by add platform_resource,
tested on STAMP537+SPI_MMC, other boards need more testing

Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 124 ++++++++++++++++++++++++++++++---------------
1 files changed, 83 insertions(+), 41 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 1a83656..891d263 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -13,6 +13,8 @@
* 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)
*
* Copyright 2004-2007 Analog Devices Inc.
*
@@ -50,18 +52,25 @@
#include <asm/portmux.h>
#include <asm/bfin5xx_spi.h>

-MODULE_AUTHOR("Bryan Wu, Luke Yang");
-MODULE_DESCRIPTION("Blackfin BF5xx SPI Contoller Driver");
+#define DRV_NAME "bfin-spi"
+#define DRV_AUTHOR "Bryan Wu, Luke Yang"
+#define DRV_DESC "Blackfin BF5xx on-chip SPI Contoller Driver"
+#define DRV_VERSION "1.0"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
MODULE_LICENSE("GPL");

-#define DRV_NAME "bfin-spi-master"
#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)

+static u32 spi_dma_ch;
+static u32 spi_regs_base;
+
#define DEFINE_SPI_REG(reg, off) \
static inline u16 read_##reg(void) \
- { return bfin_read16(SPI0_REGBASE + off); } \
+ { return bfin_read16(spi_regs_base + off); } \
static inline void write_##reg(u16 v) \
- {bfin_write16(SPI0_REGBASE + off, v); }
+ {bfin_write16(spi_regs_base + off, v); }

DEFINE_SPI_REG(CTRL, 0x00)
DEFINE_SPI_REG(FLAG, 0x04)
@@ -573,10 +582,10 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
struct chip_data *chip = drv_data->cur_chip;

dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n");
- clear_dma_irqstat(CH_SPI);
+ clear_dma_irqstat(spi_dma_ch);

/* Wait for DMA to complete */
- while (get_dma_curr_irqstat(CH_SPI) & DMA_RUN)
+ while (get_dma_curr_irqstat(spi_dma_ch) & DMA_RUN)
continue;

/*
@@ -586,12 +595,12 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
* register until it goes low for 2 successive reads
*/
if (drv_data->tx != NULL) {
- while ((bfin_read_SPI_STAT() & TXS) ||
- (bfin_read_SPI_STAT() & TXS))
+ while ((read_STAT() & TXS) ||
+ (read_STAT() & TXS))
continue;
}

- while (!(bfin_read_SPI_STAT() & SPIF))
+ while (!(read_STAT() & SPIF))
continue;

bfin_spi_disable(drv_data);
@@ -610,8 +619,8 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
/* free the irq handler before next transfer */
dev_dbg(&drv_data->pdev->dev,
"disable dma channel irq%d\n",
- CH_SPI);
- dma_disable_irq(CH_SPI);
+ spi_dma_ch);
+ dma_disable_irq(spi_dma_ch);

return IRQ_HANDLED;
}
@@ -726,19 +735,19 @@ static void pump_transfers(unsigned long data)
if (drv_data->cur_chip->enable_dma && drv_data->len > 6) {

write_STAT(BIT_STAT_CLR);
- disable_dma(CH_SPI);
- clear_dma_irqstat(CH_SPI);
+ disable_dma(spi_dma_ch);
+ clear_dma_irqstat(spi_dma_ch);
bfin_spi_disable(drv_data);

/* config dma channel */
dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
if (width == CFG_SPI_WORDSIZE16) {
- set_dma_x_count(CH_SPI, drv_data->len);
- set_dma_x_modify(CH_SPI, 2);
+ set_dma_x_count(spi_dma_ch, drv_data->len);
+ set_dma_x_modify(spi_dma_ch, 2);
dma_width = WDSIZE_16;
} else {
- set_dma_x_count(CH_SPI, drv_data->len);
- set_dma_x_modify(CH_SPI, 1);
+ set_dma_x_count(spi_dma_ch, drv_data->len);
+ set_dma_x_modify(spi_dma_ch, 1);
dma_width = WDSIZE_8;
}

@@ -753,9 +762,10 @@ static void pump_transfers(unsigned long data)
/* no irq in autobuffer mode */
dma_config =
(DMAFLOW_AUTO | RESTART | dma_width | DI_EN);
- set_dma_config(CH_SPI, dma_config);
- set_dma_start_addr(CH_SPI, (unsigned long)drv_data->tx);
- enable_dma(CH_SPI);
+ set_dma_config(spi_dma_ch, dma_config);
+ set_dma_start_addr(spi_dma_ch,
+ (unsigned long)drv_data->tx);
+ enable_dma(spi_dma_ch);
write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) |
(CFG_SPI_ENABLE << 14));

@@ -776,14 +786,15 @@ static void pump_transfers(unsigned long data)
/* clear tx reg soformer data is not shifted out */
write_TDBR(0xFF);

- set_dma_x_count(CH_SPI, drv_data->len);
+ set_dma_x_count(spi_dma_ch, drv_data->len);

/* start dma */
- dma_enable_irq(CH_SPI);
+ dma_enable_irq(spi_dma_ch);
dma_config = (WNR | RESTART | dma_width | DI_EN);
- set_dma_config(CH_SPI, dma_config);
- set_dma_start_addr(CH_SPI, (unsigned long)drv_data->rx);
- enable_dma(CH_SPI);
+ set_dma_config(spi_dma_ch, dma_config);
+ set_dma_start_addr(spi_dma_ch,
+ (unsigned long)drv_data->rx);
+ enable_dma(spi_dma_ch);

cr |=
CFG_SPI_DMAREAD | (width << 8) | (CFG_SPI_ENABLE <<
@@ -794,11 +805,12 @@ static void pump_transfers(unsigned long data)
dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");

/* start dma */
- dma_enable_irq(CH_SPI);
+ dma_enable_irq(spi_dma_ch);
dma_config = (RESTART | dma_width | DI_EN);
- set_dma_config(CH_SPI, dma_config);
- set_dma_start_addr(CH_SPI, (unsigned long)drv_data->tx);
- enable_dma(CH_SPI);
+ set_dma_config(spi_dma_ch, dma_config);
+ set_dma_start_addr(spi_dma_ch,
+ (unsigned long)drv_data->tx);
+ enable_dma(spi_dma_ch);

write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) |
(CFG_SPI_ENABLE << 14));
@@ -1030,17 +1042,17 @@ static int setup(struct spi_device *spi)
*/
if (chip->enable_dma && !dma_requested) {
/* register dma irq handler */
- if (request_dma(CH_SPI, "BF53x_SPI_DMA") < 0) {
+ if (request_dma(spi_dma_ch, "BF53x_SPI_DMA") < 0) {
dev_dbg(&spi->dev,
"Unable to request BlackFin SPI DMA channel\n");
return -ENODEV;
}
- if (set_dma_callback(CH_SPI, (void *)dma_irq_handler, drv_data)
- < 0) {
+ if (set_dma_callback(spi_dma_ch, (void *)dma_irq_handler,
+ drv_data) < 0) {
dev_dbg(&spi->dev, "Unable to set dma callback\n");
return -EPERM;
}
- dma_disable_irq(CH_SPI);
+ dma_disable_irq(spi_dma_ch);
dma_requested = 1;
}

@@ -1212,6 +1224,7 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
struct bfin5xx_spi_master *platform_info;
struct spi_master *master;
struct driver_data *drv_data = 0;
+ struct resource *res;
int status = 0;

platform_info = dev->platform_data;
@@ -1239,15 +1252,38 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
master->setup = setup;
master->transfer = transfer;

+ /* Find and map our resources */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(dev, "Cannot get IORESOURCE_MEM\n");
+ status = -ENOENT;
+ goto out_error_get_res;
+ }
+
+ spi_regs_base = (u32) ioremap(res->start, (res->end - res->start)+1);
+ if (!spi_regs_base) {
+ dev_err(dev, "Cannot map IO\n");
+ status = -ENXIO;
+ goto out_error_ioremap;
+ }
+
+ spi_dma_ch = platform_get_irq(pdev, 0);
+ if (spi_dma_ch < 0) {
+ dev_err(dev, "No DMA channel specified\n");
+ status = -ENOENT;
+ goto out_error_no_dma_ch;
+ }
+
/* Initial and start queue */
status = init_queue(drv_data);
if (status != 0) {
- dev_err(&pdev->dev, "problem initializing queue\n");
+ dev_err(dev, "problem initializing queue\n");
goto out_error_queue_alloc;
}
+
status = start_queue(drv_data);
if (status != 0) {
- dev_err(&pdev->dev, "problem starting queue\n");
+ dev_err(dev, "problem starting queue\n");
goto out_error_queue_alloc;
}

@@ -1255,14 +1291,20 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drv_data);
status = spi_register_master(master);
if (status != 0) {
- dev_err(&pdev->dev, "problem registering spi master\n");
+ dev_err(dev, "problem registering spi master\n");
goto out_error_queue_alloc;
}
- dev_dbg(&pdev->dev, "controller probe successfully\n");
+
+ dev_info(dev, "%s, Version %s, regs_base @ 0x%08x\n",
+ DRV_DESC, DRV_VERSION, spi_regs_base);
return status;

out_error_queue_alloc:
destroy_queue(drv_data);
+out_error_no_dma_ch:
+ iounmap((void *) spi_regs_base);
+out_error_ioremap:
+out_error_get_res:
out_error:
spi_master_put(master);

@@ -1288,8 +1330,8 @@ static int __devexit bfin5xx_spi_remove(struct platform_device *pdev)

/* Release DMA */
if (drv_data->master_info->enable_dma) {
- if (dma_channel_active(CH_SPI))
- free_dma(CH_SPI);
+ if (dma_channel_active(spi_dma_ch))
+ free_dma(spi_dma_ch);
}

/* Disconnect from the SPI framework */
@@ -1344,7 +1386,7 @@ static int bfin5xx_spi_resume(struct platform_device *pdev)
MODULE_ALIAS("bfin-spi-master"); /* for platform bus hotplug */
static struct platform_driver bfin5xx_spi_driver = {
.driver = {
- .name = "bfin-spi-master",
+ .name = DRV_NAME,
.owner = THIS_MODULE,
},
.suspend = bfin5xx_spi_suspend,
--
1.5.3.4

2007-10-12 03:08:39

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 10/10] Blackfin SPI driver: Clean up useless wait in bfin SPI driver

From: Sonic Zhang <[email protected]>

Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 84 ++++++++++++++++++++++++++++-----------------
1 files changed, 52 insertions(+), 32 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 0cdfc2b..bfeaa7c 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -276,22 +276,26 @@ static void u8_writer(struct driver_data *drv_data)
dev_dbg(&drv_data->pdev->dev,
"cr8-s is 0x%x\n", read_STAT());

+ /* poll for SPI completion before start */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
+
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(*(u8 *) (drv_data->tx));
while (read_STAT() & BIT_STAT_TXS)
continue;
++drv_data->tx;
}
-
- /* poll for SPI completion before returning */
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
}

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() & BIT_STAT_SPIF))
+ continue;
+
while (drv_data->tx < drv_data->tx_end) {
cs_active(chip);

@@ -304,10 +308,6 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)
udelay(chip->cs_chg_udelay);
++drv_data->tx;
}
-
- /* poll for SPI completion before returning */
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
}

static void u8_reader(struct driver_data *drv_data)
@@ -315,6 +315,10 @@ static void u8_reader(struct driver_data *drv_data)
dev_dbg(&drv_data->pdev->dev,
"cr-8 is 0x%x\n", read_STAT());

+ /* poll for SPI completion before start */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
+
/* clear TDBR buffer before read(else it will be shifted out) */
write_TDBR(0xFFFF);

@@ -337,6 +341,10 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;

+ /* poll for SPI completion before start */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
+
/* clear TDBR buffer before read(else it will be shifted out) */
write_TDBR(0xFFFF);

@@ -365,6 +373,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() & BIT_STAT_SPIF))
+ continue;
+
/* in duplex mode, clk is triggered by writing of TDBR */
while (drv_data->rx < drv_data->rx_end) {
write_TDBR(*(u8 *) (drv_data->tx));
@@ -376,16 +388,16 @@ static void u8_duplex(struct driver_data *drv_data)
++drv_data->rx;
++drv_data->tx;
}
-
- /* poll for SPI completion before returning */
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
}

static void u8_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() & BIT_STAT_SPIF))
+ continue;
+
while (drv_data->rx < drv_data->rx_end) {
cs_active(chip);

@@ -402,10 +414,6 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
++drv_data->rx;
++drv_data->tx;
}
-
- /* poll for SPI completion before returning */
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
}

static void u16_writer(struct driver_data *drv_data)
@@ -413,22 +421,26 @@ static void u16_writer(struct driver_data *drv_data)
dev_dbg(&drv_data->pdev->dev,
"cr16 is 0x%x\n", read_STAT());

+ /* poll for SPI completion before start */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
+
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(*(u16 *) (drv_data->tx));
while ((read_STAT() & BIT_STAT_TXS))
continue;
drv_data->tx += 2;
}
-
- /* poll for SPI completion before returning */
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
}

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() & BIT_STAT_SPIF))
+ continue;
+
while (drv_data->tx < drv_data->tx_end) {
cs_active(chip);

@@ -441,10 +453,6 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)
udelay(chip->cs_chg_udelay);
drv_data->tx += 2;
}
-
- /* poll for SPI completion before returning */
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
}

static void u16_reader(struct driver_data *drv_data)
@@ -452,6 +460,10 @@ static void u16_reader(struct driver_data *drv_data)
dev_dbg(&drv_data->pdev->dev,
"cr-16 is 0x%x\n", read_STAT());

+ /* poll for SPI completion before start */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
+
/* clear TDBR buffer before read(else it will be shifted out) */
write_TDBR(0xFFFF);

@@ -474,6 +486,10 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;

+ /* poll for SPI completion before start */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
+
/* clear TDBR buffer before read(else it will be shifted out) */
write_TDBR(0xFFFF);

@@ -502,6 +518,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() & BIT_STAT_SPIF))
+ continue;
+
/* in duplex mode, clk is triggered by writing of TDBR */
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(*(u16 *) (drv_data->tx));
@@ -513,16 +533,16 @@ static void u16_duplex(struct driver_data *drv_data)
drv_data->rx += 2;
drv_data->tx += 2;
}
-
- /* poll for SPI completion before returning */
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
}

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() & BIT_STAT_SPIF))
+ continue;
+
while (drv_data->tx < drv_data->tx_end) {
cs_active(chip);

@@ -539,10 +559,6 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
drv_data->rx += 2;
drv_data->tx += 2;
}
-
- /* poll for SPI completion before returning */
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
}

/* test if ther is more transfer to be done */
@@ -765,6 +781,10 @@ static void pump_transfers(unsigned long data)
dma_width = WDSIZE_8;
}

+ /* poll for SPI completion before start */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
+
/* dirty hack for autobuffer DMA mode */
if (drv_data->tx_dma == 0xFFFF) {
dev_dbg(&drv_data->pdev->dev,
--
1.5.3.4

2007-10-12 03:09:04

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 09/10] Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548

From: Sonic Zhang <[email protected]>

Current SPI driver enables SPI controller and set the SPI baud register
for each SPI transfer. But, they should never be changed within a SPI
message session, in which seveal SPI transfers are pumped. This patch
move move SPI setting to the begining of a message session. And never
disables SPI controller until an error occurs.

Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 162 ++++++++++++++++++++++++---------------------
1 files changed, 87 insertions(+), 75 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index c1516cb..0cdfc2b 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -222,9 +222,13 @@ static int restore_state(struct driver_data *drv_data)
dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");

/* Load the registers */
- write_CTRL(chip->ctl_reg);
+ cs_deactive(chip);
write_BAUD(chip->baud);
- cs_active(chip);
+ chip->ctl_reg &= (~BIT_CTL_TIMOD);
+ chip->ctl_reg |= (chip->width << 8);
+ write_CTRL(chip->ctl_reg);
+
+ bfin_spi_enable(drv_data);

if (ret)
dev_dbg(&drv_data->pdev->dev,
@@ -271,6 +275,7 @@ static void u8_writer(struct driver_data *drv_data)
{
dev_dbg(&drv_data->pdev->dev,
"cr8-s is 0x%x\n", read_STAT());
+
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(*(u8 *) (drv_data->tx));
while (read_STAT() & BIT_STAT_TXS)
@@ -293,16 +298,16 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)
write_TDBR(*(u8 *) (drv_data->tx));
while (read_STAT() & BIT_STAT_TXS)
continue;
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
++drv_data->tx;
}
- cs_deactive(chip);

+ /* poll for SPI completion before returning */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
}

static void u8_reader(struct driver_data *drv_data)
@@ -314,6 +319,7 @@ static void u8_reader(struct driver_data *drv_data)
write_TDBR(0xFFFF);

dummy_read();
+
while (drv_data->rx < drv_data->rx_end - 1) {
while (!(read_STAT() & BIT_STAT_RXS))
continue;
@@ -331,23 +337,30 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;

- while (drv_data->rx < drv_data->rx_end) {
- cs_active(chip);
+ /* clear TDBR buffer before read(else it will be shifted out) */
+ write_TDBR(0xFFFF);

- read_RDBR(); /* kick off */
- while (!(read_STAT() & BIT_STAT_RXS))
- continue;
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
- *(u8 *) (drv_data->rx) = read_SHAW();
+ cs_active(chip);
+ dummy_read();
+
+ while (drv_data->rx < drv_data->rx_end - 1) {
cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
+
+ while (!(read_STAT() & BIT_STAT_RXS))
+ continue;
+ cs_active(chip);
+ *(u8 *) (drv_data->rx) = read_RDBR();
++drv_data->rx;
}
cs_deactive(chip);

+ while (!(read_STAT() & BIT_STAT_RXS))
+ continue;
+ *(u8 *) (drv_data->rx) = read_SHAW();
+ ++drv_data->rx;
}

static void u8_duplex(struct driver_data *drv_data)
@@ -355,7 +368,7 @@ static void u8_duplex(struct driver_data *drv_data)
/* in duplex mode, clk is triggered by writing of TDBR */
while (drv_data->rx < drv_data->rx_end) {
write_TDBR(*(u8 *) (drv_data->tx));
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (read_STAT() & BIT_STAT_TXS)
continue;
while (!(read_STAT() & BIT_STAT_RXS))
continue;
@@ -363,6 +376,10 @@ static void u8_duplex(struct driver_data *drv_data)
++drv_data->rx;
++drv_data->tx;
}
+
+ /* poll for SPI completion before returning */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
}

static void u8_cs_chg_duplex(struct driver_data *drv_data)
@@ -372,9 +389,8 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
while (drv_data->rx < drv_data->rx_end) {
cs_active(chip);

-
write_TDBR(*(u8 *) (drv_data->tx));
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (read_STAT() & BIT_STAT_TXS)
continue;
while (!(read_STAT() & BIT_STAT_RXS))
continue;
@@ -386,7 +402,10 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
++drv_data->rx;
++drv_data->tx;
}
- cs_deactive(chip);
+
+ /* poll for SPI completion before returning */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
}

static void u16_writer(struct driver_data *drv_data)
@@ -416,21 +435,26 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)
write_TDBR(*(u16 *) (drv_data->tx));
while ((read_STAT() & BIT_STAT_TXS))
continue;
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
drv_data->tx += 2;
}
- cs_deactive(chip);
+
+ /* poll for SPI completion before returning */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
}

static void u16_reader(struct driver_data *drv_data)
{
dev_dbg(&drv_data->pdev->dev,
"cr-16 is 0x%x\n", read_STAT());
+
+ /* clear TDBR buffer before read(else it will be shifted out) */
+ write_TDBR(0xFFFF);
+
dummy_read();

while (drv_data->rx < (drv_data->rx_end - 2)) {
@@ -450,22 +474,30 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;

- while (drv_data->rx < drv_data->rx_end) {
- cs_active(chip);
+ /* clear TDBR buffer before read(else it will be shifted out) */
+ write_TDBR(0xFFFF);

- read_RDBR(); /* kick off */
- while (!(read_STAT() & BIT_STAT_RXS))
- continue;
- while (!(read_STAT() & BIT_STAT_SPIF))
- continue;
- *(u16 *) (drv_data->rx) = read_SHAW();
+ cs_active(chip);
+ dummy_read();
+
+ while (drv_data->rx < drv_data->rx_end) {
cs_deactive(chip);

if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
+
+ while (!(read_STAT() & BIT_STAT_RXS))
+ continue;
+ cs_active(chip);
+ *(u16 *) (drv_data->rx) = read_RDBR();
drv_data->rx += 2;
}
cs_deactive(chip);
+
+ while (!(read_STAT() & BIT_STAT_RXS))
+ continue;
+ *(u16 *) (drv_data->rx) = read_SHAW();
+ drv_data->rx += 2;
}

static void u16_duplex(struct driver_data *drv_data)
@@ -473,7 +505,7 @@ static void u16_duplex(struct driver_data *drv_data)
/* in duplex mode, clk is triggered by writing of TDBR */
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(*(u16 *) (drv_data->tx));
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (read_STAT() & BIT_STAT_TXS)
continue;
while (!(read_STAT() & BIT_STAT_RXS))
continue;
@@ -481,6 +513,10 @@ static void u16_duplex(struct driver_data *drv_data)
drv_data->rx += 2;
drv_data->tx += 2;
}
+
+ /* poll for SPI completion before returning */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
}

static void u16_cs_chg_duplex(struct driver_data *drv_data)
@@ -491,7 +527,7 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
cs_active(chip);

write_TDBR(*(u16 *) (drv_data->tx));
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (read_STAT() & BIT_STAT_TXS)
continue;
while (!(read_STAT() & BIT_STAT_RXS))
continue;
@@ -503,7 +539,10 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
drv_data->rx += 2;
drv_data->tx += 2;
}
- cs_deactive(chip);
+
+ /* poll for SPI completion before returning */
+ while (!(read_STAT() & BIT_STAT_SPIF))
+ continue;
}

/* test if ther is more transfer to be done */
@@ -587,8 +626,6 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
while (!(read_STAT() & SPIF))
continue;

- bfin_spi_disable(drv_data);
-
msg->actual_length += drv_data->len_in_bytes;

if (drv_data->cs_change)
@@ -698,12 +735,8 @@ static void pump_transfers(unsigned long data)
message->state = RUNNING_STATE;
dma_config = 0;

- /* restore spi status for each spi transfer */
- if (transfer->speed_hz) {
- write_BAUD(hz_to_spi_baud(transfer->speed_hz));
- } else {
- write_BAUD(chip->baud);
- }
+ write_STAT(BIT_STAT_CLR);
+ cr = (read_CTRL() & (~BIT_CTL_TIMOD));
cs_active(chip);

dev_dbg(&drv_data->pdev->dev,
@@ -717,10 +750,8 @@ static void pump_transfers(unsigned long data)
*/
if (drv_data->cur_chip->enable_dma && drv_data->len > 6) {

- write_STAT(BIT_STAT_CLR);
disable_dma(spi_dma_ch);
clear_dma_irqstat(spi_dma_ch);
- bfin_spi_disable(drv_data);

/* config dma channel */
dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
@@ -734,14 +765,14 @@ static void pump_transfers(unsigned long data)
dma_width = WDSIZE_8;
}

- /* set transfer width,direction. And enable spi */
- cr = (read_CTRL() & (~BIT_CTL_TIMOD));
-
/* 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(cr | CFG_SPI_DMAWRITE);
+
/* no irq in autobuffer mode */
dma_config =
(DMAFLOW_AUTO | RESTART | dma_width | DI_EN);
@@ -749,8 +780,6 @@ static void pump_transfers(unsigned long data)
set_dma_start_addr(spi_dma_ch,
(unsigned long)drv_data->tx);
enable_dma(spi_dma_ch);
- write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) |
- (CFG_SPI_ENABLE << 14));

/* just return here, there can only be one transfer in this mode */
message->status = 0;
@@ -763,11 +792,11 @@ static void pump_transfers(unsigned long data)
/* set transfer mode, and enable SPI */
dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n");

- /* disable SPI before write to TDBR */
- write_CTRL(cr & ~BIT_CTL_ENABLE);
+ /* set SPI transfer mode */
+ write_CTRL(cr | CFG_SPI_DMAREAD);

/* clear tx reg soformer data is not shifted out */
- write_TDBR(0xFF);
+ write_TDBR(0xFFFF);

set_dma_x_count(spi_dma_ch, drv_data->len);

@@ -779,14 +808,12 @@ static void pump_transfers(unsigned long data)
(unsigned long)drv_data->rx);
enable_dma(spi_dma_ch);

- cr |=
- CFG_SPI_DMAREAD | (width << 8) | (CFG_SPI_ENABLE <<
- 14);
- /* set transfer mode, and enable SPI */
- write_CTRL(cr);
} else if (drv_data->tx != NULL) {
dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n");

+ /* set SPI transfer mode */
+ write_CTRL(cr | CFG_SPI_DMAWRITE);
+
/* start dma */
dma_enable_irq(spi_dma_ch);
dma_config = (RESTART | dma_width | DI_EN);
@@ -794,28 +821,20 @@ static void pump_transfers(unsigned long data)
set_dma_start_addr(spi_dma_ch,
(unsigned long)drv_data->tx);
enable_dma(spi_dma_ch);
-
- write_CTRL(cr | CFG_SPI_DMAWRITE | (width << 8) |
- (CFG_SPI_ENABLE << 14));
-
}
} else {
/* IO mode write then read */
dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n");

- write_STAT(BIT_STAT_CLR);
-
if (drv_data->tx != NULL && drv_data->rx != NULL) {
/* full duplex mode */
BUG_ON((drv_data->tx_end - drv_data->tx) !=
(drv_data->rx_end - drv_data->rx));
- cr = (read_CTRL() & (~BIT_CTL_TIMOD));
- cr |= CFG_SPI_WRITE | (width << 8) |
- (CFG_SPI_ENABLE << 14);
dev_dbg(&drv_data->pdev->dev,
"IO duplex: cr is 0x%x\n", cr);

- write_CTRL(cr);
+ /* set SPI transfer mode */
+ write_CTRL(cr | CFG_SPI_WRITE);

drv_data->duplex(drv_data);

@@ -823,13 +842,11 @@ static void pump_transfers(unsigned long data)
tranf_success = 0;
} else if (drv_data->tx != NULL) {
/* write only half duplex */
- cr = (read_CTRL() & (~BIT_CTL_TIMOD));
- cr |= CFG_SPI_WRITE | (width << 8) |
- (CFG_SPI_ENABLE << 14);
dev_dbg(&drv_data->pdev->dev,
"IO write: cr is 0x%x\n", cr);

- write_CTRL(cr);
+ /* set SPI transfer mode */
+ write_CTRL(cr | CFG_SPI_WRITE);

drv_data->write(drv_data);

@@ -837,13 +854,11 @@ static void pump_transfers(unsigned long data)
tranf_success = 0;
} else if (drv_data->rx != NULL) {
/* read only half duplex */
- cr = (read_CTRL() & (~BIT_CTL_TIMOD));
- cr |= CFG_SPI_READ | (width << 8) |
- (CFG_SPI_ENABLE << 14);
dev_dbg(&drv_data->pdev->dev,
"IO read: cr is 0x%x\n", cr);

- write_CTRL(cr);
+ /* set SPI transfer mode */
+ write_CTRL(cr | CFG_SPI_READ);

drv_data->read(drv_data);
if (drv_data->rx != drv_data->rx_end)
@@ -858,9 +873,6 @@ static void pump_transfers(unsigned long data)
/* Update total byte transfered */
message->actual_length += drv_data->len;

- if (drv_data->cs_change)
- cs_deactive(chip);
-
/* Move to next transfer of this msg */
message->state = next_transfer(drv_data);
}
--
1.5.3.4

2007-10-12 03:09:36

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 08/10] Blackfin SPI driver: Move GPIO config to setup and cleanup

From: Sonic Zhang <[email protected]>

Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 52 +++++++++++++++++++++++---------------------
1 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index ecfb7c5..c1516cb 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -136,7 +136,6 @@ struct chip_data {
u16 flag;

u8 chip_select_num;
- u8 chip_select_requested;
u8 n_bytes;
u8 width; /* 0 or 1 */
u8 enable_dma;
@@ -216,19 +215,7 @@ static int restore_state(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
int ret = 0;
- u16 ssel[3][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},
- };
+
/* Clear status and disable clock */
write_STAT(BIT_STAT_CLR);
bfin_spi_disable(drv_data);
@@ -239,17 +226,6 @@ static int restore_state(struct driver_data *drv_data)
write_BAUD(chip->baud);
cs_active(chip);

- if (!chip->chip_select_requested) {
- int i = chip->chip_select_num;
-
- dev_dbg(&drv_data->pdev->dev, "chip select number is %d\n", i);
- if ((i > 0) && (i <= MAX_SPI_SSEL))
- ret = peripheral_request(
- ssel[drv_data->master->bus_num][i-1], DRV_NAME);
-
- chip->chip_select_requested = 1;
- }
-
if (ret)
dev_dbg(&drv_data->pdev->dev,
": request chip select number %d failed\n",
@@ -981,6 +957,22 @@ static int transfer(struct spi_device *spi, struct spi_message *msg)
return 0;
}

+#define MAX_SPI_SSEL 7
+
+static u16 ssel[3][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},
+};
+
/* first setup for new devices */
static int setup(struct spi_device *spi)
{
@@ -1109,6 +1101,12 @@ static int setup(struct spi_device *spi)

spi_set_ctldata(spi, chip);

+ dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num);
+ 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);
+
return 0;
}

@@ -1120,6 +1118,10 @@ static void cleanup(struct spi_device *spi)
{
struct chip_data *chip = spi_get_ctldata(spi);

+ if ((chip->chip_select_num > 0)
+ && (chip->chip_select_num <= spi->master->num_chipselect))
+ peripheral_free(ssel[spi->master->bus_num][chip->chip_select_num-1]);
+
kfree(chip);
}

--
1.5.3.4

2007-10-12 03:10:08

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 07/10] Blackfin SPI driver: Add SPI master controller platform device 1

From: Sonic Zhang <[email protected]>

Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 52 ++++++++++++++++++++++++++------------------
1 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 891d263..ecfb7c5 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -209,17 +209,26 @@ static void cs_deactive(struct chip_data *chip)
write_FLAG(flag);
}

-#define MAX_SPI0_SSEL 7
+#define MAX_SPI_SSEL 7

/* stop controller and re-config current chip*/
static int restore_state(struct driver_data *drv_data)
{
struct chip_data *chip = drv_data->cur_chip;
int ret = 0;
- u16 ssel[MAX_SPI0_SSEL] = {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
- P_SPI0_SSEL4, P_SPI0_SSEL5,
- P_SPI0_SSEL6, P_SPI0_SSEL7,};
-
+ u16 ssel[3][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},
+ };
/* Clear status and disable clock */
write_STAT(BIT_STAT_CLR);
bfin_spi_disable(drv_data);
@@ -234,9 +243,9 @@ static int restore_state(struct driver_data *drv_data)
int i = chip->chip_select_num;

dev_dbg(&drv_data->pdev->dev, "chip select number is %d\n", i);
-
- if ((i > 0) && (i <= MAX_SPI0_SSEL))
- ret = peripheral_request(ssel[i-1], DRV_NAME);
+ if ((i > 0) && (i <= MAX_SPI_SSEL))
+ ret = peripheral_request(
+ ssel[drv_data->master->bus_num][i-1], DRV_NAME);

chip->chip_select_requested = 1;
}
@@ -329,7 +338,6 @@ static void u8_reader(struct driver_data *drv_data)
write_TDBR(0xFFFF);

dummy_read();
-
while (drv_data->rx < drv_data->rx_end - 1) {
while (!(read_STAT() & BIT_STAT_RXS))
continue;
@@ -640,7 +648,6 @@ static void pump_transfers(unsigned long data)
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
*/
@@ -1202,17 +1209,20 @@ static inline int destroy_queue(struct driver_data *drv_data)
return 0;
}

-static int setup_pin_mux(int action)
+static int setup_pin_mux(int action, int bus_num)
{

- u16 pin_req[] = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0};
+ 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, DRV_NAME)) {
+ if (peripheral_request_list(pin_req[bus_num], DRV_NAME))
return -EFAULT;
- }
} else {
- peripheral_free_list(pin_req);
+ peripheral_free_list(pin_req[bus_num]);
}

return 0;
@@ -1236,11 +1246,6 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
return -ENOMEM;
}

- if (setup_pin_mux(1)) {
- dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
- goto out_error;
- }
-
drv_data = spi_master_get_devdata(master);
drv_data->master = master;
drv_data->master_info = platform_info;
@@ -1295,6 +1300,11 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
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\n",
DRV_DESC, DRV_VERSION, spi_regs_base);
return status;
@@ -1337,7 +1347,7 @@ static int __devexit bfin5xx_spi_remove(struct platform_device *pdev)
/* Disconnect from the SPI framework */
spi_unregister_master(drv_data->master);

- setup_pin_mux(0);
+ setup_pin_mux(0, drv_data->master->bus_num);

/* Prevent double remove */
platform_set_drvdata(pdev, NULL);
--
1.5.3.4

2007-10-12 03:10:47

by Bryan Wu

[permalink] [raw]
Subject: [PATCH 02/10] Blackfin SPI driver: use new GPIO API and add error handling

From: Michael Hennerich <[email protected]>

Signed-off-by: Michael Hennerich <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/spi/spi_bfin5xx.c | 29 +++++++++++++++++++++++------
include/asm-blackfin/mach-bf533/portmux.h | 2 +-
2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 2992ada..8041b89 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1165,6 +1165,22 @@ static inline int destroy_queue(struct driver_data *drv_data)
return 0;
}

+static int setup_pin_mux(int action)
+{
+
+ u16 pin_req[] = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0};
+
+ if (action) {
+ if (peripheral_request_list(pin_req, DRV_NAME)) {
+ return -EFAULT;
+ }
+ } else {
+ peripheral_free_list(pin_req);
+ }
+
+ return 0;
+}
+
static int __init bfin5xx_spi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1182,12 +1198,9 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
return -ENOMEM;
}

- if (peripheral_request(P_SPI0_SCK, DRV_NAME) ||
- peripheral_request(P_SPI0_MISO, DRV_NAME) ||
- peripheral_request(P_SPI0_MOSI, DRV_NAME) ) {
-
+ if (setup_pin_mux(1)) {
dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
- goto out_error_queue_alloc;
+ goto out_error;
}

drv_data = spi_master_get_devdata(master);
@@ -1223,9 +1236,11 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "controller probe successfully\n");
return status;

- out_error_queue_alloc:
+out_error_queue_alloc:
destroy_queue(drv_data);
+out_error:
spi_master_put(master);
+
return status;
}

@@ -1255,6 +1270,8 @@ static int __devexit bfin5xx_spi_remove(struct platform_device *pdev)
/* Disconnect from the SPI framework */
spi_unregister_master(drv_data->master);

+ setup_pin_mux(0);
+
/* Prevent double remove */
platform_set_drvdata(pdev, NULL);

diff --git a/include/asm-blackfin/mach-bf533/portmux.h b/include/asm-blackfin/mach-bf533/portmux.h
index b88d7a0..137f488 100644
--- a/include/asm-blackfin/mach-bf533/portmux.h
+++ b/include/asm-blackfin/mach-bf533/portmux.h
@@ -42,7 +42,7 @@
#define P_SPORT0_DRPRI (P_DONTCARE)

#define P_SPI0_MOSI (P_DONTCARE)
-#define P_SPI0_MIS0 (P_DONTCARE)
+#define P_SPI0_MISO (P_DONTCARE)
#define P_SPI0_SCK (P_DONTCARE)
#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PF7))
#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF6))
--
1.5.3.4

2007-10-12 06:26:45

by David Brownell

[permalink] [raw]
Subject: Re: [PATCH 02/10] Blackfin SPI driver: use new GPIO API and add error handling

On Thursday 11 October 2007, Bryan Wu wrote:
> @@ -1182,12 +1198,9 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
> ????????????????return -ENOMEM;
> ????????}
> ?
> -???????if (peripheral_request(P_SPI0_SCK, DRV_NAME) ||
> -??????????????? peripheral_request(P_SPI0_MISO, DRV_NAME) ||
> -??????????????? peripheral_request(P_SPI0_MOSI, DRV_NAME) ) {
> -
> +???????if (setup_pin_mux(1)) {
> ????????????????dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
> -???????????????goto out_error_queue_alloc;
> +???????????????goto out_error;
> ????????}
> ?
> ????????drv_data = spi_master_get_devdata(master);
>

Still doesn't apply ... what tree are you generating this series against??

2007-10-12 06:54:49

by Bryan Wu

[permalink] [raw]
Subject: Re: [PATCH 02/10] Blackfin SPI driver: use new GPIO API and add error handling

On Thu, 2007-10-11 at 23:26 -0700, David Brownell wrote:
> On Thursday 11 October 2007, Bryan Wu wrote:
> > @@ -1182,12 +1198,9 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
> > return -ENOMEM;
> > }
> >
> > - if (peripheral_request(P_SPI0_SCK, DRV_NAME) ||
> > - peripheral_request(P_SPI0_MISO, DRV_NAME) ||
> > - peripheral_request(P_SPI0_MOSI, DRV_NAME) ) {
> > -
> > + if (setup_pin_mux(1)) {
> > dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
> > - goto out_error_queue_alloc;
> > + goto out_error;
> > }
> >
> > drv_data = spi_master_get_devdata(master);
> >
>
> Still doesn't apply ... what tree are you generating this series against??

I apply this patch on Linus git tree at 2.6.23 tag
git-request-pull output:
---
The following changes since commit bbf25010f1a6b761914430f5fca081ec8c7accd1:
Linus Torvalds (1):
Linux 2.6.23

Bryan Wu (4):
Blackfin SPI driver: Initial supporting BF54x in SPI driver
Blackfin SPI driver: add error handing
Blackfin SPI driver: Blackfin SPI driver does not respect the per-transfer cs_change field
Blackfin SPI driver: update spi driver to support multi-ports

Michael Hennerich (1):
Blackfin SPI driver: use new GPIO API and add error handling

Mike Frysinger (1):
Blackfin SPI driver: prevent people from setting bits in ctl_reg

Sonic Zhang (4):
Blackfin SPI driver: Add SPI master controller platform device 1
Blackfin SPI driver: Move GPIO config to setup and cleanup
Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548
Blackfin SPI driver: Clean up useless wait in bfin SPI driver

drivers/spi/spi_bfin5xx.c | 586 ++++++++++++++---------
include/asm-blackfin/mach-bf533/portmux.h | 2 +-
include/asm-blackfin/mach-bf548/defBF54x_base.h | 17 +
3 files changed, 373 insertions(+), 232 deletions(-)

---
Need I send out just one SPI patch.

Thanks
-Bryan Wu

2007-10-12 17:18:18

by David Brownell

[permalink] [raw]
Subject: Re: [PATCH 02/10] Blackfin SPI driver: use new GPIO API and add error handling

On Thursday 11 October 2007, Bryan Wu wrote:
> On Thu, 2007-10-11 at 23:26 -0700, David Brownell wrote:
> > On Thursday 11 October 2007, Bryan Wu wrote:
> > > @@ -1182,12 +1198,9 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
> > > return -ENOMEM;
> > > }
> > >
> > > - if (peripheral_request(P_SPI0_SCK, DRV_NAME) ||
> > > - peripheral_request(P_SPI0_MISO, DRV_NAME) ||
> > > - peripheral_request(P_SPI0_MOSI, DRV_NAME) ) {
> > > -
> > > + if (setup_pin_mux(1)) {
> > > dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
> > > - goto out_error_queue_alloc;
> > > + goto out_error;
> > > }
> > >
> > > drv_data = spi_master_get_devdata(master);
> > >
> >
> > Still doesn't apply ... what tree are you generating this series against??
>
> I apply this patch on Linus git tree at 2.6.23 tag

Then why don't my copies of that tree have the lines flagged
above with "-" ??

In fact, if I look at the kernel.org GIT tree, it doesn't have
them either. Your tree must have somehow gotten a bunch of
private changes.


> git-request-pull output:
> ---
> The following changes since commit bbf25010f1a6b761914430f5fca081ec8c7accd1:
> Linus Torvalds (1):
> Linux 2.6.23
>
> Bryan Wu (4):
> Blackfin SPI driver: Initial supporting BF54x in SPI driver
> Blackfin SPI driver: add error handing
> Blackfin SPI driver: Blackfin SPI driver does not respect the per-transfer cs_change field
> Blackfin SPI driver: update spi driver to support multi-ports
>
> Michael Hennerich (1):
> Blackfin SPI driver: use new GPIO API and add error handling
>
> Mike Frysinger (1):
> Blackfin SPI driver: prevent people from setting bits in ctl_reg
>
> Sonic Zhang (4):
> Blackfin SPI driver: Add SPI master controller platform device 1
> Blackfin SPI driver: Move GPIO config to setup and cleanup
> Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548
> Blackfin SPI driver: Clean up useless wait in bfin SPI driver
>
> drivers/spi/spi_bfin5xx.c | 586 ++++++++++++++---------
> include/asm-blackfin/mach-bf533/portmux.h | 2 +-
> include/asm-blackfin/mach-bf548/defBF54x_base.h | 17 +
> 3 files changed, 373 insertions(+), 232 deletions(-)
>
> ---
> Need I send out just one SPI patch.
>
> Thanks
> -Bryan Wu
>


2007-10-14 17:07:07

by Bryan Wu

[permalink] [raw]
Subject: Re: [PATCH 02/10] Blackfin SPI driver: use new GPIO API and add error handling

On 10/13/07, David Brownell <[email protected]> wrote:
> On Thursday 11 October 2007, Bryan Wu wrote:
> > On Thu, 2007-10-11 at 23:26 -0700, David Brownell wrote:
> > > On Thursday 11 October 2007, Bryan Wu wrote:
> > > > @@ -1182,12 +1198,9 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
> > > > return -ENOMEM;
> > > > }
> > > >
> > > > - if (peripheral_request(P_SPI0_SCK, DRV_NAME) ||
> > > > - peripheral_request(P_SPI0_MISO, DRV_NAME) ||
> > > > - peripheral_request(P_SPI0_MOSI, DRV_NAME) ) {
> > > > -
> > > > + if (setup_pin_mux(1)) {
> > > > dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
> > > > - goto out_error_queue_alloc;
> > > > + goto out_error;
> > > > }
> > > >
> > > > drv_data = spi_master_get_devdata(master);
> > > >
> > >
> > > Still doesn't apply ... what tree are you generating this series against??
> >
> > I apply this patch on Linus git tree at 2.6.23 tag
>
> Then why don't my copies of that tree have the lines flagged
> above with "-" ??
>
> In fact, if I look at the kernel.org GIT tree, it doesn't have
> them either. Your tree must have somehow gotten a bunch of
> private changes.
>
>
Yes, the GIT tree's code is without that lines, which are introduced
by the first patch of my SPI update patches: Blackfin SPI driver:
Initial supporting BF54x in SPI driver.

So please apply the latest whole Blackfin SPI driver update patchset
including 10 patches instead of 9 patches in previous email.

Thanks a lot
Best Regards

2007-10-18 06:07:07

by Bryan Wu

[permalink] [raw]
Subject: Re: [PATCH 02/10] Blackfin SPI driver: use new GPIO API and add error handling

On 10/13/07, David Brownell <[email protected]> wrote:
> On Thursday 11 October 2007, Bryan Wu wrote:
> > On Thu, 2007-10-11 at 23:26 -0700, David Brownell wrote:
> > > On Thursday 11 October 2007, Bryan Wu wrote:
> > > > @@ -1182,12 +1198,9 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
> > > > return -ENOMEM;
> > > > }
> > > >
> > > > - if (peripheral_request(P_SPI0_SCK, DRV_NAME) ||
> > > > - peripheral_request(P_SPI0_MISO, DRV_NAME) ||
> > > > - peripheral_request(P_SPI0_MOSI, DRV_NAME) ) {
> > > > -
> > > > + if (setup_pin_mux(1)) {
> > > > dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
> > > > - goto out_error_queue_alloc;
> > > > + goto out_error;
> > > > }
> > > >
> > > > drv_data = spi_master_get_devdata(master);
> > > >
> > >
> > > Still doesn't apply ... what tree are you generating this series against??
> >
> > I apply this patch on Linus git tree at 2.6.23 tag
>
> Then why don't my copies of that tree have the lines flagged
> above with "-" ??
>
> In fact, if I look at the kernel.org GIT tree, it doesn't have
> them either. Your tree must have somehow gotten a bunch of
> private changes.
>

Did you apply these patches, or I need resent a new patchset against
latest Linus GIT tree?
I noticed in latest GIT tree the Blackfin SPI driver are modified.

Thanks
-Bryan Wu

2007-10-19 17:57:45

by David Brownell

[permalink] [raw]
Subject: Re: [PATCH 02/10] Blackfin SPI driver: use new GPIO API and add error handling

> > In fact, if I look at the kernel.org GIT tree, it doesn't have
> > them either. Your tree must have somehow gotten a bunch of
> > private changes.
>
> Did you apply these patches, or I need resent a new patchset against
> latest Linus GIT tree?

I'm still not quite sure why the patches you sent didn't apply
for me. Why don't you send refreshed patches to me after RC1.


> I noticed in latest GIT tree the Blackfin SPI driver are modified.

Yes, various cleanup patches. Missing newlines in dev_*() calls,
class_device removal, remove extra includes, and so forth. They
might conflict with your patches (I suspect they won't).

That's a big part of why you should arrange to submit patches well
in advance of the merge window opening. As a rule, maintainers
won't have/make extra time during that window to review and/or fix
nontrivial issues, or address conflicts with other patches. Try to
submit at least a few weeks before the previous kernel finalizes.

- Dave