aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi_bfin5xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi_bfin5xx.c')
-rw-r--r--drivers/spi/spi_bfin5xx.c139
1 files changed, 69 insertions, 70 deletions
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 2ef11bb70b2e..805f03bb5ef9 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1,17 +1,20 @@
1/* 1/*
2 * File: drivers/spi/bfin5xx_spi.c 2 * File: drivers/spi/bfin5xx_spi.c
3 * Based on: N/A 3 * Maintainer:
4 * Author: Luke Yang (Analog Devices Inc.) 4 * Bryan Wu <bryan.wu@analog.com>
5 * Original Author:
6 * Luke Yang (Analog Devices Inc.)
5 * 7 *
6 * Created: March. 10th 2006 8 * Created: March. 10th 2006
7 * Description: SPI controller driver for Blackfin 5xx 9 * Description: SPI controller driver for Blackfin BF5xx
8 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 10 * Bugs: Enter bugs at http://blackfin.uclinux.org/
9 * 11 *
10 * Modified: 12 * Modified:
11 * March 10, 2006 bfin5xx_spi.c Created. (Luke Yang) 13 * March 10, 2006 bfin5xx_spi.c Created. (Luke Yang)
12 * August 7, 2006 added full duplex mode (Axel Weiss & Luke Yang) 14 * August 7, 2006 added full duplex mode (Axel Weiss & Luke Yang)
15 * July 17, 2007 add support for BF54x SPI0 controller (Bryan Wu)
13 * 16 *
14 * Copyright 2004-2006 Analog Devices Inc. 17 * Copyright 2004-2007 Analog Devices Inc.
15 * 18 *
16 * This program is free software ; you can redistribute it and/or modify 19 * This program is free software ; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by 20 * it under the terms of the GNU General Public License as published by
@@ -31,27 +34,27 @@
31 34
32#include <linux/init.h> 35#include <linux/init.h>
33#include <linux/module.h> 36#include <linux/module.h>
37#include <linux/delay.h>
34#include <linux/device.h> 38#include <linux/device.h>
39#include <linux/io.h>
35#include <linux/ioport.h> 40#include <linux/ioport.h>
41#include <linux/irq.h>
36#include <linux/errno.h> 42#include <linux/errno.h>
37#include <linux/interrupt.h> 43#include <linux/interrupt.h>
38#include <linux/platform_device.h> 44#include <linux/platform_device.h>
39#include <linux/dma-mapping.h> 45#include <linux/dma-mapping.h>
40#include <linux/spi/spi.h> 46#include <linux/spi/spi.h>
41#include <linux/workqueue.h> 47#include <linux/workqueue.h>
42#include <linux/delay.h>
43 48
44#include <asm/io.h>
45#include <asm/irq.h>
46#include <asm/delay.h>
47#include <asm/dma.h> 49#include <asm/dma.h>
48 50#include <asm/portmux.h>
49#include <asm/bfin5xx_spi.h> 51#include <asm/bfin5xx_spi.h>
50 52
51MODULE_AUTHOR("Luke Yang"); 53MODULE_AUTHOR("Bryan Wu, Luke Yang");
52MODULE_DESCRIPTION("Blackfin 5xx SPI Contoller"); 54MODULE_DESCRIPTION("Blackfin BF5xx SPI Contoller Driver");
53MODULE_LICENSE("GPL"); 55MODULE_LICENSE("GPL");
54 56
57#define DRV_NAME "bfin-spi-master"
55#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) 58#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
56 59
57#define DEFINE_SPI_REG(reg, off) \ 60#define DEFINE_SPI_REG(reg, off) \
@@ -124,6 +127,7 @@ struct chip_data {
124 u16 flag; 127 u16 flag;
125 128
126 u8 chip_select_num; 129 u8 chip_select_num;
130 u8 chip_select_requested;
127 u8 n_bytes; 131 u8 n_bytes;
128 u8 width; /* 0 or 1 */ 132 u8 width; /* 0 or 1 */
129 u8 enable_dma; 133 u8 enable_dma;
@@ -188,53 +192,37 @@ static void restore_state(struct driver_data *drv_data)
188 bfin_spi_disable(drv_data); 192 bfin_spi_disable(drv_data);
189 dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n"); 193 dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
190 194
191#if defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537) 195 if (!chip->chip_select_requested) {
192 dev_dbg(&drv_data->pdev->dev,
193 "chip select number is %d\n", chip->chip_select_num);
194
195 switch (chip->chip_select_num) {
196 case 1:
197 bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3c00);
198 SSYNC();
199 break;
200 196
201 case 2: 197 dev_dbg(&drv_data->pdev->dev,
202 case 3: 198 "chip select number is %d\n", chip->chip_select_num);
203 bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJSE_SPI);
204 SSYNC();
205 bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800);
206 SSYNC();
207 break;
208
209 case 4:
210 bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS4E_SPI);
211 SSYNC();
212 bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3840);
213 SSYNC();
214 break;
215
216 case 5:
217 bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS5E_SPI);
218 SSYNC();
219 bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3820);
220 SSYNC();
221 break;
222 199
223 case 6: 200 switch (chip->chip_select_num) {
224 bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PFS6E_SPI); 201 case 1:
225 SSYNC(); 202 peripheral_request(P_SPI0_SSEL1, DRV_NAME);
226 bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3810); 203 break;
227 SSYNC(); 204 case 2:
228 break; 205 peripheral_request(P_SPI0_SSEL2, DRV_NAME);
206 break;
207 case 3:
208 peripheral_request(P_SPI0_SSEL3, DRV_NAME);
209 break;
210 case 4:
211 peripheral_request(P_SPI0_SSEL4, DRV_NAME);
212 break;
213 case 5:
214 peripheral_request(P_SPI0_SSEL5, DRV_NAME);
215 break;
216 case 6:
217 peripheral_request(P_SPI0_SSEL6, DRV_NAME);
218 break;
219 case 7:
220 peripheral_request(P_SPI0_SSEL7, DRV_NAME);
221 break;
222 }
229 223
230 case 7: 224 chip->chip_select_requested = 1;
231 bfin_write_PORT_MUX(bfin_read_PORT_MUX() | PJCE_SPI);
232 SSYNC();
233 bfin_write_PORTF_FER(bfin_read_PORTF_FER() | 0x3800);
234 SSYNC();
235 break;
236 } 225 }
237#endif
238 226
239 /* Load the registers */ 227 /* Load the registers */
240 write_CTRL(chip->ctl_reg); 228 write_CTRL(chip->ctl_reg);
@@ -277,7 +265,7 @@ static void null_reader(struct driver_data *drv_data)
277 265
278static void u8_writer(struct driver_data *drv_data) 266static void u8_writer(struct driver_data *drv_data)
279{ 267{
280 dev_dbg(&drv_data->pdev->dev, 268 dev_dbg(&drv_data->pdev->dev,
281 "cr8-s is 0x%x\n", read_STAT()); 269 "cr8-s is 0x%x\n", read_STAT());
282 while (drv_data->tx < drv_data->tx_end) { 270 while (drv_data->tx < drv_data->tx_end) {
283 write_TDBR(*(u8 *) (drv_data->tx)); 271 write_TDBR(*(u8 *) (drv_data->tx));
@@ -316,7 +304,7 @@ static void u8_cs_chg_writer(struct driver_data *drv_data)
316 304
317static void u8_reader(struct driver_data *drv_data) 305static void u8_reader(struct driver_data *drv_data)
318{ 306{
319 dev_dbg(&drv_data->pdev->dev, 307 dev_dbg(&drv_data->pdev->dev,
320 "cr-8 is 0x%x\n", read_STAT()); 308 "cr-8 is 0x%x\n", read_STAT());
321 309
322 /* clear TDBR buffer before read(else it will be shifted out) */ 310 /* 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)
403 391
404static void u16_writer(struct driver_data *drv_data) 392static void u16_writer(struct driver_data *drv_data)
405{ 393{
406 dev_dbg(&drv_data->pdev->dev, 394 dev_dbg(&drv_data->pdev->dev,
407 "cr16 is 0x%x\n", read_STAT()); 395 "cr16 is 0x%x\n", read_STAT());
408 396
409 while (drv_data->tx < drv_data->tx_end) { 397 while (drv_data->tx < drv_data->tx_end) {
@@ -700,9 +688,9 @@ static void pump_transfers(unsigned long data)
700 drv_data->write = drv_data->tx ? chip->write : null_writer; 688 drv_data->write = drv_data->tx ? chip->write : null_writer;
701 drv_data->read = drv_data->rx ? chip->read : null_reader; 689 drv_data->read = drv_data->rx ? chip->read : null_reader;
702 drv_data->duplex = chip->duplex ? chip->duplex : null_writer; 690 drv_data->duplex = chip->duplex ? chip->duplex : null_writer;
703 dev_dbg(&drv_data->pdev->dev, 691 dev_dbg(&drv_data->pdev->dev, "transfer: ",
704 "transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n", 692 "drv_data->write is %p, chip->write is %p, null_wr is %p\n",
705 drv_data->write, chip->write, null_writer); 693 drv_data->write, chip->write, null_writer);
706 694
707 /* speed and width has been set on per message */ 695 /* speed and width has been set on per message */
708 message->state = RUNNING_STATE; 696 message->state = RUNNING_STATE;
@@ -816,7 +804,7 @@ static void pump_transfers(unsigned long data)
816 /* full duplex mode */ 804 /* full duplex mode */
817 BUG_ON((drv_data->tx_end - drv_data->tx) != 805 BUG_ON((drv_data->tx_end - drv_data->tx) !=
818 (drv_data->rx_end - drv_data->rx)); 806 (drv_data->rx_end - drv_data->rx));
819 cr = (read_CTRL() & (~BIT_CTL_TIMOD)); 807 cr = (read_CTRL() & (~BIT_CTL_TIMOD));
820 cr |= CFG_SPI_WRITE | (width << 8) | 808 cr |= CFG_SPI_WRITE | (width << 8) |
821 (CFG_SPI_ENABLE << 14); 809 (CFG_SPI_ENABLE << 14);
822 dev_dbg(&drv_data->pdev->dev, 810 dev_dbg(&drv_data->pdev->dev,
@@ -834,7 +822,7 @@ static void pump_transfers(unsigned long data)
834 cr = (read_CTRL() & (~BIT_CTL_TIMOD)); 822 cr = (read_CTRL() & (~BIT_CTL_TIMOD));
835 cr |= CFG_SPI_WRITE | (width << 8) | 823 cr |= CFG_SPI_WRITE | (width << 8) |
836 (CFG_SPI_ENABLE << 14); 824 (CFG_SPI_ENABLE << 14);
837 dev_dbg(&drv_data->pdev->dev, 825 dev_dbg(&drv_data->pdev->dev,
838 "IO write: cr is 0x%x\n", cr); 826 "IO write: cr is 0x%x\n", cr);
839 827
840 write_CTRL(cr); 828 write_CTRL(cr);
@@ -849,7 +837,7 @@ static void pump_transfers(unsigned long data)
849 cr = (read_CTRL() & (~BIT_CTL_TIMOD)); 837 cr = (read_CTRL() & (~BIT_CTL_TIMOD));
850 cr |= CFG_SPI_READ | (width << 8) | 838 cr |= CFG_SPI_READ | (width << 8) |
851 (CFG_SPI_ENABLE << 14); 839 (CFG_SPI_ENABLE << 14);
852 dev_dbg(&drv_data->pdev->dev, 840 dev_dbg(&drv_data->pdev->dev,
853 "IO read: cr is 0x%x\n", cr); 841 "IO read: cr is 0x%x\n", cr);
854 842
855 write_CTRL(cr); 843 write_CTRL(cr);
@@ -861,7 +849,7 @@ static void pump_transfers(unsigned long data)
861 } 849 }
862 850
863 if (!tranf_success) { 851 if (!tranf_success) {
864 dev_dbg(&drv_data->pdev->dev, 852 dev_dbg(&drv_data->pdev->dev,
865 "IO write error!\n"); 853 "IO write error!\n");
866 message->state = ERROR_STATE; 854 message->state = ERROR_STATE;
867 } else { 855 } else {
@@ -881,9 +869,11 @@ static void pump_transfers(unsigned long data)
881/* pop a msg from queue and kick off real transfer */ 869/* pop a msg from queue and kick off real transfer */
882static void pump_messages(struct work_struct *work) 870static void pump_messages(struct work_struct *work)
883{ 871{
884 struct driver_data *drv_data = container_of(work, struct driver_data, pump_messages); 872 struct driver_data *drv_data;
885 unsigned long flags; 873 unsigned long flags;
886 874
875 drv_data = container_of(work, struct driver_data, pump_messages);
876
887 /* Lock queue and check for queue work */ 877 /* Lock queue and check for queue work */
888 spin_lock_irqsave(&drv_data->lock, flags); 878 spin_lock_irqsave(&drv_data->lock, flags);
889 if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) { 879 if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
@@ -916,8 +906,8 @@ static void pump_messages(struct work_struct *work)
916 "got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n", 906 "got a message to pump, state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
917 drv_data->cur_chip->baud, drv_data->cur_chip->flag, 907 drv_data->cur_chip->baud, drv_data->cur_chip->flag,
918 drv_data->cur_chip->ctl_reg); 908 drv_data->cur_chip->ctl_reg);
919 909
920 dev_dbg(&drv_data->pdev->dev, 910 dev_dbg(&drv_data->pdev->dev,
921 "the first transfer len is %d\n", 911 "the first transfer len is %d\n",
922 drv_data->cur_transfer->len); 912 drv_data->cur_transfer->len);
923 913
@@ -1193,6 +1183,15 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
1193 dev_err(&pdev->dev, "can not alloc spi_master\n"); 1183 dev_err(&pdev->dev, "can not alloc spi_master\n");
1194 return -ENOMEM; 1184 return -ENOMEM;
1195 } 1185 }
1186
1187 if (peripheral_request(P_SPI0_SCK, DRV_NAME) ||
1188 peripheral_request(P_SPI0_MISO, DRV_NAME) ||
1189 peripheral_request(P_SPI0_MOSI, DRV_NAME)) {
1190
1191 dev_err(&pdev->dev, ": Requesting Peripherals failed\n");
1192 goto out_error_queue_alloc;
1193 }
1194
1196 drv_data = spi_master_get_devdata(master); 1195 drv_data = spi_master_get_devdata(master);
1197 drv_data->master = master; 1196 drv_data->master = master;
1198 drv_data->master_info = platform_info; 1197 drv_data->master_info = platform_info;