提交 7235dd74 编写于 作者: L Linus Torvalds

Merge branch 'spi/next' of git://git.secretlab.ca/git/linux-2.6

* 'spi/next' of git://git.secretlab.ca/git/linux-2.6: (34 commits)
  spi/imx: add device tree probe support
  spi/imx: copy gpio number passed by platform data into driver private data
  spi/imx: use soc name in spi device type naming scheme
  spi/imx: merge type SPI_IMX_VER_0_7 into SPI_IMX_VER_0_4
  spi/imx: do not use spi_imx2_3 to name SPI_IMX_VER_2_3 function and macro
  spi/imx: use mx21 to name SPI_IMX_VER_0_0 function and macro
  spi/imx: do not make copy of spi_imx_devtype_data
  spi/dw: Add spi number into spi irq desc
  spi/tegra: Use engineering names in DT compatible property
  spi/fsl_spi: fix CPM spi driver
  mach-s3c2410: remove unused spi-gpio.h file
  spi: remove obsolete spi-s3c24xx-gpio driver
  mach-gta2: remove unused spi-gpio.h include
  mach-qt2410: convert to spi_gpio
  mach-jive: convert to spi_gpio
  spi/pxa2xx: Remove unavailable ssp_type from documentation
  spi/bfin_spi: uninline fat queue funcs
  spi/bfin_spi: constify pin array
  spi/bfin_spi: use structs for accessing hardware regs
  spi/topcliff-pch: Support new device ML7223 IOH
  ...

Fix up trivial conflict in arch/arm/mach-ep93xx/Makefile
* Freescale (Enhanced) Configurable Serial Peripheral Interface
(CSPI/eCSPI) for i.MX
Required properties:
- compatible : Should be "fsl,<soc>-cspi" or "fsl,<soc>-ecspi"
- reg : Offset and length of the register set for the device
- interrupts : Should contain CSPI/eCSPI interrupt
- fsl,spi-num-chipselects : Contains the number of the chipselect
- cs-gpios : Specifies the gpio pins to be used for chipselects.
Example:
ecspi@70010000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx51-ecspi";
reg = <0x70010000 0x4000>;
interrupts = <36>;
fsl,spi-num-chipselects = <2>;
cs-gpios = <&gpio3 24 0>, /* GPIO4_24 */
<&gpio3 25 0>; /* GPIO4_25 */
};
NVIDIA Tegra 2 SPI device
Required properties:
- compatible : should be "nvidia,tegra20-spi".
- gpios : should specify GPIOs used for chipselect.
......@@ -88,6 +88,16 @@ static void __init ts72xx_init_machine(void)
ARRAY_SIZE(ts72xx_spi_devices));
}
The driver can use DMA for the transfers also. In this case ts72xx_spi_info
becomes:
static struct ep93xx_spi_info ts72xx_spi_info = {
.num_chipselect = ARRAY_SIZE(ts72xx_spi_devices),
.use_dma = true;
};
Note that CONFIG_EP93XX_DMA should be enabled as well.
Thanks to
=========
Martin Guy, H. Hartley Sweeten and others who helped me during development of
......
......@@ -22,15 +22,11 @@ Typically a SPI master is defined in the arch/.../mach-*/board-*.c as a
found in include/linux/spi/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".
......@@ -61,7 +57,6 @@ static struct resource pxa_spi_nssp_resources[] = {
};
static struct pxa2xx_spi_master pxa_nssp_master_info = {
.ssp_type = PXA25x_NSSP, /* Type of SSP */
.clock_enable = CKEN_NSSP, /* NSSP Peripheral clock */
.num_chipselect = 1, /* Matches the number of chips attached to NSSP */
.enable_dma = 1, /* Enables NSSP DMA */
......
#
# Makefile for the linux kernel.
#
obj-y := core.o clock.o dma-m2p.o
obj-y := core.o clock.o
obj-m :=
obj-n :=
obj- :=
obj-$(CONFIG_EP93XX_DMA) += dma.o
obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o
obj-$(CONFIG_MACH_EDB93XX) += edb93xx.o
obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o
......
......@@ -506,11 +506,15 @@ static struct resource ep93xx_spi_resources[] = {
},
};
static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32);
static struct platform_device ep93xx_spi_device = {
.name = "ep93xx-spi",
.id = 0,
.dev = {
.platform_data = &ep93xx_spi_master_data,
.platform_data = &ep93xx_spi_master_data,
.coherent_dma_mask = DMA_BIT_MASK(32),
.dma_mask = &ep93xx_spi_dma_mask,
},
.num_resources = ARRAY_SIZE(ep93xx_spi_resources),
.resource = ep93xx_spi_resources,
......
/*
* arch/arm/mach-ep93xx/dma-m2p.c
* M2P DMA handling for Cirrus EP93xx chips.
*
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
* Copyright (C) 2006 Applied Data Systems
*
* Copyright (C) 2009 Ryan Mallon <ryan@bluewatersys.com>
*
* 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.
*/
/*
* On the EP93xx chip the following peripherals my be allocated to the 10
* Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
*
* I2S contains 3 Tx and 3 Rx DMA Channels
* AAC contains 3 Tx and 3 Rx DMA Channels
* UART1 contains 1 Tx and 1 Rx DMA Channels
* UART2 contains 1 Tx and 1 Rx DMA Channels
* UART3 contains 1 Tx and 1 Rx DMA Channels
* IrDA contains 1 Tx and 1 Rx DMA Channels
*
* SSP and IDE use the Memory to Memory (M2M) channels and are not covered
* with this implementation.
*/
#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/io.h>
#include <mach/dma.h>
#include <mach/hardware.h>
#define M2P_CONTROL 0x00
#define M2P_CONTROL_STALL_IRQ_EN (1 << 0)
#define M2P_CONTROL_NFB_IRQ_EN (1 << 1)
#define M2P_CONTROL_ERROR_IRQ_EN (1 << 3)
#define M2P_CONTROL_ENABLE (1 << 4)
#define M2P_INTERRUPT 0x04
#define M2P_INTERRUPT_STALL (1 << 0)
#define M2P_INTERRUPT_NFB (1 << 1)
#define M2P_INTERRUPT_ERROR (1 << 3)
#define M2P_PPALLOC 0x08
#define M2P_STATUS 0x0c
#define M2P_REMAIN 0x14
#define M2P_MAXCNT0 0x20
#define M2P_BASE0 0x24
#define M2P_MAXCNT1 0x30
#define M2P_BASE1 0x34
#define STATE_IDLE 0 /* Channel is inactive. */
#define STATE_STALL 1 /* Channel is active, no buffers pending. */
#define STATE_ON 2 /* Channel is active, one buffer pending. */
#define STATE_NEXT 3 /* Channel is active, two buffers pending. */
struct m2p_channel {
char *name;
void __iomem *base;
int irq;
struct clk *clk;
spinlock_t lock;
void *client;
unsigned next_slot:1;
struct ep93xx_dma_buffer *buffer_xfer;
struct ep93xx_dma_buffer *buffer_next;
struct list_head buffers_pending;
};
static struct m2p_channel m2p_rx[] = {
{"m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1},
{"m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3},
{"m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5},
{"m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7},
{"m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9},
{NULL},
};
static struct m2p_channel m2p_tx[] = {
{"m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0},
{"m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2},
{"m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4},
{"m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6},
{"m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8},
{NULL},
};
static void feed_buf(struct m2p_channel *ch, struct ep93xx_dma_buffer *buf)
{
if (ch->next_slot == 0) {
writel(buf->size, ch->base + M2P_MAXCNT0);
writel(buf->bus_addr, ch->base + M2P_BASE0);
} else {
writel(buf->size, ch->base + M2P_MAXCNT1);
writel(buf->bus_addr, ch->base + M2P_BASE1);
}
ch->next_slot ^= 1;
}
static void choose_buffer_xfer(struct m2p_channel *ch)
{
struct ep93xx_dma_buffer *buf;
ch->buffer_xfer = NULL;
if (!list_empty(&ch->buffers_pending)) {
buf = list_entry(ch->buffers_pending.next,
struct ep93xx_dma_buffer, list);
list_del(&buf->list);
feed_buf(ch, buf);
ch->buffer_xfer = buf;
}
}
static void choose_buffer_next(struct m2p_channel *ch)
{
struct ep93xx_dma_buffer *buf;
ch->buffer_next = NULL;
if (!list_empty(&ch->buffers_pending)) {
buf = list_entry(ch->buffers_pending.next,
struct ep93xx_dma_buffer, list);
list_del(&buf->list);
feed_buf(ch, buf);
ch->buffer_next = buf;
}
}
static inline void m2p_set_control(struct m2p_channel *ch, u32 v)
{
/*
* The control register must be read immediately after being written so
* that the internal state machine is correctly updated. See the ep93xx
* users' guide for details.
*/
writel(v, ch->base + M2P_CONTROL);
readl(ch->base + M2P_CONTROL);
}
static inline int m2p_channel_state(struct m2p_channel *ch)
{
return (readl(ch->base + M2P_STATUS) >> 4) & 0x3;
}
static irqreturn_t m2p_irq(int irq, void *dev_id)
{
struct m2p_channel *ch = dev_id;
struct ep93xx_dma_m2p_client *cl;
u32 irq_status, v;
int error = 0;
cl = ch->client;
spin_lock(&ch->lock);
irq_status = readl(ch->base + M2P_INTERRUPT);
if (irq_status & M2P_INTERRUPT_ERROR) {
writel(M2P_INTERRUPT_ERROR, ch->base + M2P_INTERRUPT);
error = 1;
}
if ((irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) == 0) {
spin_unlock(&ch->lock);
return IRQ_NONE;
}
switch (m2p_channel_state(ch)) {
case STATE_IDLE:
pr_crit("dma interrupt without a dma buffer\n");
BUG();
break;
case STATE_STALL:
cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
if (ch->buffer_next != NULL) {
cl->buffer_finished(cl->cookie, ch->buffer_next,
0, error);
}
choose_buffer_xfer(ch);
choose_buffer_next(ch);
if (ch->buffer_xfer != NULL)
cl->buffer_started(cl->cookie, ch->buffer_xfer);
break;
case STATE_ON:
cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
ch->buffer_xfer = ch->buffer_next;
choose_buffer_next(ch);
cl->buffer_started(cl->cookie, ch->buffer_xfer);
break;
case STATE_NEXT:
pr_crit("dma interrupt while next\n");
BUG();
break;
}
v = readl(ch->base + M2P_CONTROL) & ~(M2P_CONTROL_STALL_IRQ_EN |
M2P_CONTROL_NFB_IRQ_EN);
if (ch->buffer_xfer != NULL)
v |= M2P_CONTROL_STALL_IRQ_EN;
if (ch->buffer_next != NULL)
v |= M2P_CONTROL_NFB_IRQ_EN;
m2p_set_control(ch, v);
spin_unlock(&ch->lock);
return IRQ_HANDLED;
}
static struct m2p_channel *find_free_channel(struct ep93xx_dma_m2p_client *cl)
{
struct m2p_channel *ch;
int i;
if (cl->flags & EP93XX_DMA_M2P_RX)
ch = m2p_rx;
else
ch = m2p_tx;
for (i = 0; ch[i].base; i++) {
struct ep93xx_dma_m2p_client *client;
client = ch[i].client;
if (client != NULL) {
int port;
port = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
if (port == (client->flags &
EP93XX_DMA_M2P_PORT_MASK)) {
pr_warning("DMA channel already used by %s\n",
cl->name ? : "unknown client");
return ERR_PTR(-EBUSY);
}
}
}
for (i = 0; ch[i].base; i++) {
if (ch[i].client == NULL)
return ch + i;
}
pr_warning("No free DMA channel for %s\n",
cl->name ? : "unknown client");
return ERR_PTR(-ENODEV);
}
static void channel_enable(struct m2p_channel *ch)
{
struct ep93xx_dma_m2p_client *cl = ch->client;
u32 v;
clk_enable(ch->clk);
v = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
writel(v, ch->base + M2P_PPALLOC);
v = cl->flags & EP93XX_DMA_M2P_ERROR_MASK;
v |= M2P_CONTROL_ENABLE | M2P_CONTROL_ERROR_IRQ_EN;
m2p_set_control(ch, v);
}
static void channel_disable(struct m2p_channel *ch)
{
u32 v;
v = readl(ch->base + M2P_CONTROL);
v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
m2p_set_control(ch, v);
while (m2p_channel_state(ch) >= STATE_ON)
cpu_relax();
m2p_set_control(ch, 0x0);
while (m2p_channel_state(ch) == STATE_STALL)
cpu_relax();
clk_disable(ch->clk);
}
int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *cl)
{
struct m2p_channel *ch;
int err;
ch = find_free_channel(cl);
if (IS_ERR(ch))
return PTR_ERR(ch);
err = request_irq(ch->irq, m2p_irq, 0, cl->name ? : "dma-m2p", ch);
if (err)
return err;
ch->client = cl;
ch->next_slot = 0;
ch->buffer_xfer = NULL;
ch->buffer_next = NULL;
INIT_LIST_HEAD(&ch->buffers_pending);
cl->channel = ch;
channel_enable(ch);
return 0;
}
EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_register);
void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *cl)
{
struct m2p_channel *ch = cl->channel;
channel_disable(ch);
free_irq(ch->irq, ch);
ch->client = NULL;
}
EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_unregister);
void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *cl,
struct ep93xx_dma_buffer *buf)
{
struct m2p_channel *ch = cl->channel;
unsigned long flags;
u32 v;
spin_lock_irqsave(&ch->lock, flags);
v = readl(ch->base + M2P_CONTROL);
if (ch->buffer_xfer == NULL) {
ch->buffer_xfer = buf;
feed_buf(ch, buf);
cl->buffer_started(cl->cookie, buf);
v |= M2P_CONTROL_STALL_IRQ_EN;
m2p_set_control(ch, v);
} else if (ch->buffer_next == NULL) {
ch->buffer_next = buf;
feed_buf(ch, buf);
v |= M2P_CONTROL_NFB_IRQ_EN;
m2p_set_control(ch, v);
} else {
list_add_tail(&buf->list, &ch->buffers_pending);
}
spin_unlock_irqrestore(&ch->lock, flags);
}
EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit);
void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *cl,
struct ep93xx_dma_buffer *buf)
{
struct m2p_channel *ch = cl->channel;
list_add_tail(&buf->list, &ch->buffers_pending);
}
EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit_recursive);
void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *cl)
{
struct m2p_channel *ch = cl->channel;
channel_disable(ch);
ch->next_slot = 0;
ch->buffer_xfer = NULL;
ch->buffer_next = NULL;
INIT_LIST_HEAD(&ch->buffers_pending);
channel_enable(ch);
}
EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_flush);
static int init_channel(struct m2p_channel *ch)
{
ch->clk = clk_get(NULL, ch->name);
if (IS_ERR(ch->clk))
return PTR_ERR(ch->clk);
spin_lock_init(&ch->lock);
ch->client = NULL;
return 0;
}
static int __init ep93xx_dma_m2p_init(void)
{
int i;
int ret;
for (i = 0; m2p_rx[i].base; i++) {
ret = init_channel(m2p_rx + i);
if (ret)
return ret;
}
for (i = 0; m2p_tx[i].base; i++) {
ret = init_channel(m2p_tx + i);
if (ret)
return ret;
}
pr_info("M2P DMA subsystem initialized\n");
return 0;
}
arch_initcall(ep93xx_dma_m2p_init);
/*
* arch/arm/mach-ep93xx/dma.c
*
* Platform support code for the EP93xx dmaengine driver.
*
* Copyright (C) 2011 Mika Westerberg
*
* This work is based on the original dma-m2p implementation with
* following copyrights:
*
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
* Copyright (C) 2006 Applied Data Systems
* Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
*
* 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.
*/
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <mach/dma.h>
#include <mach/hardware.h>
#define DMA_CHANNEL(_name, _base, _irq) \
{ .name = (_name), .base = (_base), .irq = (_irq) }
/*
* DMA M2P channels.
*
* On the EP93xx chip the following peripherals my be allocated to the 10
* Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
*
* I2S contains 3 Tx and 3 Rx DMA Channels
* AAC contains 3 Tx and 3 Rx DMA Channels
* UART1 contains 1 Tx and 1 Rx DMA Channels
* UART2 contains 1 Tx and 1 Rx DMA Channels
* UART3 contains 1 Tx and 1 Rx DMA Channels
* IrDA contains 1 Tx and 1 Rx DMA Channels
*
* Registers are mapped statically in ep93xx_map_io().
*/
static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
};
static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
.channels = ep93xx_dma_m2p_channels,
.num_channels = ARRAY_SIZE(ep93xx_dma_m2p_channels),
};
static struct platform_device ep93xx_dma_m2p_device = {
.name = "ep93xx-dma-m2p",
.id = -1,
.dev = {
.platform_data = &ep93xx_dma_m2p_data,
},
};
/*
* DMA M2M channels.
*
* There are 2 M2M channels which support memcpy/memset and in addition simple
* hardware requests from/to SSP and IDE. We do not implement an external
* hardware requests.
*
* Registers are mapped statically in ep93xx_map_io().
*/
static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
};
static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
.channels = ep93xx_dma_m2m_channels,
.num_channels = ARRAY_SIZE(ep93xx_dma_m2m_channels),
};
static struct platform_device ep93xx_dma_m2m_device = {
.name = "ep93xx-dma-m2m",
.id = -1,
.dev = {
.platform_data = &ep93xx_dma_m2m_data,
},
};
static int __init ep93xx_dma_init(void)
{
platform_device_register(&ep93xx_dma_m2p_device);
platform_device_register(&ep93xx_dma_m2m_device);
return 0;
}
arch_initcall(ep93xx_dma_init);
/**
* DOC: EP93xx DMA M2P memory to peripheral and peripheral to memory engine
*
* The EP93xx DMA M2P subsystem handles DMA transfers between memory and
* peripherals. DMA M2P channels are available for audio, UARTs and IrDA.
* See chapter 10 of the EP93xx users guide for full details on the DMA M2P
* engine.
*
* See sound/soc/ep93xx/ep93xx-pcm.c for an example use of the DMA M2P code.
*
*/
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
#include <linux/list.h>
#include <linux/types.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
/**
* struct ep93xx_dma_buffer - Information about a buffer to be transferred
* using the DMA M2P engine
/*
* M2P channels.
*
* @list: Entry in DMA buffer list
* @bus_addr: Physical address of the buffer
* @size: Size of the buffer in bytes
* Note that these values are also directly used for setting the PPALLOC
* register.
*/
struct ep93xx_dma_buffer {
struct list_head list;
u32 bus_addr;
u16 size;
};
#define EP93XX_DMA_I2S1 0
#define EP93XX_DMA_I2S2 1
#define EP93XX_DMA_AAC1 2
#define EP93XX_DMA_AAC2 3
#define EP93XX_DMA_AAC3 4
#define EP93XX_DMA_I2S3 5
#define EP93XX_DMA_UART1 6
#define EP93XX_DMA_UART2 7
#define EP93XX_DMA_UART3 8
#define EP93XX_DMA_IRDA 9
/* M2M channels */
#define EP93XX_DMA_SSP 10
#define EP93XX_DMA_IDE 11
/**
* struct ep93xx_dma_m2p_client - Information about a DMA M2P client
*
* @name: Unique name for this client
* @flags: Client flags
* @cookie: User data to pass to callback functions
* @buffer_started: Non NULL function to call when a transfer is started.
* The arguments are the user data cookie and the DMA
* buffer which is starting.
* @buffer_finished: Non NULL function to call when a transfer is completed.
* The arguments are the user data cookie, the DMA buffer
* which has completed, and a boolean flag indicating if
* the transfer had an error.
* struct ep93xx_dma_data - configuration data for the EP93xx dmaengine
* @port: peripheral which is requesting the channel
* @direction: TX/RX channel
* @name: optional name for the channel, this is displayed in /proc/interrupts
*
* This information is passed as private channel parameter in a filter
* function. Note that this is only needed for slave/cyclic channels. For
* memcpy channels %NULL data should be passed.
*/
struct ep93xx_dma_m2p_client {
char *name;
u8 flags;
void *cookie;
void (*buffer_started)(void *cookie,
struct ep93xx_dma_buffer *buf);
void (*buffer_finished)(void *cookie,
struct ep93xx_dma_buffer *buf,
int bytes, int error);
/* private: Internal use only */
void *channel;
struct ep93xx_dma_data {
int port;
enum dma_data_direction direction;
const char *name;
};
/* DMA M2P ports */
#define EP93XX_DMA_M2P_PORT_I2S1 0x00
#define EP93XX_DMA_M2P_PORT_I2S2 0x01
#define EP93XX_DMA_M2P_PORT_AAC1 0x02
#define EP93XX_DMA_M2P_PORT_AAC2 0x03
#define EP93XX_DMA_M2P_PORT_AAC3 0x04
#define EP93XX_DMA_M2P_PORT_I2S3 0x05
#define EP93XX_DMA_M2P_PORT_UART1 0x06
#define EP93XX_DMA_M2P_PORT_UART2 0x07
#define EP93XX_DMA_M2P_PORT_UART3 0x08
#define EP93XX_DMA_M2P_PORT_IRDA 0x09
#define EP93XX_DMA_M2P_PORT_MASK 0x0f
/* DMA M2P client flags */
#define EP93XX_DMA_M2P_TX 0x00 /* Memory to peripheral */
#define EP93XX_DMA_M2P_RX 0x10 /* Peripheral to memory */
/*
* DMA M2P client error handling flags. See the EP93xx users guide
* documentation on the DMA M2P CONTROL register for more details
*/
#define EP93XX_DMA_M2P_ABORT_ON_ERROR 0x20 /* Abort on peripheral error */
#define EP93XX_DMA_M2P_IGNORE_ERROR 0x40 /* Ignore peripheral errors */
#define EP93XX_DMA_M2P_ERROR_MASK 0x60 /* Mask of error bits */
/**
* ep93xx_dma_m2p_client_register - Register a client with the DMA M2P
* subsystem
*
* @m2p: Client information to register
* returns 0 on success
*
* The DMA M2P subsystem allocates a channel and an interrupt line for the DMA
* client
* struct ep93xx_dma_chan_data - platform specific data for a DMA channel
* @name: name of the channel, used for getting the right clock for the channel
* @base: mapped registers
* @irq: interrupt number used by this channel
*/
int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *m2p);
struct ep93xx_dma_chan_data {
const char *name;
void __iomem *base;
int irq;
};
/**
* ep93xx_dma_m2p_client_unregister - Unregister a client from the DMA M2P
* subsystem
*
* @m2p: Client to unregister
* struct ep93xx_dma_platform_data - platform data for the dmaengine driver
* @channels: array of channels which are passed to the driver
* @num_channels: number of channels in the array
*
* Any transfers currently in progress will be completed in hardware, but
* ignored in software.
* This structure is passed to the DMA engine driver via platform data. For
* M2P channels, contract is that even channels are for TX and odd for RX.
* There is no requirement for the M2M channels.
*/
void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *m2p);
struct ep93xx_dma_platform_data {
struct ep93xx_dma_chan_data *channels;
size_t num_channels;
};
/**
* ep93xx_dma_m2p_submit - Submit a DMA M2P transfer
*
* @m2p: DMA Client to submit the transfer on
* @buf: DMA Buffer to submit
*
* If the current or next transfer positions are free on the M2P client then
* the transfer is started immediately. If not, the transfer is added to the
* list of pending transfers. This function must not be called from the
* buffer_finished callback for an M2P channel.
*
*/
void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *m2p,
struct ep93xx_dma_buffer *buf);
static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan)
{
return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p");
}
/**
* ep93xx_dma_m2p_submit_recursive - Put a DMA transfer on the pending list
* for an M2P channel
* ep93xx_dma_chan_direction - returns direction the channel can be used
* @chan: channel
*
* @m2p: DMA Client to submit the transfer on
* @buf: DMA Buffer to submit
*
* This function must only be called from the buffer_finished callback for an
* M2P channel. It is commonly used to add the next transfer in a chained list
* of DMA transfers.
* This function can be used in filter functions to find out whether the
* channel supports given DMA direction. Only M2P channels have such
* limitation, for M2M channels the direction is configurable.
*/
void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *m2p,
struct ep93xx_dma_buffer *buf);
static inline enum dma_data_direction
ep93xx_dma_chan_direction(struct dma_chan *chan)
{
if (!ep93xx_dma_chan_is_m2p(chan))
return DMA_NONE;
/**
* ep93xx_dma_m2p_flush - Flush all pending transfers on a DMA M2P client
*
* @m2p: DMA client to flush transfers on
*
* Any transfers currently in progress will be completed in hardware, but
* ignored in software.
*
*/
void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *m2p);
/* even channels are for TX, odd for RX */
return (chan->chan_id % 2 == 0) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
}
#endif /* __ASM_ARCH_DMA_H */
......@@ -7,9 +7,11 @@ struct spi_device;
* struct ep93xx_spi_info - EP93xx specific SPI descriptor
* @num_chipselect: number of chip selects on this board, must be
* at least one
* @use_dma: use DMA for the transfers
*/
struct ep93xx_spi_info {
int num_chipselect;
bool use_dma;
};
/**
......
......@@ -282,9 +282,10 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
_REGISTER_CLOCK("imx25-cspi.0", NULL, cspi1_clk)
_REGISTER_CLOCK("imx25-cspi.1", NULL, cspi2_clk)
_REGISTER_CLOCK("imx25-cspi.2", NULL, cspi3_clk)
/* i.mx25 has the i.mx35 type cspi */
_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk)
_REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk)
_REGISTER_CLOCK("imx35-cspi.2", NULL, cspi3_clk)
_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk)
_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
......
......@@ -1442,7 +1442,8 @@ static struct clk_lookup mx51_lookups[] = {
_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
/* i.mx51 has the i.mx35 type cspi */
_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
......@@ -1471,9 +1472,11 @@ static struct clk_lookup mx53_lookups[] = {
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
_REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
_REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
_REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
/* i.mx53 has the i.mx51 type ecspi */
_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
/* i.mx53 has the i.mx25 type cspi */
_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
};
......
/* arch/arm/mach-s3c2410/include/mach/spi-gpio.h
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - SPI Controller platform_device info
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_SPIGPIO_H
#define __ASM_ARCH_SPIGPIO_H __FILE__
struct s3c2410_spigpio_info {
unsigned long pin_clk;
unsigned long pin_mosi;
unsigned long pin_miso;
int num_chipselect;
int bus_num;
void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
};
#endif /* __ASM_ARCH_SPIGPIO_H */
......@@ -32,7 +32,7 @@
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/spi/spi_gpio.h>
#include <linux/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
......@@ -53,8 +53,6 @@
#include <mach/fb.h>
#include <plat/nand.h>
#include <plat/udc.h>
#include <mach/spi.h>
#include <mach/spi-gpio.h>
#include <plat/iic.h>
#include <plat/common-smdk.h>
......@@ -216,32 +214,16 @@ static struct platform_device qt2410_led = {
/* SPI */
static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
{
switch (cs) {
case BITBANG_CS_ACTIVE:
gpio_set_value(S3C2410_GPB(5), 0);
break;
case BITBANG_CS_INACTIVE:
gpio_set_value(S3C2410_GPB(5), 1);
break;
}
}
static struct s3c2410_spigpio_info spi_gpio_cfg = {
.pin_clk = S3C2410_GPG(7),
.pin_mosi = S3C2410_GPG(6),
.pin_miso = S3C2410_GPG(5),
.chip_select = &spi_gpio_cs,
static struct spi_gpio_platform_data spi_gpio_cfg = {
.sck = S3C2410_GPG(7),
.mosi = S3C2410_GPG(6),
.miso = S3C2410_GPG(5),
};
static struct platform_device qt2410_spi = {
.name = "s3c24xx-spi-gpio",
.id = 1,
.dev = {
.platform_data = &spi_gpio_cfg,
},
.name = "spi-gpio",
.id = 1,
.dev.platform_data = &spi_gpio_cfg,
};
/* Board devices */
......
......@@ -25,6 +25,7 @@
#include <video/ili9320.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
......@@ -38,7 +39,6 @@
#include <mach/regs-gpio.h>
#include <mach/regs-mem.h>
#include <mach/regs-lcd.h>
#include <mach/spi-gpio.h>
#include <mach/fb.h>
#include <asm/mach-types.h>
......@@ -389,45 +389,30 @@ static struct ili9320_platdata jive_lcm_config = {
/* LCD SPI support */
static void jive_lcd_spi_chipselect(struct s3c2410_spigpio_info *spi, int cs)
{
gpio_set_value(S3C2410_GPB(7), cs ? 0 : 1);
}
static struct s3c2410_spigpio_info jive_lcd_spi = {
.bus_num = 1,
.pin_clk = S3C2410_GPG(8),
.pin_mosi = S3C2410_GPB(8),
.num_chipselect = 1,
.chip_select = jive_lcd_spi_chipselect,
static struct spi_gpio_platform_data jive_lcd_spi = {
.sck = S3C2410_GPG(8),
.mosi = S3C2410_GPB(8),
.miso = SPI_GPIO_NO_MISO,
};
static struct platform_device jive_device_lcdspi = {
.name = "spi_s3c24xx_gpio",
.name = "spi-gpio",
.id = 1,
.num_resources = 0,
.dev.platform_data = &jive_lcd_spi,
};
/* WM8750 audio code SPI definition */
static void jive_wm8750_chipselect(struct s3c2410_spigpio_info *spi, int cs)
{
gpio_set_value(S3C2410_GPH(10), cs ? 0 : 1);
}
/* WM8750 audio code SPI definition */
static struct s3c2410_spigpio_info jive_wm8750_spi = {
.bus_num = 2,
.pin_clk = S3C2410_GPB(4),
.pin_mosi = S3C2410_GPB(9),
.num_chipselect = 1,
.chip_select = jive_wm8750_chipselect,
static struct spi_gpio_platform_data jive_wm8750_spi = {
.sck = S3C2410_GPB(4),
.mosi = S3C2410_GPB(9),
.miso = SPI_GPIO_NO_MISO,
};
static struct platform_device jive_device_wm8750 = {
.name = "spi_s3c24xx_gpio",
.name = "spi-gpio",
.id = 2,
.num_resources = 0,
.dev.platform_data = &jive_wm8750_spi,
};
......@@ -441,12 +426,14 @@ static struct spi_board_info __initdata jive_spi_devs[] = {
.mode = SPI_MODE_3, /* CPOL=1, CPHA=1 */
.max_speed_hz = 100000,
.platform_data = &jive_lcm_config,
.controller_data = (void *)S3C2410_GPB(7),
}, {
.modalias = "WM8750",
.bus_num = 2,
.chip_select = 0,
.mode = SPI_MODE_0, /* CPOL=0, CPHA=0 */
.max_speed_hz = 100000,
.controller_data = (void *)S3C2410_GPH(10),
},
};
......
......@@ -74,7 +74,6 @@
#include <mach/fb.h>
#include <mach/spi.h>
#include <mach/spi-gpio.h>
#include <plat/usb-control.h>
#include <mach/regs-mem.h>
#include <mach/hardware.h>
......
......@@ -40,9 +40,10 @@ const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
#endif
#ifdef CONFIG_SOC_IMX25
/* i.mx25 has the i.mx35 type cspi */
const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
#define imx25_cspi_data_entry(_id, _hwid) \
imx_spi_imx_data_entry(MX25, CSPI, "imx25-cspi", _id, _hwid, SZ_16K)
imx_spi_imx_data_entry(MX25, CSPI, "imx35-cspi", _id, _hwid, SZ_16K)
imx25_cspi_data_entry(0, 1),
imx25_cspi_data_entry(1, 2),
imx25_cspi_data_entry(2, 3),
......@@ -79,8 +80,9 @@ const struct imx_spi_imx_data imx35_cspi_data[] __initconst = {
#endif /* ifdef CONFIG_SOC_IMX35 */
#ifdef CONFIG_SOC_IMX51
/* i.mx51 has the i.mx35 type cspi */
const struct imx_spi_imx_data imx51_cspi_data __initconst =
imx_spi_imx_data_entry_single(MX51, CSPI, "imx51-cspi", 2, , SZ_4K);
imx_spi_imx_data_entry_single(MX51, CSPI, "imx35-cspi", 2, , SZ_4K);
const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
#define imx51_ecspi_data_entry(_id, _hwid) \
......@@ -91,12 +93,14 @@ const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
#endif /* ifdef CONFIG_SOC_IMX51 */
#ifdef CONFIG_SOC_IMX53
/* i.mx53 has the i.mx35 type cspi */
const struct imx_spi_imx_data imx53_cspi_data __initconst =
imx_spi_imx_data_entry_single(MX53, CSPI, "imx53-cspi", 0, , SZ_4K);
imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 0, , SZ_4K);
/* i.mx53 has the i.mx51 type ecspi */
const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
#define imx53_ecspi_data_entry(_id, _hwid) \
imx_spi_imx_data_entry(MX53, ECSPI, "imx53-ecspi", _id, _hwid, SZ_4K)
imx_spi_imx_data_entry(MX53, ECSPI, "imx51-ecspi", _id, _hwid, SZ_4K)
imx53_ecspi_data_entry(0, 1),
imx53_ecspi_data_entry(1, 2),
};
......
......@@ -237,6 +237,13 @@ config MXS_DMA
Support the MXS DMA engine. This engine including APBH-DMA
and APBX-DMA is integrated into Freescale i.MX23/28 chips.
config EP93XX_DMA
bool "Cirrus Logic EP93xx DMA support"
depends on ARCH_EP93XX
select DMA_ENGINE
help
Enable support for the Cirrus Logic EP93xx M2P/M2M DMA controller.
config DMA_ENGINE
bool
......
......@@ -25,3 +25,4 @@ obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
obj-$(CONFIG_PL330_DMA) += pl330.o
obj-$(CONFIG_PCH_DMA) += pch_dma.o
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
此差异已折叠。
......@@ -86,9 +86,6 @@ config SPI_BFIN_SPORT
help
Enable support for a SPI bus via the Blackfin SPORT peripheral.
This driver can also be built as a module. If so, the module
will be called spi_bfin_sport.
config SPI_AU1550
tristate "Au1550/Au12x0 SPI Controller"
depends on (SOC_AU1550 || SOC_AU1200) && EXPERIMENTAL
......@@ -97,9 +94,6 @@ config SPI_AU1550
If you say yes to this option, support will be included for the
Au1550 SPI controller (may also work with Au1200,Au1210,Au1250).
This driver can also be built as a module. If so, the module
will be called au1550_spi.
config SPI_BITBANG
tristate "Utilities for Bitbanging SPI masters"
help
......@@ -130,9 +124,6 @@ config SPI_COLDFIRE_QSPI
This enables support for the Coldfire QSPI controller in master
mode.
This driver can also be built as a module. If so, the module
will be called coldfire_qspi.
config SPI_DAVINCI
tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller"
depends on SPI_MASTER && ARCH_DAVINCI
......@@ -140,9 +131,6 @@ config SPI_DAVINCI
help
SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
This driver can also be built as a module. The module will be called
davinci_spi.
config SPI_EP93XX
tristate "Cirrus Logic EP93xx SPI controller"
depends on ARCH_EP93XX
......@@ -150,9 +138,6 @@ config SPI_EP93XX
This enables using the Cirrus EP93xx SPI controller in master
mode.
To compile this driver as a module, choose M here. The module will be
called ep93xx_spi.
config SPI_GPIO
tristate "GPIO-based bitbanging SPI Master"
depends on GENERIC_GPIO
......@@ -169,21 +154,6 @@ config SPI_GPIO
GPIO operations, you should be able to leverage that for better
speed with a custom version of this driver; see the source code.
config SPI_IMX_VER_IMX1
def_bool y if SOC_IMX1
config SPI_IMX_VER_0_0
def_bool y if SOC_IMX21 || SOC_IMX27
config SPI_IMX_VER_0_4
def_bool y if SOC_IMX31
config SPI_IMX_VER_0_7
def_bool y if ARCH_MX25 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
config SPI_IMX_VER_2_3
def_bool y if SOC_IMX51 || SOC_IMX53
config SPI_IMX
tristate "Freescale i.MX SPI controllers"
depends on ARCH_MXC
......@@ -328,16 +298,6 @@ config SPI_S3C24XX_FIQ
no free DMA channels, or when doing transfers that required both
TX and RX data paths.
config SPI_S3C24XX_GPIO
tristate "Samsung S3C24XX series SPI by GPIO"
depends on ARCH_S3C2410 && EXPERIMENTAL
select SPI_BITBANG
help
SPI driver for Samsung S3C24XX series ARM SoCs using
GPIO lines to provide the SPI bus. This can be used where
the inbuilt hardware cannot provide the transfer mode, or
where the board is using non hardware connected pins.
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
depends on (ARCH_S3C64XX || ARCH_S5P64X0)
......@@ -385,16 +345,16 @@ config SPI_TI_SSP
This selects an SPI master implementation using a TI sequencer
serial port.
To compile this driver as a module, choose M here: the
module will be called ti-ssp-spi.
config SPI_TOPCLIFF_PCH
tristate "Topcliff PCH SPI Controller"
tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH SPI controller"
depends on PCI
help
SPI driver for the Topcliff PCH (Platform Controller Hub) SPI bus
used in some x86 embedded processors.
This driver also supports the ML7213, a companion chip for the
Atom E6xx series and compatible with the Intel EG20T PCH.
config SPI_TXX9
tristate "Toshiba TXx9 SPI controller"
depends on GENERIC_GPIO && CPU_TX49XX
......
......@@ -7,68 +7,55 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
# small core, mostly translating board-specific
# config declarations into driver model code
obj-$(CONFIG_SPI_MASTER) += spi.o
obj-$(CONFIG_SPI_SPIDEV) += spidev.o
# SPI master controller drivers (bus)
obj-$(CONFIG_SPI_ALTERA) += spi_altera.o
obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o
obj-$(CONFIG_SPI_ATH79) += ath79_spi.o
obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o
obj-$(CONFIG_SPI_BFIN_SPORT) += spi_bfin_sport.o
obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += coldfire_qspi.o
obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o
obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o
obj-$(CONFIG_SPI_DW_PCI) += dw_spi_midpci.o
dw_spi_midpci-objs := dw_spi_pci.o dw_spi_mid.o
obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o
obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi.o
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o
obj-$(CONFIG_SPI_OC_TINY) += spi_oc_tiny.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o
obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o
obj-$(CONFIG_SPI_ORION) += orion_spi.o
obj-$(CONFIG_SPI_PL022) += amba-pl022.o
obj-$(CONFIG_SPI_MPC512x_PSC) += mpc512x_psc_spi.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
obj-$(CONFIG_SPI_MPC52xx) += mpc52xx_spi.o
obj-$(CONFIG_SPI_FSL_LIB) += spi_fsl_lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi_fsl_espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi_fsl_spi.o
obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o
obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx_hw.o
obj-$(CONFIG_SPI_S3C64XX) += spi_s3c64xx.o
obj-$(CONFIG_SPI_TEGRA) += spi_tegra.o
obj-$(CONFIG_SPI_TI_SSP) += ti-ssp-spi.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi_topcliff_pch.o
obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
obj-$(CONFIG_SPI_SH) += spi_sh.o
obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
obj-$(CONFIG_SPI_ALTERA) += spi-altera.o
obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o
obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o
obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o
obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
obj-$(CONFIG_SPI_GPIO) += spi-gpio.o
obj-$(CONFIG_SPI_IMX) += spi-imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += spi-omap-uwire.o
obj-$(CONFIG_SPI_OMAP_100K) += spi-omap-100k.o
obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o
obj-$(CONFIG_SPI_ORION) += spi-orion.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
spi-s3c24xx-hw-y := spi-s3c24xx.o
spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o
obj-$(CONFIG_SPI_SH) += spi-sh.o
obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
obj-$(CONFIG_SPI_SH_SCI) += spi-sh-sci.o
obj-$(CONFIG_SPI_STMP3XXX) += spi-stmp.o
obj-$(CONFIG_SPI_TEGRA) += spi-tegra.o
obj-$(CONFIG_SPI_TI_SSP) += spi-ti-ssp.o
obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
# special build for s3c24xx spi driver with fiq support
spi_s3c24xx_hw-y := spi_s3c24xx.o
spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
# ... add above this line ...
# SPI protocol drivers (device/link on bus)
obj-$(CONFIG_SPI_SPIDEV) += spidev.o
obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
# ... add above this line ...
# SPI slave controller drivers (upstream link)
# ... add above this line ...
# SPI slave drivers (protocol for that link)
# ... add above this line ...
/*
* Register definitions for Atmel Serial Peripheral Interface (SPI)
*
* Copyright (C) 2006 Atmel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ATMEL_SPI_H__
#define __ATMEL_SPI_H__
/* SPI register offsets */
#define SPI_CR 0x0000
#define SPI_MR 0x0004
#define SPI_RDR 0x0008
#define SPI_TDR 0x000c
#define SPI_SR 0x0010
#define SPI_IER 0x0014
#define SPI_IDR 0x0018
#define SPI_IMR 0x001c
#define SPI_CSR0 0x0030
#define SPI_CSR1 0x0034
#define SPI_CSR2 0x0038
#define SPI_CSR3 0x003c
#define SPI_RPR 0x0100
#define SPI_RCR 0x0104
#define SPI_TPR 0x0108
#define SPI_TCR 0x010c
#define SPI_RNPR 0x0110
#define SPI_RNCR 0x0114
#define SPI_TNPR 0x0118
#define SPI_TNCR 0x011c
#define SPI_PTCR 0x0120
#define SPI_PTSR 0x0124
/* Bitfields in CR */
#define SPI_SPIEN_OFFSET 0
#define SPI_SPIEN_SIZE 1
#define SPI_SPIDIS_OFFSET 1
#define SPI_SPIDIS_SIZE 1
#define SPI_SWRST_OFFSET 7
#define SPI_SWRST_SIZE 1
#define SPI_LASTXFER_OFFSET 24
#define SPI_LASTXFER_SIZE 1
/* Bitfields in MR */
#define SPI_MSTR_OFFSET 0
#define SPI_MSTR_SIZE 1
#define SPI_PS_OFFSET 1
#define SPI_PS_SIZE 1
#define SPI_PCSDEC_OFFSET 2
#define SPI_PCSDEC_SIZE 1
#define SPI_FDIV_OFFSET 3
#define SPI_FDIV_SIZE 1
#define SPI_MODFDIS_OFFSET 4
#define SPI_MODFDIS_SIZE 1
#define SPI_LLB_OFFSET 7
#define SPI_LLB_SIZE 1
#define SPI_PCS_OFFSET 16
#define SPI_PCS_SIZE 4
#define SPI_DLYBCS_OFFSET 24
#define SPI_DLYBCS_SIZE 8
/* Bitfields in RDR */
#define SPI_RD_OFFSET 0
#define SPI_RD_SIZE 16
/* Bitfields in TDR */
#define SPI_TD_OFFSET 0
#define SPI_TD_SIZE 16
/* Bitfields in SR */
#define SPI_RDRF_OFFSET 0
#define SPI_RDRF_SIZE 1
#define SPI_TDRE_OFFSET 1
#define SPI_TDRE_SIZE 1
#define SPI_MODF_OFFSET 2
#define SPI_MODF_SIZE 1
#define SPI_OVRES_OFFSET 3
#define SPI_OVRES_SIZE 1
#define SPI_ENDRX_OFFSET 4
#define SPI_ENDRX_SIZE 1
#define SPI_ENDTX_OFFSET 5
#define SPI_ENDTX_SIZE 1
#define SPI_RXBUFF_OFFSET 6
#define SPI_RXBUFF_SIZE 1
#define SPI_TXBUFE_OFFSET 7
#define SPI_TXBUFE_SIZE 1
#define SPI_NSSR_OFFSET 8
#define SPI_NSSR_SIZE 1
#define SPI_TXEMPTY_OFFSET 9
#define SPI_TXEMPTY_SIZE 1
#define SPI_SPIENS_OFFSET 16
#define SPI_SPIENS_SIZE 1
/* Bitfields in CSR0 */
#define SPI_CPOL_OFFSET 0
#define SPI_CPOL_SIZE 1
#define SPI_NCPHA_OFFSET 1
#define SPI_NCPHA_SIZE 1
#define SPI_CSAAT_OFFSET 3
#define SPI_CSAAT_SIZE 1
#define SPI_BITS_OFFSET 4
#define SPI_BITS_SIZE 4
#define SPI_SCBR_OFFSET 8
#define SPI_SCBR_SIZE 8
#define SPI_DLYBS_OFFSET 16
#define SPI_DLYBS_SIZE 8
#define SPI_DLYBCT_OFFSET 24
#define SPI_DLYBCT_SIZE 8
/* Bitfields in RCR */
#define SPI_RXCTR_OFFSET 0
#define SPI_RXCTR_SIZE 16
/* Bitfields in TCR */
#define SPI_TXCTR_OFFSET 0
#define SPI_TXCTR_SIZE 16
/* Bitfields in RNCR */
#define SPI_RXNCR_OFFSET 0
#define SPI_RXNCR_SIZE 16
/* Bitfields in TNCR */
#define SPI_TXNCR_OFFSET 0
#define SPI_TXNCR_SIZE 16
/* Bitfields in PTCR */
#define SPI_RXTEN_OFFSET 0
#define SPI_RXTEN_SIZE 1
#define SPI_RXTDIS_OFFSET 1
#define SPI_RXTDIS_SIZE 1
#define SPI_TXTEN_OFFSET 8
#define SPI_TXTEN_SIZE 1
#define SPI_TXTDIS_OFFSET 9
#define SPI_TXTDIS_SIZE 1
/* Constants for BITS */
#define SPI_BITS_8_BPT 0
#define SPI_BITS_9_BPT 1
#define SPI_BITS_10_BPT 2
#define SPI_BITS_11_BPT 3
#define SPI_BITS_12_BPT 4
#define SPI_BITS_13_BPT 5
#define SPI_BITS_14_BPT 6
#define SPI_BITS_15_BPT 7
#define SPI_BITS_16_BPT 8
/* Bit manipulation macros */
#define SPI_BIT(name) \
(1 << SPI_##name##_OFFSET)
#define SPI_BF(name,value) \
(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
#define SPI_BFEXT(name,value) \
(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
#define SPI_BFINS(name,value,old) \
( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
| SPI_BF(name,value))
/* Register access macros */
#define spi_readl(port,reg) \
__raw_readl((port)->regs + SPI_##reg)
#define spi_writel(port,reg,value) \
__raw_writel((value), (port)->regs + SPI_##reg)
#endif /* __ATMEL_SPI_H__ */
......@@ -232,7 +232,7 @@ static __devinit int ath79_spi_probe(struct platform_device *pdev)
goto err_put_master;
}
sp->base = ioremap(r->start, r->end - r->start + 1);
sp->base = ioremap(r->start, resource_size(r));
if (!sp->base) {
ret = -ENXIO;
goto err_put_master;
......
......@@ -25,7 +25,160 @@
#include <mach/gpio.h>
#include <mach/cpu.h>
#include "atmel_spi.h"
/* SPI register offsets */
#define SPI_CR 0x0000
#define SPI_MR 0x0004
#define SPI_RDR 0x0008
#define SPI_TDR 0x000c
#define SPI_SR 0x0010
#define SPI_IER 0x0014
#define SPI_IDR 0x0018
#define SPI_IMR 0x001c
#define SPI_CSR0 0x0030
#define SPI_CSR1 0x0034
#define SPI_CSR2 0x0038
#define SPI_CSR3 0x003c
#define SPI_RPR 0x0100
#define SPI_RCR 0x0104
#define SPI_TPR 0x0108
#define SPI_TCR 0x010c
#define SPI_RNPR 0x0110
#define SPI_RNCR 0x0114
#define SPI_TNPR 0x0118
#define SPI_TNCR 0x011c
#define SPI_PTCR 0x0120
#define SPI_PTSR 0x0124
/* Bitfields in CR */
#define SPI_SPIEN_OFFSET 0
#define SPI_SPIEN_SIZE 1
#define SPI_SPIDIS_OFFSET 1
#define SPI_SPIDIS_SIZE 1
#define SPI_SWRST_OFFSET 7
#define SPI_SWRST_SIZE 1
#define SPI_LASTXFER_OFFSET 24
#define SPI_LASTXFER_SIZE 1
/* Bitfields in MR */
#define SPI_MSTR_OFFSET 0
#define SPI_MSTR_SIZE 1
#define SPI_PS_OFFSET 1
#define SPI_PS_SIZE 1
#define SPI_PCSDEC_OFFSET 2
#define SPI_PCSDEC_SIZE 1
#define SPI_FDIV_OFFSET 3
#define SPI_FDIV_SIZE 1
#define SPI_MODFDIS_OFFSET 4
#define SPI_MODFDIS_SIZE 1
#define SPI_LLB_OFFSET 7
#define SPI_LLB_SIZE 1
#define SPI_PCS_OFFSET 16
#define SPI_PCS_SIZE 4
#define SPI_DLYBCS_OFFSET 24
#define SPI_DLYBCS_SIZE 8
/* Bitfields in RDR */
#define SPI_RD_OFFSET 0
#define SPI_RD_SIZE 16
/* Bitfields in TDR */
#define SPI_TD_OFFSET 0
#define SPI_TD_SIZE 16
/* Bitfields in SR */
#define SPI_RDRF_OFFSET 0
#define SPI_RDRF_SIZE 1
#define SPI_TDRE_OFFSET 1
#define SPI_TDRE_SIZE 1
#define SPI_MODF_OFFSET 2
#define SPI_MODF_SIZE 1
#define SPI_OVRES_OFFSET 3
#define SPI_OVRES_SIZE 1
#define SPI_ENDRX_OFFSET 4
#define SPI_ENDRX_SIZE 1
#define SPI_ENDTX_OFFSET 5
#define SPI_ENDTX_SIZE 1
#define SPI_RXBUFF_OFFSET 6
#define SPI_RXBUFF_SIZE 1
#define SPI_TXBUFE_OFFSET 7
#define SPI_TXBUFE_SIZE 1
#define SPI_NSSR_OFFSET 8
#define SPI_NSSR_SIZE 1
#define SPI_TXEMPTY_OFFSET 9
#define SPI_TXEMPTY_SIZE 1
#define SPI_SPIENS_OFFSET 16
#define SPI_SPIENS_SIZE 1
/* Bitfields in CSR0 */
#define SPI_CPOL_OFFSET 0
#define SPI_CPOL_SIZE 1
#define SPI_NCPHA_OFFSET 1
#define SPI_NCPHA_SIZE 1
#define SPI_CSAAT_OFFSET 3
#define SPI_CSAAT_SIZE 1
#define SPI_BITS_OFFSET 4
#define SPI_BITS_SIZE 4
#define SPI_SCBR_OFFSET 8
#define SPI_SCBR_SIZE 8
#define SPI_DLYBS_OFFSET 16
#define SPI_DLYBS_SIZE 8
#define SPI_DLYBCT_OFFSET 24
#define SPI_DLYBCT_SIZE 8
/* Bitfields in RCR */
#define SPI_RXCTR_OFFSET 0
#define SPI_RXCTR_SIZE 16
/* Bitfields in TCR */
#define SPI_TXCTR_OFFSET 0
#define SPI_TXCTR_SIZE 16
/* Bitfields in RNCR */
#define SPI_RXNCR_OFFSET 0
#define SPI_RXNCR_SIZE 16
/* Bitfields in TNCR */
#define SPI_TXNCR_OFFSET 0
#define SPI_TXNCR_SIZE 16
/* Bitfields in PTCR */
#define SPI_RXTEN_OFFSET 0
#define SPI_RXTEN_SIZE 1
#define SPI_RXTDIS_OFFSET 1
#define SPI_RXTDIS_SIZE 1
#define SPI_TXTEN_OFFSET 8
#define SPI_TXTEN_SIZE 1
#define SPI_TXTDIS_OFFSET 9
#define SPI_TXTDIS_SIZE 1
/* Constants for BITS */
#define SPI_BITS_8_BPT 0
#define SPI_BITS_9_BPT 1
#define SPI_BITS_10_BPT 2
#define SPI_BITS_11_BPT 3
#define SPI_BITS_12_BPT 4
#define SPI_BITS_13_BPT 5
#define SPI_BITS_14_BPT 6
#define SPI_BITS_15_BPT 7
#define SPI_BITS_16_BPT 8
/* Bit manipulation macros */
#define SPI_BIT(name) \
(1 << SPI_##name##_OFFSET)
#define SPI_BF(name,value) \
(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
#define SPI_BFEXT(name,value) \
(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
#define SPI_BFINS(name,value,old) \
( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
| SPI_BF(name,value))
/* Register access macros */
#define spi_readl(port,reg) \
__raw_readl((port)->regs + SPI_##reg)
#define spi_writel(port,reg,value) \
__raw_writel((value), (port)->regs + SPI_##reg)
/*
* The core SPI transfer engine just talks to a register bank to set up
......
/*
* au1550_spi.c - au1550 psc spi controller driver
* au1550 psc spi controller driver
* may work also with au1200, au1210, au1250
* will not work on au1000, au1100 and au1500 (no full spi controller there)
*
......
......@@ -58,7 +58,7 @@ struct bfin_spi_master_data {
struct spi_master *master;
/* Regs base of SPI controller */
void __iomem *regs_base;
struct bfin_spi_regs __iomem *regs;
/* Pin request list */
u16 *pin_req;
......@@ -122,34 +122,14 @@ struct bfin_spi_slave_data {
const struct bfin_spi_transfer_ops *ops;
};
#define DEFINE_SPI_REG(reg, off) \
static inline u16 read_##reg(struct bfin_spi_master_data *drv_data) \
{ return bfin_read16(drv_data->regs_base + off); } \
static inline void write_##reg(struct bfin_spi_master_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 bfin_spi_master_data *drv_data)
{
u16 cr;
cr = read_CTRL(drv_data);
write_CTRL(drv_data, (cr | BIT_CTL_ENABLE));
bfin_write_or(&drv_data->regs->ctl, BIT_CTL_ENABLE);
}
static void bfin_spi_disable(struct bfin_spi_master_data *drv_data)
{
u16 cr;
cr = read_CTRL(drv_data);
write_CTRL(drv_data, (cr & (~BIT_CTL_ENABLE)));
bfin_write_and(&drv_data->regs->ctl, ~BIT_CTL_ENABLE);
}
/* Caculate the SPI_BAUD register value based on input HZ */
......@@ -172,10 +152,10 @@ static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
unsigned long limit = loops_per_jiffy << 1;
/* wait for stop and clear stat */
while (!(read_STAT(drv_data) & BIT_STAT_SPIF) && --limit)
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF) && --limit)
cpu_relax();
write_STAT(drv_data, BIT_STAT_CLR);
bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
return limit;
}
......@@ -183,29 +163,19 @@ static int bfin_spi_flush(struct bfin_spi_master_data *drv_data)
/* Chip select operation functions for cs_change flag */
static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip)
{
if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
u16 flag = read_FLAG(drv_data);
flag &= ~chip->flag;
write_FLAG(drv_data, flag);
} else {
if (likely(chip->chip_select_num < MAX_CTRL_CS))
bfin_write_and(&drv_data->regs->flg, ~chip->flag);
else
gpio_set_value(chip->cs_gpio, 0);
}
}
static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
struct bfin_spi_slave_data *chip)
{
if (likely(chip->chip_select_num < MAX_CTRL_CS)) {
u16 flag = read_FLAG(drv_data);
flag |= chip->flag;
write_FLAG(drv_data, flag);
} else {
if (likely(chip->chip_select_num < MAX_CTRL_CS))
bfin_write_or(&drv_data->regs->flg, chip->flag);
else
gpio_set_value(chip->cs_gpio, 1);
}
/* Move delay here for consistency */
if (chip->cs_chg_udelay)
......@@ -216,25 +186,15 @@ static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data,
static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data,
struct bfin_spi_slave_data *chip)
{
if (chip->chip_select_num < MAX_CTRL_CS) {
u16 flag = read_FLAG(drv_data);
flag |= (chip->flag >> 8);
write_FLAG(drv_data, flag);
}
if (chip->chip_select_num < MAX_CTRL_CS)
bfin_write_or(&drv_data->regs->flg, chip->flag >> 8);
}
static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data,
struct bfin_spi_slave_data *chip)
{
if (chip->chip_select_num < MAX_CTRL_CS) {
u16 flag = read_FLAG(drv_data);
flag &= ~(chip->flag >> 8);
write_FLAG(drv_data, flag);
}
if (chip->chip_select_num < MAX_CTRL_CS)
bfin_write_and(&drv_data->regs->flg, ~(chip->flag >> 8));
}
/* stop controller and re-config current chip*/
......@@ -243,15 +203,15 @@ static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
struct bfin_spi_slave_data *chip = drv_data->cur_chip;
/* Clear status and disable clock */
write_STAT(drv_data, BIT_STAT_CLR);
bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
bfin_spi_disable(drv_data);
dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n");
SSYNC();
/* Load the registers */
write_CTRL(drv_data, chip->ctl_reg);
write_BAUD(drv_data, chip->baud);
bfin_write(&drv_data->regs->ctl, chip->ctl_reg);
bfin_write(&drv_data->regs->baud, chip->baud);
bfin_spi_enable(drv_data);
bfin_spi_cs_active(drv_data, chip);
......@@ -260,7 +220,7 @@ static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data)
/* used to kick off transfer in rx mode and read unwanted RX data */
static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data)
{
(void) read_RDBR(drv_data);
(void) bfin_read(&drv_data->regs->rdbr);
}
static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
......@@ -269,10 +229,10 @@ static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
/* wait until transfer finished.
checking SPIF or TXS may not guarantee transfer completion */
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
/* discard RX data and clear RXS */
bfin_spi_dummy_read(drv_data);
......@@ -287,10 +247,10 @@ static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
write_TDBR(drv_data, tx_val);
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
bfin_write(&drv_data->regs->tdbr, tx_val);
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
*(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
}
}
......@@ -300,10 +260,10 @@ static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
write_TDBR(drv_data, (*(u8 *) (drv_data->tx++)));
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++)));
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
*(u8 *) (drv_data->rx++) = read_RDBR(drv_data);
*(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr);
}
}
......@@ -319,11 +279,11 @@ static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->tx < drv_data->tx_end) {
write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
drv_data->tx += 2;
/* wait until transfer finished.
checking SPIF or TXS may not guarantee transfer completion */
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
/* discard RX data and clear RXS */
bfin_spi_dummy_read(drv_data);
......@@ -338,10 +298,10 @@ static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
write_TDBR(drv_data, tx_val);
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
bfin_write(&drv_data->regs->tdbr, tx_val);
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
*(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
drv_data->rx += 2;
}
}
......@@ -352,11 +312,11 @@ static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data)
bfin_spi_dummy_read(drv_data);
while (drv_data->rx < drv_data->rx_end) {
write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx)));
drv_data->tx += 2;
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
*(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr);
drv_data->rx += 2;
}
}
......@@ -428,7 +388,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
int loop = 0;
/* wait until transfer finished. */
while (!(read_STAT(drv_data) & BIT_STAT_RXS))
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS))
cpu_relax();
if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) ||
......@@ -439,11 +399,11 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
if (n_bytes % 2) {
u16 *buf = (u16 *)drv_data->rx;
for (loop = 0; loop < n_bytes / 2; loop++)
*buf++ = read_RDBR(drv_data);
*buf++ = bfin_read(&drv_data->regs->rdbr);
} else {
u8 *buf = (u8 *)drv_data->rx;
for (loop = 0; loop < n_bytes; loop++)
*buf++ = read_RDBR(drv_data);
*buf++ = bfin_read(&drv_data->regs->rdbr);
}
drv_data->rx += n_bytes;
}
......@@ -468,15 +428,15 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
u16 *buf = (u16 *)drv_data->rx;
u16 *buf2 = (u16 *)drv_data->tx;
for (loop = 0; loop < n_bytes / 2; loop++) {
*buf++ = read_RDBR(drv_data);
write_TDBR(drv_data, *buf2++);
*buf++ = bfin_read(&drv_data->regs->rdbr);
bfin_write(&drv_data->regs->tdbr, *buf2++);
}
} else {
u8 *buf = (u8 *)drv_data->rx;
u8 *buf2 = (u8 *)drv_data->tx;
for (loop = 0; loop < n_bytes; loop++) {
*buf++ = read_RDBR(drv_data);
write_TDBR(drv_data, *buf2++);
*buf++ = bfin_read(&drv_data->regs->rdbr);
bfin_write(&drv_data->regs->tdbr, *buf2++);
}
}
} else if (drv_data->rx) {
......@@ -485,14 +445,14 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
if (n_bytes % 2) {
u16 *buf = (u16 *)drv_data->rx;
for (loop = 0; loop < n_bytes / 2; loop++) {
*buf++ = read_RDBR(drv_data);
write_TDBR(drv_data, chip->idle_tx_val);
*buf++ = bfin_read(&drv_data->regs->rdbr);
bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
}
} else {
u8 *buf = (u8 *)drv_data->rx;
for (loop = 0; loop < n_bytes; loop++) {
*buf++ = read_RDBR(drv_data);
write_TDBR(drv_data, chip->idle_tx_val);
*buf++ = bfin_read(&drv_data->regs->rdbr);
bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
}
}
} else if (drv_data->tx) {
......@@ -501,14 +461,14 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
if (n_bytes % 2) {
u16 *buf = (u16 *)drv_data->tx;
for (loop = 0; loop < n_bytes / 2; loop++) {
read_RDBR(drv_data);
write_TDBR(drv_data, *buf++);
bfin_read(&drv_data->regs->rdbr);
bfin_write(&drv_data->regs->tdbr, *buf++);
}
} else {
u8 *buf = (u8 *)drv_data->tx;
for (loop = 0; loop < n_bytes; loop++) {
read_RDBR(drv_data);
write_TDBR(drv_data, *buf++);
bfin_read(&drv_data->regs->rdbr);
bfin_write(&drv_data->regs->tdbr, *buf++);
}
}
}
......@@ -528,19 +488,19 @@ static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id)
struct spi_message *msg = drv_data->cur_msg;
unsigned long timeout;
unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel);
u16 spistat = read_STAT(drv_data);
u16 spistat = bfin_read(&drv_data->regs->stat);
dev_dbg(&drv_data->pdev->dev,
"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
dmastat, spistat);
if (drv_data->rx != NULL) {
u16 cr = read_CTRL(drv_data);
u16 cr = bfin_read(&drv_data->regs->ctl);
/* discard old RX data and clear RXS */
bfin_spi_dummy_read(drv_data);
write_CTRL(drv_data, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
write_CTRL(drv_data, cr & ~BIT_CTL_TIMOD); /* Restore State */
write_STAT(drv_data, BIT_STAT_CLR); /* Clear Status */
bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_ENABLE); /* Disable SPI */
bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_TIMOD); /* Restore State */
bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); /* Clear Status */
}
clear_dma_irqstat(drv_data->dma_channel);
......@@ -552,17 +512,17 @@ static irqreturn_t bfin_spi_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(drv_data) & BIT_STAT_TXS) ||
(read_STAT(drv_data) & BIT_STAT_TXS))
while ((bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS) ||
(bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS))
cpu_relax();
}
dev_dbg(&drv_data->pdev->dev,
"in dma_irq_handler dmastat:0x%x spistat:0x%x\n",
dmastat, read_STAT(drv_data));
dmastat, bfin_read(&drv_data->regs->stat));
timeout = jiffies + HZ;
while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
if (!time_before(jiffies, timeout)) {
dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
break;
......@@ -699,9 +659,9 @@ static void bfin_spi_pump_transfers(unsigned long data)
bfin_spi_giveback(drv_data);
return;
}
cr = read_CTRL(drv_data) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE);
cr |= cr_width;
write_CTRL(drv_data, cr);
bfin_write(&drv_data->regs->ctl, cr);
dev_dbg(&drv_data->pdev->dev,
"transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n",
......@@ -712,11 +672,11 @@ static void bfin_spi_pump_transfers(unsigned long data)
/* Speed setup (surely valid because already checked) */
if (transfer->speed_hz)
write_BAUD(drv_data, hz_to_spi_baud(transfer->speed_hz));
bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
else
write_BAUD(drv_data, chip->baud);
bfin_write(&drv_data->regs->baud, chip->baud);
write_STAT(drv_data, BIT_STAT_CLR);
bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
bfin_spi_cs_active(drv_data, chip);
dev_dbg(&drv_data->pdev->dev,
......@@ -749,7 +709,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
}
/* poll for SPI completion before start */
while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
cpu_relax();
/* dirty hack for autobuffer DMA mode */
......@@ -766,7 +726,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
enable_dma(drv_data->dma_channel);
/* start SPI transfer */
write_CTRL(drv_data, cr | BIT_CTL_TIMOD_DMA_TX);
bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TIMOD_DMA_TX);
/* just return here, there can only be one transfer
* in this mode
......@@ -821,7 +781,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
set_dma_config(drv_data->dma_channel, dma_config);
local_irq_save(flags);
SSYNC();
write_CTRL(drv_data, cr);
bfin_write(&drv_data->regs->ctl, cr);
enable_dma(drv_data->dma_channel);
dma_enable_irq(drv_data->dma_channel);
local_irq_restore(flags);
......@@ -835,7 +795,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
* problems with setting up the output value in TDBR prior to the
* start of the transfer.
*/
write_CTRL(drv_data, cr | BIT_CTL_TXMOD);
bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TXMOD);
if (chip->pio_interrupt) {
/* SPI irq should have been disabled by now */
......@@ -845,19 +805,19 @@ static void bfin_spi_pump_transfers(unsigned long data)
/* start transfer */
if (drv_data->tx == NULL)
write_TDBR(drv_data, chip->idle_tx_val);
bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val);
else {
int loop;
if (bits_per_word % 16 == 0) {
u16 *buf = (u16 *)drv_data->tx;
for (loop = 0; loop < bits_per_word / 16;
loop++) {
write_TDBR(drv_data, *buf++);
bfin_write(&drv_data->regs->tdbr, *buf++);
}
} else if (bits_per_word % 8 == 0) {
u8 *buf = (u8 *)drv_data->tx;
for (loop = 0; loop < bits_per_word / 8; loop++)
write_TDBR(drv_data, *buf++);
bfin_write(&drv_data->regs->tdbr, *buf++);
}
drv_data->tx += drv_data->n_bytes;
......@@ -1005,7 +965,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
#define MAX_SPI_SSEL 7
static u16 ssel[][MAX_SPI_SSEL] = {
static const u16 ssel[][MAX_SPI_SSEL] = {
{P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3,
P_SPI0_SSEL4, P_SPI0_SSEL5,
P_SPI0_SSEL6, P_SPI0_SSEL7},
......@@ -1226,7 +1186,7 @@ static void bfin_spi_cleanup(struct spi_device *spi)
spi_set_ctldata(spi, NULL);
}
static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
{
INIT_LIST_HEAD(&drv_data->queue);
spin_lock_init(&drv_data->lock);
......@@ -1248,7 +1208,7 @@ static inline int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
return 0;
}
static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
{
unsigned long flags;
......@@ -1270,7 +1230,7 @@ static inline int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
return 0;
}
static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
static int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
{
unsigned long flags;
unsigned limit = 500;
......@@ -1299,7 +1259,7 @@ static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
return status;
}
static inline int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
{
int status;
......@@ -1353,8 +1313,8 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
goto out_error_get_res;
}
drv_data->regs_base = ioremap(res->start, resource_size(res));
if (drv_data->regs_base == NULL) {
drv_data->regs = ioremap(res->start, resource_size(res));
if (drv_data->regs == NULL) {
dev_err(dev, "Cannot map IO\n");
status = -ENXIO;
goto out_error_ioremap;
......@@ -1397,8 +1357,8 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
/* Reset SPI registers. If these registers were used by the boot loader,
* the sky may fall on your head if you enable the dma controller.
*/
write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
write_FLAG(drv_data, 0xFF00);
bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
bfin_write(&drv_data->regs->flg, 0xFF00);
/* Register with the SPI framework */
platform_set_drvdata(pdev, drv_data);
......@@ -1408,15 +1368,15 @@ static int __init bfin_spi_probe(struct platform_device *pdev)
goto out_error_queue_alloc;
}
dev_info(dev, "%s, Version %s, regs_base@%p, dma channel@%d\n",
DRV_DESC, DRV_VERSION, drv_data->regs_base,
dev_info(dev, "%s, Version %s, regs@%p, dma channel@%d\n",
DRV_DESC, DRV_VERSION, drv_data->regs,
drv_data->dma_channel);
return status;
out_error_queue_alloc:
bfin_spi_destroy_queue(drv_data);
out_error_free_io:
iounmap((void *) drv_data->regs_base);
iounmap(drv_data->regs);
out_error_ioremap:
out_error_get_res:
spi_master_put(master);
......@@ -1473,14 +1433,14 @@ static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
if (status != 0)
return status;
drv_data->ctrl_reg = read_CTRL(drv_data);
drv_data->flag_reg = read_FLAG(drv_data);
drv_data->ctrl_reg = bfin_read(&drv_data->regs->ctl);
drv_data->flag_reg = bfin_read(&drv_data->regs->flg);
/*
* reset SPI_CTL and SPI_FLG registers
*/
write_CTRL(drv_data, BIT_CTL_CPHA | BIT_CTL_MASTER);
write_FLAG(drv_data, 0xFF00);
bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER);
bfin_write(&drv_data->regs->flg, 0xFF00);
return 0;
}
......@@ -1490,8 +1450,8 @@ static int bfin_spi_resume(struct platform_device *pdev)
struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
int status = 0;
write_CTRL(drv_data, drv_data->ctrl_reg);
write_FLAG(drv_data, drv_data->flag_reg);
bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg);
bfin_write(&drv_data->regs->flg, drv_data->flag_reg);
/* Start the queue running */
status = bfin_spi_start_queue(drv_data);
......
/*
* spi_bitbang.c - polling/bitbanging SPI master controller driver utilities
* polling/bitbanging SPI master controller driver utilities
*
* 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
......@@ -68,7 +68,7 @@ static unsigned bitbang_txrx_8(
unsigned ns,
struct spi_transfer *t
) {
unsigned bits = spi->bits_per_word;
unsigned bits = t->bits_per_word ? : spi->bits_per_word;
unsigned count = t->len;
const u8 *tx = t->tx_buf;
u8 *rx = t->rx_buf;
......@@ -94,7 +94,7 @@ static unsigned bitbang_txrx_16(
unsigned ns,
struct spi_transfer *t
) {
unsigned bits = spi->bits_per_word;
unsigned bits = t->bits_per_word ? : spi->bits_per_word;
unsigned count = t->len;
const u16 *tx = t->tx_buf;
u16 *rx = t->rx_buf;
......@@ -120,7 +120,7 @@ static unsigned bitbang_txrx_32(
unsigned ns,
struct spi_transfer *t
) {
unsigned bits = spi->bits_per_word;
unsigned bits = t->bits_per_word ? : spi->bits_per_word;
unsigned count = t->len;
const u32 *tx = t->tx_buf;
u32 *rx = t->rx_buf;
......
/*
* spi_butterfly.c - parport-to-butterfly adapter
* parport-to-butterfly adapter
*
* Copyright (C) 2005 David Brownell
*
......@@ -149,7 +149,7 @@ static void butterfly_chipselect(struct spi_device *spi, int value)
#define spidelay(X) do{}while(0)
//#define spidelay ndelay
#include "spi_bitbang_txrx.h"
#include "spi-bitbang-txrx.h"
static u32
butterfly_txrx_word_mode0(struct spi_device *spi,
......
/*
* dw_spi_mid.c - special handling for DW core on Intel MID platform
* Special handling for DW core on Intel MID platform
*
* Copyright (c) 2009, Intel Corporation.
*
......@@ -23,7 +23,7 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include "dw_spi.h"
#include "spi-dw.h"
#ifdef CONFIG_SPI_DW_MID_DMA
#include <linux/intel_mid_dma.h>
......
/*
* dw_spi_mmio.c - Memory-mapped interface driver for DW SPI Core
* Memory-mapped interface driver for DW SPI Core
*
* Copyright (c) 2010, Octasic semiconductor.
*
......@@ -16,7 +16,7 @@
#include <linux/spi/spi.h>
#include <linux/scatterlist.h>
#include "dw_spi.h"
#include "spi-dw.h"
#define DRIVER_NAME "dw_spi_mmio"
......
/*
* dw_spi_pci.c - PCI interface driver for DW SPI Core
* PCI interface driver for DW SPI Core
*
* Copyright (c) 2009, Intel Corporation.
*
......@@ -22,7 +22,7 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include "dw_spi.h"
#include "spi-dw.h"
#define DRIVER_NAME "dw_spi_pci"
......
/*
* dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c)
* Designware SPI core controller driver (refer pxa2xx_spi.c)
*
* Copyright (c) 2009, Intel Corporation.
*
......@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include "dw_spi.h"
#include "spi-dw.h"
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
......@@ -818,9 +818,11 @@ int __devinit dw_spi_add_host(struct dw_spi *dws)
dws->prev_chip = NULL;
dws->dma_inited = 0;
dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
snprintf(dws->name, sizeof(dws->name), "dw_spi%d",
dws->bus_num);
ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
"dw_spi", dws);
dws->name, dws);
if (ret < 0) {
dev_err(&master->dev, "can not get IRQ\n");
goto err_free_master;
......
......@@ -96,6 +96,7 @@ struct dw_spi {
struct spi_device *cur_dev;
struct device *parent_dev;
enum dw_ssi_type type;
char name[16];
void __iomem *regs;
unsigned long paddr;
......
/*
* Driver for Cirrus Logic EP93xx SPI controller.
*
* Copyright (c) 2010 Mika Westerberg
* Copyright (C) 2010-2011 Mika Westerberg
*
* Explicit FIFO handling code was inspired by amba-pl022 driver.
*
......@@ -21,13 +21,16 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/scatterlist.h>
#include <linux/spi/spi.h>
#include <mach/dma.h>
#include <mach/ep93xx_spi.h>
#define SSPCR0 0x0000
......@@ -71,6 +74,7 @@
* @pdev: pointer to platform device
* @clk: clock for the controller
* @regs_base: pointer to ioremap()'d registers
* @sspdr_phys: physical address of the SSPDR register
* @irq: IRQ number used by the driver
* @min_rate: minimum clock rate (in Hz) supported by the controller
* @max_rate: maximum clock rate (in Hz) supported by the controller
......@@ -84,6 +88,14 @@
* @rx: current byte in transfer to receive
* @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one
* frame decreases this level and sending one frame increases it.
* @dma_rx: RX DMA channel
* @dma_tx: TX DMA channel
* @dma_rx_data: RX parameters passed to the DMA engine
* @dma_tx_data: TX parameters passed to the DMA engine
* @rx_sgt: sg table for RX transfers
* @tx_sgt: sg table for TX transfers
* @zeropage: dummy page used as RX buffer when only TX buffer is passed in by
* the client
*
* This structure holds EP93xx SPI controller specific information. When
* @running is %true, driver accepts transfer requests from protocol drivers.
......@@ -100,6 +112,7 @@ struct ep93xx_spi {
const struct platform_device *pdev;
struct clk *clk;
void __iomem *regs_base;
unsigned long sspdr_phys;
int irq;
unsigned long min_rate;
unsigned long max_rate;
......@@ -112,6 +125,13 @@ struct ep93xx_spi {
size_t tx;
size_t rx;
size_t fifo_level;
struct dma_chan *dma_rx;
struct dma_chan *dma_tx;
struct ep93xx_dma_data dma_rx_data;
struct ep93xx_dma_data dma_tx_data;
struct sg_table rx_sgt;
struct sg_table tx_sgt;
void *zeropage;
};
/**
......@@ -496,14 +516,195 @@ static int ep93xx_spi_read_write(struct ep93xx_spi *espi)
espi->fifo_level++;
}
if (espi->rx == t->len) {
msg->actual_length += t->len;
if (espi->rx == t->len)
return 0;
}
return -EINPROGRESS;
}
static void ep93xx_spi_pio_transfer(struct ep93xx_spi *espi)
{
/*
* Now everything is set up for the current transfer. We prime the TX
* FIFO, enable interrupts, and wait for the transfer to complete.
*/
if (ep93xx_spi_read_write(espi)) {
ep93xx_spi_enable_interrupts(espi);
wait_for_completion(&espi->wait);
}
}
/**
* ep93xx_spi_dma_prepare() - prepares a DMA transfer
* @espi: ep93xx SPI controller struct
* @dir: DMA transfer direction
*
* Function configures the DMA, maps the buffer and prepares the DMA
* descriptor. Returns a valid DMA descriptor in case of success and ERR_PTR
* in case of failure.
*/
static struct dma_async_tx_descriptor *
ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
{
struct spi_transfer *t = espi->current_msg->state;
struct dma_async_tx_descriptor *txd;
enum dma_slave_buswidth buswidth;
struct dma_slave_config conf;
struct scatterlist *sg;
struct sg_table *sgt;
struct dma_chan *chan;
const void *buf, *pbuf;
size_t len = t->len;
int i, ret, nents;
if (bits_per_word(espi) > 8)
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
else
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
memset(&conf, 0, sizeof(conf));
conf.direction = dir;
if (dir == DMA_FROM_DEVICE) {
chan = espi->dma_rx;
buf = t->rx_buf;
sgt = &espi->rx_sgt;
conf.src_addr = espi->sspdr_phys;
conf.src_addr_width = buswidth;
} else {
chan = espi->dma_tx;
buf = t->tx_buf;
sgt = &espi->tx_sgt;
conf.dst_addr = espi->sspdr_phys;
conf.dst_addr_width = buswidth;
}
ret = dmaengine_slave_config(chan, &conf);
if (ret)
return ERR_PTR(ret);
/*
* We need to split the transfer into PAGE_SIZE'd chunks. This is
* because we are using @espi->zeropage to provide a zero RX buffer
* for the TX transfers and we have only allocated one page for that.
*
* For performance reasons we allocate a new sg_table only when
* needed. Otherwise we will re-use the current one. Eventually the
* last sg_table is released in ep93xx_spi_release_dma().
*/
nents = DIV_ROUND_UP(len, PAGE_SIZE);
if (nents != sgt->nents) {
sg_free_table(sgt);
ret = sg_alloc_table(sgt, nents, GFP_KERNEL);
if (ret)
return ERR_PTR(ret);
}
pbuf = buf;
for_each_sg(sgt->sgl, sg, sgt->nents, i) {
size_t bytes = min_t(size_t, len, PAGE_SIZE);
if (buf) {
sg_set_page(sg, virt_to_page(pbuf), bytes,
offset_in_page(pbuf));
} else {
sg_set_page(sg, virt_to_page(espi->zeropage),
bytes, 0);
}
pbuf += bytes;
len -= bytes;
}
if (WARN_ON(len)) {
dev_warn(&espi->pdev->dev, "len = %d expected 0!", len);
return ERR_PTR(-EINVAL);
}
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
if (!nents)
return ERR_PTR(-ENOMEM);
txd = chan->device->device_prep_slave_sg(chan, sgt->sgl, nents,
dir, DMA_CTRL_ACK);
if (!txd) {
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
return ERR_PTR(-ENOMEM);
}
return txd;
}
/**
* ep93xx_spi_dma_finish() - finishes with a DMA transfer
* @espi: ep93xx SPI controller struct
* @dir: DMA transfer direction
*
* Function finishes with the DMA transfer. After this, the DMA buffer is
* unmapped.
*/
static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
enum dma_data_direction dir)
{
struct dma_chan *chan;
struct sg_table *sgt;
if (dir == DMA_FROM_DEVICE) {
chan = espi->dma_rx;
sgt = &espi->rx_sgt;
} else {
chan = espi->dma_tx;
sgt = &espi->tx_sgt;
}
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
}
static void ep93xx_spi_dma_callback(void *callback_param)
{
complete(callback_param);
}
static void ep93xx_spi_dma_transfer(struct ep93xx_spi *espi)
{
struct spi_message *msg = espi->current_msg;
struct dma_async_tx_descriptor *rxd, *txd;
rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE);
if (IS_ERR(rxd)) {
dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
msg->status = PTR_ERR(rxd);
return;
}
txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE);
if (IS_ERR(txd)) {
ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd));
msg->status = PTR_ERR(txd);
return;
}
/* We are ready when RX is done */
rxd->callback = ep93xx_spi_dma_callback;
rxd->callback_param = &espi->wait;
/* Now submit both descriptors and wait while they finish */
dmaengine_submit(rxd);
dmaengine_submit(txd);
dma_async_issue_pending(espi->dma_rx);
dma_async_issue_pending(espi->dma_tx);
wait_for_completion(&espi->wait);
ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE);
ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
}
/**
* ep93xx_spi_process_transfer() - processes one SPI transfer
* @espi: ep93xx SPI controller struct
......@@ -556,13 +757,14 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
espi->tx = 0;
/*
* Now everything is set up for the current transfer. We prime the TX
* FIFO, enable interrupts, and wait for the transfer to complete.
* There is no point of setting up DMA for the transfers which will
* fit into the FIFO and can be transferred with a single interrupt.
* So in these cases we will be using PIO and don't bother for DMA.
*/
if (ep93xx_spi_read_write(espi)) {
ep93xx_spi_enable_interrupts(espi);
wait_for_completion(&espi->wait);
}
if (espi->dma_rx && t->len > SPI_FIFO_SIZE)
ep93xx_spi_dma_transfer(espi);
else
ep93xx_spi_pio_transfer(espi);
/*
* In case of error during transmit, we bail out from processing
......@@ -571,6 +773,8 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
if (msg->status)
return;
msg->actual_length += t->len;
/*
* After this transfer is finished, perform any possible
* post-transfer actions requested by the protocol driver.
......@@ -752,6 +956,75 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
static bool ep93xx_spi_dma_filter(struct dma_chan *chan, void *filter_param)
{
if (ep93xx_dma_chan_is_m2p(chan))
return false;
chan->private = filter_param;
return true;
}
static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
{
dma_cap_mask_t mask;
int ret;
espi->zeropage = (void *)get_zeroed_page(GFP_KERNEL);
if (!espi->zeropage)
return -ENOMEM;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
espi->dma_rx_data.port = EP93XX_DMA_SSP;
espi->dma_rx_data.direction = DMA_FROM_DEVICE;
espi->dma_rx_data.name = "ep93xx-spi-rx";
espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter,
&espi->dma_rx_data);
if (!espi->dma_rx) {
ret = -ENODEV;
goto fail_free_page;
}
espi->dma_tx_data.port = EP93XX_DMA_SSP;
espi->dma_tx_data.direction = DMA_TO_DEVICE;
espi->dma_tx_data.name = "ep93xx-spi-tx";
espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter,
&espi->dma_tx_data);
if (!espi->dma_tx) {
ret = -ENODEV;
goto fail_release_rx;
}
return 0;
fail_release_rx:
dma_release_channel(espi->dma_rx);
espi->dma_rx = NULL;
fail_free_page:
free_page((unsigned long)espi->zeropage);
return ret;
}
static void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
{
if (espi->dma_rx) {
dma_release_channel(espi->dma_rx);
sg_free_table(&espi->rx_sgt);
}
if (espi->dma_tx) {
dma_release_channel(espi->dma_tx);
sg_free_table(&espi->tx_sgt);
}
if (espi->zeropage)
free_page((unsigned long)espi->zeropage);
}
static int __init ep93xx_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
......@@ -818,6 +1091,7 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
goto fail_put_clock;
}
espi->sspdr_phys = res->start + SSPDR;
espi->regs_base = ioremap(res->start, resource_size(res));
if (!espi->regs_base) {
dev_err(&pdev->dev, "failed to map resources\n");
......@@ -832,10 +1106,13 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
goto fail_unmap_regs;
}
if (info->use_dma && ep93xx_spi_setup_dma(espi))
dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
espi->wq = create_singlethread_workqueue("ep93xx_spid");
if (!espi->wq) {
dev_err(&pdev->dev, "unable to create workqueue\n");
goto fail_free_irq;
goto fail_free_dma;
}
INIT_WORK(&espi->msg_work, ep93xx_spi_work);
INIT_LIST_HEAD(&espi->msg_queue);
......@@ -857,7 +1134,8 @@ static int __init ep93xx_spi_probe(struct platform_device *pdev)
fail_free_queue:
destroy_workqueue(espi->wq);
fail_free_irq:
fail_free_dma:
ep93xx_spi_release_dma(espi);
free_irq(espi->irq, espi);
fail_unmap_regs:
iounmap(espi->regs_base);
......@@ -901,6 +1179,7 @@ static int __exit ep93xx_spi_remove(struct platform_device *pdev)
}
spin_unlock_irq(&espi->lock);
ep93xx_spi_release_dma(espi);
free_irq(espi->irq, espi);
iounmap(espi->regs_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......
......@@ -22,7 +22,7 @@
#include <linux/err.h>
#include <sysdev/fsl_soc.h>
#include "spi_fsl_lib.h"
#include "spi-fsl-lib.h"
/* eSPI Controller registers */
struct fsl_espi_reg {
......
......@@ -25,7 +25,7 @@
#include <linux/of_spi.h>
#include <sysdev/fsl_soc.h>
#include "spi_fsl_lib.h"
#include "spi-fsl-lib.h"
#define MPC8XXX_SPI_RX_BUF(type) \
void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
......
......@@ -37,7 +37,7 @@
#include <asm/cpm.h>
#include <asm/qe.h>
#include "spi_fsl_lib.h"
#include "spi-fsl-lib.h"
/* CPM1 and CPM2 are mutually exclusive. */
#ifdef CONFIG_CPM1
......@@ -684,7 +684,7 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
struct device_node *np = dev->of_node;
const u32 *iprop;
int size;
unsigned long spi_base_ofs;
void __iomem *spi_base;
unsigned long pram_ofs = -ENOMEM;
/* Can't use of_address_to_resource(), QE muram isn't at 0. */
......@@ -702,33 +702,27 @@ static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
return pram_ofs;
}
/* CPM1 and CPM2 pram must be at a fixed addr. */
if (!iprop || size != sizeof(*iprop) * 4)
return -ENOMEM;
spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
if (IS_ERR_VALUE(spi_base_ofs))
return -ENOMEM;
spi_base = of_iomap(np, 1);
if (spi_base == NULL)
return -EINVAL;
if (mspi->flags & SPI_CPM2) {
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
if (!IS_ERR_VALUE(pram_ofs)) {
u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
out_be16(spi_base, pram_ofs);
}
out_be16(spi_base, pram_ofs);
} else {
struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
struct spi_pram __iomem *pram = spi_base;
u16 rpbase = in_be16(&pram->rpbase);
/* Microcode relocation patch applied? */
if (rpbase)
pram_ofs = rpbase;
else
return spi_base_ofs;
else {
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
out_be16(spi_base, pram_ofs);
}
}
cpm_muram_free(spi_base_ofs);
iounmap(spi_base);
return pram_ofs;
}
......
/*
* spi_gpio.c - SPI master driver using generic bitbanged GPIO
* SPI master driver using generic bitbanged GPIO
*
* Copyright (C) 2006,2008 David Brownell
*
......@@ -69,7 +69,7 @@ struct spi_gpio {
* #define SPI_MOSI_GPIO 120
* #define SPI_SCK_GPIO 121
* #define SPI_N_CHIPSEL 4
* #include "spi_gpio.c"
* #include "spi-gpio.c"
*/
#ifndef DRIVER_NAME
......@@ -127,7 +127,7 @@ static inline int getmiso(const struct spi_device *spi)
*/
#define spidelay(nsecs) do {} while (0)
#include "spi_bitbang_txrx.h"
#include "spi-bitbang-txrx.h"
/*
* These functions can leverage inline expansion of GPIO calls to shrink
......
/*
* spi_lm70llp.c - driver for LM70EVAL-LLP board for the LM70 sensor
* Driver for LM70EVAL-LLP board for the LM70 sensor
*
* Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
*
......@@ -174,7 +174,7 @@ static inline int getmiso(struct spi_device *s)
}
/*--------------------------------------------------------------------*/
#include "spi_bitbang_txrx.h"
#include "spi-bitbang-txrx.h"
static void lm70_chipselect(struct spi_device *spi, int value)
{
......
/* linux/drivers/spi/spi_nuc900.c
*
/*
* Copyright (c) 2009 Nuvoton technology.
* Wan ZongShun <mcuos.com@gmail.com>
*
......@@ -7,7 +6,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
*/
#include <linux/init.h>
#include <linux/spinlock.h>
......
/*
* omap_uwire.c -- MicroWire interface driver for OMAP
* MicroWire interface driver for OMAP
*
* Copyright 2003 MontaVista Software Inc. <source@mvista.com>
*
......
......@@ -1116,8 +1116,8 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
status = -ENODEV;
goto err1;
}
if (!request_mem_region(r->start, (r->end - r->start) + 1,
dev_name(&pdev->dev))) {
if (!request_mem_region(r->start, resource_size(r),
dev_name(&pdev->dev))) {
status = -EBUSY;
goto err1;
}
......@@ -1125,7 +1125,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
r->start += pdata->regs_offset;
r->end += pdata->regs_offset;
mcspi->phys = r->start;
mcspi->base = ioremap(r->start, r->end - r->start + 1);
mcspi->base = ioremap(r->start, resource_size(r));
if (!mcspi->base) {
dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
status = -ENOMEM;
......@@ -1190,7 +1190,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
err3:
kfree(mcspi->dma_channels);
err2:
release_mem_region(r->start, (r->end - r->start) + 1);
release_mem_region(r->start, resource_size(r));
iounmap(mcspi->base);
err1:
return status;
......@@ -1210,7 +1210,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
omap2_mcspi_disable_clocks(mcspi);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(r->start, (r->end - r->start) + 1);
release_mem_region(r->start, resource_size(r));
base = mcspi->base;
spi_unregister_master(master);
......
......@@ -502,7 +502,7 @@ static int __init spi_ppc4xx_of_probe(struct platform_device *op)
goto free_gpios;
}
hw->mapbase = resource.start;
hw->mapsize = resource.end - resource.start + 1;
hw->mapsize = resource_size(&resource);
/* Sanity check */
if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) {
......
......@@ -17,7 +17,7 @@
#include <mach/regs-irq.h>
#include <plat/regs-spi.h>
#include "spi_s3c24xx_fiq.h"
#include "spi-s3c24xx-fiq.h"
.text
......
/* linux/drivers/spi/spi_s3c64xx.c
*
/*
* Copyright (C) 2009 Samsung Electronics Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
......
/*
* tle62x0.c -- support Infineon TLE62x0 driver chips
* Support Infineon TLE62x0 driver chips
*
* Copyright (c) 2007 Simtec Electronics
* Ben Dooks, <ben@simtec.co.uk>
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册