/*
*
* This file contains a driver for the Freescale Smart DMA engine
*
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/dmaengine.h>
#include <asm/irq.h>
#include <mach/sdma.h>
#include <mach/dma.h>
#include <mach/hardware.h>
/* SDMA registers */
#define SDMA_H_C0PTR 0x000
#define SDMA_H_INTR 0x004
#define SDMA_H_STATSTOP 0x008
#define SDMA_H_START 0x00c
#define SDMA_H_EVTOVR 0x010
#define SDMA_H_DSPOVR 0x014
#define SDMA_H_HOSTOVR 0x018
#define SDMA_H_EVTPEND 0x01c
#define SDMA_H_DSPENBL 0x020
#define SDMA_H_RESET 0x024
#define SDMA_H_EVTERR 0x028
#define SDMA_H_INTRMSK 0x02c
#define SDMA_H_PSW 0x030
#define SDMA_H_EVTERRDBG 0x034
#define SDMA_H_CONFIG 0x038
#define SDMA_ONCE_ENB 0x040
#define SDMA_ONCE_DATA 0x044
#define SDMA_ONCE_INSTR 0x048
#define SDMA_ONCE_STAT 0x04c
#define SDMA_ONCE_CMD 0x050
#define SDMA_EVT_MIRROR 0x054
#define SDMA_ILLINSTADDR 0x058
#define SDMA_CHN0ADDR 0x05c
#define SDMA_ONCE_RTB 0x060
#define SDMA_XTRIG_CONF1 0x070
#define SDMA_XTRIG_CONF2 0x074
#define SDMA_CHNENBL0_V2 0x200
#define SDMA_CHNENBL0_V1 0x080
#define SDMA_CHNPRI_0 0x100
/*
* Buffer descriptor status values.
*/
#define BD_DONE 0x01
#define BD_WRAP 0x02
#define BD_CONT 0x04
#define BD_INTR 0x08
#define BD_RROR 0x10
#define BD_LAST 0x20
#define BD_EXTD 0x80
/*
* Data Node descriptor status values.
*/
#define DND_END_OF_FRAME 0x80
#define DND_END_OF_XFER 0x40
#define DND_DONE 0x20
#define DND_UNUSED 0x01
/*
* IPCV2 descriptor status values.
*/
#define BD_IPCV2_END_OF_FRAME 0x40
#define IPCV2_MAX_NODES 50
/*
* Error bit set in the CCB status field by the SDMA,
* in setbd routine, in case of a transfer error
*/
#define DATA_ERROR 0x10000000
/*
* Buffer descriptor commands.
*/
#define C0_ADDR 0x01
#define C0_LOAD 0x02
#define C0_DUMP 0x03
#define C0_SETCTX 0x07
#define C0_GETCTX 0x03
#define C0_SETDM 0x01
#define C0_SETPM 0x04
#define C0_GETDM 0x02
#define C0_GETPM 0x08
/*
* Change endianness indicator in the BD command field
*/
#define CHANGE_ENDIANNESS 0x80
/*
* Mode/Count of data node descriptors - IPCv2
*/
struct sdma_mode_count {
u32 count : 16; /* size of the buffer pointed by this BD */
u32 status : 8; /* E,R,I,C,W,D status bits stored here */
u32 command : 8; /* command mostlky used for channel 0 */
};
/*
* Buffer descriptor
*/
struct sdma_buffer_descriptor {
struct sdma_mode_count mode;
u32 buffer_addr; /* address of the buffer described */
u32 ext_buffer_addr; /* extended buffer address */
} __attribute__ ((packed));
/**
* struct sdma_channel_control - Channel control Block
*
* @current_bd_ptr current buffer descriptor processed
* @base_bd_ptr first element of buffer descriptor array
* @unused padding. The SDMA engine expects an array of 128 byte
* control blocks
*/
struct sdma_channel_control {
u32 current_bd_ptr;
u32 base_bd_ptr;
u32 unused[2];
} __attribute__ ((packed));
/**
* struct sdma_state_registers - SDMA context for a channel
*
* @pc: program counter
* @t: test bit: status of arithmetic & test instruction
* @rpc: return program counter
* @sf: source fault while loading data
* @spc: loop start program counter
* @df: destination fault while storing data
* @epc: loop end program counter
* @lm: loop mode
*/
struct sdma_state_registers {
u32 pc :14;
u32 unused1: 1;
u32 t : 1;
u32 rpc :14;
u32 unused0: 1;
u32 sf : 1;
u32 spc :14;
u32 unused2: 1;
u32 df : 1;
u32 epc :14;
u32 lm : 2;
} __attribute__ ((packed));
/**
* struct sdma_context_data - sdma context specific to a channel
*
* @channel_state: channel state bits
* @gReg: general registers
* @mda: burst dma destination address register
* @msa: burst dma source address register
* @ms: burst dma status register
* @md: burst dma data register
* @pda: peripheral dma destination address register
* @psa: peripheral dma source address register
* @ps: peripheral dma status register
* @pd: peripheral dma data register
* @ca: CRC polynomial register
* @cs: CRC accumulator register
* @dda: dedicated core destination address register
* @dsa: dedicated core source address register
* @ds: dedicated core status register
* @dd: dedicated core data register
*/
struct sdma_context_data {
struct sdma_state_registers channel_state;
u32 gReg[8];
u32 mda;
u32 msa;
u32 ms;
u32 md;
u32 pda;
u32 psa;
u32 ps;
u32 pd;
u32 ca;
u32 cs;
u32 dda;
u32 dsa;
u32 ds;
u32 dd;
u32 scratch0;
u32 scratch1;
u32 scratch2;
u32 scratch3;
u32 scratch4;
u32 scratch5;
u32 scratch6;
u32 scratch7;
} __attribute__ ((packed));
#define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
struct sdma_engine;
/**
* struct sdma_channel - housekeeping for a SDMA channel
*
* @sdma pointer to the SDMA engine for this channel
* @channel the channel number, matches dmaengine chan_id + 1
* @direction transfer type. Needed for setting SDMA script
* @peripheral_type Peripheral type. Needed for setting SDMA script
* @event_id0 aka dma request line
* @event_id1 for channels that use 2 events
* @word_size peripheral access size
* @buf_tail ID of the buffer that was processed
* @done channel completion
* @num_bd max NUM_BD. number of descriptors currently handling
*/
struct sdma_channel {
struct sdma_engine *sdma;
unsigned int channel;
enum dma_data_direction direction;
enum sdma_peripheral_type peripheral_type;
unsigned int event_id0;
unsigned int event_id1;
enum dma_slave_buswidth word_size;
unsigned int buf_tail;
struct completion done;
unsigned int num_bd;
struct sdma_buffer_descriptor *bd;
dma_addr_t bd_phys;
unsigned int pc_from_device, pc_to_device;
unsigned long flags;
dma_addr_t per_address;
u32 event_mask0, event_mask1;
u32 watermark_level;
u32 shp_addr, per_addr;
struct dma_chan chan;
spinlock_t lock;
struct dma_async_tx_descriptor desc;
dma_cookie_t last_completed;
enum dma_status status;
};
#define IMX_DMA_SG_LOOP (1 << 0)
#define MAX_DMA_CHANNELS 32
#define MXC_SDMA_DEFAULT_PRIORITY 1
#define MXC_SDMA_MIN_PRIORITY 1
#define MXC_SDMA_MAX_PRIORITY 7
#define SDMA_FIRMWARE_MAGIC 0x414d4453
/**
* struct sdma_firmware_header - Layout of the firmware image
*
* @magic "SDMA"
* @version_major increased whenever layout of struct sdma_script_start_addrs
* changes.
* @version_minor firmware minor version (for binary compatible changes)
* @script_addrs_start offset of struct sdma_script_start_addrs in this image
* @num_script_addrs Number of script addresses in this image
* @ram_code_start offset of SDMA ram image in this firmware image
* @ram_code_size size of SDMA ram image
* @script_addrs Stores the start address of the SDMA scripts
* (in SDMA memory space)
*/
struct sdma_firmware_header {
u32 magic;
u32 version_major;
u32 version_minor;
u32 script_addrs_start;
u32 num_script_addrs;
u32 ram_code_start;
u32 ram_code_size;
};
struct sdma_engine {
struct device *dev;
struct device_dma_parameters dma_parms;
struct sdma_channel channel[MAX_DMA_CHANNELS];
struct sdma_channel_control *channel_control;
void __iomem *regs;
unsigned int version;