forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial BF54x SPI support - support BF54x SPI0 - clean up some code (whitespace etc) - will support multiports in the future - start using portmux calls Signed-off-by: Bryan Wu <[email protected]> Signed-off-by: David Brownell <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
- Loading branch information
Bryan Wu
authored and
Linus Torvalds
committed
Dec 5, 2007
1 parent
c24b260
commit 131b17d
Showing
2 changed files
with
86 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,20 @@ | ||
/* | ||
* File: drivers/spi/bfin5xx_spi.c | ||
* Based on: N/A | ||
* Author: Luke Yang (Analog Devices Inc.) | ||
* File: drivers/spi/bfin5xx_spi.c | ||
* Maintainer: | ||
* Bryan Wu <[email protected]> | ||
* Original Author: | ||
* Luke Yang (Analog Devices Inc.) | ||
* | ||
* Created: March. 10th 2006 | ||
* Description: SPI controller driver for Blackfin 5xx | ||
* Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
* Created: March. 10th 2006 | ||
* Description: SPI controller driver for Blackfin BF5xx | ||
* Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
* | ||
* Modified: | ||
* March 10, 2006 bfin5xx_spi.c Created. (Luke Yang) | ||
* August 7, 2006 added full duplex mode (Axel Weiss & Luke Yang) | ||
* July 17, 2007 add support for BF54x SPI0 controller (Bryan Wu) | ||
* | ||
* Copyright 2004-2006 Analog Devices Inc. | ||
* Copyright 2004-2007 Analog Devices Inc. | ||
* | ||
* This program is free software ; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
|
@@ -31,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; | ||
if (!chip->chip_select_requested) { | ||
|
||
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; | ||
|
||
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) { | ||
|
@@ -700,9 +688,9 @@ static void pump_transfers(unsigned long data) | |
drv_data->write = drv_data->tx ? chip->write : null_writer; | ||
drv_data->read = drv_data->rx ? chip->read : null_reader; | ||
drv_data->duplex = chip->duplex ? chip->duplex : null_writer; | ||
dev_dbg(&drv_data->pdev->dev, | ||
"transfer: drv_data->write is %p, chip->write is %p, null_wr is %p\n", | ||
drv_data->write, chip->write, null_writer); | ||
dev_dbg(&drv_data->pdev->dev, "transfer: ", | ||
"drv_data->write is %p, chip->write is %p, null_wr is %p\n", | ||
drv_data->write, chip->write, null_writer); | ||
|
||
/* speed and width has been set on per message */ | ||
message->state = RUNNING_STATE; | ||
|
@@ -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 { | ||
|
@@ -881,9 +869,11 @@ static void pump_transfers(unsigned long data) | |
/* pop a msg from queue and kick off real transfer */ | ||
static void pump_messages(struct work_struct *work) | ||
{ | ||
struct driver_data *drv_data = container_of(work, struct driver_data, pump_messages); | ||
struct driver_data *drv_data; | ||
unsigned long flags; | ||
|
||
drv_data = container_of(work, struct driver_data, pump_messages); | ||
|
||
/* Lock queue and check for queue work */ | ||
spin_lock_irqsave(&drv_data->lock, flags); | ||
if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) { | ||
|
@@ -916,8 +906,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 +1183,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; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters