Add Broadcom / Netgear changes from RAXE 1.0.0.48
[project/bcm63xx/u-boot.git] / arch / arm / mach-bcmbca / ddrinit_dpfe.c
1 /* SPDX-License-Identifier: GPL-2.0+
2 *
3 * Copyright 2019 Broadcom Ltd.
4 */
5
6 #include <common.h>
7 #include <asm/arch/ddr.h>
8
9 #include "spl_ddrinit.h"
10 #include "ddrinit_dpfe.h"
11 #include "boot_blob.h"
12 #include "tpl_params.h"
13
14 typedef int (*load_dpfe_seg_fun)(dpfe_seg_param* param);
15
16 /*
17 This is a stub function for jtag load.
18 cmm script will have a breakpoint, stop here and load the next stage of the dpfe
19 */
20 static int load_dpfe_segment_stub(dpfe_seg_param* param)
21 {
22 static int last_seg=0;
23
24 /* cmm script sets this to 1 when it reaches the last stage of dpfe */
25 return last_seg;
26 }
27 static int load_dpfe_segment(dpfe_seg_param* param)
28 {
29 int last_seg = -1, rc;
30 int size = param->buf_size;
31 uint32_t magic = BP_DDR_IS_DDR4(param->mcb_sel) ? DPFE_DDR4_TABLE_MAGIC|param->seg_id : DPFE_DDR3_TABLE_MAGIC|param->seg_id;
32
33 if (param->seg_buf && param->buf_size) {
34 rc = load_boot_blob(magic, param->seg_id, param->seg_buf, &size);
35 if (rc == BOOT_BLOB_NOT_IN_HASTTBL) { /* seg id not in has table. try with last seg id flag */
36 size = param->buf_size;
37 rc = load_boot_blob(magic|0x80, param->seg_id|0x80, param->seg_buf, &size);
38 if (rc == BOOT_BLOB_SUCCESS)
39 last_seg = 1;
40 else
41 last_seg = rc;
42 } else
43 last_seg = rc;
44 }
45 debug("load_dpfe_segment %d return %d\n", param->seg_id, last_seg);
46 return last_seg;
47 }
48
49
50 /* return 1 if there is alias, 0 no alias. memsize in MB */
51 static int memc_alias_test(uint32_t memsize)
52 {
53 volatile uint32_t *base_addr;
54 volatile uint32_t *test_addr;
55 uint64_t test_size, total_size;
56 #ifdef CONFIG_BCMBCA_IKOS
57 uint32_t data;
58 #endif
59 int ret = 0;
60
61 total_size = ((uint64_t) (memsize)) << 20;
62 base_addr = (volatile uint32_t *)((uintptr_t) CONFIG_SYS_SDRAM_BASE);
63
64 for (test_size = 256; test_size < total_size;
65 test_size = test_size << 1) {
66 test_addr =
67 (volatile uint32_t *)((uintptr_t) base_addr +
68 (uintptr_t) test_size);
69 #if defined(PHYS_SDRAM_2)
70 /* if we are over the lower memory region from 0 to 2GB, we shift to the upper memory region */
71 if (test_size >= PHYS_SDRAM_1_SIZE)
72 test_addr =
73 (volatile uint32_t *)((uintptr_t) test_addr +
74 PHYS_SDRAM_1_SIZE);
75 #endif
76 #ifdef CONFIG_BCMBCA_IKOS
77 data = *test_addr;
78 #endif
79 *base_addr = 0;
80 *test_addr = 0xaa55beef;
81 if (*base_addr == *test_addr) {
82 printf("alias detected at 0x%p\n", test_addr);
83 ret = 1;
84 break;
85 }
86 /* check base addr and make sure it does not get overriden */
87 if (*base_addr != 0x0) {
88 printf("alias test at 0x%p corrupted base 0x%x 0x%x\n",
89 test_addr, *base_addr, *test_addr);
90 ret = 1;
91 break;
92 }
93 #ifdef CONFIG_BCMBCA_IKOS
94 *test_addr = data;
95 #endif
96 }
97
98 return ret;
99 }
100
101 static int memory_test_range(uint32_t *addr, uint32_t size)
102 {
103 uint32_t *temp;
104 int i, ret = 0;
105 uint32_t data;
106
107 for (temp = addr, i = 0; i < size/sizeof(uint32_t); i++)
108 *temp++ = i;
109
110 for (temp = addr, i = 0; i < size/sizeof(uint32_t); i++) {
111 data = *temp++;
112 if (data != i)
113 break;
114 }
115
116 if (i != size/sizeof(uint32_t)) {
117 printf("DDR test failed at 0x%p\n\r", addr+i);
118 ret = -1;
119 }
120
121 return ret;
122 }
123
124 /* return 1 if there is error, 0 no error. memsize in MB */
125 static int memc_memory_test(uint32_t memsize)
126 {
127 uint32_t *addr;
128 int ret = 0;
129 uint64_t total_size;
130
131 total_size = ((uint64_t) (memsize)) << 20;
132
133 addr = (uint32_t *)CONFIG_SYS_SDRAM_BASE;
134 ret = memory_test_range(addr, SZ_4K);
135 #if defined(PHYS_SDRAM_2)
136 if (total_size > PHYS_SDRAM_1_SIZE) {
137 addr = (uint32_t *)PHYS_SDRAM_2;
138 total_size -= PHYS_SDRAM_1_SIZE;
139 while ((int64_t)total_size) {
140 ret |= memory_test_range(addr, SZ_4K);
141 total_size -= SZ_1G;
142 addr = (uint32_t*)((uint64_t)addr + SZ_1G);
143 }
144 }
145 #endif
146 if (!ret)
147 printf("DDR test done successfully\n\r");
148 else {
149 ret = -2;
150 }
151
152 return ret;
153 }
154
155
156 int ddr_init_dpfe(ddr_init_param * ddrinit_params)
157 {
158 uint32_t ret, memcfg, ddr_size;
159 int is_safemode;
160 uint8_t *seg_buf = NULL;
161 int seg_id, last_seg;
162 dpfe_seg_param seg_params;
163 dpfe_param dpfe_params;
164 dpfe_func run_dpfe;
165 load_dpfe_seg_fun load_dpfe_segment_p=load_dpfe_segment;
166
167
168 if (IS_JTAG_LOADED(boot_params))
169 {
170 load_dpfe_segment_p=load_dpfe_segment_stub;
171 }
172
173 is_safemode = ddrinit_params->safe_mode;
174 memcfg = ddrinit_params->mcb_sel;
175
176 seg_buf = (void *)ddrinit_params->dpfe_segbuf;
177 run_dpfe = (dpfe_func)ddrinit_params->dpfe_stdalone;
178
179 dpfe_params.mcb = (uint32_t *) ddrinit_params->mcb;
180 #ifdef CONFIG_BCMBCA_DDRC_SCRAMBLER
181 dpfe_params.seed = ddrinit_params->seed;
182 #endif
183 dpfe_params.ddr_size = &ddr_size;
184 dpfe_params.seg_param = &seg_params;
185 dpfe_params.dpfe_option = 0;
186
187 if (is_safemode)
188 dpfe_params.dpfe_option |= DPFE_OPTION_SAFEMODE;
189
190 seg_id = last_seg = 0;
191 dpfe_params.dpfe_option |= DPFE_OPTION_SEG_FIRST;
192
193 seg_params.seg_buf = seg_buf;
194 seg_params.mcb_sel = memcfg;
195 seg_params.buf_size = CONFIG_DPFE_SEGSIZE;;
196
197 while (!last_seg) {
198 seg_params.seg_id = seg_id;
199 last_seg = load_dpfe_segment_p(&seg_params);
200 if (last_seg < 0) {
201 printf("failed to load dpfe segment %d!\n\r", seg_id);
202 return -1;
203 }
204 if (last_seg)
205 dpfe_params.dpfe_option |= DPFE_OPTION_SEG_LAST;
206
207 ret = run_dpfe(&dpfe_params);
208 if (ret < 0) {
209 return -1;
210 }
211
212 if (ret > 0) {
213 printf("shmoo finish early at segment %d!\n\r", seg_id);
214 break;
215 }
216
217 dpfe_params.dpfe_option &= ~DPFE_OPTION_SEG_MASK;
218 seg_id++;
219 }
220
221 /* make sure configure register write are really carried over to target block */
222 __asm__ __volatile__("dsb sy");
223 __asm__ __volatile__("isb");
224
225 /* get the ddr size in mega bytes */
226 if (ddrinit_params->ddr_size != NULL)
227 *ddrinit_params->ddr_size = ddr_size;
228
229
230 /* Make sure it is configured size is not larger the actual size */
231 if (is_safemode == 0) {
232 if (memc_alias_test(ddr_size)) {
233 printf
234 ("\nMemory alias detected. Probably wrong memory size is specified or memory subsystem not working\n");
235 return -3;
236 }
237 }
238
239 if ((ret = memc_memory_test(ddr_size)))
240 return ret;
241
242 return ret;
243 }