1 /* SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2019 Broadcom Ltd.
7 #include <asm/arch/ddr.h>
9 #include "spl_ddrinit.h"
10 #include "ddrinit_dpfe.h"
11 #include "boot_blob.h"
12 #include "tpl_params.h"
14 typedef int (*load_dpfe_seg_fun
)(dpfe_seg_param
* param
);
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
20 static int load_dpfe_segment_stub(dpfe_seg_param
* param
)
22 static int last_seg
=0;
24 /* cmm script sets this to 1 when it reaches the last stage of dpfe */
27 static int load_dpfe_segment(dpfe_seg_param
* param
)
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
;
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
)
45 debug("load_dpfe_segment %d return %d\n", param
->seg_id
, last_seg
);
50 /* return 1 if there is alias, 0 no alias. memsize in MB */
51 static int memc_alias_test(uint32_t memsize
)
53 volatile uint32_t *base_addr
;
54 volatile uint32_t *test_addr
;
55 uint64_t test_size
, total_size
;
56 #ifdef CONFIG_BCMBCA_IKOS
61 total_size
= ((uint64_t) (memsize
)) << 20;
62 base_addr
= (volatile uint32_t *)((uintptr_t) CONFIG_SYS_SDRAM_BASE
);
64 for (test_size
= 256; test_size
< total_size
;
65 test_size
= test_size
<< 1) {
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
)
73 (volatile uint32_t *)((uintptr_t) test_addr
+
76 #ifdef CONFIG_BCMBCA_IKOS
80 *test_addr
= 0xaa55beef;
81 if (*base_addr
== *test_addr
) {
82 printf("alias detected at 0x%p\n", test_addr
);
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
);
93 #ifdef CONFIG_BCMBCA_IKOS
101 static int memory_test_range(uint32_t *addr
, uint32_t size
)
107 for (temp
= addr
, i
= 0; i
< size
/sizeof(uint32_t); i
++)
110 for (temp
= addr
, i
= 0; i
< size
/sizeof(uint32_t); i
++) {
116 if (i
!= size
/sizeof(uint32_t)) {
117 printf("DDR test failed at 0x%p\n\r", addr
+i
);
124 /* return 1 if there is error, 0 no error. memsize in MB */
125 static int memc_memory_test(uint32_t memsize
)
131 total_size
= ((uint64_t) (memsize
)) << 20;
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
);
142 addr
= (uint32_t*)((uint64_t)addr
+ SZ_1G
);
147 printf("DDR test done successfully\n\r");
156 int ddr_init_dpfe(ddr_init_param
* ddrinit_params
)
158 uint32_t ret
, memcfg
, ddr_size
;
160 uint8_t *seg_buf
= NULL
;
161 int seg_id
, last_seg
;
162 dpfe_seg_param seg_params
;
163 dpfe_param dpfe_params
;
165 load_dpfe_seg_fun load_dpfe_segment_p
=load_dpfe_segment
;
168 if (IS_JTAG_LOADED(boot_params
))
170 load_dpfe_segment_p
=load_dpfe_segment_stub
;
173 is_safemode
= ddrinit_params
->safe_mode
;
174 memcfg
= ddrinit_params
->mcb_sel
;
176 seg_buf
= (void *)ddrinit_params
->dpfe_segbuf
;
177 run_dpfe
= (dpfe_func
)ddrinit_params
->dpfe_stdalone
;
179 dpfe_params
.mcb
= (uint32_t *) ddrinit_params
->mcb
;
180 #ifdef CONFIG_BCMBCA_DDRC_SCRAMBLER
181 dpfe_params
.seed
= ddrinit_params
->seed
;
183 dpfe_params
.ddr_size
= &ddr_size
;
184 dpfe_params
.seg_param
= &seg_params
;
185 dpfe_params
.dpfe_option
= 0;
188 dpfe_params
.dpfe_option
|= DPFE_OPTION_SAFEMODE
;
190 seg_id
= last_seg
= 0;
191 dpfe_params
.dpfe_option
|= DPFE_OPTION_SEG_FIRST
;
193 seg_params
.seg_buf
= seg_buf
;
194 seg_params
.mcb_sel
= memcfg
;
195 seg_params
.buf_size
= CONFIG_DPFE_SEGSIZE
;;
198 seg_params
.seg_id
= seg_id
;
199 last_seg
= load_dpfe_segment_p(&seg_params
);
201 printf("failed to load dpfe segment %d!\n\r", seg_id
);
205 dpfe_params
.dpfe_option
|= DPFE_OPTION_SEG_LAST
;
207 ret
= run_dpfe(&dpfe_params
);
213 printf("shmoo finish early at segment %d!\n\r", seg_id
);
217 dpfe_params
.dpfe_option
&= ~DPFE_OPTION_SEG_MASK
;
221 /* make sure configure register write are really carried over to target block */
222 __asm__
__volatile__("dsb sy");
223 __asm__
__volatile__("isb");
225 /* get the ddr size in mega bytes */
226 if (ddrinit_params
->ddr_size
!= NULL
)
227 *ddrinit_params
->ddr_size
= ddr_size
;
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
)) {
234 ("\nMemory alias detected. Probably wrong memory size is specified or memory subsystem not working\n");
239 if ((ret
= memc_memory_test(ddr_size
)))