1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | /*
* 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
|