1 /* 2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <common/debug.h> 9 #include <drivers/delay_timer.h> 10 #include <errno.h> 11 #include <gpcdma.h> 12 #include <lib/mmio.h> 13 #include <lib/utils_def.h> 14 #include <platform_def.h> 15 #include <stdbool.h> 16 #include <tegra_def.h> 17 18 /* DMA channel registers */ 19 #define DMA_CH_CSR U(0x0) 20 #define DMA_CH_CSR_WEIGHT_SHIFT U(10) 21 #define DMA_CH_CSR_XFER_MODE_SHIFT U(21) 22 #define DMA_CH_CSR_DMA_MODE_MEM2MEM U(4) 23 #define DMA_CH_CSR_DMA_MODE_FIXEDPATTERN U(6) 24 #define DMA_CH_CSR_IRQ_MASK_ENABLE (U(1) << 15) 25 #define DMA_CH_CSR_RUN_ONCE (U(1) << 27) 26 #define DMA_CH_CSR_ENABLE (U(1) << 31) 27 28 #define DMA_CH_STAT U(0x4) 29 #define DMA_CH_STAT_BUSY (U(1) << 31) 30 31 #define DMA_CH_SRC_PTR U(0xC) 32 33 #define DMA_CH_DST_PTR U(0x10) 34 35 #define DMA_CH_HI_ADR_PTR U(0x14) 36 #define DMA_CH_HI_ADR_PTR_SRC_MASK U(0xFF) 37 #define DMA_CH_HI_ADR_PTR_DST_SHIFT U(16) 38 #define DMA_CH_HI_ADR_PTR_DST_MASK U(0xFF) 39 40 #define DMA_CH_MC_SEQ U(0x18) 41 #define DMA_CH_MC_SEQ_REQ_CNT_SHIFT U(25) 42 #define DMA_CH_MC_SEQ_REQ_CNT_VAL U(0x10) 43 #define DMA_CH_MC_SEQ_BURST_SHIFT U(23) 44 #define DMA_CH_MC_SEQ_BURST_16_WORDS U(0x3) 45 46 #define DMA_CH_WORD_COUNT U(0x20) 47 #define DMA_CH_FIXED_PATTERN U(0x34) 48 #define DMA_CH_TZ U(0x38) 49 #define DMA_CH_TZ_ACCESS_ENABLE U(0) 50 #define DMA_CH_TZ_ACCESS_DISABLE U(3) 51 52 #define MAX_TRANSFER_SIZE (1U*1024U*1024U*1024U) /* 1GB */ 53 #define GPCDMA_TIMEOUT_MS U(100) 54 #define GPCDMA_RESET_BIT (U(1) << 1) 55 56 static bool init_done; 57 58 static void tegra_gpcdma_write32(uint32_t offset, uint32_t val) 59 { 60 mmio_write_32(TEGRA_GPCDMA_BASE + offset, val); 61 } 62 63 static uint32_t tegra_gpcdma_read32(uint32_t offset) 64 { 65 return mmio_read_32(TEGRA_GPCDMA_BASE + offset); 66 } 67 68 static void tegra_gpcdma_init(void) 69 { 70 /* assert reset for DMA engine */ 71 mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPCDMA_RST_SET_REG_OFFSET, 72 GPCDMA_RESET_BIT); 73 74 udelay(2); 75 76 /* de-assert reset for DMA engine */ 77 mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPCDMA_RST_CLR_REG_OFFSET, 78 GPCDMA_RESET_BIT); 79 } 80 81 static void tegra_gpcdma_memcpy_priv(uint64_t dst_addr, uint64_t src_addr, 82 uint32_t num_bytes, uint32_t mode) 83 { 84 uint32_t val, timeout = 0; 85 int32_t ret = 0; 86 87 /* sanity check byte count */ 88 if ((num_bytes > MAX_TRANSFER_SIZE) || ((num_bytes & 0x3U) != U(0))) { 89 ret = -EINVAL; 90 } 91 92 /* initialise GPCDMA block */ 93 if (!init_done) { 94 tegra_gpcdma_init(); 95 init_done = true; 96 } 97 98 /* make sure channel isn't busy */ 99 val = tegra_gpcdma_read32(DMA_CH_STAT); 100 if ((val & DMA_CH_STAT_BUSY) == DMA_CH_STAT_BUSY) { 101 ERROR("DMA channel is busy\n"); 102 ret = -EBUSY; 103 } 104 105 if (ret == 0) { 106 107 /* disable any DMA transfers */ 108 tegra_gpcdma_write32(DMA_CH_CSR, 0); 109 110 /* enable DMA access to TZDRAM */ 111 tegra_gpcdma_write32(DMA_CH_TZ, DMA_CH_TZ_ACCESS_ENABLE); 112 113 /* configure MC sequencer */ 114 val = (DMA_CH_MC_SEQ_REQ_CNT_VAL << DMA_CH_MC_SEQ_REQ_CNT_SHIFT) | 115 (DMA_CH_MC_SEQ_BURST_16_WORDS << DMA_CH_MC_SEQ_BURST_SHIFT); 116 tegra_gpcdma_write32(DMA_CH_MC_SEQ, val); 117 118 /* reset fixed pattern */ 119 tegra_gpcdma_write32(DMA_CH_FIXED_PATTERN, 0); 120 121 /* populate src and dst address registers */ 122 tegra_gpcdma_write32(DMA_CH_SRC_PTR, (uint32_t)src_addr); 123 tegra_gpcdma_write32(DMA_CH_DST_PTR, (uint32_t)dst_addr); 124 125 val = (uint32_t)((src_addr >> 32) & DMA_CH_HI_ADR_PTR_SRC_MASK); 126 val |= (uint32_t)(((dst_addr >> 32) & DMA_CH_HI_ADR_PTR_DST_MASK) << 127 DMA_CH_HI_ADR_PTR_DST_SHIFT); 128 tegra_gpcdma_write32(DMA_CH_HI_ADR_PTR, val); 129 130 /* transfer size (in words) */ 131 tegra_gpcdma_write32(DMA_CH_WORD_COUNT, ((num_bytes >> 2) - 1U)); 132 133 /* populate value for CSR */ 134 val = (mode << DMA_CH_CSR_XFER_MODE_SHIFT) | 135 DMA_CH_CSR_RUN_ONCE | (U(1) << DMA_CH_CSR_WEIGHT_SHIFT) | 136 DMA_CH_CSR_IRQ_MASK_ENABLE; 137 tegra_gpcdma_write32(DMA_CH_CSR, val); 138 139 /* enable transfer */ 140 val = tegra_gpcdma_read32(DMA_CH_CSR); 141 val |= DMA_CH_CSR_ENABLE; 142 tegra_gpcdma_write32(DMA_CH_CSR, val); 143 144 /* wait till transfer completes */ 145 do { 146 147 /* read the status */ 148 val = tegra_gpcdma_read32(DMA_CH_STAT); 149 if ((val & DMA_CH_STAT_BUSY) != DMA_CH_STAT_BUSY) { 150 break; 151 } 152 153 mdelay(1); 154 timeout++; 155 156 } while (timeout < GPCDMA_TIMEOUT_MS); 157 158 /* flag timeout error */ 159 if (timeout == GPCDMA_TIMEOUT_MS) { 160 ERROR("DMA transfer timed out\n"); 161 } 162 163 dsbsy(); 164 165 /* disable DMA access to TZDRAM */ 166 tegra_gpcdma_write32(DMA_CH_TZ, DMA_CH_TZ_ACCESS_DISABLE); 167 isb(); 168 } 169 } 170 171 /******************************************************************************* 172 * Memcpy using GPCDMA block (Mem2Mem copy) 173 ******************************************************************************/ 174 void tegra_gpcdma_memcpy(uint64_t dst_addr, uint64_t src_addr, 175 uint32_t num_bytes) 176 { 177 tegra_gpcdma_memcpy_priv(dst_addr, src_addr, num_bytes, 178 DMA_CH_CSR_DMA_MODE_MEM2MEM); 179 } 180 181 /******************************************************************************* 182 * Memset using GPCDMA block (Fixed pattern write) 183 ******************************************************************************/ 184 void tegra_gpcdma_zeromem(uint64_t dst_addr, uint32_t num_bytes) 185 { 186 tegra_gpcdma_memcpy_priv(dst_addr, 0, num_bytes, 187 DMA_CH_CSR_DMA_MODE_FIXEDPATTERN); 188 } 189