/*
* Copyright (C) 2017 Spreadtrum Communications Inc.
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/dma/sprd-dma.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_dma.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "virt-dma.h"
#define SPRD_DMA_CHN_REG_OFFSET 0x1000
#define SPRD_DMA_CHN_REG_LENGTH 0x40
#define SPRD_DMA_MEMCPY_MIN_SIZE 64
/* DMA global registers definition */
#define SPRD_DMA_GLB_PAUSE 0x0
#define SPRD_DMA_GLB_FRAG_WAIT 0x4
#define SPRD_DMA_GLB_REQ_PEND0_EN 0x8
#define SPRD_DMA_GLB_REQ_PEND1_EN 0xc
#define SPRD_DMA_GLB_INT_RAW_STS 0x10
#define SPRD_DMA_GLB_INT_MSK_STS 0x14
#define SPRD_DMA_GLB_REQ_STS 0x18
#define SPRD_DMA_GLB_CHN_EN_STS 0x1c
#define SPRD_DMA_GLB_DEBUG_STS 0x20
#define SPRD_DMA_GLB_ARB_SEL_STS 0x24
#define SPRD_DMA_GLB_2STAGE_GRP1 0x28
#define SPRD_DMA_GLB_2STAGE_GRP2 0x2c
#define SPRD_DMA_GLB_REQ_UID(uid) (0x4 * ((uid) - 1))
#define SPRD_DMA_GLB_REQ_UID_OFFSET 0x2000
/* DMA channel registers definition */
#define SPRD_DMA_CHN_PAUSE 0x0
#define SPRD_DMA_CHN_REQ 0x4
#define SPRD_DMA_CHN_CFG 0x8
#define SPRD_DMA_CHN_INTC 0xc
#define SPRD_DMA_CHN_SRC_ADDR 0x10
#define SPRD_DMA_CHN_DES_ADDR 0x14
#define SPRD_DMA_CHN_FRG_LEN 0x18
#define SPRD_DMA_CHN_BLK_LEN 0x1c
#define SPRD_DMA_CHN_TRSC_LEN 0x20
#define SPRD_DMA_CHN_TRSF_STEP 0x24
#define SPRD_DMA_CHN_WARP_PTR 0x28
#define SPRD_DMA_CHN_WARP_TO 0x2c
#define SPRD_DMA_CHN_LLIST_PTR 0x30
#define SPRD_DMA_CHN_FRAG_STEP 0x34
#define SPRD_DMA_CHN_SRC_BLK_STEP 0x38
#define SPRD_DMA_CHN_DES_BLK_STEP 0x3c
/* SPRD_DMA_GLB_2STAGE_GRP register definition */
#define SPRD_DMA_GLB_2STAGE_EN BIT(24)
#define SPRD_DMA_GLB_CHN_INT_MASK GENMASK(23, 20)
#define SPRD_DMA_GLB_DEST_INT BIT(22)
#define SPRD_DMA_GLB_SRC_INT BIT(20)
#define SPRD_DMA_GLB_LIST_DONE_TRG BIT(19)
#define SPRD_DMA_GLB_TRANS_DONE_TRG BIT(18)
#define SPRD_DMA_GLB_BLOCK_DONE_TRG BIT(17)
#define SPRD_DMA_GLB_FRAG_DONE_TRG BIT(16)
#define SPRD_DMA_GLB_TRG_OFFSET 16
#define SPRD_DMA_GLB_DEST_CHN_MASK GENMASK(13, 8)
#define SPRD_DMA_GLB_DEST_CHN_OFFSET 8
#define SPRD_DMA_GLB_SRC_CHN_MASK GENMASK(5, 0)
/* SPRD_DMA_CHN_INTC register definition */
#define SPRD_DMA_INT_MASK GENMASK(4, 0)
#define SPRD_DMA_INT_CLR_OFFSET 24
#define SPRD_DMA_FRAG_INT_EN BIT(0)
#define SPRD_DMA_BLK_INT_EN BIT(1)
#define SPRD_DMA_TRANS_INT_EN BIT(2)
#define SPRD_DMA_LIST_INT_EN BIT(3)
#define SPRD_DMA_CFG_ERR_INT_EN BIT(4)
/* SPRD_DMA_CHN_CFG register definition */
#define SPRD_DMA_CHN_EN BIT(0)
#define SPRD_DMA_LINKLIST_EN BIT(4)
#define SPRD_DMA_WAIT_BDONE_OFFSET 24
#define SPRD_DMA_DONOT_WAIT_BDONE 1
/* SPRD_DMA_CHN_REQ register definition */
#define SPRD_DMA_REQ_EN BIT(0)
/* SPRD_DMA_CHN_PAUSE register definition */
#define SPRD_DMA_PAUSE_EN BIT(0)
#define SPRD_DMA_PAUSE_STS BIT(2)
#define SPRD_DMA_PAUSE_CNT 0x2000
/* DMA_CHN_WARP_* register definition */
#define SPRD_DMA_HIGH_ADDR_MASK GENMASK(31, 28)
#define SPRD_DMA_LOW_ADDR_MASK GENMASK(31, 0)
#define SPRD_DMA_WRAP_ADDR_MASK GENMASK(27, 0)
#define SPRD_DMA_HIGH_ADDR_OFFSET 4
/* SPRD_DMA_CHN_INTC register definition */
#define SPRD_DMA_FRAG_INT_STS BIT(16)
#define SPRD_DMA_BLK_INT_STS BIT(17)
#define SPRD_DMA_TRSC_INT_STS BIT(18)
#define SPRD_DMA_LIST_INT_STS BIT(19)
#define SPRD_DMA_CFGERR_INT_STS BIT(20)
#define SPRD_DMA_CHN_INT_STS \
(SPRD_DMA_FRAG_INT_STS | SPRD_DMA_BLK_INT_STS | \
SPRD_DMA_TRSC_INT_STS | SPRD_DMA_LIST_INT_STS | \
SPRD_DMA_CFGERR_INT_STS)
/* SPRD_DMA_CHN_FRG_LEN register definition */
#define SPRD_DMA_SRC_DATAWIDTH_OFFSET 30
#define SPRD_DMA_DES_DATAWIDTH_OFFSET 28
#define SPRD_DMA_SWT_MODE_OFFSET 26
#define SPRD_DMA_REQ_MODE_OFFSET 24
#define SPRD_DMA_REQ_MODE_MASK GENMASK(1, 0)
#define SPRD_DMA_WRAP_SEL_DEST BIT(23)
#define SPRD_DMA_WRAP_EN BIT(22)
#define SPRD_DMA_FIX_SEL_OFFSET 21
#define SPRD_DMA_FIX_EN_OFFSET 20
#define SPRD_DMA_LLIST_END BIT(19)
#define SPRD_DMA_FRG_LEN_MASK GENMASK(16, 0)
/* SPRD_DMA_CHN_BLK_LEN register definition */
#define SPRD_DMA_BLK_LEN_MASK GENMASK(16, 0)
/* SPRD_DMA_CHN_TRSC_LEN register definition */
#define SPRD_DMA_TRSC_LEN_MASK GENMASK(27, 0)
/* SPRD_DMA_CHN_TRSF_STEP register definition */
#define SPRD_DMA_DEST_TRSF_STEP_OFFSET 16
#define SPRD_DMA_SRC_TRSF_STEP_OFFSET 0
#define SPRD_DMA_TRSF_STEP_MASK GENMASK(15, 0)
/* SPRD DMA_SRC_BLK_STEP register definition */
#define SPRD_DMA_LLIST_HIGH_MASK GENMASK(31, 28)
#define SPRD_DMA_LLIST_HIGH_SHIFT 28
/* define DMA channel mode & trigger mode mask */
#define SPRD_DMA_CHN_MODE_MASK GENMASK(7, 0)
#define SPRD_DMA_TRG_MODE_MASK GENMASK(7, 0)
#define SPRD_DMA_INT_TYPE_MASK GENMASK(7, 0)
/* define the DMA transfer step type */
#define SPRD_DMA_NONE_STEP 0
#define SPRD_DMA_BYTE_STEP 1
#define SPRD_DMA_SHORT_STEP 2
#define SPRD_DMA_WORD_STEP 4
#define SPRD_DMA_DWORD_STEP 8
#define SPRD_DMA_SOFTWARE_UID 0
/* dma data width values */
enum sprd_dma_datawidth {
SPRD_DMA_DATAWIDTH_1_BYTE,
SPRD_DMA_DATAWIDTH_2_BYTES,
SPRD_DMA_DATAWIDTH_4_BYTES,
SPRD_DMA_DATAWIDTH_8_BYTES,
};
/* dma channel hardware configuration */
struct sprd_dma_chn_hw {
u32 pause;
u32 req;
u32 cfg;
u32 intc;
u32 src_addr;
u32 des_addr;
u32 frg_len;
u32 blk_len;
u32 trsc_len;
u32 trsf_step;
u32 wrap_ptr;
u32 wrap_to;
u32 llist_ptr;
u32 frg_step;
u32 src_blk_step;
u32 des_blk_step;
};
/* dma request description */
struct sprd_dma_desc {
struct virt_dma_desc vd;
struct sprd_dma_chn_hw chn_hw;
enum dma_transfer_direction dir;
};
/* dma channel description */
struct sprd_dma_chn