Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/spi-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/spi-2.6: [PATCH] SPI: spi_bitbang: clocking fixes [PATCH] spi: Update to PXA2xx SPI Driver [PATCH] SPI: busnum == 0 needs to work [PATCH] SPI: devices can require LSB-first encodings [PATCH] SPI: Renamed bitbang_transfer_setup to spi_bitbang_setup_transfer and export it [PATCH] SPI: Add David as the SPI subsystem maintainer [PATCH] SPI: spi bounce buffer has a minimum length [PATCH] SPI: spi whitespace fixes [PATCH] SPI: add PXA2xx SSP SPI Driver [PATCH] SPI: per-transfer overrides for wordsize and clocking
This commit is contained in:
commit
0c056c50a6
234
Documentation/spi/pxa2xx
Normal file
234
Documentation/spi/pxa2xx
Normal file
@ -0,0 +1,234 @@
|
||||
PXA2xx SPI on SSP driver HOWTO
|
||||
===================================================
|
||||
This a mini howto on the pxa2xx_spi driver. The driver turns a PXA2xx
|
||||
synchronous serial port into a SPI master controller
|
||||
(see Documentation/spi/spi_summary). The driver has the following features
|
||||
|
||||
- Support for any PXA2xx SSP
|
||||
- SSP PIO and SSP DMA data transfers.
|
||||
- External and Internal (SSPFRM) chip selects.
|
||||
- Per slave device (chip) configuration.
|
||||
- Full suspend, freeze, resume support.
|
||||
|
||||
The driver is built around a "spi_message" fifo serviced by workqueue and a
|
||||
tasklet. The workqueue, "pump_messages", drives message fifo and the tasklet
|
||||
(pump_transfer) is responsible for queuing SPI transactions and setting up and
|
||||
launching the dma/interrupt driven transfers.
|
||||
|
||||
Declaring PXA2xx Master Controllers
|
||||
-----------------------------------
|
||||
Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
|
||||
"platform device". The master configuration is passed to the driver via a table
|
||||
found in include/asm-arm/arch-pxa/pxa2xx_spi.h:
|
||||
|
||||
struct pxa2xx_spi_master {
|
||||
enum pxa_ssp_type ssp_type;
|
||||
u32 clock_enable;
|
||||
u16 num_chipselect;
|
||||
u8 enable_dma;
|
||||
};
|
||||
|
||||
The "pxa2xx_spi_master.ssp_type" field must have a value between 1 and 3 and
|
||||
informs the driver which features a particular SSP supports.
|
||||
|
||||
The "pxa2xx_spi_master.clock_enable" field is used to enable/disable the
|
||||
corresponding SSP peripheral block in the "Clock Enable Register (CKEN"). See
|
||||
the "PXA2xx Developer Manual" section "Clocks and Power Management".
|
||||
|
||||
The "pxa2xx_spi_master.num_chipselect" field is used to determine the number of
|
||||
slave device (chips) attached to this SPI master.
|
||||
|
||||
The "pxa2xx_spi_master.enable_dma" field informs the driver that SSP DMA should
|
||||
be used. This caused the driver to acquire two DMA channels: rx_channel and
|
||||
tx_channel. The rx_channel has a higher DMA service priority the tx_channel.
|
||||
See the "PXA2xx Developer Manual" section "DMA Controller".
|
||||
|
||||
NSSP MASTER SAMPLE
|
||||
------------------
|
||||
Below is a sample configuration using the PXA255 NSSP.
|
||||
|
||||
static struct resource pxa_spi_nssp_resources[] = {
|
||||
[0] = {
|
||||
.start = __PREG(SSCR0_P(2)), /* Start address of NSSP */
|
||||
.end = __PREG(SSCR0_P(2)) + 0x2c, /* Range of registers */
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_NSSP, /* NSSP IRQ */
|
||||
.end = IRQ_NSSP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct pxa2xx_spi_master pxa_nssp_master_info = {
|
||||
.ssp_type = PXA25x_NSSP, /* Type of SSP */
|
||||
.clock_enable = CKEN9_NSSP, /* NSSP Peripheral clock */
|
||||
.num_chipselect = 1, /* Matches the number of chips attached to NSSP */
|
||||
.enable_dma = 1, /* Enables NSSP DMA */
|
||||
};
|
||||
|
||||
static struct platform_device pxa_spi_nssp = {
|
||||
.name = "pxa2xx-spi", /* MUST BE THIS VALUE, so device match driver */
|
||||
.id = 2, /* Bus number, MUST MATCH SSP number 1..n */
|
||||
.resource = pxa_spi_nssp_resources,
|
||||
.num_resources = ARRAY_SIZE(pxa_spi_nssp_resources),
|
||||
.dev = {
|
||||
.platform_data = &pxa_nssp_master_info, /* Passed to driver */
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&pxa_spi_nssp,
|
||||
};
|
||||
|
||||
static void __init board_init(void)
|
||||
{
|
||||
(void)platform_add_device(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
||||
Declaring Slave Devices
|
||||
-----------------------
|
||||
Typically each SPI slave (chip) is defined in the arch/.../mach-*/board-*.c
|
||||
using the "spi_board_info" structure found in "linux/spi/spi.h". See
|
||||
"Documentation/spi/spi_summary" for additional information.
|
||||
|
||||
Each slave device attached to the PXA must provide slave specific configuration
|
||||
information via the structure "pxa2xx_spi_chip" found in
|
||||
"include/asm-arm/arch-pxa/pxa2xx_spi.h". The pxa2xx_spi master controller driver
|
||||
will uses the configuration whenever the driver communicates with the slave
|
||||
device.
|
||||
|
||||
struct pxa2xx_spi_chip {
|
||||
u8 tx_threshold;
|
||||
u8 rx_threshold;
|
||||
u8 dma_burst_size;
|
||||
u32 timeout_microsecs;
|
||||
u8 enable_loopback;
|
||||
void (*cs_control)(u32 command);
|
||||
};
|
||||
|
||||
The "pxa2xx_spi_chip.tx_threshold" and "pxa2xx_spi_chip.rx_threshold" fields are
|
||||
used to configure the SSP hardware fifo. These fields are critical to the
|
||||
performance of pxa2xx_spi driver and misconfiguration will result in rx
|
||||
fifo overruns (especially in PIO mode transfers). Good default values are
|
||||
|
||||
.tx_threshold = 12,
|
||||
.rx_threshold = 4,
|
||||
|
||||
The "pxa2xx_spi_chip.dma_burst_size" field is used to configure PXA2xx DMA
|
||||
engine and is related the "spi_device.bits_per_word" field. Read and understand
|
||||
the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers
|
||||
to determine the correct value. An SSP configured for byte-wide transfers would
|
||||
use a value of 8.
|
||||
|
||||
The "pxa2xx_spi_chip.timeout_microsecs" fields is used to efficiently handle
|
||||
trailing bytes in the SSP receiver fifo. The correct value for this field is
|
||||
dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific
|
||||
slave device. Please note the the PXA2xx SSP 1 does not support trailing byte
|
||||
timeouts and must busy-wait any trailing bytes.
|
||||
|
||||
The "pxa2xx_spi_chip.enable_loopback" field is used to place the SSP porting
|
||||
into internal loopback mode. In this mode the SSP controller internally
|
||||
connects the SSPTX pin the the SSPRX pin. This is useful for initial setup
|
||||
testing.
|
||||
|
||||
The "pxa2xx_spi_chip.cs_control" field is used to point to a board specific
|
||||
function for asserting/deasserting a slave device chip select. If the field is
|
||||
NULL, the pxa2xx_spi master controller driver assumes that the SSP port is
|
||||
configured to use SSPFRM instead.
|
||||
|
||||
NSSP SALVE SAMPLE
|
||||
-----------------
|
||||
The pxa2xx_spi_chip structure is passed to the pxa2xx_spi driver in the
|
||||
"spi_board_info.controller_data" field. Below is a sample configuration using
|
||||
the PXA255 NSSP.
|
||||
|
||||
/* Chip Select control for the CS8415A SPI slave device */
|
||||
static void cs8415a_cs_control(u32 command)
|
||||
{
|
||||
if (command & PXA2XX_CS_ASSERT)
|
||||
GPCR(2) = GPIO_bit(2);
|
||||
else
|
||||
GPSR(2) = GPIO_bit(2);
|
||||
}
|
||||
|
||||
/* Chip Select control for the CS8405A SPI slave device */
|
||||
static void cs8405a_cs_control(u32 command)
|
||||
{
|
||||
if (command & PXA2XX_CS_ASSERT)
|
||||
GPCR(3) = GPIO_bit(3);
|
||||
else
|
||||
GPSR(3) = GPIO_bit(3);
|
||||
}
|
||||
|
||||
static struct pxa2xx_spi_chip cs8415a_chip_info = {
|
||||
.tx_threshold = 12, /* SSP hardward FIFO threshold */
|
||||
.rx_threshold = 4, /* SSP hardward FIFO threshold */
|
||||
.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
|
||||
.timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
|
||||
.cs_control = cs8415a_cs_control, /* Use external chip select */
|
||||
};
|
||||
|
||||
static struct pxa2xx_spi_chip cs8405a_chip_info = {
|
||||
.tx_threshold = 12, /* SSP hardward FIFO threshold */
|
||||
.rx_threshold = 4, /* SSP hardward FIFO threshold */
|
||||
.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
|
||||
.timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */
|
||||
.cs_control = cs8405a_cs_control, /* Use external chip select */
|
||||
};
|
||||
|
||||
static struct spi_board_info streetracer_spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "cs8415a", /* Name of spi_driver for this device */
|
||||
.max_speed_hz = 3686400, /* Run SSP as fast a possbile */
|
||||
.bus_num = 2, /* Framework bus number */
|
||||
.chip_select = 0, /* Framework chip select */
|
||||
.platform_data = NULL; /* No spi_driver specific config */
|
||||
.controller_data = &cs8415a_chip_info, /* Master chip config */
|
||||
.irq = STREETRACER_APCI_IRQ, /* Slave device interrupt */
|
||||
},
|
||||
{
|
||||
.modalias = "cs8405a", /* Name of spi_driver for this device */
|
||||
.max_speed_hz = 3686400, /* Run SSP as fast a possbile */
|
||||
.bus_num = 2, /* Framework bus number */
|
||||
.chip_select = 1, /* Framework chip select */
|
||||
.controller_data = &cs8405a_chip_info, /* Master chip config */
|
||||
.irq = STREETRACER_APCI_IRQ, /* Slave device interrupt */
|
||||
},
|
||||
};
|
||||
|
||||
static void __init streetracer_init(void)
|
||||
{
|
||||
spi_register_board_info(streetracer_spi_board_info,
|
||||
ARRAY_SIZE(streetracer_spi_board_info));
|
||||
}
|
||||
|
||||
|
||||
DMA and PIO I/O Support
|
||||
-----------------------
|
||||
The pxa2xx_spi driver support both DMA and interrupt driven PIO message
|
||||
transfers. The driver defaults to PIO mode and DMA transfers must enabled by
|
||||
setting the "enable_dma" flag in the "pxa2xx_spi_master" structure and and
|
||||
ensuring that the "pxa2xx_spi_chip.dma_burst_size" field is non-zero. The DMA
|
||||
mode support both coherent and stream based DMA mappings.
|
||||
|
||||
The following logic is used to determine the type of I/O to be used on
|
||||
a per "spi_transfer" basis:
|
||||
|
||||
if !enable_dma or dma_burst_size == 0 then
|
||||
always use PIO transfers
|
||||
|
||||
if spi_message.is_dma_mapped and rx_dma_buf != 0 and tx_dma_buf != 0 then
|
||||
use coherent DMA mode
|
||||
|
||||
if rx_buf and tx_buf are aligned on 8 byte boundary then
|
||||
use streaming DMA mode
|
||||
|
||||
otherwise
|
||||
use PIO transfer
|
||||
|
||||
THANKS TO
|
||||
---------
|
||||
|
||||
David Brownell and others for mentoring the development of this driver.
|
||||
|
@ -414,7 +414,33 @@ to get the driver-private data allocated for that device.
|
||||
The driver will initialize the fields of that spi_master, including the
|
||||
bus number (maybe the same as the platform device ID) and three methods
|
||||
used to interact with the SPI core and SPI protocol drivers. It will
|
||||
also initialize its own internal state.
|
||||
also initialize its own internal state. (See below about bus numbering
|
||||
and those methods.)
|
||||
|
||||
After you initialize the spi_master, then use spi_register_master() to
|
||||
publish it to the rest of the system. At that time, device nodes for
|
||||
the controller and any predeclared spi devices will be made available,
|
||||
and the driver model core will take care of binding them to drivers.
|
||||
|
||||
If you need to remove your SPI controller driver, spi_unregister_master()
|
||||
will reverse the effect of spi_register_master().
|
||||
|
||||
|
||||
BUS NUMBERING
|
||||
|
||||
Bus numbering is important, since that's how Linux identifies a given
|
||||
SPI bus (shared SCK, MOSI, MISO). Valid bus numbers start at zero. On
|
||||
SOC systems, the bus numbers should match the numbers defined by the chip
|
||||
manufacturer. For example, hardware controller SPI2 would be bus number 2,
|
||||
and spi_board_info for devices connected to it would use that number.
|
||||
|
||||
If you don't have such hardware-assigned bus number, and for some reason
|
||||
you can't just assign them, then provide a negative bus number. That will
|
||||
then be replaced by a dynamically assigned number. You'd then need to treat
|
||||
this as a non-static configuration (see above).
|
||||
|
||||
|
||||
SPI MASTER METHODS
|
||||
|
||||
master->setup(struct spi_device *spi)
|
||||
This sets up the device clock rate, SPI mode, and word sizes.
|
||||
@ -431,6 +457,9 @@ also initialize its own internal state.
|
||||
state it dynamically associates with that device. If you do that,
|
||||
be sure to provide the cleanup() method to free that state.
|
||||
|
||||
|
||||
SPI MESSAGE QUEUE
|
||||
|
||||
The bulk of the driver will be managing the I/O queue fed by transfer().
|
||||
|
||||
That queue could be purely conceptual. For example, a driver used only
|
||||
@ -440,6 +469,9 @@ But the queue will probably be very real, using message->queue, PIO,
|
||||
often DMA (especially if the root filesystem is in SPI flash), and
|
||||
execution contexts like IRQ handlers, tasklets, or workqueues (such
|
||||
as keventd). Your driver can be as fancy, or as simple, as you need.
|
||||
Such a transfer() method would normally just add the message to a
|
||||
queue, and then start some asynchronous transfer engine (unless it's
|
||||
already running).
|
||||
|
||||
|
||||
THANKS TO
|
||||
|
@ -2518,6 +2518,12 @@ M: perex@suse.cz
|
||||
L: alsa-devel@alsa-project.org
|
||||
S: Maintained
|
||||
|
||||
SPI SUBSYSTEM
|
||||
P: David Brownell
|
||||
M: dbrownell@users.sourceforge.net
|
||||
L: spi-devel-general@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
TPM DEVICE DRIVER
|
||||
P: Kylene Hall
|
||||
M: kjhall@us.ibm.com
|
||||
|
@ -75,6 +75,14 @@ config SPI_BUTTERFLY
|
||||
inexpensive battery powered microcontroller evaluation board.
|
||||
This same cable can be used to flash new firmware.
|
||||
|
||||
config SPI_PXA2XX
|
||||
tristate "PXA2xx SSP SPI master"
|
||||
depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
|
||||
help
|
||||
This enables using a PXA2xx SSP port as a SPI master controller.
|
||||
The driver can be configured to use any SSP port and additional
|
||||
documentation can be found a Documentation/spi/pxa2xx.
|
||||
|
||||
#
|
||||
# Add new SPI master controllers in alphabetical order above this line
|
||||
#
|
||||
|
@ -13,6 +13,7 @@ obj-$(CONFIG_SPI_MASTER) += spi.o
|
||||
# SPI master controller drivers (bus)
|
||||
obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
|
||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
|
||||
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
|
||||
# ... add above this line ...
|
||||
|
||||
# SPI protocol drivers (device/link on bus)
|
||||
|
1467
drivers/spi/pxa2xx_spi.c
Normal file
1467
drivers/spi/pxa2xx_spi.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
|
||||
int __init_or_module
|
||||
spi_register_master(struct spi_master *master)
|
||||
{
|
||||
static atomic_t dyn_bus_id = ATOMIC_INIT(0);
|
||||
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<16) - 1);
|
||||
struct device *dev = master->cdev.dev;
|
||||
int status = -ENODEV;
|
||||
int dynamic = 0;
|
||||
@ -404,7 +404,7 @@ spi_register_master(struct spi_master *master)
|
||||
return -ENODEV;
|
||||
|
||||
/* convention: dynamically assigned bus IDs count down from the max */
|
||||
if (master->bus_num == 0) {
|
||||
if (master->bus_num < 0) {
|
||||
master->bus_num = atomic_dec_return(&dyn_bus_id);
|
||||
dynamic = 1;
|
||||
}
|
||||
@ -522,7 +522,8 @@ int spi_sync(struct spi_device *spi, struct spi_message *message)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_sync);
|
||||
|
||||
#define SPI_BUFSIZ (SMP_CACHE_BYTES)
|
||||
/* portable code must never pass more than 32 bytes */
|
||||
#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
|
||||
|
||||
static u8 *buf;
|
||||
|
||||
|
@ -138,6 +138,45 @@ static unsigned bitbang_txrx_32(
|
||||
return t->len - count;
|
||||
}
|
||||
|
||||
int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct spi_bitbang_cs *cs = spi->controller_state;
|
||||
u8 bits_per_word;
|
||||
u32 hz;
|
||||
|
||||
if (t) {
|
||||
bits_per_word = t->bits_per_word;
|
||||
hz = t->speed_hz;
|
||||
} else {
|
||||
bits_per_word = 0;
|
||||
hz = 0;
|
||||
}
|
||||
|
||||
/* spi_transfer level calls that work per-word */
|
||||
if (!bits_per_word)
|
||||
bits_per_word = spi->bits_per_word;
|
||||
if (bits_per_word <= 8)
|
||||
cs->txrx_bufs = bitbang_txrx_8;
|
||||
else if (bits_per_word <= 16)
|
||||
cs->txrx_bufs = bitbang_txrx_16;
|
||||
else if (bits_per_word <= 32)
|
||||
cs->txrx_bufs = bitbang_txrx_32;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
/* nsecs = (clock period)/2 */
|
||||
if (!hz)
|
||||
hz = spi->max_speed_hz;
|
||||
if (hz) {
|
||||
cs->nsecs = (1000000000/2) / hz;
|
||||
if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer);
|
||||
|
||||
/**
|
||||
* spi_bitbang_setup - default setup for per-word I/O loops
|
||||
*/
|
||||
@ -145,8 +184,16 @@ int spi_bitbang_setup(struct spi_device *spi)
|
||||
{
|
||||
struct spi_bitbang_cs *cs = spi->controller_state;
|
||||
struct spi_bitbang *bitbang;
|
||||
int retval;
|
||||
|
||||
if (!spi->max_speed_hz)
|
||||
bitbang = spi_master_get_devdata(spi->master);
|
||||
|
||||
/* REVISIT: some systems will want to support devices using lsb-first
|
||||
* bit encodings on the wire. In pure software that would be trivial,
|
||||
* just bitbang_txrx_le_cphaX() routines shifting the other way, and
|
||||
* some hardware controllers also have this support.
|
||||
*/
|
||||
if ((spi->mode & SPI_LSB_FIRST) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!cs) {
|
||||
@ -155,32 +202,20 @@ int spi_bitbang_setup(struct spi_device *spi)
|
||||
return -ENOMEM;
|
||||
spi->controller_state = cs;
|
||||
}
|
||||
bitbang = spi_master_get_devdata(spi->master);
|
||||
|
||||
if (!spi->bits_per_word)
|
||||
spi->bits_per_word = 8;
|
||||
|
||||
/* spi_transfer level calls that work per-word */
|
||||
if (spi->bits_per_word <= 8)
|
||||
cs->txrx_bufs = bitbang_txrx_8;
|
||||
else if (spi->bits_per_word <= 16)
|
||||
cs->txrx_bufs = bitbang_txrx_16;
|
||||
else if (spi->bits_per_word <= 32)
|
||||
cs->txrx_bufs = bitbang_txrx_32;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
/* per-word shift register access, in hardware or bitbanging */
|
||||
cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
|
||||
if (!cs->txrx_word)
|
||||
return -EINVAL;
|
||||
|
||||
/* nsecs = (clock period)/2 */
|
||||
cs->nsecs = (1000000000/2) / (spi->max_speed_hz);
|
||||
if (cs->nsecs > MAX_UDELAY_MS * 1000)
|
||||
return -EINVAL;
|
||||
retval = spi_bitbang_setup_transfer(spi, NULL);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
|
||||
dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
|
||||
__FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
|
||||
spi->bits_per_word, 2 * cs->nsecs);
|
||||
|
||||
@ -246,6 +281,8 @@ static void bitbang_work(void *_bitbang)
|
||||
unsigned tmp;
|
||||
unsigned cs_change;
|
||||
int status;
|
||||
int (*setup_transfer)(struct spi_device *,
|
||||
struct spi_transfer *);
|
||||
|
||||
m = container_of(bitbang->queue.next, struct spi_message,
|
||||
queue);
|
||||
@ -262,6 +299,7 @@ static void bitbang_work(void *_bitbang)
|
||||
tmp = 0;
|
||||
cs_change = 1;
|
||||
status = 0;
|
||||
setup_transfer = NULL;
|
||||
|
||||
list_for_each_entry (t, &m->transfers, transfer_list) {
|
||||
if (bitbang->shutdown) {
|
||||
@ -269,6 +307,20 @@ static void bitbang_work(void *_bitbang)
|
||||
break;
|
||||
}
|
||||
|
||||
/* override or restore speed and wordsize */
|
||||
if (t->speed_hz || t->bits_per_word) {
|
||||
setup_transfer = bitbang->setup_transfer;
|
||||
if (!setup_transfer) {
|
||||
status = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (setup_transfer) {
|
||||
status = setup_transfer(spi, t);
|
||||
if (status < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* set up default clock polarity, and activate chip;
|
||||
* this implicitly updates clock and spi modes as
|
||||
* previously recorded for this device via setup().
|
||||
@ -325,6 +377,10 @@ static void bitbang_work(void *_bitbang)
|
||||
m->status = status;
|
||||
m->complete(m->context);
|
||||
|
||||
/* restore speed and wordsize */
|
||||
if (setup_transfer)
|
||||
setup_transfer(spi, NULL);
|
||||
|
||||
/* normally deactivate chipselect ... unless no error and
|
||||
* cs_change has hinted that the next message will probably
|
||||
* be for this chip too.
|
||||
@ -348,6 +404,7 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
|
||||
{
|
||||
struct spi_bitbang *bitbang;
|
||||
unsigned long flags;
|
||||
int status = 0;
|
||||
|
||||
m->actual_length = 0;
|
||||
m->status = -EINPROGRESS;
|
||||
@ -357,11 +414,15 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
|
||||
return -ESHUTDOWN;
|
||||
|
||||
spin_lock_irqsave(&bitbang->lock, flags);
|
||||
list_add_tail(&m->queue, &bitbang->queue);
|
||||
queue_work(bitbang->workqueue, &bitbang->work);
|
||||
if (!spi->max_speed_hz)
|
||||
status = -ENETDOWN;
|
||||
else {
|
||||
list_add_tail(&m->queue, &bitbang->queue);
|
||||
queue_work(bitbang->workqueue, &bitbang->work);
|
||||
}
|
||||
spin_unlock_irqrestore(&bitbang->lock, flags);
|
||||
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
|
||||
|
||||
@ -406,6 +467,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
|
||||
bitbang->use_dma = 0;
|
||||
bitbang->txrx_bufs = spi_bitbang_bufs;
|
||||
if (!bitbang->master->setup) {
|
||||
if (!bitbang->setup_transfer)
|
||||
bitbang->setup_transfer =
|
||||
spi_bitbang_setup_transfer;
|
||||
bitbang->master->setup = spi_bitbang_setup;
|
||||
bitbang->master->cleanup = spi_bitbang_cleanup;
|
||||
}
|
||||
|
68
include/asm-arm/arch-pxa/pxa2xx_spi.h
Normal file
68
include/asm-arm/arch-pxa/pxa2xx_spi.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef PXA2XX_SPI_H_
|
||||
#define PXA2XX_SPI_H_
|
||||
|
||||
#define PXA2XX_CS_ASSERT (0x01)
|
||||
#define PXA2XX_CS_DEASSERT (0x02)
|
||||
|
||||
#if defined(CONFIG_PXA25x)
|
||||
#define CLOCK_SPEED_HZ 3686400
|
||||
#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00)
|
||||
#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#elif defined(CONFIG_PXA27x)
|
||||
#define CLOCK_SPEED_HZ 13000000
|
||||
#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
|
||||
#endif
|
||||
|
||||
#define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1)))))
|
||||
#define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2)))))
|
||||
#define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3)))))
|
||||
|
||||
enum pxa_ssp_type {
|
||||
SSP_UNDEFINED = 0,
|
||||
PXA25x_SSP, /* pxa 210, 250, 255, 26x */
|
||||
PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */
|
||||
PXA27x_SSP,
|
||||
};
|
||||
|
||||
/* device.platform_data for SSP controller devices */
|
||||
struct pxa2xx_spi_master {
|
||||
enum pxa_ssp_type ssp_type;
|
||||
u32 clock_enable;
|
||||
u16 num_chipselect;
|
||||
u8 enable_dma;
|
||||
};
|
||||
|
||||
/* spi_board_info.controller_data for SPI slave devices,
|
||||
* copied to spi_device.platform_data ... mostly for dma tuning
|
||||
*/
|
||||
struct pxa2xx_spi_chip {
|
||||
u8 tx_threshold;
|
||||
u8 rx_threshold;
|
||||
u8 dma_burst_size;
|
||||
u32 timeout_microsecs;
|
||||
u8 enable_loopback;
|
||||
void (*cs_control)(u32 command);
|
||||
};
|
||||
|
||||
#endif /*PXA2XX_SPI_H_*/
|
@ -31,18 +31,23 @@ extern struct bus_type spi_bus_type;
|
||||
* @master: SPI controller used with the device.
|
||||
* @max_speed_hz: Maximum clock rate to be used with this chip
|
||||
* (on this board); may be changed by the device's driver.
|
||||
* The spi_transfer.speed_hz can override this for each transfer.
|
||||
* @chip-select: Chipselect, distinguishing chips handled by "master".
|
||||
* @mode: The spi mode defines how data is clocked out and in.
|
||||
* This may be changed by the device's driver.
|
||||
* The "active low" default for chipselect mode can be overridden,
|
||||
* as can the "MSB first" default for each word in a transfer.
|
||||
* @bits_per_word: Data transfers involve one or more words; word sizes
|
||||
* like eight or 12 bits are common. In-memory wordsizes are
|
||||
* like eight or 12 bits are common. In-memory wordsizes are
|
||||
* powers of two bytes (e.g. 20 bit samples use 32 bits).
|
||||
* This may be changed by the device's driver.
|
||||
* This may be changed by the device's driver, or left at the
|
||||
* default (0) indicating protocol words are eight bit bytes.
|
||||
* The spi_transfer.bits_per_word can override this for each transfer.
|
||||
* @irq: Negative, or the number passed to request_irq() to receive
|
||||
* interrupts from this device.
|
||||
* interrupts from this device.
|
||||
* @controller_state: Controller's runtime state
|
||||
* @controller_data: Board-specific definitions for controller, such as
|
||||
* FIFO initialization parameters; from board_info.controller_data
|
||||
* FIFO initialization parameters; from board_info.controller_data
|
||||
*
|
||||
* An spi_device is used to interchange data between an SPI slave
|
||||
* (usually a discrete chip) and CPU memory.
|
||||
@ -65,6 +70,7 @@ struct spi_device {
|
||||
#define SPI_MODE_2 (SPI_CPOL|0)
|
||||
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
|
||||
#define SPI_CS_HIGH 0x04 /* chipselect active high? */
|
||||
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
|
||||
u8 bits_per_word;
|
||||
int irq;
|
||||
void *controller_state;
|
||||
@ -73,7 +79,6 @@ struct spi_device {
|
||||
|
||||
// likely need more hooks for more protocol options affecting how
|
||||
// the controller talks to each chip, like:
|
||||
// - bit order (default is wordwise msb-first)
|
||||
// - memory packing (12 bit samples into low bits, others zeroed)
|
||||
// - priority
|
||||
// - drop chipselect after each word
|
||||
@ -143,13 +148,13 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
|
||||
* struct spi_master - interface to SPI master controller
|
||||
* @cdev: class interface to this driver
|
||||
* @bus_num: board-specific (and often SOC-specific) identifier for a
|
||||
* given SPI controller.
|
||||
* given SPI controller.
|
||||
* @num_chipselect: chipselects are used to distinguish individual
|
||||
* SPI slaves, and are numbered from zero to num_chipselects.
|
||||
* each slave has a chipselect signal, but it's common that not
|
||||
* every chipselect is connected to a slave.
|
||||
* SPI slaves, and are numbered from zero to num_chipselects.
|
||||
* each slave has a chipselect signal, but it's common that not
|
||||
* every chipselect is connected to a slave.
|
||||
* @setup: updates the device mode and clocking records used by a
|
||||
* device's SPI controller; protocol code may call this.
|
||||
* device's SPI controller; protocol code may call this.
|
||||
* @transfer: adds a message to the controller's transfer queue.
|
||||
* @cleanup: frees controller-specific state
|
||||
*
|
||||
@ -167,13 +172,13 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
|
||||
struct spi_master {
|
||||
struct class_device cdev;
|
||||
|
||||
/* other than zero (== assign one dynamically), bus_num is fully
|
||||
/* other than negative (== assign one dynamically), bus_num is fully
|
||||
* board-specific. usually that simplifies to being SOC-specific.
|
||||
* example: one SOC has three SPI controllers, numbered 1..3,
|
||||
* example: one SOC has three SPI controllers, numbered 0..2,
|
||||
* and one board's schematics might show it using SPI-2. software
|
||||
* would normally use bus_num=2 for that controller.
|
||||
*/
|
||||
u16 bus_num;
|
||||
s16 bus_num;
|
||||
|
||||
/* chipselects will be integral to many controllers; some others
|
||||
* might use board-specific GPIOs.
|
||||
@ -268,10 +273,14 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
|
||||
* @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped
|
||||
* @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped
|
||||
* @len: size of rx and tx buffers (in bytes)
|
||||
* @speed_hz: Select a speed other then the device default for this
|
||||
* transfer. If 0 the default (from spi_device) is used.
|
||||
* @bits_per_word: select a bits_per_word other then the device default
|
||||
* for this transfer. If 0 the default (from spi_device) is used.
|
||||
* @cs_change: affects chipselect after this transfer completes
|
||||
* @delay_usecs: microseconds to delay after this transfer before
|
||||
* (optionally) changing the chipselect status, then starting
|
||||
* the next transfer or completing this spi_message.
|
||||
* (optionally) changing the chipselect status, then starting
|
||||
* the next transfer or completing this spi_message.
|
||||
* @transfer_list: transfers are sequenced through spi_message.transfers
|
||||
*
|
||||
* SPI transfers always write the same number of bytes as they read.
|
||||
@ -322,7 +331,9 @@ struct spi_transfer {
|
||||
dma_addr_t rx_dma;
|
||||
|
||||
unsigned cs_change:1;
|
||||
u8 bits_per_word;
|
||||
u16 delay_usecs;
|
||||
u32 speed_hz;
|
||||
|
||||
struct list_head transfer_list;
|
||||
};
|
||||
@ -356,7 +367,7 @@ struct spi_transfer {
|
||||
* and its transfers, ignore them until its completion callback.
|
||||
*/
|
||||
struct spi_message {
|
||||
struct list_head transfers;
|
||||
struct list_head transfers;
|
||||
|
||||
struct spi_device *spi;
|
||||
|
||||
@ -374,7 +385,7 @@ struct spi_message {
|
||||
*/
|
||||
|
||||
/* completion is reported through a callback */
|
||||
void (*complete)(void *context);
|
||||
void (*complete)(void *context);
|
||||
void *context;
|
||||
unsigned actual_length;
|
||||
int status;
|
||||
|
@ -30,6 +30,12 @@ struct spi_bitbang {
|
||||
|
||||
struct spi_master *master;
|
||||
|
||||
/* setup_transfer() changes clock and/or wordsize to match settings
|
||||
* for this transfer; zeroes restore defaults from spi_device.
|
||||
*/
|
||||
int (*setup_transfer)(struct spi_device *spi,
|
||||
struct spi_transfer *t);
|
||||
|
||||
void (*chipselect)(struct spi_device *spi, int is_on);
|
||||
#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */
|
||||
#define BITBANG_CS_INACTIVE 0
|
||||
@ -51,6 +57,8 @@ struct spi_bitbang {
|
||||
extern int spi_bitbang_setup(struct spi_device *spi);
|
||||
extern void spi_bitbang_cleanup(const struct spi_device *spi);
|
||||
extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
|
||||
extern int spi_bitbang_setup_transfer(struct spi_device *spi,
|
||||
struct spi_transfer *t);
|
||||
|
||||
/* start or stop queue processing */
|
||||
extern int spi_bitbang_start(struct spi_bitbang *spi);
|
||||
|
Loading…
x
Reference in New Issue
Block a user