- add BF54x support - add multi SPI ports support - fixup some bugs -
From: Mike Frysinger <michael.frysinger@analog.com>
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 <michael.frysinger@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
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
-
- 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 <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
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 */
...Add cs_active/cs_deactive functions and try to catch the cs_change flag.
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
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;
...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 <bryan.wu@analog.com>
---
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 ...From: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
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, ...From: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
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 ...From: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
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 ...This doesn't apply against 2.6.23 ... ? -
Oops, I missed the first patch in this patch series. It will be sent as soon as possible. Thanks a lot -Bryan -
From: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
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 = ...From: Sonic Zhang <sonic.zhang@analog.com>
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 <sonic.zhang@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
---
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 ...