]>
Commit | Line | Data |
---|---|---|
01c7714a JRO |
1 | // SPDX-License-Identifier: MIT |
2 | /* | |
3 | * Copyright(c) 2015 - 2020 Xilinx, Inc. | |
4 | * | |
5 | * Jorge Ramirez-Ortiz <jorge@foundries.io> | |
6 | */ | |
7 | ||
d678a59d | 8 | #include <common.h> |
01c7714a JRO |
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 | ||
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 | ||
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 | ||
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 | } |