blob: bf189b41a3d3cd49753993d840b572e940cd9af6 [file] [log] [blame]
/*
* Copyright 2020 Broadcom
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef DMA_PL330_H
#define DMA_PL330_H
#include <drivers/dma.h>
#define DT_DRV_COMPAT arm_dma_pl330
/*
* Max burst length and max burst size for 32bit system with
* 128bit bus width for memory to memory data transfer
*
* Burst length is encoded in following format for pl330
* b0000 = 1 data transfer
* b0001 = 2 data transfers
* b0010 = 3 data transfers
* .
* .
* b1111 = 16 data transfers
*
* Burst size is encoded in following format for pl330
* b000 = 1 byte
* b001 = 2 bytes
* b010 = 4 bytes
* b011 = 8 bytes
* b100 = 16 bytes
* b101 = 32 bytes
* b110 = 64 bytes
* b111 = 128 bytes.
*/
#define MAX_BURST_LEN 0xf /* 16byte data */
#define MAX_BURST_SIZE_LOG2 4
/*
* PL330 works only on 4GB boundary.
* PL330 has 32bit registers for source and destination addresses
*/
#define PL330_MAX_OFFSET 0x100000000
/* PL330 supports max 16MB dma based on AXI bus size */
#define PL330_MAX_DMA_SIZE 0x1000000
/* Maximum possible values for PL330 ucode loop counters */
#define PL330_LOOP_COUNTER0_MAX 0x100
#define PL330_LOOP_COUNTER1_MAX 0x100
#define MAX_DMA_CHANNELS DT_INST_PROP(0, dma_channels)
#define DMAC_PL330_CS0 0x100
#define DMAC_PL330_DBGSTATUS 0xd00
#define DMAC_PL330_DBGCMD 0xd04
#define DMAC_PL330_DBGINST0 0xd08
#define DMAC_PL330_DBGINST1 0xd0c
/*
* TIMEOUT value of 100000us is kept to cover all possible data
* transfer sizes, with lesser time out value(10us) DMA channel
* appears to be busy on FPGA/Emul environment. Ideally 100000us
* timeout value should never hit.
*/
#define DMA_TIMEOUT_US 100000
#define CH_STATUS_MASK 0xf
#define DATA_MASK 0xf
#define DMA_INTSR1_SHIFT 24
#define DMA_INTSR0_SHIFT 16
#define DMA_INTSR0 0xa0
#define DMA_SECURE_SHIFT 17
#define DMA_CH_SHIFT 8
#define CONTROL_OFFSET 0x4
#define HIGHER_32_ADDR_MASK 0x0f
#define DST_ADDR_SHIFT 0x4
#define MICROCODE_SIZE_MAX 0x400
#define TOTAL_MICROCODE_SIZE (MAX_DMA_CHANNELS * MICROCODE_SIZE_MAX)
#define GET_MAX_DMA_SIZE(byte_width, burst_len) \
(PL330_LOOP_COUNTER0_MAX * PL330_LOOP_COUNTER1_MAX * \
(byte_width) * ((burst_len) + 1))
#define CC_SRCINC_SHIFT 0
#define CC_DSTINC_SHIFT 14
#define CC_SRCPRI_SHIFT 8
#define CC_DSTPRI_SHIFT 22
#define CC_DSTNS_SHIFT 23
#define CC_SRCBRSTLEN_SHIFT 4
#define CC_DSTBRSTLEN_SHIFT 18
#define CC_SRCBRSTSIZE_SHIFT 1
#define CC_DSTBRSTSIZE_SHIFT 15
#define CC_SRCCCTRL_SHIFT 11
#define CC_SRCCCTRL_MASK 0x7
#define CC_DSTCCTRL_SHIFT 25
#define CC_DRCCCTRL_MASK 0x7
#define CC_SWAP_SHIFT 28
#define SRC_PRI_NONSEC_VALUE 0x2
#define SRC_PRI_SEC_VALUE 0x0
#define OP_DMA_MOV 0xbc
#define OP_DMA_LOOP_COUNT1 0x22
#define OP_DMA_LOOP 0x20
#define OP_DMA_LD 0x4
#define OP_DMA_ST 0x8
#define OP_DMA_SEV 0x34
#define OP_DMA_END 0x00
#define OP_DMA_LP_BK_JMP1 0x38
#define OP_DMA_LP_BK_JMP2 0x3c
#define SZ_CMD_DMAMOV 0x6
enum dmamov_type {
/* Source Address Register */
SAR = 0,
/* Channel Control Register */
CCR,
/* Destination Address Register */
DAR,
};
/* Channel specific private data */
struct dma_pl330_ch_internal {
uint64_t src_addr;
uint64_t dst_addr;
int src_burst_sz;
uint32_t src_burst_len;
int dst_burst_sz;
uint32_t dst_burst_len;
uint32_t trans_size;
uint32_t dst_id;
uint32_t src_id;
uint32_t perip_type;
uint32_t breq_only;
uint32_t src_cache_ctrl;
uint32_t dst_cache_ctrl;
uint32_t dst_inc;
uint32_t src_inc;
int nonsec_mode;
};
struct dma_pl330_ch_config {
/* Channel configuration details */
uint64_t src_addr;
enum dma_addr_adj src_addr_adj;
uint64_t dst_addr;
enum dma_addr_adj dst_addr_adj;
enum dma_channel_direction direction;
uint32_t trans_size;
void *user_data;
dma_callback_t dma_callback;
mem_addr_t dma_exec_addr;
struct k_mutex ch_mutex;
int channel_active;
/* Channel specific private data */
struct dma_pl330_ch_internal internal;
};
struct dma_pl330_config {
mem_addr_t mcode_base;
mem_addr_t reg_base;
#ifdef CONFIG_DMA_64BIT
mem_addr_t control_reg_base;
#endif
};
struct dma_pl330_dev_data {
struct dma_pl330_ch_config channels[MAX_DMA_CHANNELS];
};
#endif