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