* [PATCH 01/14] Blackfin SPI driver: Initial supporting BF54x in SPI driver
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
@ 2007-10-30 9:17 ` Bryan Wu
2007-10-30 9:17 ` [PATCH 02/14] Blackfin SPI driver: use new GPIO API and add error handling Bryan Wu
` (13 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:17 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, linux-kernel-u79uwXL29TY76Z2rM5mHXA
- support BF54x SPI0
- clean up some code
- will support multiports in the future
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
drivers/spi/spi_bfin5xx.c | 129 +++++++++++------------
include/asm-blackfin/mach-bf548/defBF54x_base.h | 17 +++
2 files changed, 80 insertions(+), 66 deletions(-)
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 2ef11bb..621a3eb 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 <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
+ * 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,27 +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/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) \
@@ -124,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;
@@ -188,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);
@@ -277,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));
@@ -316,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) */
@@ -403,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) {
@@ -816,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,
@@ -834,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);
@@ -849,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);
@@ -861,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 {
@@ -916,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);
@@ -1193,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 da979cb..319a485 100644
--- a/include/asm-blackfin/mach-bf548/defBF54x_base.h
+++ b/include/asm-blackfin/mach-bf548/defBF54x_base.h
@@ -1644,8 +1644,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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 02/14] Blackfin SPI driver: use new GPIO API and add error handling
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
2007-10-30 9:17 ` [PATCH 01/14] Blackfin SPI driver: Initial supporting BF54x in SPI driver Bryan Wu
@ 2007-10-30 9:17 ` Bryan Wu
2007-10-30 9:17 ` [PATCH 03/14] Blackfin SPI driver: add error handing Bryan Wu
` (12 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:17 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Michael Hennerich
From: Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Michael Hennerich <michael.hennerich-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 621a3eb..eeaa65d 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 03/14] Blackfin SPI driver: add error handing
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
2007-10-30 9:17 ` [PATCH 01/14] Blackfin SPI driver: Initial supporting BF54x in SPI driver Bryan Wu
2007-10-30 9:17 ` [PATCH 02/14] Blackfin SPI driver: use new GPIO API and add error handling Bryan Wu
@ 2007-10-30 9:17 ` Bryan Wu
2007-10-30 9:17 ` [PATCH 04/14] Blackfin SPI driver: Blackfin SPI driver does not respect the per-transfer cs_change field Bryan Wu
` (11 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:17 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Michael Hennerich
- 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-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 eeaa65d..49f4eac 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 04/14] Blackfin SPI driver: Blackfin SPI driver does not respect the per-transfer cs_change field
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (2 preceding siblings ...)
2007-10-30 9:17 ` [PATCH 03/14] Blackfin SPI driver: add error handing Bryan Wu
@ 2007-10-30 9:17 ` Bryan Wu
2007-10-30 9:17 ` [PATCH 05/14] Blackfin SPI driver: prevent people from setting bits in ctl_reg Bryan Wu
` (10 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:17 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Add cs_active/cs_deactive functions and try to catch the cs_change flag.
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 49f4eac..1a55aa7 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 05/14] Blackfin SPI driver: prevent people from setting bits in ctl_reg
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (3 preceding siblings ...)
2007-10-30 9:17 ` [PATCH 04/14] Blackfin SPI driver: Blackfin SPI driver does not respect the per-transfer cs_change field Bryan Wu
@ 2007-10-30 9:17 ` Bryan Wu
2007-10-30 9:17 ` [PATCH 06/14] Blackfin SPI driver: update spi driver to support multi-ports Bryan Wu
` (9 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:17 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, Mike Frysinger, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Mike Frysinger <michael.frysinger-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
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-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 1a55aa7..e4d64a0 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 06/14] Blackfin SPI driver: update spi driver to support multi-ports
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (4 preceding siblings ...)
2007-10-30 9:17 ` [PATCH 05/14] Blackfin SPI driver: prevent people from setting bits in ctl_reg Bryan Wu
@ 2007-10-30 9:17 ` Bryan Wu
2007-10-30 9:17 ` [PATCH 07/14] Blackfin SPI driver: Add SPI master controller platform device 1 Bryan Wu
` (8 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:17 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, linux-kernel-u79uwXL29TY76Z2rM5mHXA
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-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 e4d64a0..3f3630c 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 07/14] Blackfin SPI driver: Add SPI master controller platform device 1
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (5 preceding siblings ...)
2007-10-30 9:17 ` [PATCH 06/14] Blackfin SPI driver: update spi driver to support multi-ports Bryan Wu
@ 2007-10-30 9:17 ` Bryan Wu
2007-10-30 19:08 ` David Brownell
2007-10-30 9:17 ` [PATCH 08/14] Blackfin SPI driver: Move GPIO config to setup and cleanup Bryan Wu
` (7 subsequent siblings)
14 siblings, 1 reply; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:17 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, Sonic Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 3f3630c..3bd8359 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH 07/14] Blackfin SPI driver: Add SPI master controller platform device 1
2007-10-30 9:17 ` [PATCH 07/14] Blackfin SPI driver: Add SPI master controller platform device 1 Bryan Wu
@ 2007-10-30 19:08 ` David Brownell
[not found] ` <200710301208.13367.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
0 siblings, 1 reply; 34+ messages in thread
From: David Brownell @ 2007-10-30 19:08 UTC (permalink / raw)
To: Bryan Wu; +Cc: spi-devel-general, linux-kernel, Sonic Zhang
On Tuesday 30 October 2007, Bryan Wu wrote:
> 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>
The patch comments in this series leave a bit to be desired,
especially patches from Sonic. (Several are like this one:
just a $SUBJECT, no description.) I've improved them in the
versions I'll be sending on ...
It's worth noting that in this case the $SUBJECT doesn't
relate *at all* to what this patch actually does! Namely,
it uses the portmux mechanism to add support for two more
SPI buses ... it doesn't add a platform device.
- Dave
> ---
> 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 3f3630c..3bd8359 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
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH 08/14] Blackfin SPI driver: Move GPIO config to setup and cleanup
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (6 preceding siblings ...)
2007-10-30 9:17 ` [PATCH 07/14] Blackfin SPI driver: Add SPI master controller platform device 1 Bryan Wu
@ 2007-10-30 9:17 ` Bryan Wu
2007-10-30 9:18 ` [PATCH 09/14] Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548 Bryan Wu
` (6 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:17 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, Sonic Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 3bd8359..7f95797 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 09/14] Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (7 preceding siblings ...)
2007-10-30 9:17 ` [PATCH 08/14] Blackfin SPI driver: Move GPIO config to setup and cleanup Bryan Wu
@ 2007-10-30 9:18 ` Bryan Wu
2007-10-30 20:05 ` David Brownell
2007-10-30 9:18 ` [PATCH 10/14] Blackfin SPI driver: Clean up useless wait in bfin SPI driver Bryan Wu
` (5 subsequent siblings)
14 siblings, 1 reply; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:18 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, Sonic Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
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-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 7f95797..e1fd197 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH 09/14] Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548
2007-10-30 9:18 ` [PATCH 09/14] Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548 Bryan Wu
@ 2007-10-30 20:05 ` David Brownell
2007-10-31 6:50 ` Bryan Wu
0 siblings, 1 reply; 34+ messages in thread
From: David Brownell @ 2007-10-30 20:05 UTC (permalink / raw)
To: Bryan Wu; +Cc: spi-devel-general, linux-kernel, Sonic Zhang
On Tuesday 30 October 2007, Bryan Wu wrote:
> 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.
That's actually not true. If a driver sets spi_transfer.max_speed_hz
to a nonzero value that's different from the previous bit rate (which
may be spi_device.max_speed_hz), it should be updated before that
transfer segment. Example, sometimes data can't be clocked out at
the same rate commands can be clocked in.
Similarly with spi_transfer.bits_per_word ... again, it's very possible
that commands and data have different sizes.
Of course, if those values don't change, there'd be no point in
reconfiguring any aspect of those communications parameters...
I'll be forwarding this patch, since this looks like another case
where the main effect of the patch doesn't match its description
and since this patch series has taken too long already. (Does this
patch even really relate primarily to working with an ST M25P16
flash part??) Though it'd be reasonable to be more hard-nosed
about this and insist on another go-around for thesse patches.
(Making this the fifth one??)
But I *STRONGLY* suggest someone revisit the issue of whether those
two per-transfer options are now being handled correctly. As well
as update procedures so that the patch comments start to have a
direct correspondence to what the patches have changed...
- Dave
> This patch
> move move SPI setting to the begining of a message session. And never
> disables SPI controller until an error occurs.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 09/14] Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548
2007-10-30 20:05 ` David Brownell
@ 2007-10-31 6:50 ` Bryan Wu
2007-10-31 7:11 ` David Brownell
0 siblings, 1 reply; 34+ messages in thread
From: Bryan Wu @ 2007-10-31 6:50 UTC (permalink / raw)
To: David Brownell; +Cc: Bryan Wu, spi-devel-general, linux-kernel, Sonic Zhang
On Tue, 2007-10-30 at 13:05 -0700, David Brownell wrote:
> On Tuesday 30 October 2007, Bryan Wu wrote:
> > 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.
>
> That's actually not true. If a driver sets spi_transfer.max_speed_hz
> to a nonzero value that's different from the previous bit rate (which
> may be spi_device.max_speed_hz), it should be updated before that
> transfer segment. Example, sometimes data can't be clocked out at
> the same rate commands can be clocked in.
>
> Similarly with spi_transfer.bits_per_word ... again, it's very possible
> that commands and data have different sizes.
>
I agree with you here.
Maybe there are some confusion of mixing up the spi_trasnfer.speed_hz
with the spi_device.max_speed_hz.
spi_device.max_speed_hz comes from spi_board_info.max_speed_hz, it is
for the default max speed value.
spi_transfer.speed_hz comes from upper applications for each spi
transfer setting.
Am I right?
I will fix this later.
> Of course, if those values don't change, there'd be no point in
> reconfiguring any aspect of those communications parameters...
>
>
> I'll be forwarding this patch, since this looks like another case
> where the main effect of the patch doesn't match its description
> and since this patch series has taken too long already. (Does this
> patch even really relate primarily to working with an ST M25P16
> flash part??) Though it'd be reasonable to be more hard-nosed
> about this and insist on another go-around for thesse patches.
> (Making this the fifth one??)
>
> But I *STRONGLY* suggest someone revisit the issue of whether those
> two per-transfer options are now being handled correctly. As well
> as update procedures so that the patch comments start to have a
> direct correspondence to what the patches have changed...
>
OK, we will test this on our hardware.
Thanks, Dave
-Bryan Wu
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH 09/14] Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548
2007-10-31 6:50 ` Bryan Wu
@ 2007-10-31 7:11 ` David Brownell
[not found] ` <200710310011.33545.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
0 siblings, 1 reply; 34+ messages in thread
From: David Brownell @ 2007-10-31 7:11 UTC (permalink / raw)
To: bryan.wu-OyLXuOCK7orQT0dZR+AlfA
Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Sonic Zhang,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Tuesday 30 October 2007, Bryan Wu wrote:
> Maybe there are some confusion of mixing up the spi_trasnfer.speed_hz
> with the spi_device.max_speed_hz.
>
> spi_device.max_speed_hz comes from spi_board_info.max_speed_hz, it is
> for the default max speed value.
It's initialized from board_info, yes. Drivers can override it
using spi_setup().
One would expect they only override _downwards_ but that's not
guaranteed anywhere. A driver might have a way to establish that
this particular board can run faster, for example.
> spi_transfer.speed_hz comes from upper applications for each spi
> transfer setting.
Certainly; all spi_transfer records come from applications!
If that value is zero, that transfer segment uses the limit
from the spi_device ... otherwise, it can differ. Again,
the limits can vary based on devise characteristics; maybe
it can't feed data as fast for some commands.
(ISTR the M25P16 in $SUBJECT has two read commands, one of
which is only usable at clock rates below 33 MHz or so, but
most other commands can work above that speed just fine.)
- Dave
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 34+ messages in thread
* [PATCH 10/14] Blackfin SPI driver: Clean up useless wait in bfin SPI driver
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (8 preceding siblings ...)
2007-10-30 9:18 ` [PATCH 09/14] Blackfin SPI driver: Fix SPI driver to work with SPI flash ST25P16 on bf548 Bryan Wu
@ 2007-10-30 9:18 ` Bryan Wu
2007-10-30 9:18 ` [PATCH 11/14] Blackfin SPI driver: Move global SPI regs_base and dma_ch to struct driver_data Bryan Wu
` (4 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:18 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, Sonic Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
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 e1fd197..d69719b 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
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 11/14] Blackfin SPI driver: Move global SPI regs_base and dma_ch to struct driver_data
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (9 preceding siblings ...)
2007-10-30 9:18 ` [PATCH 10/14] Blackfin SPI driver: Clean up useless wait in bfin SPI driver Bryan Wu
@ 2007-10-30 9:18 ` Bryan Wu
2007-10-30 9:18 ` [PATCH 12/14] Blackfin SPI driver: Fix bug in u16_cs_chg_reader to read data_len-2 bytes data firstly, then read out the last 2 bytes data Bryan Wu
` (3 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:18 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Test on BF54x SPI Flash with 2 SPI master driver enabled
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
drivers/spi/spi_bfin5xx.c | 357 +++++++++++++++++++++++----------------------
1 files changed, 182 insertions(+), 175 deletions(-)
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index d69719b..5924903 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -63,29 +63,12 @@ MODULE_LICENSE("GPL");
#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(spi_regs_base + off); } \
-static inline void write_##reg(u16 v) \
- {bfin_write16(spi_regs_base + off, v); }
-
-DEFINE_SPI_REG(CTRL, 0x00)
-DEFINE_SPI_REG(FLAG, 0x04)
-DEFINE_SPI_REG(STAT, 0x08)
-DEFINE_SPI_REG(TDBR, 0x0C)
-DEFINE_SPI_REG(RDBR, 0x10)
-DEFINE_SPI_REG(BAUD, 0x14)
-DEFINE_SPI_REG(SHAW, 0x18)
#define START_STATE ((void*)0)
#define RUNNING_STATE ((void*)1)
#define DONE_STATE ((void*)2)
#define ERROR_STATE ((void*)-1)
#define QUEUE_RUNNING 0
#define QUEUE_STOPPED 1
-int dma_requested;
struct driver_data {
/* Driver model hookup */
@@ -94,6 +77,9 @@ struct driver_data {
/* SPI framework hookup */
struct spi_master *master;
+ /* Regs base of SPI controller */
+ u32 regs_base;
+
/* BFIN hookup */
struct bfin5xx_spi_master *master_info;
@@ -118,9 +104,14 @@ struct driver_data {
void *tx_end;
void *rx;
void *rx_end;
+
+ /* DMA stuffs */
+ int dma_channel;
int dma_mapped;
+ int dma_requested;
dma_addr_t rx_dma;
dma_addr_t tx_dma;
+
size_t rx_map_len;
size_t tx_map_len;
u8 n_bytes;
@@ -147,20 +138,34 @@ struct chip_data {
void (*duplex) (struct driver_data *);
};
+#define DEFINE_SPI_REG(reg, off) \
+static inline u16 read_##reg(struct driver_data *drv_data) \
+ { return bfin_read16(drv_data->regs_base + off); } \
+static inline void write_##reg(struct driver_data *drv_data, u16 v) \
+ { bfin_write16(drv_data->regs_base + off, v); }
+
+DEFINE_SPI_REG(CTRL, 0x00)
+DEFINE_SPI_REG(FLAG, 0x04)
+DEFINE_SPI_REG(STAT, 0x08)
+DEFINE_SPI_REG(TDBR, 0x0C)
+DEFINE_SPI_REG(RDBR, 0x10)
+DEFINE_SPI_REG(BAUD, 0x14)
+DEFINE_SPI_REG(SHAW, 0x18)
+
static void bfin_spi_enable(struct driver_data *drv_data)
{
u16 cr;
- cr = read_CTRL();
- write_CTRL(cr | BIT_CTL_ENABLE);
+ cr = read_CTRL(drv_data);
+ write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
}
static void bfin_spi_disable(struct driver_data *drv_data)
{
u16 cr;
- cr = read_CTRL();
- write_CTRL(cr & (~BIT_CTL_ENABLE));
+ cr = read_CTRL(drv_data);
+ write_CTRL(drv_data, (cr & (~BIT_CTL_ENABLE)));
}
/* Caculate the SPI_BAUD register value based on input HZ */
@@ -180,32 +185,32 @@ static int flush(struct driver_data *drv_data)
unsigned long limit = loops_per_jiffy << 1;
/* wait for stop and clear stat */
- while (!(read_STAT() & BIT_STAT_SPIF) && limit--)
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && limit--)
continue;
- write_STAT(BIT_STAT_CLR);
+ write_STAT(drv_data, BIT_STAT_CLR);
return limit;
}
/* Chip select operation functions for cs_change flag */
-static void cs_active(struct chip_data *chip)
+static void cs_active(struct driver_data *drv_data, struct chip_data *chip)
{
- u16 flag = read_FLAG();
+ u16 flag = read_FLAG(drv_data);
flag |= chip->flag;
flag &= ~(chip->flag << 8);
- write_FLAG(flag);
+ write_FLAG(drv_data, flag);
}
-static void cs_deactive(struct chip_data *chip)
+static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
{
- u16 flag = read_FLAG();
+ u16 flag = read_FLAG(drv_data);
flag |= (chip->flag << 8);
- write_FLAG(flag);
+ write_FLAG(drv_data, flag);
}
#define MAX_SPI_SSEL 7
@@ -217,16 +222,16 @@ static int restore_state(struct driver_data *drv_data)
int ret = 0;
/* Clear status and disable clock */
- write_STAT(BIT_STAT_CLR);
+ write_STAT(drv_data, BIT_STAT_CLR);
bfin_spi_disable(drv_data);
dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
/* Load the registers */
- cs_deactive(chip);
- write_BAUD(chip->baud);
+ 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(chip->ctl_reg);
+ write_CTRL(drv_data, chip->ctl_reg);
bfin_spi_enable(drv_data);
@@ -239,10 +244,10 @@ static int restore_state(struct driver_data *drv_data)
}
/* used to kick off transfer in rx mode */
-static unsigned short dummy_read(void)
+static unsigned short dummy_read(struct driver_data *drv_data)
{
unsigned short tmp;
- tmp = read_RDBR();
+ tmp = read_RDBR(drv_data);
return tmp;
}
@@ -251,8 +256,8 @@ static void null_writer(struct driver_data *drv_data)
u8 n_bytes = drv_data->n_bytes;
while (drv_data->tx < drv_data->tx_end) {
- write_TDBR(0);
- while ((read_STAT() & BIT_STAT_TXS))
+ write_TDBR(drv_data, 0);
+ while ((read_STAT(drv_data) & BIT_STAT_TXS))
continue;
drv_data->tx += n_bytes;
}
@@ -261,12 +266,12 @@ static void null_writer(struct driver_data *drv_data)
static void null_reader(struct driver_data *drv_data)
{
u8 n_bytes = drv_data->n_bytes;
- dummy_read();
+ dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- dummy_read();
+ dummy_read(drv_data);
drv_data->rx += n_bytes;
}
}
@@ -274,15 +279,15 @@ static void null_reader(struct driver_data *drv_data)
static void u8_writer(struct driver_data *drv_data)
{
dev_dbg(&drv_data->pdev->dev,
- "cr8-s is 0x%x\n", read_STAT());
+ "cr8-s is 0x%x\n", read_STAT(drv_data));
/* poll for SPI completion before start */
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
while (drv_data->tx < drv_data->tx_end) {
- write_TDBR(*(u8 *) (drv_data->tx));
- while (read_STAT() & BIT_STAT_TXS)
+ write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+ while (read_STAT(drv_data) & BIT_STAT_TXS)
continue;
++drv_data->tx;
}
@@ -293,16 +298,16 @@ 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))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
while (drv_data->tx < drv_data->tx_end) {
- cs_active(chip);
+ cs_active(drv_data, chip);
- write_TDBR(*(u8 *) (drv_data->tx));
- while (read_STAT() & BIT_STAT_TXS)
+ write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+ while (read_STAT(drv_data) & BIT_STAT_TXS)
continue;
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
@@ -313,27 +318,27 @@ 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,
- "cr-8 is 0x%x\n", read_STAT());
+ "cr-8 is 0x%x\n", read_STAT(drv_data));
/* poll for SPI completion before start */
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
/* clear TDBR buffer before read(else it will be shifted out) */
- write_TDBR(0xFFFF);
+ write_TDBR(drv_data, 0xFFFF);
- dummy_read();
+ dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end - 1) {
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u8 *) (drv_data->rx) = read_RDBR();
+ *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
++drv_data->rx;
}
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u8 *) (drv_data->rx) = read_SHAW();
+ *(u8 *) (drv_data->rx) = read_SHAW(drv_data);
++drv_data->rx;
}
@@ -342,49 +347,49 @@ 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))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
/* clear TDBR buffer before read(else it will be shifted out) */
- write_TDBR(0xFFFF);
+ write_TDBR(drv_data, 0xFFFF);
- cs_active(chip);
- dummy_read();
+ cs_active(drv_data, chip);
+ dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end - 1) {
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- cs_active(chip);
- *(u8 *) (drv_data->rx) = read_RDBR();
+ cs_active(drv_data, chip);
+ *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
++drv_data->rx;
}
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u8 *) (drv_data->rx) = read_SHAW();
+ *(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() & BIT_STAT_SPIF))
+ 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(*(u8 *) (drv_data->tx));
- while (read_STAT() & BIT_STAT_TXS)
+ write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+ while (read_STAT(drv_data) & BIT_STAT_TXS)
continue;
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u8 *) (drv_data->rx) = read_RDBR();
+ *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
++drv_data->rx;
++drv_data->tx;
}
@@ -395,19 +400,19 @@ 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))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
while (drv_data->rx < drv_data->rx_end) {
- cs_active(chip);
+ cs_active(drv_data, chip);
- write_TDBR(*(u8 *) (drv_data->tx));
- while (read_STAT() & BIT_STAT_TXS)
+ write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+ while (read_STAT(drv_data) & BIT_STAT_TXS)
continue;
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u8 *) (drv_data->rx) = read_RDBR();
- cs_deactive(chip);
+ *(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+ cs_deactive(drv_data, chip);
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
@@ -419,15 +424,15 @@ 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,
- "cr16 is 0x%x\n", read_STAT());
+ "cr16 is 0x%x\n", read_STAT(drv_data));
/* poll for SPI completion before start */
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
while (drv_data->tx < drv_data->tx_end) {
- write_TDBR(*(u16 *) (drv_data->tx));
- while ((read_STAT() & BIT_STAT_TXS))
+ write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+ while ((read_STAT(drv_data) & BIT_STAT_TXS))
continue;
drv_data->tx += 2;
}
@@ -438,16 +443,16 @@ 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))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
while (drv_data->tx < drv_data->tx_end) {
- cs_active(chip);
+ cs_active(drv_data, chip);
- write_TDBR(*(u16 *) (drv_data->tx));
- while ((read_STAT() & BIT_STAT_TXS))
+ write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+ while ((read_STAT(drv_data) & BIT_STAT_TXS))
continue;
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
@@ -458,27 +463,27 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)
static void u16_reader(struct driver_data *drv_data)
{
dev_dbg(&drv_data->pdev->dev,
- "cr-16 is 0x%x\n", read_STAT());
+ "cr-16 is 0x%x\n", read_STAT(drv_data));
/* poll for SPI completion before start */
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
/* clear TDBR buffer before read(else it will be shifted out) */
- write_TDBR(0xFFFF);
+ write_TDBR(drv_data, 0xFFFF);
- dummy_read();
+ dummy_read(drv_data);
while (drv_data->rx < (drv_data->rx_end - 2)) {
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u16 *) (drv_data->rx) = read_RDBR();
+ *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
drv_data->rx += 2;
}
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u16 *) (drv_data->rx) = read_SHAW();
+ *(u16 *) (drv_data->rx) = read_SHAW(drv_data);
drv_data->rx += 2;
}
@@ -487,49 +492,49 @@ 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))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
/* clear TDBR buffer before read(else it will be shifted out) */
- write_TDBR(0xFFFF);
+ write_TDBR(drv_data, 0xFFFF);
- cs_active(chip);
- dummy_read();
+ cs_active(drv_data, chip);
+ dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- cs_active(chip);
- *(u16 *) (drv_data->rx) = read_RDBR();
+ cs_active(drv_data, chip);
+ *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
drv_data->rx += 2;
}
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u16 *) (drv_data->rx) = read_SHAW();
+ *(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() & BIT_STAT_SPIF))
+ 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(*(u16 *) (drv_data->tx));
- while (read_STAT() & BIT_STAT_TXS)
+ write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+ while (read_STAT(drv_data) & BIT_STAT_TXS)
continue;
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u16 *) (drv_data->rx) = read_RDBR();
+ *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
drv_data->rx += 2;
drv_data->tx += 2;
}
@@ -540,19 +545,19 @@ 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))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
while (drv_data->tx < drv_data->tx_end) {
- cs_active(chip);
+ cs_active(drv_data, chip);
- write_TDBR(*(u16 *) (drv_data->tx));
- while (read_STAT() & BIT_STAT_TXS)
+ write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+ while (read_STAT(drv_data) & BIT_STAT_TXS)
continue;
- while (!(read_STAT() & BIT_STAT_RXS))
+ while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
- *(u16 *) (drv_data->rx) = read_RDBR();
- cs_deactive(chip);
+ *(u16 *) (drv_data->rx) = read_RDBR(drv_data);
+ cs_deactive(drv_data, chip);
if (chip->cs_chg_udelay)
udelay(chip->cs_chg_udelay);
@@ -603,12 +608,12 @@ 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) {
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
bfin_spi_disable(drv_data);
}
if (!drv_data->cs_change)
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
if (msg->complete)
msg->complete(msg->context);
@@ -617,14 +622,14 @@ static void giveback(struct driver_data *drv_data)
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;
+ struct spi_message *msg = drv_data->cur_msg;
dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n");
- clear_dma_irqstat(spi_dma_ch);
+ clear_dma_irqstat(drv_data->dma_channel);
/* Wait for DMA to complete */
- while (get_dma_curr_irqstat(spi_dma_ch) & DMA_RUN)
+ while (get_dma_curr_irqstat(drv_data->dma_channel) & DMA_RUN)
continue;
/*
@@ -634,18 +639,18 @@ 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 ((read_STAT() & TXS) ||
- (read_STAT() & TXS))
+ while ((read_STAT(drv_data) & TXS) ||
+ (read_STAT(drv_data) & TXS))
continue;
}
- while (!(read_STAT() & SPIF))
+ while (!(read_STAT(drv_data) & SPIF))
continue;
msg->actual_length += drv_data->len_in_bytes;
if (drv_data->cs_change)
- cs_deactive(chip);
+ cs_deactive(drv_data, chip);
/* Move to next transfer */
msg->state = next_transfer(drv_data);
@@ -656,8 +661,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",
- spi_dma_ch);
- dma_disable_irq(spi_dma_ch);
+ drv_data->dma_channel);
+ dma_disable_irq(drv_data->dma_channel);
return IRQ_HANDLED;
}
@@ -751,9 +756,9 @@ static void pump_transfers(unsigned long data)
message->state = RUNNING_STATE;
dma_config = 0;
- write_STAT(BIT_STAT_CLR);
- cr = (read_CTRL() & (~BIT_CTL_TIMOD));
- cs_active(chip);
+ write_STAT(drv_data, BIT_STAT_CLR);
+ cr = (read_CTRL(drv_data) & (~BIT_CTL_TIMOD));
+ cs_active(drv_data, chip);
dev_dbg(&drv_data->pdev->dev,
"now pumping a transfer: width is %d, len is %d\n",
@@ -766,23 +771,23 @@ static void pump_transfers(unsigned long data)
*/
if (drv_data->cur_chip->enable_dma && drv_data->len > 6) {
- disable_dma(spi_dma_ch);
- clear_dma_irqstat(spi_dma_ch);
+ disable_dma(drv_data->dma_channel);
+ clear_dma_irqstat(drv_data->dma_channel);
/* config dma channel */
dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n");
if (width == CFG_SPI_WORDSIZE16) {
- set_dma_x_count(spi_dma_ch, drv_data->len);
- set_dma_x_modify(spi_dma_ch, 2);
+ set_dma_x_count(drv_data->dma_channel, drv_data->len);
+ set_dma_x_modify(drv_data->dma_channel, 2);
dma_width = WDSIZE_16;
} else {
- set_dma_x_count(spi_dma_ch, drv_data->len);
- set_dma_x_modify(spi_dma_ch, 1);
+ set_dma_x_count(drv_data->dma_channel, drv_data->len);
+ set_dma_x_modify(drv_data->dma_channel, 1);
dma_width = WDSIZE_8;
}
/* poll for SPI completion before start */
- while (!(read_STAT() & BIT_STAT_SPIF))
+ while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
continue;
/* dirty hack for autobuffer DMA mode */
@@ -791,15 +796,15 @@ static void pump_transfers(unsigned long data)
"doing autobuffer DMA out.\n");
/* set SPI transfer mode */
- write_CTRL(cr | CFG_SPI_DMAWRITE);
+ write_CTRL(drv_data, (cr | CFG_SPI_DMAWRITE));
/* no irq in autobuffer mode */
dma_config =
(DMAFLOW_AUTO | RESTART | dma_width | DI_EN);
- set_dma_config(spi_dma_ch, dma_config);
- set_dma_start_addr(spi_dma_ch,
+ set_dma_config(drv_data->dma_channel, dma_config);
+ set_dma_start_addr(drv_data->dma_channel,
(unsigned long)drv_data->tx);
- enable_dma(spi_dma_ch);
+ enable_dma(drv_data->dma_channel);
/* just return here, there can only be one transfer in this mode */
message->status = 0;
@@ -813,34 +818,34 @@ static void pump_transfers(unsigned long data)
dev_dbg(&drv_data->pdev->dev, "doing DMA in.\n");
/* set SPI transfer mode */
- write_CTRL(cr | CFG_SPI_DMAREAD);
+ write_CTRL(drv_data, (cr | CFG_SPI_DMAREAD));
/* clear tx reg soformer data is not shifted out */
- write_TDBR(0xFFFF);
+ write_TDBR(drv_data, 0xFFFF);
- set_dma_x_count(spi_dma_ch, drv_data->len);
+ set_dma_x_count(drv_data->dma_channel, drv_data->len);
/* start dma */
- dma_enable_irq(spi_dma_ch);
+ dma_enable_irq(drv_data->dma_channel);
dma_config = (WNR | RESTART | dma_width | DI_EN);
- set_dma_config(spi_dma_ch, dma_config);
- set_dma_start_addr(spi_dma_ch,
+ set_dma_config(drv_data->dma_channel, dma_config);
+ set_dma_start_addr(drv_data->dma_channel,
(unsigned long)drv_data->rx);
- enable_dma(spi_dma_ch);
+ enable_dma(drv_data->dma_channel);
} 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);
+ write_CTRL(drv_data, (cr | CFG_SPI_DMAWRITE));
/* start dma */
- dma_enable_irq(spi_dma_ch);
+ dma_enable_irq(drv_data->dma_channel);
dma_config = (RESTART | dma_width | DI_EN);
- set_dma_config(spi_dma_ch, dma_config);
- set_dma_start_addr(spi_dma_ch,
+ set_dma_config(drv_data->dma_channel, dma_config);
+ set_dma_start_addr(drv_data->dma_channel,
(unsigned long)drv_data->tx);
- enable_dma(spi_dma_ch);
+ enable_dma(drv_data->dma_channel);
}
} else {
/* IO mode write then read */
@@ -854,7 +859,7 @@ static void pump_transfers(unsigned long data)
"IO duplex: cr is 0x%x\n", cr);
/* set SPI transfer mode */
- write_CTRL(cr | CFG_SPI_WRITE);
+ write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
drv_data->duplex(drv_data);
@@ -866,7 +871,7 @@ static void pump_transfers(unsigned long data)
"IO write: cr is 0x%x\n", cr);
/* set SPI transfer mode */
- write_CTRL(cr | CFG_SPI_WRITE);
+ write_CTRL(drv_data, (cr | CFG_SPI_WRITE));
drv_data->write(drv_data);
@@ -878,7 +883,7 @@ static void pump_transfers(unsigned long data)
"IO read: cr is 0x%x\n", cr);
/* set SPI transfer mode */
- write_CTRL(cr | CFG_SPI_READ);
+ write_CTRL(drv_data, (cr | CFG_SPI_READ));
drv_data->read(drv_data);
if (drv_data->rx != drv_data->rx_end)
@@ -1071,20 +1076,20 @@ static int setup(struct spi_device *spi)
* if any one SPI chip is registered and wants DMA, request the
* DMA channel for it
*/
- if (chip->enable_dma && !dma_requested) {
+ if (chip->enable_dma && !drv_data->dma_requested) {
/* register dma irq handler */
- if (request_dma(spi_dma_ch, "BF53x_SPI_DMA") < 0) {
+ if (request_dma(drv_data->dma_channel, "BF53x_SPI_DMA") < 0) {
dev_dbg(&spi->dev,
"Unable to request BlackFin SPI DMA channel\n");
return -ENODEV;
}
- if (set_dma_callback(spi_dma_ch, (void *)dma_irq_handler,
- drv_data) < 0) {
+ if (set_dma_callback(drv_data->dma_channel,
+ (void *)dma_irq_handler, drv_data) < 0) {
dev_dbg(&spi->dev, "Unable to set dma callback\n");
return -EPERM;
}
- dma_disable_irq(spi_dma_ch);
- dma_requested = 1;
+ dma_disable_irq(drv_data->dma_channel);
+ drv_data->dma_requested = 1;
}
/*
@@ -1299,15 +1304,16 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
goto out_error_get_res;
}
- spi_regs_base = (u32) ioremap(res->start, (res->end - res->start)+1);
- if (!spi_regs_base) {
+ drv_data->regs_base = (u32) ioremap(res->start,
+ (res->end - res->start + 1));
+ if (!drv_data->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) {
+ drv_data->dma_channel = platform_get_irq(pdev, 0);
+ if (drv_data->dma_channel < 0) {
dev_err(dev, "No DMA channel specified\n");
status = -ENOENT;
goto out_error_no_dma_ch;
@@ -1339,14 +1345,15 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
goto out_error;
}
- dev_info(dev, "%s, Version %s, regs_base @ 0x%08x\n",
- DRV_DESC, DRV_VERSION, spi_regs_base);
+ dev_info(dev, "%s, Version %s, regs_base@0x%08x, dma channel@%d\n",
+ DRV_DESC, DRV_VERSION, drv_data->regs_base,
+ drv_data->dma_channel);
return status;
out_error_queue_alloc:
destroy_queue(drv_data);
out_error_no_dma_ch:
- iounmap((void *) spi_regs_base);
+ iounmap((void *) drv_data->regs_base);
out_error_ioremap:
out_error_get_res:
out_error:
@@ -1374,8 +1381,8 @@ static int __devexit bfin5xx_spi_remove(struct platform_device *pdev)
/* Release DMA */
if (drv_data->master_info->enable_dma) {
- if (dma_channel_active(spi_dma_ch))
- free_dma(spi_dma_ch);
+ if (dma_channel_active(drv_data->dma_channel))
+ free_dma(drv_data->dma_channel);
}
/* Disconnect from the SPI framework */
--
1.5.3.4
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 12/14] Blackfin SPI driver: Fix bug in u16_cs_chg_reader to read data_len-2 bytes data firstly, then read out the last 2 bytes data
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (10 preceding siblings ...)
2007-10-30 9:18 ` [PATCH 11/14] Blackfin SPI driver: Move global SPI regs_base and dma_ch to struct driver_data Bryan Wu
@ 2007-10-30 9:18 ` Bryan Wu
2007-10-30 9:18 ` [PATCH 13/14] Blackfin SPI driver: Move cs_chg_udelay to cs_deactive to fix bug when some SPI LCD driver needs delay after cs_deactive Bryan Wu
` (2 subsequent siblings)
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:18 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
drivers/spi/spi_bfin5xx.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 5924903..41282bf 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -501,7 +501,7 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
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)
--
1.5.3.4
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 13/14] Blackfin SPI driver: Move cs_chg_udelay to cs_deactive to fix bug when some SPI LCD driver needs delay after cs_deactive
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (11 preceding siblings ...)
2007-10-30 9:18 ` [PATCH 12/14] Blackfin SPI driver: Fix bug in u16_cs_chg_reader to read data_len-2 bytes data firstly, then read out the last 2 bytes data Bryan Wu
@ 2007-10-30 9:18 ` Bryan Wu
[not found] ` <1193735885-8202-14-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
2007-10-30 9:18 ` [PATCH 14/14] Blackfin SPI driver: set correct baud for spi mmc and enable SPI after DMA Bryan Wu
2007-10-30 20:24 ` [PATCH 00/14] Blackfin on-chip SPI controller driver updates and bug-fixing David Brownell
14 siblings, 1 reply; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:18 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Cameron Barfield
Fix bug reported by Cameron Barfield <cbarfield-uxMF5PKaPIoXhy9q4Lf3Ug@public.gmane.org>
https://blackfin.uclinux.org/gf/project/uclinux-dist/forum/?action=ForumBrowse&forum_id=39&_forum_action=ForumMessageBrowse&thread_id=23630&feedback=Message%20replied.
Cc: Cameron Barfield <cbarfield-uxMF5PKaPIoXhy9q4Lf3Ug@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
drivers/spi/spi_bfin5xx.c | 24 +++++++++---------------
include/asm-blackfin/bfin5xx_spi.h | 2 +-
2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 41282bf..0b22932 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -132,7 +132,7 @@ struct chip_data {
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 *);
@@ -211,6 +211,10 @@ static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip)
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
@@ -307,10 +311,9 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)
write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
while (read_STAT(drv_data) & BIT_STAT_TXS)
continue;
+
cs_deactive(drv_data, chip);
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
++drv_data->tx;
}
}
@@ -359,9 +362,6 @@ static void u8_cs_chg_reader(struct driver_data *drv_data)
while (drv_data->rx < drv_data->rx_end - 1) {
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);
@@ -412,10 +412,9 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data)
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
*(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;
}
@@ -452,10 +451,9 @@ static void u16_cs_chg_writer(struct driver_data *drv_data)
write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
while ((read_STAT(drv_data) & BIT_STAT_TXS))
continue;
+
cs_deactive(drv_data, chip);
- if (chip->cs_chg_udelay)
- udelay(chip->cs_chg_udelay);
drv_data->tx += 2;
}
}
@@ -504,9 +502,6 @@ static void u16_cs_chg_reader(struct driver_data *drv_data)
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;
cs_active(drv_data, chip);
@@ -557,10 +552,9 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data)
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
continue;
*(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;
}
diff --git a/include/asm-blackfin/bfin5xx_spi.h b/include/asm-blackfin/bfin5xx_spi.h
index f617d87..d4485b3 100644
--- a/include/asm-blackfin/bfin5xx_spi.h
+++ b/include/asm-blackfin/bfin5xx_spi.h
@@ -162,7 +162,7 @@ struct bfin5xx_spi_chip {
u8 enable_dma;
u8 bits_per_word;
u8 cs_change_per_word;
- u8 cs_chg_udelay;
+ u16 cs_chg_udelay; /* Some devices require 16-bit delays */
};
#endif /* _SPI_CHANNEL_H_ */
--
1.5.3.4
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH 14/14] Blackfin SPI driver: set correct baud for spi mmc and enable SPI after DMA.
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (12 preceding siblings ...)
2007-10-30 9:18 ` [PATCH 13/14] Blackfin SPI driver: Move cs_chg_udelay to cs_deactive to fix bug when some SPI LCD driver needs delay after cs_deactive Bryan Wu
@ 2007-10-30 9:18 ` Bryan Wu
2007-10-30 20:24 ` [PATCH 00/14] Blackfin on-chip SPI controller driver updates and bug-fixing David Brownell
14 siblings, 0 replies; 34+ messages in thread
From: Bryan Wu @ 2007-10-30 9:18 UTC (permalink / raw)
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Bryan Wu, Sonic Zhang, linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
SPI is enabled only after DMA is started.
Signed-off-by: Sonic Zhang <sonic.zhang-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
---
drivers/spi/spi_bfin5xx.c | 23 +++++++++++++----------
1 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 0b22932..83c866d 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -231,13 +231,13 @@ static int restore_state(struct driver_data *drv_data)
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);
bfin_spi_enable(drv_data);
+ cs_active(drv_data, chip);
if (ret)
dev_dbg(&drv_data->pdev->dev,
@@ -767,6 +767,7 @@ static void pump_transfers(unsigned long data)
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");
@@ -789,9 +790,6 @@ static void pump_transfers(unsigned long data)
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);
@@ -800,6 +798,9 @@ static void pump_transfers(unsigned long data)
(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));
+
/* just return here, there can only be one transfer in this mode */
message->status = 0;
giveback(drv_data);
@@ -811,9 +812,6 @@ static void pump_transfers(unsigned long data)
/* 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);
@@ -827,12 +825,12 @@ static void pump_transfers(unsigned long data)
(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);
@@ -840,6 +838,9 @@ static void pump_transfers(unsigned long data)
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 */
@@ -1138,6 +1139,8 @@ static int setup(struct spi_device *spi)
peripheral_request(ssel[spi->master->bus_num]
[chip->chip_select_num-1], DRV_NAME);
+ cs_deactive(drv_data, chip);
+
return 0;
}
--
1.5.3.4
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH 00/14] Blackfin on-chip SPI controller driver updates and bug-fixing
[not found] ` <1193735885-8202-1-git-send-email-bryan.wu-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
` (13 preceding siblings ...)
2007-10-30 9:18 ` [PATCH 14/14] Blackfin SPI driver: set correct baud for spi mmc and enable SPI after DMA Bryan Wu
@ 2007-10-30 20:24 ` David Brownell
[not found] ` <200710301324.07691.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
14 siblings, 1 reply; 34+ messages in thread
From: David Brownell @ 2007-10-30 20:24 UTC (permalink / raw)
To: Bryan Wu
Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Tuesday 30 October 2007, Bryan Wu wrote:
> - BF54x supported
> - multi-port supported
> - bunch of bug fixing
OK, I forwarded these with some more checkpatch.pl fixes.
But as I commented elsewhere, please work harder to make sure
that your patch comments actually match the patches!!
And also, pay closer attention to when you may be making
changes that make device drivers work differently over
your spi_master controller driver than anyone elses ...
such platform-specific behaviors are undesirable, and when
they go against specified behavior they are also bugs.
- Dave
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
^ permalink raw reply [flat|nested] 34+ messages in thread