Commit e3e1288e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx: (48 commits)
  DMAENGINE: move COH901318 to arch_initcall
  dma: imx-dma: fix signedness bug
  dma/timberdale: simplify conditional
  ste_dma40: remove channel_type
  ste_dma40: remove enum for endianess
  ste_dma40: remove TIM_FOR_LINK option
  ste_dma40: move mode_opt to separate config
  ste_dma40: move channel mode to a separate field
  ste_dma40: move priority to separate field
  ste_dma40: add variable to indicate valid dma_cfg
  async_tx: make async_tx channel switching opt-in
  move async raid6 test to lib/Kconfig.debug
  dmaengine: Add Freescale i.MX1/21/27 DMA driver
  intel_mid_dma: change the slave interface
  intel_mid_dma: fix the WARN_ONs
  intel_mid_dma: Add sg list support to DMA driver
  intel_mid_dma: Allow DMAC2 to share interrupt
  intel_mid_dma: Allow IRQ sharing
  intel_mid_dma: Add runtime PM support
  DMAENGINE: define a dummy filter function for ste_dma40
  ...
parents 9ae6d039 964dc256
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#define imx_has_dma_v1() (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27()) #define imx_has_dma_v1() (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
#include <mach/dma.h>
#define IMX_DMA_CHANNELS 16 #define IMX_DMA_CHANNELS 16
#define DMA_MODE_READ 0 #define DMA_MODE_READ 0
...@@ -96,12 +98,6 @@ int imx_dma_request(int channel, const char *name); ...@@ -96,12 +98,6 @@ int imx_dma_request(int channel, const char *name);
void imx_dma_free(int channel); void imx_dma_free(int channel);
enum imx_dma_prio {
DMA_PRIO_HIGH = 0,
DMA_PRIO_MEDIUM = 1,
DMA_PRIO_LOW = 2
};
int imx_dma_request_by_prio(const char *name, enum imx_dma_prio prio); int imx_dma_request_by_prio(const char *name, enum imx_dma_prio prio);
#endif /* __MACH_DMA_V1_H__ */ #endif /* __MACH_DMA_V1_H__ */
...@@ -208,35 +208,25 @@ static struct resource dma40_resources[] = { ...@@ -208,35 +208,25 @@ static struct resource dma40_resources[] = {
/* Default configuration for physcial memcpy */ /* Default configuration for physcial memcpy */
struct stedma40_chan_cfg dma40_memcpy_conf_phy = { struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
.channel_type = (STEDMA40_CHANNEL_IN_PHY_MODE | .mode = STEDMA40_MODE_PHYSICAL,
STEDMA40_LOW_PRIORITY_CHANNEL |
STEDMA40_PCHAN_BASIC_MODE),
.dir = STEDMA40_MEM_TO_MEM, .dir = STEDMA40_MEM_TO_MEM,
.src_info.endianess = STEDMA40_LITTLE_ENDIAN,
.src_info.data_width = STEDMA40_BYTE_WIDTH, .src_info.data_width = STEDMA40_BYTE_WIDTH,
.src_info.psize = STEDMA40_PSIZE_PHY_1, .src_info.psize = STEDMA40_PSIZE_PHY_1,
.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
.dst_info.endianess = STEDMA40_LITTLE_ENDIAN,
.dst_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH,
.dst_info.psize = STEDMA40_PSIZE_PHY_1, .dst_info.psize = STEDMA40_PSIZE_PHY_1,
.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
}; };
/* Default configuration for logical memcpy */ /* Default configuration for logical memcpy */
struct stedma40_chan_cfg dma40_memcpy_conf_log = { struct stedma40_chan_cfg dma40_memcpy_conf_log = {
.channel_type = (STEDMA40_CHANNEL_IN_LOG_MODE |
STEDMA40_LOW_PRIORITY_CHANNEL |
STEDMA40_LCHAN_SRC_LOG_DST_LOG |
STEDMA40_NO_TIM_FOR_LINK),
.dir = STEDMA40_MEM_TO_MEM, .dir = STEDMA40_MEM_TO_MEM,
.src_info.endianess = STEDMA40_LITTLE_ENDIAN,
.src_info.data_width = STEDMA40_BYTE_WIDTH, .src_info.data_width = STEDMA40_BYTE_WIDTH,
.src_info.psize = STEDMA40_PSIZE_LOG_1, .src_info.psize = STEDMA40_PSIZE_LOG_1,
.src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
.dst_info.endianess = STEDMA40_LITTLE_ENDIAN,
.dst_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH,
.dst_info.psize = STEDMA40_PSIZE_LOG_1, .dst_info.psize = STEDMA40_PSIZE_LOG_1,
.dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
...@@ -269,7 +259,6 @@ static struct stedma40_platform_data dma40_plat_data = { ...@@ -269,7 +259,6 @@ static struct stedma40_platform_data dma40_plat_data = {
.memcpy_len = ARRAY_SIZE(dma40_memcpy_event), .memcpy_len = ARRAY_SIZE(dma40_memcpy_event),
.memcpy_conf_phy = &dma40_memcpy_conf_phy, .memcpy_conf_phy = &dma40_memcpy_conf_phy,
.memcpy_conf_log = &dma40_memcpy_conf_log, .memcpy_conf_log = &dma40_memcpy_conf_log,
.llis_per_log = 8,
.disabled_channels = {-1}, .disabled_channels = {-1},
}; };
......
/*
* Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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_MXC_DMA_H__
#define __ASM_ARCH_MXC_DMA_H__
#include <linux/scatterlist.h>
#include <linux/device.h>
#include <linux/dmaengine.h>
/*
* This enumerates peripheral types. Used for SDMA.
*/
enum sdma_peripheral_type {
IMX_DMATYPE_SSI, /* MCU domain SSI */
IMX_DMATYPE_SSI_SP, /* Shared SSI */
IMX_DMATYPE_MMC, /* MMC */
IMX_DMATYPE_SDHC, /* SDHC */
IMX_DMATYPE_UART, /* MCU domain UART */
IMX_DMATYPE_UART_SP, /* Shared UART */
IMX_DMATYPE_FIRI, /* FIRI */
IMX_DMATYPE_CSPI, /* MCU domain CSPI */
IMX_DMATYPE_CSPI_SP, /* Shared CSPI */
IMX_DMATYPE_SIM, /* SIM */
IMX_DMATYPE_ATA, /* ATA */
IMX_DMATYPE_CCM, /* CCM */
IMX_DMATYPE_EXT, /* External peripheral */
IMX_DMATYPE_MSHC, /* Memory Stick Host Controller */
IMX_DMATYPE_MSHC_SP, /* Shared Memory Stick Host Controller */
IMX_DMATYPE_DSP, /* DSP */
IMX_DMATYPE_MEMORY, /* Memory */
IMX_DMATYPE_FIFO_MEMORY,/* FIFO type Memory */
IMX_DMATYPE_SPDIF, /* SPDIF */
IMX_DMATYPE_IPU_MEMORY, /* IPU Memory */
IMX_DMATYPE_ASRC, /* ASRC */
IMX_DMATYPE_ESAI, /* ESAI */
};
enum imx_dma_prio {
DMA_PRIO_HIGH = 0,
DMA_PRIO_MEDIUM = 1,
DMA_PRIO_LOW = 2
};
struct imx_dma_data {
int dma_request; /* DMA request line */
enum sdma_peripheral_type peripheral_type;
int priority;
};
static inline int imx_dma_is_ipu(struct dma_chan *chan)
{
return !strcmp(dev_name(chan->device->dev), "ipu-core");
}
static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
{
return !strcmp(dev_name(chan->device->dev), "imx-sdma") ||
!strcmp(dev_name(chan->device->dev), "imx-dma");
}
#endif
#ifndef __MACH_MXC_SDMA_H__
#define __MACH_MXC_SDMA_H__
/**
* struct sdma_platform_data - platform specific data for SDMA engine
*
* @sdma_version The version of this SDMA engine
* @cpu_name used to generate the firmware name
* @to_version CPU Tape out version
*/
struct sdma_platform_data {
int sdma_version;
char *cpu_name;
int to_version;
};
#endif /* __MACH_MXC_SDMA_H__ */
/* /*
* arch/arm/plat-nomadik/include/plat/ste_dma40.h * Copyright (C) ST-Ericsson SA 2007-2010
* * Author: Per Forlin <per.forlin@stericsson.com> for ST-Ericsson
* Copyright (C) ST-Ericsson 2007-2010 * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL) version 2 * License terms: GNU General Public License (GPL) version 2
* Author: Per Friden <per.friden@stericsson.com>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*/ */
...@@ -19,37 +17,20 @@ ...@@ -19,37 +17,20 @@
#define STEDMA40_DEV_DST_MEMORY (-1) #define STEDMA40_DEV_DST_MEMORY (-1)
#define STEDMA40_DEV_SRC_MEMORY (-1) #define STEDMA40_DEV_SRC_MEMORY (-1)
/* enum stedma40_mode {
* Description of bitfields of channel_type variable is available in STEDMA40_MODE_LOGICAL = 0,
* the info structure. STEDMA40_MODE_PHYSICAL,
*/ STEDMA40_MODE_OPERATION,
};
/* Priority */ enum stedma40_mode_opt {
#define STEDMA40_INFO_PRIO_TYPE_POS 2 STEDMA40_PCHAN_BASIC_MODE = 0,
#define STEDMA40_HIGH_PRIORITY_CHANNEL (0x1 << STEDMA40_INFO_PRIO_TYPE_POS) STEDMA40_LCHAN_SRC_LOG_DST_LOG = 0,
#define STEDMA40_LOW_PRIORITY_CHANNEL (0x2 << STEDMA40_INFO_PRIO_TYPE_POS) STEDMA40_PCHAN_MODULO_MODE,
STEDMA40_PCHAN_DOUBLE_DST_MODE,
/* Mode */ STEDMA40_LCHAN_SRC_PHY_DST_LOG,
#define STEDMA40_INFO_CH_MODE_TYPE_POS 6 STEDMA40_LCHAN_SRC_LOG_DST_PHY,
#define STEDMA40_CHANNEL_IN_PHY_MODE (0x1 << STEDMA40_INFO_CH_MODE_TYPE_POS) };
#define STEDMA40_CHANNEL_IN_LOG_MODE (0x2 << STEDMA40_INFO_CH_MODE_TYPE_POS)
#define STEDMA40_CHANNEL_IN_OPER_MODE (0x3 << STEDMA40_INFO_CH_MODE_TYPE_POS)
/* Mode options */
#define STEDMA40_INFO_CH_MODE_OPT_POS 8
#define STEDMA40_PCHAN_BASIC_MODE (0x1 << STEDMA40_INFO_CH_MODE_OPT_POS)
#define STEDMA40_PCHAN_MODULO_MODE (0x2 << STEDMA40_INFO_CH_MODE_OPT_POS)
#define STEDMA40_PCHAN_DOUBLE_DST_MODE (0x3 << STEDMA40_INFO_CH_MODE_OPT_POS)
#define STEDMA40_LCHAN_SRC_PHY_DST_LOG (0x1 << STEDMA40_INFO_CH_MODE_OPT_POS)
#define STEDMA40_LCHAN_SRC_LOG_DST_PHS (0x2 << STEDMA40_INFO_CH_MODE_OPT_POS)
#define STEDMA40_LCHAN_SRC_LOG_DST_LOG (0x3 << STEDMA40_INFO_CH_MODE_OPT_POS)
/* Interrupt */
#define STEDMA40_INFO_TIM_POS 10
#define STEDMA40_NO_TIM_FOR_LINK (0x0 << STEDMA40_INFO_TIM_POS)
#define STEDMA40_TIM_FOR_LINK (0x1 << STEDMA40_INFO_TIM_POS)
/* End of channel_type configuration */
#define STEDMA40_ESIZE_8_BIT 0x0 #define STEDMA40_ESIZE_8_BIT 0x0
#define STEDMA40_ESIZE_16_BIT 0x1 #define STEDMA40_ESIZE_16_BIT 0x1
...@@ -72,16 +53,14 @@ ...@@ -72,16 +53,14 @@
#define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8 #define STEDMA40_PSIZE_LOG_8 STEDMA40_PSIZE_PHY_8
#define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16 #define STEDMA40_PSIZE_LOG_16 STEDMA40_PSIZE_PHY_16
/* Maximum number of possible physical channels */
#define STEDMA40_MAX_PHYS 32
enum stedma40_flow_ctrl { enum stedma40_flow_ctrl {
STEDMA40_NO_FLOW_CTRL, STEDMA40_NO_FLOW_CTRL,
STEDMA40_FLOW_CTRL, STEDMA40_FLOW_CTRL,
}; };
enum stedma40_endianess {
STEDMA40_LITTLE_ENDIAN,
STEDMA40_BIG_ENDIAN
};
enum stedma40_periph_data_width { enum stedma40_periph_data_width {
STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT, STEDMA40_BYTE_WIDTH = STEDMA40_ESIZE_8_BIT,
STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT, STEDMA40_HALFWORD_WIDTH = STEDMA40_ESIZE_16_BIT,
...@@ -89,34 +68,40 @@ enum stedma40_periph_data_width { ...@@ -89,34 +68,40 @@ enum stedma40_periph_data_width {
STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT STEDMA40_DOUBLEWORD_WIDTH = STEDMA40_ESIZE_64_BIT
}; };
struct stedma40_half_channel_info {
enum stedma40_endianess endianess;
enum stedma40_periph_data_width data_width;
int psize;
enum stedma40_flow_ctrl flow_ctrl;
};
enum stedma40_xfer_dir { enum stedma40_xfer_dir {
STEDMA40_MEM_TO_MEM, STEDMA40_MEM_TO_MEM = 1,
STEDMA40_MEM_TO_PERIPH, STEDMA40_MEM_TO_PERIPH,
STEDMA40_PERIPH_TO_MEM, STEDMA40_PERIPH_TO_MEM,
STEDMA40_PERIPH_TO_PERIPH STEDMA40_PERIPH_TO_PERIPH
}; };
/**
* struct stedma40_chan_cfg - dst/src channel configuration
*
* @big_endian: true if the src/dst should be read as big endian
* @data_width: Data width of the src/dst hardware
* @p_size: Burst size
* @flow_ctrl: Flow control on/off.
*/
struct stedma40_half_channel_info {
bool big_endian;
enum stedma40_periph_data_width data_width;
int psize;
enum stedma40_flow_ctrl flow_ctrl;
};
/** /**
* struct stedma40_chan_cfg - Structure to be filled by client drivers. * struct stedma40_chan_cfg - Structure to be filled by client drivers.
* *
* @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH
* @channel_type: priority, mode, mode options and interrupt configuration. * @high_priority: true if high-priority
* @mode: channel mode: physical, logical, or operation
* @mode_opt: options for the chosen channel mode
* @src_dev_type: Src device type * @src_dev_type: Src device type
* @dst_dev_type: Dst device type * @dst_dev_type: Dst device type
* @src_info: Parameters for dst half channel * @src_info: Parameters for dst half channel
* @dst_info: Parameters for dst half channel * @dst_info: Parameters for dst half channel
* @pre_transfer_data: Data to be passed on to the pre_transfer() function.
* @pre_transfer: Callback used if needed before preparation of transfer.
* Only called if device is set. size of bytes to transfer
* (in case of multiple element transfer size is size of the first element).
* *
* *
* This structure has to be filled by the client drivers. * This structure has to be filled by the client drivers.
...@@ -125,15 +110,13 @@ enum stedma40_xfer_dir { ...@@ -125,15 +110,13 @@ enum stedma40_xfer_dir {
*/ */
struct stedma40_chan_cfg { struct stedma40_chan_cfg {
enum stedma40_xfer_dir dir; enum stedma40_xfer_dir dir;
unsigned int channel_type; bool high_priority;
enum stedma40_mode mode;
enum stedma40_mode_opt mode_opt;
int src_dev_type; int src_dev_type;
int dst_dev_type; int dst_dev_type;
struct stedma40_half_channel_info src_info; struct stedma40_half_channel_info src_info;
struct stedma40_half_channel_info dst_info; struct stedma40_half_channel_info dst_info;
void *pre_transfer_data;
int (*pre_transfer) (struct dma_chan *chan,
void *data,
int size);
}; };
/** /**
...@@ -146,7 +129,6 @@ struct stedma40_chan_cfg { ...@@ -146,7 +129,6 @@ struct stedma40_chan_cfg {
* @memcpy_len: length of memcpy * @memcpy_len: length of memcpy
* @memcpy_conf_phy: default configuration of physical channel memcpy * @memcpy_conf_phy: default configuration of physical channel memcpy
* @memcpy_conf_log: default configuration of logical channel memcpy * @memcpy_conf_log: default configuration of logical channel memcpy
* @llis_per_log: number of max linked list items per logical channel
* @disabled_channels: A vector, ending with -1, that marks physical channels * @disabled_channels: A vector, ending with -1, that marks physical channels
* that are for different reasons not available for the driver. * that are for different reasons not available for the driver.
*/ */
...@@ -158,23 +140,10 @@ struct stedma40_platform_data { ...@@ -158,23 +140,10 @@ struct stedma40_platform_data {
u32 memcpy_len; u32 memcpy_len;
struct stedma40_chan_cfg *memcpy_conf_phy; struct stedma40_chan_cfg *memcpy_conf_phy;
struct stedma40_chan_cfg *memcpy_conf_log; struct stedma40_chan_cfg *memcpy_conf_log;
unsigned int llis_per_log; int disabled_channels[STEDMA40_MAX_PHYS];
int disabled_channels[8];
}; };
/** #ifdef CONFIG_STE_DMA40
* setdma40_set_psize() - Used for changing the package size of an
* already configured dma channel.
*
* @chan: dmaengine handle
* @src_psize: new package side for src. (STEDMA40_PSIZE*)
* @src_psize: new package side for dst. (STEDMA40_PSIZE*)
*
* returns 0 on ok, otherwise negative error number.
*/
int stedma40_set_psize(struct dma_chan *chan,
int src_psize,
int dst_psize);
/** /**
* stedma40_filter() - Provides stedma40_chan_cfg to the * stedma40_filter() - Provides stedma40_chan_cfg to the
...@@ -237,4 +206,21 @@ dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan, ...@@ -237,4 +206,21 @@ dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
direction, flags); direction, flags);
} }
#else
static inline bool stedma40_filter(struct dma_chan *chan, void *data)
{
return false;
}
static inline struct
dma_async_tx_descriptor *stedma40_slave_mem(struct dma_chan *chan,
dma_addr_t addr,
unsigned int size,
enum dma_data_direction direction,
unsigned long flags)
{
return NULL;
}
#endif
#endif #endif
/*
* Freescale MPC83XX / MPC85XX DMA Controller
*
* Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__
#define __ARCH_POWERPC_ASM_FSLDMA_H__
#include <linux/slab.h>
#include <linux/dmaengine.h>
/*
* Definitions for the Freescale DMA controller's DMA_SLAVE implemention
*
* The Freescale DMA_SLAVE implementation was designed to handle many-to-many
* transfers. An example usage would be an accelerated copy between two
* scatterlists. Another example use would be an accelerated copy from
* multiple non-contiguous device buffers into a single scatterlist.
*
* A DMA_SLAVE transaction is defined by a struct fsl_dma_slave. This
* structure contains a list of hardware addresses that should be copied
* to/from the scatterlist passed into device_prep_slave_sg(). The structure
* also has some fields to enable hardware-specific features.
*/
/**
* struct fsl_dma_hw_addr
* @entry: linked list entry
* @address: the hardware address
* @length: length to transfer
*
* Holds a single physical hardware address / length pair for use
* with the DMAEngine DMA_SLAVE API.
*/
struct fsl_dma_hw_addr {
struct list_head entry;
dma_addr_t address;
size_t length;
};
/**
* struct fsl_dma_slave
* @addresses: a linked list of struct fsl_dma_hw_addr structures
* @request_count: value for DMA request count
* @src_loop_size: setup and enable constant source-address DMA transfers
* @dst_loop_size: setup and enable constant destination address DMA transfers
* @external_start: enable externally started DMA transfers
* @external_pause: enable externally paused DMA transfers
*
* Holds a list of address / length pairs for use with the DMAEngine
* DMA_SLAVE API implementation for the Freescale DMA controller.
*/
struct fsl_dma_slave {
/* List of hardware address/length pairs */
struct list_head addresses;
/* Support for extra controller features */
unsigned int request_count;
unsigned int src_loop_size;
unsigned int dst_loop_size;
bool external_start;
bool external_pause;
};
/**
* fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave
* @slave: the &struct fsl_dma_slave to add to
* @address: the hardware address to add
* @length: the length of bytes to transfer from @address
*
* Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on
* success, -ERRNO otherwise.
*/
static inline int fsl_dma_slave_append(struct fsl_dma_slave *slave,
dma_addr_t address, size_t length)
{
struct fsl_dma_hw_addr *addr;
addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
if (!addr)
return -ENOMEM;
INIT_LIST_HEAD(&addr->entry);
addr->address = address;
addr->length = length;
list_add_tail(&addr->entry, &slave->addresses);
return 0;
}
/**
* fsl_dma_slave_free - free a struct fsl_dma_slave
* @slave: the struct fsl_dma_slave to free
*
* Free a struct fsl_dma_slave and all associated address/length pairs
*/
static inline void fsl_dma_slave_free(struct fsl_dma_slave *slave)
{
struct fsl_dma_hw_addr *addr, *tmp;
if (slave) {
list_for_each_entry_safe(addr, tmp, &slave->addresses, entry) {
list_del(&addr->entry);
kfree(addr);
}
kfree(slave);
}
}
/**
* fsl_dma_slave_alloc - allocate a struct fsl_dma_slave
* @gfp: the flags to pass to kmalloc when allocating this structure
*
* Allocate a struct fsl_dma_slave for use by the DMA_SLAVE API. Returns a new
* struct fsl_dma_slave on success, or NULL on failure.
*/
static inline struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp)
{
struct fsl_dma_slave *slave;
slave = kzalloc(sizeof(*slave), gfp);
if (!slave)
return NULL;
INIT_LIST_HEAD(&slave->addresses);
return slave;
}
#endif /* __ARCH_POWERPC_ASM_FSLDMA_H__ */
...@@ -24,19 +24,6 @@ config ASYNC_RAID6_RECOV ...@@ -24,19 +24,6 @@ config ASYNC_RAID6_RECOV
select ASYNC_PQ select ASYNC_PQ
select ASYNC_XOR select ASYNC_XOR
config ASYNC_RAID6_TEST
tristate "Self test for hardware accelerated raid6 recovery"
depends on ASYNC_RAID6_RECOV
select ASYNC_MEMCPY
---help---
This is a one-shot self test that permutes through the
recovery of all the possible two disk failure scenarios for a
N-disk array. Recovery is performed with the asynchronous
raid6 recovery routines, and will optionally use an offload
engine if one is available.
If unsure, say N.
config ASYNC_TX_DISABLE_PQ_VAL_DMA config ASYNC_TX_DISABLE_PQ_VAL_DMA
bool bool
......
...@@ -46,15 +46,22 @@ config INTEL_MID_DMAC ...@@ -46,15 +46,22 @@ config INTEL_MID_DMAC
If unsure, say N. If unsure, say N.
config ASYNC_TX_DISABLE_CHANNEL_SWITCH config ASYNC_TX_ENABLE_CHANNEL_SWITCH
bool bool
config AMBA_PL08X
bool "ARM PrimeCell PL080 or PL081 support"
depends on ARM_AMBA && EXPERIMENTAL
select DMA_ENGINE
help
Platform has a PL08x DMAC device
which can provide DMA engine support
config INTEL_IOATDMA config INTEL_IOATDMA
tristate "Intel I/OAT DMA support" tristate "Intel I/OAT DMA support"
depends on PCI && X86 depends on PCI && X86
select DMA_ENGINE select DMA_ENGINE
select DCA select DCA
select ASYNC_TX_DISABLE_CHANNEL_SWITCH
select ASYNC_TX_DISABLE_PQ_VAL_DMA select ASYNC_TX_DISABLE_PQ_VAL_DMA
select ASYNC_TX_DISABLE_XOR_VAL_DMA select ASYNC_TX_DISABLE_XOR_VAL_DMA
help help
...@@ -69,6 +76,7 @@ config INTEL_IOP_ADMA ...@@ -69,6 +76,7 @@ config INTEL_IOP_ADMA
tristate "Intel IOP ADMA support" tristate "Intel IOP ADMA support"
depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
select DMA_ENGINE select DMA_ENGINE
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
help help
Enable support for the Intel(R) IOP Series RAID engines. Enable support for the Intel(R) IOP Series RAID engines.
...@@ -93,6 +101,7 @@ config FSL_DMA ...@@ -93,6 +101,7 @@ config FSL_DMA
tristate "Freescale Elo and Elo Plus DMA support" tristate "Freescale Elo and Elo Plus DMA support"
depends on FSL_SOC depends on FSL_SOC
select DMA_ENGINE select DMA_ENGINE
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
---help--- ---help---
Enable support for the Freescale Elo and Elo Plus DMA controllers. Enable support for the Freescale Elo and Elo Plus DMA controllers.
The Elo is the DMA controller on some 82xx and 83xx parts, and the The Elo is the DMA controller on some 82xx and 83xx parts, and the
...@@ -109,6 +118,7 @@ config MV_XOR ...@@ -109,6 +118,7 @@ config MV_XOR
bool "Marvell XOR engine support" bool "Marvell XOR engine support"
depends on PLAT_ORION depends on PLAT_ORION
select DMA_ENGINE select DMA_ENGINE
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
---help--- ---help---
Enable support for the Marvell XOR engine. Enable support for the Marvell XOR engine.
...@@ -166,6 +176,7 @@ config AMCC_PPC440SPE_ADMA ...@@ -166,6 +176,7 @@ config AMCC_PPC440SPE_ADMA
depends on 440SPe || 440SP depends on 440SPe || 440SP
select DMA_ENGINE select DMA_ENGINE
select ARCH_HAS_ASYNC_TX_FIND_CHANNEL select ARCH_HAS_ASYNC_TX_FIND_CHANNEL
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
help help
Enable support for the AMCC PPC440SPe RAID engines. Enable support for the AMCC PPC440SPe RAID engines.
...@@ -195,6 +206,22 @@ config PCH_DMA ...@@ -195,6 +206,22 @@ config PCH_DMA
help help
Enable support for the Topcliff PCH DMA engine. Enable support for the Topcliff PCH DMA engine.
config IMX_SDMA
tristate "i.MX SDMA support"
depends on ARCH_MX25 || ARCH_MX3 || ARCH_MX5
select DMA_ENGINE
help
Support the i.MX SDMA engine. This engine is integrated into
Freescale i.MX25/31/35/51 chips.
config IMX_DMA
tristate "i.MX DMA support"
depends on ARCH_MX1 || ARCH_MX21 || MACH_MX27
select DMA_ENGINE
help
Support the i.MX DMA engine. This engine is integrated into
Freescale i.MX1/21/27 chips.
config DMA_ENGINE config DMA_ENGINE
bool bool
......
...@@ -21,7 +21,10 @@ obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o ...@@ -21,7 +21,10 @@ obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
obj-$(CONFIG_SH_DMAE) += shdma.o obj-$(CONFIG_SH_DMAE) += shdma.o
obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
obj-$(CONFIG_IMX_DMA) += imx-dma.o
obj-$(CONFIG_TIMB_DMA) += timb_dma.o obj-$(CONFIG_TIMB_DMA) += timb_dma.o
obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
obj-$(CONFIG_PL330_DMA) += pl330.o obj-$(CONFIG_PL330_DMA) += pl330.o
obj-$(CONFIG_PCH_DMA) += pch_dma.o obj-$(CONFIG_PCH_DMA) += pch_dma.o
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
This diff is collapsed.
...@@ -1610,7 +1610,7 @@ int __init coh901318_init(void) ...@@ -1610,7 +1610,7 @@ int __init coh901318_init(void)
{ {
return platform_driver_probe(&coh901318_driver, coh901318_probe); return platform_driver_probe(&coh901318_driver, coh901318_probe);
} }
subsys_initcall(coh901318_init); arch_initcall(coh901318_init);
void __exit coh901318_exit(void) void __exit coh901318_exit(void)
{ {
......
...@@ -690,8 +690,12 @@ int dma_async_device_register(struct dma_device *device) ...@@ -690,8 +690,12 @@ int dma_async_device_register(struct dma_device *device)
!device->device_prep_dma_memset); !device->device_prep_dma_memset);
BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) && BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) &&
!device->device_prep_dma_interrupt); !device->device_prep_dma_interrupt);
BUG_ON(dma_has_cap(DMA_SG, device->cap_mask) &&
!device->device_prep_dma_sg);
BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
!device->device_prep_slave_sg); !device->device_prep_slave_sg);
BUG_ON(dma_has_cap(DMA_CYCLIC, device->cap_mask) &&
!device->device_prep_dma_cyclic);
BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) && BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
!device->device_control); !device->device_control);
...@@ -702,7 +706,7 @@ int dma_async_device_register(struct dma_device *device) ...@@ -702,7 +706,7 @@ int dma_async_device_register(struct dma_device *device)
BUG_ON(!device->dev); BUG_ON(!device->dev);
/* note: this only matters in the /* note: this only matters in the
* CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y case * CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=n case
*/ */
if (device_has_all_tx_types(device)) if (device_has_all_tx_types(device))
dma_cap_set(DMA_ASYNC_TX, device->cap_mask); dma_cap_set(DMA_ASYNC_TX, device->cap_mask);
...@@ -976,7 +980,7 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx, ...@@ -976,7 +980,7 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
struct dma_chan *chan) struct dma_chan *chan)
{ {
tx->chan = chan; tx->chan = chan;
#ifndef CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH #ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH
spin_lock_init(&tx->lock); spin_lock_init(&tx->lock);
#endif #endif
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -29,11 +29,12 @@ ...@@ -29,11 +29,12 @@
#include <linux/dmapool.h> #include <linux/dmapool.h>
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
#define INTEL_MID_DMA_DRIVER_VERSION "1.0.5" #define INTEL_MID_DMA_DRIVER_VERSION "1.1.0"
#define REG_BIT0 0x00000001 #define REG_BIT0 0x00000001
#define REG_BIT8 0x00000100 #define REG_BIT8 0x00000100
#define INT_MASK_WE 0x8
#define CLEAR_DONE 0xFFFFEFFF
#define UNMASK_INTR_REG(chan_num) \ #define UNMASK_INTR_REG(chan_num) \
((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num)) ((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num))
#define MASK_INTR_REG(chan_num) (REG_BIT8 << chan_num) #define MASK_INTR_REG(chan_num) (REG_BIT8 << chan_num)
...@@ -41,6 +42,9 @@ ...@@ -41,6 +42,9 @@
#define ENABLE_CHANNEL(chan_num) \ #define ENABLE_CHANNEL(chan_num) \
((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num)) ((REG_BIT0 << chan_num) | (REG_BIT8 << chan_num))
#define DISABLE_CHANNEL(chan_num) \
(REG_BIT8 << chan_num)
#define DESCS_PER_CHANNEL 16 #define DESCS_PER_CHANNEL 16
/*DMA Registers*/ /*DMA Registers*/
/*registers associated with channel programming*/ /*registers associated with channel programming*/
...@@ -50,6 +54,7 @@ ...@@ -50,6 +54,7 @@
/*CH X REG = (DMA_CH_SIZE)*CH_NO + REG*/ /*CH X REG = (DMA_CH_SIZE)*CH_NO + REG*/
#define SAR 0x00 /* Source Address Register*/ #define SAR 0x00 /* Source Address Register*/
#define DAR 0x08 /* Destination Address Register*/ #define DAR 0x08 /* Destination Address Register*/
#define LLP 0x10 /* Linked List Pointer Register*/
#define CTL_LOW 0x18 /* Control Register*/ #define CTL_LOW 0x18 /* Control Register*/
#define CTL_HIGH 0x1C /* Control Register*/ #define CTL_HIGH 0x1C /* Control Register*/
#define CFG_LOW 0x40 /* Configuration Register Low*/ #define CFG_LOW 0x40 /* Configuration Register Low*/
...@@ -112,8 +117,8 @@ union intel_mid_dma_ctl_lo { ...@@ -112,8 +117,8 @@ union intel_mid_dma_ctl_lo {
union intel_mid_dma_ctl_hi { union intel_mid_dma_ctl_hi {
struct { struct {
u32 block_ts:12; /*block transfer size*/ u32 block_ts:12; /*block transfer size*/
/*configured by DMAC*/ u32 done:1; /*Done - updated by DMAC*/
u32 reser:20; u32 reser:19; /*configured by DMAC*/
} ctlx; } ctlx;
u32 ctl_hi; u32 ctl_hi;
...@@ -152,6 +157,7 @@ union intel_mid_dma_cfg_hi { ...@@ -152,6 +157,7 @@ union intel_mid_dma_cfg_hi {
u32 cfg_hi; u32 cfg_hi;
}; };
/** /**
* struct intel_mid_dma_chan - internal mid representation of a DMA channel * struct intel_mid_dma_chan - internal mid representation of a DMA channel
* @chan: dma_chan strcture represetation for mid chan * @chan: dma_chan strcture represetation for mid chan
...@@ -166,7 +172,10 @@ union intel_mid_dma_cfg_hi { ...@@ -166,7 +172,10 @@ union intel_mid_dma_cfg_hi {
* @slave: dma slave struture * @slave: dma slave struture
* @descs_allocated: total number of decsiptors allocated * @descs_allocated: total number of decsiptors allocated
* @dma: dma device struture pointer * @dma: dma device struture pointer
* @busy: bool representing if ch is busy (active txn) or not
* @in_use: bool representing if ch is in use or not * @in_use: bool representing if ch is in use or not
* @raw_tfr: raw trf interrupt recieved
* @raw_block: raw block interrupt recieved
*/ */
struct intel_mid_dma_chan { struct intel_mid_dma_chan {
struct dma_chan chan; struct dma_chan chan;
...@@ -178,10 +187,13 @@ struct intel_mid_dma_chan { ...@@ -178,10 +187,13 @@ struct intel_mid_dma_chan {
struct list_head active_list; struct list_head active_list;
struct list_head queue; struct list_head queue;
struct list_head free_list; struct list_head free_list;
struct intel_mid_dma_slave *slave;
unsigned int descs_allocated; unsigned int descs_allocated;
struct middma_device *dma; struct middma_device *dma;
bool busy;
bool in_use; bool in_use;
u32 raw_tfr;
u32 raw_block;
struct intel_mid_dma_slave *mid_slave;
}; };
static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan( static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan(
...@@ -190,6 +202,10 @@ static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan( ...@@ -190,6 +202,10 @@ static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan(
return container_of(chan, struct intel_mid_dma_chan, chan); return container_of(chan, struct intel_mid_dma_chan, chan);
} }
enum intel_mid_dma_state {
RUNNING = 0,
SUSPENDED,
};
/** /**
* struct middma_device - internal representation of a DMA device * struct middma_device - internal representation of a DMA device
* @pdev: PCI device * @pdev: PCI device
...@@ -205,6 +221,7 @@ static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan( ...@@ -205,6 +221,7 @@ static inline struct intel_mid_dma_chan *to_intel_mid_dma_chan(
* @max_chan: max number of chs supported (from drv_data) * @max_chan: max number of chs supported (from drv_data)
* @block_size: Block size of DMA transfer supported (from drv_data) * @block_size: Block size of DMA transfer supported (from drv_data)
* @pimr_mask: MMIO register addr for periphral interrupt (from drv_data) * @pimr_mask: MMIO register addr for periphral interrupt (from drv_data)
* @state: dma PM device state
*/ */
struct middma_device { struct middma_device {
struct pci_dev *pdev; struct pci_dev *pdev;
...@@ -220,6 +237,7 @@ struct middma_device { ...@@ -220,6 +237,7 @@ struct middma_device {
int max_chan; int max_chan;
int block_size; int block_size;
unsigned int pimr_mask; unsigned int pimr_mask;
enum intel_mid_dma_state state;
}; };
static inline struct middma_device *to_middma_device(struct dma_device *common) static inline struct middma_device *to_middma_device(struct dma_device *common)
...@@ -238,14 +256,27 @@ struct intel_mid_dma_desc { ...@@ -238,14 +256,27 @@ struct intel_mid_dma_desc {
u32 cfg_lo; u32 cfg_lo;
u32 ctl_lo; u32 ctl_lo;
u32 ctl_hi; u32 ctl_hi;
struct pci_pool *lli_pool;
struct intel_mid_dma_lli *lli;
dma_addr_t lli_phys;
unsigned int lli_length;
unsigned int current_lli;
dma_addr_t next; dma_addr_t next;
enum dma_data_direction dirn; enum dma_data_direction dirn;
enum dma_status status; enum dma_status status;
enum intel_mid_dma_width width; /*width of DMA txn*/ enum dma_slave_buswidth width; /*width of DMA txn*/
enum intel_mid_dma_mode cfg_mode; /*mode configuration*/ enum intel_mid_dma_mode cfg_mode; /*mode configuration*/
}; };
struct intel_mid_dma_lli {
dma_addr_t sar;
dma_addr_t dar;
dma_addr_t llp;
u32 ctl_lo;
u32 ctl_hi;
} __attribute__ ((packed));
static inline int test_ch_en(void __iomem *dma, u32 ch_no) static inline int test_ch_en(void __iomem *dma, u32 ch_no)
{ {
u32 en_reg = ioread32(dma + DMA_CHAN_EN); u32 en_reg = ioread32(dma + DMA_CHAN_EN);
...@@ -257,4 +288,14 @@ static inline struct intel_mid_dma_desc *to_intel_mid_dma_desc ...@@ -257,4 +288,14 @@ static inline struct intel_mid_dma_desc *to_intel_mid_dma_desc
{ {
return container_of(txd, struct intel_mid_dma_desc, txd); return container_of(txd, struct intel_mid_dma_desc, txd);
} }
static inline struct intel_mid_dma_slave *to_intel_mid_dma_slave
(struct dma_slave_config *slave)
{
return container_of(slave, struct intel_mid_dma_slave, dma_slave);
}
int dma_resume(struct pci_dev *pci);
#endif /*__INTEL_MID_DMAC_REGS_H__*/ #endif /*__INTEL_MID_DMAC_REGS_H__*/
This diff is collapsed.
/* /*
* driver/dma/ste_dma40_ll.c * Copyright (C) ST-Ericsson SA 2007-2010
* * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson
* Copyright (C) ST-Ericsson 2007-2010 * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL) version 2 * License terms: GNU General Public License (GPL) version 2
* Author: Per Friden <per.friden@stericsson.com>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -39,16 +37,13 @@ void d40_log_cfg(struct stedma40_chan_cfg *cfg, ...@@ -39,16 +37,13 @@ void d40_log_cfg(struct stedma40_chan_cfg *cfg,
cfg->dir == STEDMA40_PERIPH_TO_PERIPH) cfg->dir == STEDMA40_PERIPH_TO_PERIPH)
l3 |= 1 << D40_MEM_LCSP3_DCFG_MST_POS; l3 |= 1 << D40_MEM_LCSP3_DCFG_MST_POS;
l3 |= 1 << D40_MEM_LCSP3_DCFG_TIM_POS;
l3 |= 1 << D40_MEM_LCSP3_DCFG_EIM_POS; l3 |= 1 << D40_MEM_LCSP3_DCFG_EIM_POS;
l3 |= cfg->dst_info.psize << D40_MEM_LCSP3_DCFG_PSIZE_POS; l3 |= cfg->dst_info.psize << D40_MEM_LCSP3_DCFG_PSIZE_POS;
l3 |= cfg->dst_info.data_width << D40_MEM_LCSP3_DCFG_ESIZE_POS; l3 |= cfg->dst_info.data_width << D40_MEM_LCSP3_DCFG_ESIZE_POS;
l3 |= 1 << D40_MEM_LCSP3_DTCP_POS;
l1 |= 1 << D40_MEM_LCSP1_SCFG_EIM_POS; l1 |= 1 << D40_MEM_LCSP1_SCFG_EIM_POS;
l1 |= cfg->src_info.psize << D40_MEM_LCSP1_SCFG_PSIZE_POS; l1 |= cfg->src_info.psize << D40_MEM_LCSP1_SCFG_PSIZE_POS;
l1 |= cfg->src_info.data_width << D40_MEM_LCSP1_SCFG_ESIZE_POS; l1 |= cfg->src_info.data_width << D40_MEM_LCSP1_SCFG_ESIZE_POS;
l1 |= 1 << D40_MEM_LCSP1_STCP_POS;
*lcsp1 = l1; *lcsp1 = l1;
*lcsp3 = l3; *lcsp3 = l3;
...@@ -113,13 +108,15 @@ void d40_phy_cfg(struct stedma40_chan_cfg *cfg, ...@@ -113,13 +108,15 @@ void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
src |= 1 << D40_SREG_CFG_LOG_GIM_POS; src |= 1 << D40_SREG_CFG_LOG_GIM_POS;
} }
if (cfg->channel_type & STEDMA40_HIGH_PRIORITY_CHANNEL) { if (cfg->high_priority) {
src |= 1 << D40_SREG_CFG_PRI_POS; src |= 1 << D40_SREG_CFG_PRI_POS;
dst |= 1 << D40_SREG_CFG_PRI_POS; dst |= 1 << D40_SREG_CFG_PRI_POS;
} }
src |= cfg->src_info.endianess << D40_SREG_CFG_LBE_POS; if (cfg->src_info.big_endian)
dst |= cfg->dst_info.endianess << D40_SREG_CFG_LBE_POS; src |= 1 << D40_SREG_CFG_LBE_POS;
if (cfg->dst_info.big_endian)
dst |= 1 << D40_SREG_CFG_LBE_POS;
*src_cfg = src; *src_cfg = src;
*dst_cfg = dst; *dst_cfg = dst;
...@@ -197,8 +194,7 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, ...@@ -197,8 +194,7 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
dma_addr_t lli_phys, dma_addr_t lli_phys,
u32 reg_cfg, u32 reg_cfg,
u32 data_width, u32 data_width,
int psize, int psize)
bool term_int)
{ {
int total_size = 0; int total_size = 0;
int i; int i;
...@@ -238,7 +234,7 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, ...@@ -238,7 +234,7 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
} }
return total_size; return total_size;
err: err:
return err; return err;
} }
...@@ -271,11 +267,59 @@ void d40_phy_lli_write(void __iomem *virtbase, ...@@ -271,11 +267,59 @@ void d40_phy_lli_write(void __iomem *virtbase,
/* DMA logical lli operations */ /* DMA logical lli operations */
static void d40_log_lli_link(struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
int next)
{
u32 slos = 0;
u32 dlos = 0;
if (next != -EINVAL) {
slos = next * 2;
dlos = next * 2 + 1;
} else {
lli_dst->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK;
lli_dst->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK;
}
lli_src->lcsp13 = (lli_src->lcsp13 & ~D40_MEM_LCSP1_SLOS_MASK) |
(slos << D40_MEM_LCSP1_SLOS_POS);
lli_dst->lcsp13 = (lli_dst->lcsp13 & ~D40_MEM_LCSP1_SLOS_MASK) |
(dlos << D40_MEM_LCSP1_SLOS_POS);
}
void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
int next)
{
d40_log_lli_link(lli_dst, lli_src, next);
writel(lli_src->lcsp02, &lcpa[0].lcsp0);
writel(lli_src->lcsp13, &lcpa[0].lcsp1);
writel(lli_dst->lcsp02, &lcpa[0].lcsp2);
writel(lli_dst->lcsp13, &lcpa[0].lcsp3);
}
void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
int next)
{
d40_log_lli_link(lli_dst, lli_src, next);
writel(lli_src->lcsp02, &lcla[0].lcsp02);
writel(lli_src->lcsp13, &lcla[0].lcsp13);
writel(lli_dst->lcsp02, &lcla[1].lcsp02);
writel(lli_dst->lcsp13, &lcla[1].lcsp13);
}
void d40_log_fill_lli(struct d40_log_lli *lli, void d40_log_fill_lli(struct d40_log_lli *lli,
dma_addr_t data, u32 data_size, dma_addr_t data, u32 data_size,
u32 lli_next_off, u32 reg_cfg, u32 reg_cfg,
u32 data_width, u32 data_width,
bool term_int, bool addr_inc) bool addr_inc)
{ {
lli->lcsp13 = reg_cfg; lli->lcsp13 = reg_cfg;
...@@ -290,165 +334,69 @@ void d40_log_fill_lli(struct d40_log_lli *lli, ...@@ -290,165 +334,69 @@ void d40_log_fill_lli(struct d40_log_lli *lli,
if (addr_inc) if (addr_inc)
lli->lcsp13 |= D40_MEM_LCSP1_SCFG_INCR_MASK; lli->lcsp13 |= D40_MEM_LCSP1_SCFG_INCR_MASK;
lli->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK;
/* If this scatter list entry is the last one, no next link */
lli->lcsp13 |= (lli_next_off << D40_MEM_LCSP1_SLOS_POS) &
D40_MEM_LCSP1_SLOS_MASK;
if (term_int)
lli->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK;
else
lli->lcsp13 &= ~D40_MEM_LCSP1_SCFG_TIM_MASK;
} }
int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, int d40_log_sg_to_dev(struct scatterlist *sg,
struct scatterlist *sg,
int sg_len, int sg_len,
struct d40_log_lli_bidir *lli, struct d40_log_lli_bidir *lli,
struct d40_def_lcsp *lcsp, struct d40_def_lcsp *lcsp,
u32 src_data_width, u32 src_data_width,
u32 dst_data_width, u32 dst_data_width,
enum dma_data_direction direction, enum dma_data_direction direction,
bool term_int, dma_addr_t dev_addr, int max_len, dma_addr_t dev_addr)
int llis_per_log)
{ {
int total_size = 0; int total_size = 0;
struct scatterlist *current_sg = sg; struct scatterlist *current_sg = sg;
int i; int i;
u32 next_lli_off_dst = 0;
u32 next_lli_off_src = 0;
for_each_sg(sg, current_sg, sg_len, i) { for_each_sg(sg, current_sg, sg_len, i) {
total_size += sg_dma_len(current_sg); total_size += sg_dma_len(current_sg);
/*
* If this scatter list entry is the last one or
* max length, terminate link.
*/
if (sg_len - 1 == i || ((i+1) % max_len == 0)) {
next_lli_off_src = 0;
next_lli_off_dst = 0;
} else {
if (next_lli_off_dst == 0 &&
next_lli_off_src == 0) {
/* The first lli will be at next_lli_off */
next_lli_off_dst = (lcla->dst_id *
llis_per_log + 1);
next_lli_off_src = (lcla->src_id *
llis_per_log + 1);
} else {
next_lli_off_dst++;
next_lli_off_src++;
}
}
if (direction == DMA_TO_DEVICE) { if (direction == DMA_TO_DEVICE) {
d40_log_fill_lli(&lli->src[i], d40_log_fill_lli(&lli->src[i],
sg_phys(current_sg), sg_phys(current_sg),
sg_dma_len(current_sg), sg_dma_len(current_sg),
next_lli_off_src,
lcsp->lcsp1, src_data_width, lcsp->lcsp1, src_data_width,
false,
true); true);
d40_log_fill_lli(&lli->dst[i], d40_log_fill_lli(&lli->dst[i],
dev_addr, dev_addr,
sg_dma_len(current_sg), sg_dma_len(current_sg),
next_lli_off_dst,
lcsp->lcsp3, dst_data_width, lcsp->lcsp3, dst_data_width,
/* No next == terminal interrupt */
term_int && !next_lli_off_dst,
false); false);
} else { } else {
d40_log_fill_lli(&lli->dst[i], d40_log_fill_lli(&lli->dst[i],
sg_phys(current_sg), sg_phys(current_sg),
sg_dma_len(current_sg), sg_dma_len(current_sg),
next_lli_off_dst,
lcsp->lcsp3, dst_data_width, lcsp->lcsp3, dst_data_width,
/* No next == terminal interrupt */
term_int && !next_lli_off_dst,
true); true);
d40_log_fill_lli(&lli->src[i], d40_log_fill_lli(&lli->src[i],
dev_addr, dev_addr,
sg_dma_len(current_sg), sg_dma_len(current_sg),
next_lli_off_src,
lcsp->lcsp1, src_data_width, lcsp->lcsp1, src_data_width,
false,
false); false);
} }
} }
return total_size; return total_size;
} }
int d40_log_sg_to_lli(int lcla_id, int d40_log_sg_to_lli(struct scatterlist *sg,
struct scatterlist *sg,
int sg_len, int sg_len,
struct d40_log_lli *lli_sg, struct d40_log_lli *lli_sg,
u32 lcsp13, /* src or dst*/ u32 lcsp13, /* src or dst*/
u32 data_width, u32 data_width)
bool term_int, int max_len, int llis_per_log)
{ {
int total_size = 0; int total_size = 0;
struct scatterlist *current_sg = sg; struct scatterlist *current_sg = sg;
int i; int i;
u32 next_lli_off = 0;
for_each_sg(sg, current_sg, sg_len, i) { for_each_sg(sg, current_sg, sg_len, i) {
total_size += sg_dma_len(current_sg); total_size += sg_dma_len(current_sg);
/*
* If this scatter list entry is the last one or
* max length, terminate link.
*/
if (sg_len - 1 == i || ((i+1) % max_len == 0))
next_lli_off = 0;
else {
if (next_lli_off == 0)
/* The first lli will be at next_lli_off */
next_lli_off = lcla_id * llis_per_log + 1;
else
next_lli_off++;
}
d40_log_fill_lli(&lli_sg[i], d40_log_fill_lli(&lli_sg[i],
sg_phys(current_sg), sg_phys(current_sg),
sg_dma_len(current_sg), sg_dma_len(current_sg),
next_lli_off,
lcsp13, data_width, lcsp13, data_width,
term_int && !next_lli_off,
true); true);
} }
return total_size; return total_size;
} }
int d40_log_lli_write(struct d40_log_lli_full *lcpa,
struct d40_log_lli *lcla_src,
struct d40_log_lli *lcla_dst,
struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
int llis_per_log)
{
u32 slos;
u32 dlos;
int i;
writel(lli_src->lcsp02, &lcpa->lcsp0);
writel(lli_src->lcsp13, &lcpa->lcsp1);
writel(lli_dst->lcsp02, &lcpa->lcsp2);
writel(lli_dst->lcsp13, &lcpa->lcsp3);
slos = lli_src->lcsp13 & D40_MEM_LCSP1_SLOS_MASK;
dlos = lli_dst->lcsp13 & D40_MEM_LCSP3_DLOS_MASK;
for (i = 0; (i < llis_per_log) && slos && dlos; i++) {
writel(lli_src[i + 1].lcsp02, &lcla_src[i].lcsp02);
writel(lli_src[i + 1].lcsp13, &lcla_src[i].lcsp13);
writel(lli_dst[i + 1].lcsp02, &lcla_dst[i].lcsp02);
writel(lli_dst[i + 1].lcsp13, &lcla_dst[i].lcsp13);
slos = lli_src[i + 1].lcsp13 & D40_MEM_LCSP1_SLOS_MASK;
dlos = lli_dst[i + 1].lcsp13 & D40_MEM_LCSP3_DLOS_MASK;
}
return i;
}
/* /*
* driver/dma/ste_dma40_ll.h * Copyright (C) ST-Ericsson SA 2007-2010
* * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson SA
* Copyright (C) ST-Ericsson 2007-2010 * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson SA
* License terms: GNU General Public License (GPL) version 2 * License terms: GNU General Public License (GPL) version 2
* Author: Per Friden <per.friden@stericsson.com>
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*/ */
#ifndef STE_DMA40_LL_H #ifndef STE_DMA40_LL_H
#define STE_DMA40_LL_H #define STE_DMA40_LL_H
...@@ -132,6 +130,13 @@ ...@@ -132,6 +130,13 @@
#define D40_DREG_PRMSO 0x014 #define D40_DREG_PRMSO 0x014
#define D40_DREG_PRMOE 0x018 #define D40_DREG_PRMOE 0x018
#define D40_DREG_PRMOO 0x01C #define D40_DREG_PRMOO 0x01C
#define D40_DREG_PRMO_PCHAN_BASIC 0x1
#define D40_DREG_PRMO_PCHAN_MODULO 0x2
#define D40_DREG_PRMO_PCHAN_DOUBLE_DST 0x3
#define D40_DREG_PRMO_LCHAN_SRC_PHY_DST_LOG 0x1
#define D40_DREG_PRMO_LCHAN_SRC_LOG_DST_PHY 0x2
#define D40_DREG_PRMO_LCHAN_SRC_LOG_DST_LOG 0x3
#define D40_DREG_LCPA 0x020 #define D40_DREG_LCPA 0x020
#define D40_DREG_LCLA 0x024 #define D40_DREG_LCLA 0x024
#define D40_DREG_ACTIVE 0x050 #define D40_DREG_ACTIVE 0x050
...@@ -163,6 +168,9 @@ ...@@ -163,6 +168,9 @@
#define D40_DREG_PERIPHID0 0xFE0 #define D40_DREG_PERIPHID0 0xFE0
#define D40_DREG_PERIPHID1 0xFE4 #define D40_DREG_PERIPHID1 0xFE4
#define D40_DREG_PERIPHID2 0xFE8 #define D40_DREG_PERIPHID2 0xFE8
#define D40_DREG_PERIPHID2_REV_POS 4
#define D40_DREG_PERIPHID2_REV_MASK (0xf << D40_DREG_PERIPHID2_REV_POS)
#define D40_DREG_PERIPHID2_DESIGNER_MASK 0xf
#define D40_DREG_PERIPHID3 0xFEC #define D40_DREG_PERIPHID3 0xFEC
#define D40_DREG_CELLID0 0xFF0 #define D40_DREG_CELLID0 0xFF0
#define D40_DREG_CELLID1 0xFF4 #define D40_DREG_CELLID1 0xFF4
...@@ -199,8 +207,6 @@ struct d40_phy_lli { ...@@ -199,8 +207,6 @@ struct d40_phy_lli {
* *
* @src: Register settings for src channel. * @src: Register settings for src channel.
* @dst: Register settings for dst channel. * @dst: Register settings for dst channel.
* @dst_addr: Physical destination address.
* @src_addr: Physical source address.
* *
* All DMA transfers have a source and a destination. * All DMA transfers have a source and a destination.
*/ */
...@@ -208,8 +214,6 @@ struct d40_phy_lli { ...@@ -208,8 +214,6 @@ struct d40_phy_lli {
struct d40_phy_lli_bidir { struct d40_phy_lli_bidir {
struct d40_phy_lli *src; struct d40_phy_lli *src;
struct d40_phy_lli *dst; struct d40_phy_lli *dst;
dma_addr_t dst_addr;
dma_addr_t src_addr;
}; };
...@@ -271,29 +275,16 @@ struct d40_def_lcsp { ...@@ -271,29 +275,16 @@ struct d40_def_lcsp {
u32 lcsp1; u32 lcsp1;
}; };
/**
* struct d40_lcla_elem - Info for one LCA element.
*
* @src_id: logical channel src id
* @dst_id: logical channel dst id
* @src: LCPA formated src parameters
* @dst: LCPA formated dst parameters
*
*/
struct d40_lcla_elem {
int src_id;
int dst_id;
struct d40_log_lli *src;
struct d40_log_lli *dst;
};
/* Physical channels */ /* Physical channels */
void d40_phy_cfg(struct stedma40_chan_cfg *cfg, void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
u32 *src_cfg, u32 *dst_cfg, bool is_log); u32 *src_cfg,
u32 *dst_cfg,
bool is_log);
void d40_log_cfg(struct stedma40_chan_cfg *cfg, void d40_log_cfg(struct stedma40_chan_cfg *cfg,
u32 *lcsp1, u32 *lcsp2); u32 *lcsp1,
u32 *lcsp2);
int d40_phy_sg_to_lli(struct scatterlist *sg, int d40_phy_sg_to_lli(struct scatterlist *sg,
int sg_len, int sg_len,
...@@ -302,8 +293,7 @@ int d40_phy_sg_to_lli(struct scatterlist *sg, ...@@ -302,8 +293,7 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
dma_addr_t lli_phys, dma_addr_t lli_phys,
u32 reg_cfg, u32 reg_cfg,
u32 data_width, u32 data_width,
int psize, int psize);
bool term_int);
int d40_phy_fill_lli(struct d40_phy_lli *lli, int d40_phy_fill_lli(struct d40_phy_lli *lli,
dma_addr_t data, dma_addr_t data,
...@@ -323,35 +313,35 @@ void d40_phy_lli_write(void __iomem *virtbase, ...@@ -323,35 +313,35 @@ void d40_phy_lli_write(void __iomem *virtbase,
/* Logical channels */ /* Logical channels */
void d40_log_fill_lli(struct d40_log_lli *lli, void d40_log_fill_lli(struct d40_log_lli *lli,
dma_addr_t data, u32 data_size, dma_addr_t data,
u32 lli_next_off, u32 reg_cfg, u32 data_size,
u32 reg_cfg,
u32 data_width, u32 data_width,
bool term_int, bool addr_inc); bool addr_inc);
int d40_log_sg_to_dev(struct d40_lcla_elem *lcla, int d40_log_sg_to_dev(struct scatterlist *sg,
struct scatterlist *sg,
int sg_len, int sg_len,
struct d40_log_lli_bidir *lli, struct d40_log_lli_bidir *lli,
struct d40_def_lcsp *lcsp, struct d40_def_lcsp *lcsp,
u32 src_data_width, u32 src_data_width,
u32 dst_data_width, u32 dst_data_width,
enum dma_data_direction direction, enum dma_data_direction direction,
bool term_int, dma_addr_t dev_addr, int max_len, dma_addr_t dev_addr);
int llis_per_log);
int d40_log_sg_to_lli(struct scatterlist *sg,
int d40_log_lli_write(struct d40_log_lli_full *lcpa,
struct d40_log_lli *lcla_src,
struct d40_log_lli *lcla_dst,
struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
int llis_per_log);
int d40_log_sg_to_lli(int lcla_id,
struct scatterlist *sg,
int sg_len, int sg_len,
struct d40_log_lli *lli_sg, struct d40_log_lli *lli_sg,
u32 lcsp13, /* src or dst*/ u32 lcsp13, /* src or dst*/
u32 data_width, u32 data_width);
bool term_int, int max_len, int llis_per_log);
void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
int next);
void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
int next);
#endif /* STE_DMA40_LLI_H */ #endif /* STE_DMA40_LLI_H */
...@@ -759,7 +759,7 @@ static int __devinit td_probe(struct platform_device *pdev) ...@@ -759,7 +759,7 @@ static int __devinit td_probe(struct platform_device *pdev)
pdata->channels + i; pdata->channels + i;
/* even channels are RX, odd are TX */ /* even channels are RX, odd are TX */
if (((i % 2) && pchan->rx) || (!(i % 2) && !pchan->rx)) { if ((i % 2) == pchan->rx) {
dev_err(&pdev->dev, "Wrong channel configuration\n"); dev_err(&pdev->dev, "Wrong channel configuration\n");
err = -EINVAL; err = -EINVAL;
goto err_tasklet_kill; goto err_tasklet_kill;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment