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 
ecc_zdma_restore(void)45 static 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 
ecc_dram_bank_init(u64 addr,u64 len)60 static 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;
71 retry:
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 	}
153 done:
154 	ecc_zdma_restore();
155 }
156 
zynqmp_ecc_init(void)157 void 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