1// SPDX-License-Identifier: MIT 2/* 3 * Copyright(c) 2015 - 2020 Xilinx, Inc. 4 * 5 * Jorge Ramirez-Ortiz <jorge@foundries.io> 6 */ 7 8#include <common.h> 9#include <cpu_func.h> 10#include <asm/arch/hardware.h> 11#include <asm/arch/ecc_spl_init.h> 12#include <asm/io.h> 13#include <linux/delay.h> 14 15#define ZDMA_TRANSFER_MAX_LEN (0x3FFFFFFFU - 7U) 16#define ZDMA_CH_STATUS ((ADMA_CH0_BASEADDR) + 0x0000011CU) 17#define ZDMA_CH_STATUS_STATE_MASK 0x00000003U 18#define ZDMA_CH_STATUS_STATE_DONE 0x00000000U 19#define ZDMA_CH_STATUS_STATE_ERR 0x00000003U 20#define ZDMA_CH_CTRL0 ((ADMA_CH0_BASEADDR) + 0x00000110U) 21#define ZDMA_CH_CTRL0_POINT_TYPE_MASK (u32)0x00000040U 22#define ZDMA_CH_CTRL0_POINT_TYPE_NORMAL (u32)0x00000000U 23#define ZDMA_CH_CTRL0_MODE_MASK (u32)0x00000030U 24#define ZDMA_CH_CTRL0_MODE_WR_ONLY (u32)0x00000010U 25#define ZDMA_CH_CTRL0_TOTAL_BYTE_COUNT ((ADMA_CH0_BASEADDR) + 0x00000188U) 26#define ZDMA_CH_WR_ONLY_WORD0 ((ADMA_CH0_BASEADDR) + 0x00000148U) 27#define ZDMA_CH_WR_ONLY_WORD1 ((ADMA_CH0_BASEADDR) + 0x0000014CU) 28#define ZDMA_CH_WR_ONLY_WORD2 ((ADMA_CH0_BASEADDR) + 0x00000150U) 29#define ZDMA_CH_WR_ONLY_WORD3 ((ADMA_CH0_BASEADDR) + 0x00000154U) 30#define ZDMA_CH_DST_DSCR_WORD0 ((ADMA_CH0_BASEADDR) + 0x00000138U) 31#define ZDMA_CH_DST_DSCR_WORD0_LSB_MASK 0xFFFFFFFFU 32#define ZDMA_CH_DST_DSCR_WORD1 ((ADMA_CH0_BASEADDR) + 0x0000013CU) 33#define ZDMA_CH_DST_DSCR_WORD1_MSB_MASK 0x0001FFFFU 34#define ZDMA_CH_SRC_DSCR_WORD2 ((ADMA_CH0_BASEADDR) + 0x00000130U) 35#define ZDMA_CH_DST_DSCR_WORD2 ((ADMA_CH0_BASEADDR) + 0x00000140U) 36#define ZDMA_CH_CTRL2 ((ADMA_CH0_BASEADDR) + 0x00000200U) 37#define ZDMA_CH_CTRL2_EN_MASK 0x00000001U 38#define ZDMA_CH_ISR ((ADMA_CH0_BASEADDR) + 0x00000100U) 39#define ZDMA_CH_ISR_DMA_DONE_MASK 0x00000400U 40#define ECC_INIT_VAL_WORD 0xDEADBEEFU 41 42#define ZDMA_IDLE_TIMEOUT_USEC 1000000 43#define ZDMA_DONE_TIMEOUT_USEC 5000000 44 45static void ecc_zdma_restore(void) 46{ 47 /* Restore reset values for the DMA registers used */ 48 writel(ZDMA_CH_CTRL0, 0x00000080U); 49 writel(ZDMA_CH_WR_ONLY_WORD0, 0x00000000U); 50 writel(ZDMA_CH_WR_ONLY_WORD1, 0x00000000U); 51 writel(ZDMA_CH_WR_ONLY_WORD2, 0x00000000U); 52 writel(ZDMA_CH_WR_ONLY_WORD3, 0x00000000U); 53 writel(ZDMA_CH_DST_DSCR_WORD0, 0x00000000U); 54 writel(ZDMA_CH_DST_DSCR_WORD1, 0x00000000U); 55 writel(ZDMA_CH_SRC_DSCR_WORD2, 0x00000000U); 56 writel(ZDMA_CH_DST_DSCR_WORD2, 0x00000000U); 57 writel(ZDMA_CH_CTRL0_TOTAL_BYTE_COUNT, 0x00000000U); 58} 59 60static void ecc_dram_bank_init(u64 addr, u64 len) 61{ 62 bool retry = true; 63 u32 timeout; 64 u64 bytes; 65 u32 size; 66 u64 src; 67 u32 reg; 68 69 if (!len) 70 return; 71retry: 72 bytes = len; 73 src = addr; 74 ecc_zdma_restore(); 75 while (bytes > 0) { 76 size = bytes > ZDMA_TRANSFER_MAX_LEN ? 77 ZDMA_TRANSFER_MAX_LEN : (u32)bytes; 78 79 /* Wait until the DMA is in idle state */ 80 timeout = ZDMA_IDLE_TIMEOUT_USEC; 81 do { 82 udelay(1); 83 reg = readl(ZDMA_CH_STATUS); 84 reg &= ZDMA_CH_STATUS_STATE_MASK; 85 if (!timeout--) { 86 puts("error, ECC DMA failed to idle\n"); 87 goto done; 88 } 89 90 } while ((reg != ZDMA_CH_STATUS_STATE_DONE) && 91 (reg != ZDMA_CH_STATUS_STATE_ERR)); 92 93 /* Enable Simple (Write Only) Mode */ 94 reg = readl(ZDMA_CH_CTRL0); 95 reg &= (ZDMA_CH_CTRL0_POINT_TYPE_MASK | 96 ZDMA_CH_CTRL0_MODE_MASK); 97 reg |= (ZDMA_CH_CTRL0_POINT_TYPE_NORMAL | 98 ZDMA_CH_CTRL0_MODE_WR_ONLY); 99 writel(reg, ZDMA_CH_CTRL0); 100 101 /* Fill in the data to be written */ 102 writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD0); 103 writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD1); 104 writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD2); 105 writel(ECC_INIT_VAL_WORD, ZDMA_CH_WR_ONLY_WORD3); 106 107 /* Write Destination Address */ 108 writel((u32)(src & ZDMA_CH_DST_DSCR_WORD0_LSB_MASK), 109 ZDMA_CH_DST_DSCR_WORD0); 110 writel((u32)((src >> 32) & ZDMA_CH_DST_DSCR_WORD1_MSB_MASK), 111 ZDMA_CH_DST_DSCR_WORD1); 112 113 /* Size to be Transferred. Recommended to set both src and dest sizes */ 114 writel(size, ZDMA_CH_SRC_DSCR_WORD2); 115 writel(size, ZDMA_CH_DST_DSCR_WORD2); 116 117 /* DMA Enable */ 118 reg = readl(ZDMA_CH_CTRL2); 119 reg |= ZDMA_CH_CTRL2_EN_MASK; 120 writel(reg, ZDMA_CH_CTRL2); 121 122 /* Check the status of the transfer by polling on DMA Done */ 123 timeout = ZDMA_DONE_TIMEOUT_USEC; 124 do { 125 udelay(1); 126 reg = readl(ZDMA_CH_ISR); 127 reg &= ZDMA_CH_ISR_DMA_DONE_MASK; 128 if (!timeout--) { 129 puts("error, ECC DMA timeout\n"); 130 goto done; 131 } 132 } while (reg != ZDMA_CH_ISR_DMA_DONE_MASK); 133 134 /* Clear DMA status */ 135 reg = readl(ZDMA_CH_ISR); 136 reg |= ZDMA_CH_ISR_DMA_DONE_MASK; 137 writel(ZDMA_CH_ISR_DMA_DONE_MASK, ZDMA_CH_ISR); 138 139 /* Read the channel status for errors */ 140 reg = readl(ZDMA_CH_STATUS); 141 if (reg == ZDMA_CH_STATUS_STATE_ERR) { 142 if (retry) { 143 retry = false; 144 goto retry; 145 } 146 puts("error, ECC DMA error\n"); 147 break; 148 } 149 150 bytes -= size; 151 src += size; 152 } 153done: 154 ecc_zdma_restore(); 155} 156 157void zynqmp_ecc_init(void) 158{ 159 ecc_dram_bank_init(CONFIG_SPL_ZYNQMP_DRAM_BANK1_BASE, 160 CONFIG_SPL_ZYNQMP_DRAM_BANK1_LEN); 161 ecc_dram_bank_init(CONFIG_SPL_ZYNQMP_DRAM_BANK2_BASE, 162 CONFIG_SPL_ZYNQMP_DRAM_BANK2_LEN); 163} 164