1 /* 2 * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdint.h> 8 #include <string.h> 9 10 #include <arch_helpers.h> 11 #include <common/debug.h> 12 #include <lib/mmio.h> 13 14 #include "cpg_registers.h" 15 #include "rcar_def.h" 16 #include "rcar_private.h" 17 18 /* DMA CHANNEL setting (0/16/32) */ 19 #if RCAR_LSI == RCAR_V3M 20 #define DMA_CH 16 21 #else 22 #define DMA_CH 0 23 #endif 24 25 #if (DMA_CH == 0) 26 #define SYS_DMAC_BIT ((uint32_t)1U << 19U) 27 #define DMA_BASE (0xE6700000U) 28 #elif (DMA_CH == 16) 29 #define SYS_DMAC_BIT ((uint32_t)1U << 18U) 30 #define DMA_BASE (0xE7300000U) 31 #elif (DMA_CH == 32) 32 #define SYS_DMAC_BIT ((uint32_t)1U << 17U) 33 #define DMA_BASE (0xE7320000U) 34 #else 35 #define SYS_DMAC_BIT ((uint32_t)1U << 19U) 36 #define DMA_BASE (0xE6700000U) 37 #endif 38 39 /* DMA operation */ 40 #define DMA_DMAOR (DMA_BASE + 0x0060U) 41 /* DMA secure control */ 42 #define DMA_DMASEC (DMA_BASE + 0x0030U) 43 /* DMA channel clear */ 44 #define DMA_DMACHCLR (DMA_BASE + 0x0080U) 45 /* DMA source address */ 46 #define DMA_DMASAR (DMA_BASE + 0x8000U) 47 /* DMA destination address */ 48 #define DMA_DMADAR (DMA_BASE + 0x8004U) 49 /* DMA transfer count */ 50 #define DMA_DMATCR (DMA_BASE + 0x8008U) 51 /* DMA channel control */ 52 #define DMA_DMACHCR (DMA_BASE + 0x800CU) 53 /* DMA fixed destination address */ 54 #define DMA_DMAFIXDAR (DMA_BASE + 0x8014U) 55 56 #define DMA_USE_CHANNEL (0x00000001U) 57 #define DMAOR_INITIAL (0x0301U) 58 #define DMACHCLR_CH_ALL (0x0000FFFFU) 59 #define DMAFIXDAR_32BIT_SHIFT (32U) 60 #define DMAFIXDAR_DAR_MASK (0x000000FFU) 61 #define DMADAR_BOUNDARY_ADDR (0x100000000ULL) 62 #define DMATCR_CNT_SHIFT (6U) 63 #define DMATCR_MAX (0x00FFFFFFU) 64 #define DMACHCR_TRN_MODE (0x00105409U) 65 #define DMACHCR_DE_BIT (0x00000001U) 66 #define DMACHCR_TE_BIT (0x00000002U) 67 #define DMACHCR_CHE_BIT (0x80000000U) 68 69 #define DMA_SIZE_UNIT FLASH_TRANS_SIZE_UNIT 70 #define DMA_FRACTION_MASK (0xFFU) 71 #define DMA_DST_LIMIT (0x10000000000ULL) 72 73 /* transfer length limit */ 74 #define DMA_LENGTH_LIMIT ((DMATCR_MAX * (1U << DMATCR_CNT_SHIFT)) \ 75 & ~DMA_FRACTION_MASK) 76 77 static void dma_enable(void) 78 { 79 mstpcr_write(CPG_SMSTPCR2, CPG_MSTPSR2, SYS_DMAC_BIT); 80 } 81 82 static void dma_setup(void) 83 { 84 mmio_write_16(DMA_DMAOR, 0); 85 mmio_write_32(DMA_DMACHCLR, DMACHCLR_CH_ALL); 86 } 87 88 static void dma_start(uintptr_t dst, uint32_t src, uint32_t len) 89 { 90 mmio_write_16(DMA_DMAOR, DMAOR_INITIAL); 91 mmio_write_32(DMA_DMAFIXDAR, (dst >> DMAFIXDAR_32BIT_SHIFT) & 92 DMAFIXDAR_DAR_MASK); 93 mmio_write_32(DMA_DMADAR, dst & UINT32_MAX); 94 mmio_write_32(DMA_DMASAR, src); 95 mmio_write_32(DMA_DMATCR, len >> DMATCR_CNT_SHIFT); 96 mmio_write_32(DMA_DMASEC, DMA_USE_CHANNEL); 97 mmio_write_32(DMA_DMACHCR, DMACHCR_TRN_MODE); 98 } 99 100 static void dma_end(void) 101 { 102 while ((mmio_read_32(DMA_DMACHCR) & DMACHCR_TE_BIT) == 0) { 103 if ((mmio_read_32(DMA_DMACHCR) & DMACHCR_CHE_BIT) != 0U) { 104 ERROR("BL2: DMA - Channel Address Error\n"); 105 panic(); 106 break; 107 } 108 } 109 /* DMA transfer Disable */ 110 mmio_clrbits_32(DMA_DMACHCR, DMACHCR_DE_BIT); 111 while ((mmio_read_32(DMA_DMACHCR) & DMACHCR_DE_BIT) != 0) 112 ; 113 114 mmio_write_32(DMA_DMASEC, 0); 115 mmio_write_16(DMA_DMAOR, 0); 116 mmio_write_32(DMA_DMACHCLR, DMA_USE_CHANNEL); 117 } 118 119 void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len) 120 { 121 uint32_t dma_len = len; 122 123 if (len & DMA_FRACTION_MASK) 124 dma_len = (len + DMA_SIZE_UNIT) & ~DMA_FRACTION_MASK; 125 126 if (!dma_len || dma_len > DMA_LENGTH_LIMIT) { 127 ERROR("BL2: DMA - size invalid, length (0x%x)\n", dma_len); 128 panic(); 129 } 130 131 if (src & DMA_FRACTION_MASK) { 132 ERROR("BL2: DMA - src address invalid (0x%x), len=(0x%x)\n", 133 src, dma_len); 134 panic(); 135 } 136 137 if ((dst & UINT32_MAX) + dma_len > DMADAR_BOUNDARY_ADDR || 138 (dst + dma_len > DMA_DST_LIMIT) || 139 (dst & DMA_FRACTION_MASK)) { 140 ERROR("BL2: DMA - dest address invalid (0x%lx), len=(0x%x)\n", 141 dst, dma_len); 142 panic(); 143 } 144 145 dma_start(dst, src, dma_len); 146 dma_end(); 147 } 148 149 void rcar_dma_init(void) 150 { 151 dma_enable(); 152 dma_setup(); 153 } 154