/*
* Xilinx DPDMA Engine driver
*
* Copyright (C) 2015 Xilinx, Inc.
*
* Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/dmapool.h>
#include <linux/gfp.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_dma.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/wait.h>
#include "../dmaengine.h"
/* DPDMA registers */
#define XILINX_DPDMA_ERR_CTRL 0x0
#define XILINX_DPDMA_ISR 0x4
#define XILINX_DPDMA_IMR 0x8
#define XILINX_DPDMA_IEN 0xc
#define XILINX_DPDMA_IDS 0x10
#define XILINX_DPDMA_INTR_DESC_DONE_MASK (0x3f << 0)
#define XILINX_DPDMA_INTR_DESC_DONE_SHIFT 0
#define XILINX_DPDMA_INTR_NO_OSTAND_MASK (0x3f << 6)
#define XILINX_DPDMA_INTR_NO_OSTAND_SHIFT 6
#define XILINX_DPDMA_INTR_AXI_ERR_MASK (0x3f << 12)
#define XILINX_DPDMA_INTR_AXI_ERR_SHIFT 12
#define XILINX_DPDMA_INTR_DESC_ERR_MASK (0x3f << 18)
#define XILINX_DPDMA_INTR_DESC_ERR_SHIFT 16
#define XILINX_DPDMA_INTR_WR_CMD_FIFO_FULL BIT(24)
#define XILINX_DPDMA_INTR_WR_DATA_FIFO_FULL BIT(25)
#define XILINX_DPDMA_INTR_AXI_4K_CROSS BIT(26)
#define XILINX_DPDMA_INTR_VSYNC BIT(27)
#define XILINX_DPDMA_INTR_CHAN_ERR_MASK 0x41000
#define XILINX_DPDMA_INTR_CHAN_ERR 0xfff000
#define XILINX_DPDMA_INTR_GLOBAL_ERR 0x7000000
#define XILINX_DPDMA_INTR_ERR_ALL 0x7fff000
#define XILINX_DPDMA_INTR_ALL 0xfffffff
#define XILINX_DPDMA_EISR 0x14
#define XILINX_DPDMA_EIMR 0x18
#define XILINX_DPDMA_EIEN 0x1c
#define XILINX_DPDMA_EIDS 0x20
#define XILINX_DPDMA_EINTR_INV_APB BIT(0)
#define XILINX_DPDMA_EINTR_RD_AXI_ERR_MASK (0x3f << 1)
#define XILINX_DPDMA_EINTR_RD_AXI_ERR_SHIFT 1
#define XILINX_DPDMA_EINTR_PRE_ERR_MASK (0x3f << 7)
#define XILINX_DPDMA_EINTR_PRE_ERR_SHIFT 7
#define XILINX_DPDMA_EINTR_CRC_ERR_MASK (0x3f << 13)
#define XILINX_DPDMA_EINTR_CRC_ERR_SHIFT 13
#define XILINX_DPDMA_EINTR_WR_AXI_ERR_MASK (0x3f << 19)
#define XILINX_DPDMA_EINTR_WR_AXI_ERR_SHIFT 19
#define XILINX_DPDMA_EINTR_DESC_DONE_ERR_MASK (0x3f << 25)
#define XILINX_DPDMA_EINTR_DESC_DONE_ERR_SHIFT 25
#define XILINX_DPDMA_EINTR_RD_CMD_FIFO_FULL BIT(32)
#define XILINX_DPDMA_EINTR_CHAN_ERR_MASK 0x2082082
#define XILINX_DPDMA_EINTR_CHAN_ERR 0x7ffffffe
#define XILINX_DPDMA_EINTR_GLOBAL_ERR 0x80000001
#define XILINX_DPDMA_EINTR_ALL 0xffffffff
#define XILINX_DPDMA_CNTL 0x100
#define XILINX_DPDMA_GBL 0x104
#define XILINX_DPDMA_GBL_TRIG_SHIFT 0
#define XILINX_DPDMA_GBL_RETRIG_SHIFT 6
#define XILINX_DPDMA_ALC0_CNTL 0x108
#define XILINX_DPDMA_ALC0_STATUS 0x10c
#define XILINX_DPDMA_ALC0_MAX 0x110
#define XILINX_DPDMA_ALC0_MIN 0x114
#define XILINX_DPDMA_ALC0_ACC 0x118
#define XILINX_DPDMA_ALC0_ACC_TRAN 0x11c
#define XILINX_DPDMA_ALC1_CNTL 0x120
#define XILINX_DPDMA_ALC1_STATUS 0x124
#define XILINX_DPDMA_ALC1_MAX 0x128
#define XILINX_DPDMA_ALC1_MIN 0x12c
#define XILINX_DPDMA_ALC1_ACC 0x130
#define XILINX_DPDMA_ALC1_ACC_TRAN 0x134
/* Channel register */
#define XILINX_DPDMA_CH_BASE 0x200
#define XILINX_DPDMA_CH_OFFSET 0x100
#define XILINX_DPDMA_CH_DESC_START_ADDRE 0x0
#define XILINX_DPDMA_CH_DESC_START_ADDR 0x4
#define XILINX_DPDMA_CH_DESC_NEXT_ADDRE 0x8
#define XILINX_DPDMA_CH_DESC_NEXT_ADDR 0xc
#define XILINX_DPDMA_CH_PYLD_CUR_ADDRE 0x10
#define XILINX_DPDMA_CH_PYLD_CUR_ADDR 0x14
#define XILINX_DPDMA_CH_CNTL 0x18
#define XILINX_DPDMA_CH_CNTL_ENABLE BIT(0)
#define XILINX_DPDMA_CH_CNTL_PAUSE BIT(1)
#define XILINX_DPDMA_CH_STATUS 0x1c
#define XILINX_DPDMA_CH_STATUS_OTRAN_CNT_MASK (0xf << 21)
#define XILINX_DPDMA_CH_STATUS_OTRAN_CNT_SHIFT 21
#define XILINX_DPDMA_CH_VDO 0x20
#define XILINX_DPDMA_CH_PYLD_SZ 0x24
#define XILINX_DPDMA_CH_DESC_ID 0x28
/* DPDMA descriptor fields */
#define XILINX_DPDMA_DESC_CONTROL_PREEMBLE (0xa5)
#define XILINX_DPDMA_DESC_CONTROL_COMPLETE_INTR BIT(8)
#define XILINX_DPDMA_DESC_CONTROL_DESC_UPDATE BIT(9)
#define XILINX_DPDMA_DESC_CONTROL_IGNORE_DONE BIT(10)
#define XILINX_DPDMA_DESC_CONTROL_FRAG_MODE BIT(18)
#define XILINX_DPDMA_DESC_CONTROL_LAST BIT(19)
#define XILINX_DPDMA_DESC_CONTROL_ENABLE_CRC BIT(20)
#define XILINX_DPDMA_DESC_CONTROL_LAST_OF_FRAME BIT(21)
#define XILINX_DPDMA_DESC_ID_MASK (0xffff << 0)
#define XILINX_DPDMA_DESC_ID_SHIFT (0)
#define XILINX_DPDMA_DESC_HSIZE_STRIDE_HSIZE_MASK (0x3ffff << 0)
#define XILINX_DPDMA_DESC_HSIZE_STRIDE_HSIZE_SHIFT (0)
#define XILINX_DPDMA_DESC_HSIZE_STRIDE_STRIDE_MASK (0x3fff << 18)
#define XILINX_DPDMA_DESC_HSIZE_STRIDE_STRIDE_SHIFT (18)
#define XILINX_DPDMA_DESC_ADDR_EXT_ADDR_MASK (0xfff)
#define XILINX_DPDMA_DESC_ADDR_EXT_ADDR_SHIFT (16)
#define XILINX_DPDMA_ALIGN_BYTES 256
#define XILINX_DPDMA_NUM_CHAN 6
#define XILINX_DPDMA_PAGE_MASK ((1 << 12) - 1)
#define XILINX_DPDMA_PAGE_SHIFT 12
/**
* struct xilinx_dpdma_hw_desc - DPDMA hardware descriptor
* @control: control configuration field
* @desc_id: descriptor ID
* @xfer_size: transfer size
* @hsize_stride: horizontal size and stride
* @timestamp_lsb: LSB of time stamp
* @timestamp_msb: MSB of time stamp
* @addr_ext: upper 16 bit of 48 bit address (next_desc and src_addr)
* @next_desc: next descriptor 32 bit address
* @src_addr: payload source address (lower 32 bit of 1st 4KB page)
* @addr_ext_23: upper 16 bit of 48 bit address (src_addr2 and src_addr3)
* @addr_ext_45: upper 16 bit of 48 bit address (src_addr4 and src_addr5)
* @src_addr2: payload source address (lower 32 bit of 2nd 4KB page)
* @src_addr3: payload source address (lower 32 bit of 3rd 4KB page)
* @src_addr4: payload source address (lower 32 bit of 4th 4KB page)
* @src_addr5: payload source address (lower 32 bit of 5th 4KB page)
* @crc: descriptor CRC
*/
struct xilinx_dpdma_hw_desc {
u32 control;
u32 desc_id;
u32 xfer_size;
u32 hsize_stride;
u32 timestamp_lsb;
u32 timestamp_msb;
u32 addr_ext;
u32 next_desc;
u32 src_addr;
u32 addr_ext_23;
u32 addr_ext_45;
u32 src_addr2;
u32 src_addr3;
u32 src_addr4;
u32 src_addr5;
u32 crc;
} __aligned(XILINX_DPDMA_ALIGN_BYTES);
/**
* struct xilinx_dpdma_sw_desc - DPDMA software descriptor
* @hw: DPDMA hardware descriptor
* @node: list node for software descriptors
* @phys: physical address of the software descriptor
*/
struct xilinx_dpdma_sw_desc {
struct xilinx_dpdma_hw_desc hw;
struct list_head node;
dma_addr_t phys;
};
/**
* enum xilinx_dpdma_tx_desc_status - DPDMA tx descriptor status
* @PREPARED: descriptor is prepared for transaction
* @ACTIVE: transaction is (being) done successfully
* @ERRORED: descriptor generates some errors
*/
enum xilinx_dpdma_tx_desc_status {
PREPARED,
ACTIVE,
ERRORED
};
/**
* struct xilinx_dpdma_tx_desc - DPDMA transaction descriptor
* @async_tx: DMA async transaction descriptor
* @descriptors: list of software descriptors
* @node: list node for transaction descriptors
* @status: tx descriptor status
* @done_cnt: number of complete notification to deliver
*/
struct xilinx_dpdma_tx_desc {
struct dma_async_tx_descriptor async_tx;
struct list_head descriptors;
struct list_head node;
enum xilinx_dpdma_tx_desc_status status;
unsigned int done_cnt;
};
/**
* enum xilinx_dpdma_chan_id - DPDMA channel ID
* @VIDEO0: video 1st channel
* @VIDEO1: video 2nd channel for multi plane yuv formats
*
评论3
最新资源