1 // SPDX-License-Identifier: GPL-2.0+
11 #include <asm/arch/ddr.h>
12 #include <asm/arch/ddr.h>
13 #include <asm/arch/lpddr4_define.h>
14 #include <asm/sections.h>
16 DECLARE_GLOBAL_DATA_PTR
;
18 #define IMEM_LEN 32768 /* byte */
19 #define DMEM_LEN 16384 /* byte */
20 #define IMEM_2D_OFFSET 49152
22 #define IMEM_OFFSET_ADDR 0x00050000
23 #define DMEM_OFFSET_ADDR 0x00054000
24 #define DDR_TRAIN_CODE_BASE_ADDR IP2APB_DDRPHY_IPS_BASE_ADDR(0)
26 /* We need PHY iMEM PHY is 32KB padded */
27 void ddr_load_train_firmware(enum fw_type type
)
31 unsigned long pr_to32
, pr_from32
;
32 unsigned long fw_offset
= type
? IMEM_2D_OFFSET
: 0;
33 unsigned long imem_start
= (unsigned long)&_end
+ fw_offset
;
34 unsigned long dmem_start
= imem_start
+ IMEM_LEN
;
36 pr_from32
= imem_start
;
37 pr_to32
= DDR_TRAIN_CODE_BASE_ADDR
+ 4 * IMEM_OFFSET_ADDR
;
38 for (i
= 0x0; i
< IMEM_LEN
; ) {
39 tmp32
= readl(pr_from32
);
40 writew(tmp32
& 0x0000ffff, pr_to32
);
42 writew((tmp32
>> 16) & 0x0000ffff, pr_to32
);
48 pr_from32
= dmem_start
;
49 pr_to32
= DDR_TRAIN_CODE_BASE_ADDR
+ 4 * DMEM_OFFSET_ADDR
;
50 for (i
= 0x0; i
< DMEM_LEN
; ) {
51 tmp32
= readl(pr_from32
);
52 writew(tmp32
& 0x0000ffff, pr_to32
);
54 writew((tmp32
>> 16) & 0x0000ffff, pr_to32
);
60 debug("check ddr4_pmu_train_imem code\n");
61 pr_from32
= imem_start
;
62 pr_to32
= DDR_TRAIN_CODE_BASE_ADDR
+ 4 * IMEM_OFFSET_ADDR
;
63 for (i
= 0x0; i
< IMEM_LEN
; ) {
64 tmp32
= (readw(pr_to32
) & 0x0000ffff);
66 tmp32
+= ((readw(pr_to32
) & 0x0000ffff) << 16);
68 if (tmp32
!= readl(pr_from32
)) {
69 debug("%lx %lx\n", pr_from32
, pr_to32
);
77 printf("check ddr4_pmu_train_imem code fail=%d\n", error
);
79 debug("check ddr4_pmu_train_imem code pass\n");
81 debug("check ddr4_pmu_train_dmem code\n");
82 pr_from32
= dmem_start
;
83 pr_to32
= DDR_TRAIN_CODE_BASE_ADDR
+ 4 * DMEM_OFFSET_ADDR
;
84 for (i
= 0x0; i
< DMEM_LEN
;) {
85 tmp32
= (readw(pr_to32
) & 0x0000ffff);
87 tmp32
+= ((readw(pr_to32
) & 0x0000ffff) << 16);
88 if (tmp32
!= readl(pr_from32
)) {
89 debug("%lx %lx\n", pr_from32
, pr_to32
);
98 printf("check ddr4_pmu_train_dmem code fail=%d", error
);
100 debug("check ddr4_pmu_train_dmem code pass\n");
103 void ddrphy_trained_csr_save(struct dram_cfg_param
*ddrphy_csr
,
108 /* enable the ddrphy apb */
109 dwc_ddrphy_apb_wr(0xd0000, 0x0);
110 dwc_ddrphy_apb_wr(0xc0080, 0x3);
111 for (i
= 0; i
< num
; i
++) {
112 ddrphy_csr
->val
= dwc_ddrphy_apb_rd(ddrphy_csr
->reg
);
115 /* disable the ddrphy apb */
116 dwc_ddrphy_apb_wr(0xc0080, 0x2);
117 dwc_ddrphy_apb_wr(0xd0000, 0x1);
120 void dram_config_save(struct dram_timing_info
*timing_info
,
121 unsigned long saved_timing_base
)
124 struct dram_timing_info
*saved_timing
= (struct dram_timing_info
*)saved_timing_base
;
125 struct dram_cfg_param
*cfg
;
127 saved_timing
->ddrc_cfg_num
= timing_info
->ddrc_cfg_num
;
128 saved_timing
->ddrphy_cfg_num
= timing_info
->ddrphy_cfg_num
;
129 saved_timing
->ddrphy_trained_csr_num
= ddrphy_trained_csr_num
;
130 saved_timing
->ddrphy_pie_num
= timing_info
->ddrphy_pie_num
;
132 /* save the fsp table */
133 for (i
= 0; i
< 4; i
++)
134 saved_timing
->fsp_table
[i
] = timing_info
->fsp_table
[i
];
136 cfg
= (struct dram_cfg_param
*)(saved_timing_base
+
137 sizeof(*timing_info
));
139 /* save ddrc config */
140 saved_timing
->ddrc_cfg
= cfg
;
141 for (i
= 0; i
< timing_info
->ddrc_cfg_num
; i
++) {
142 cfg
->reg
= timing_info
->ddrc_cfg
[i
].reg
;
143 cfg
->val
= timing_info
->ddrc_cfg
[i
].val
;
147 /* save ddrphy config */
148 saved_timing
->ddrphy_cfg
= cfg
;
149 for (i
= 0; i
< timing_info
->ddrphy_cfg_num
; i
++) {
150 cfg
->reg
= timing_info
->ddrphy_cfg
[i
].reg
;
151 cfg
->val
= timing_info
->ddrphy_cfg
[i
].val
;
155 /* save the ddrphy csr */
156 saved_timing
->ddrphy_trained_csr
= cfg
;
157 for (i
= 0; i
< ddrphy_trained_csr_num
; i
++) {
158 cfg
->reg
= ddrphy_trained_csr
[i
].reg
;
159 cfg
->val
= ddrphy_trained_csr
[i
].val
;
163 /* save the ddrphy pie */
164 saved_timing
->ddrphy_pie
= cfg
;
165 for (i
= 0; i
< timing_info
->ddrphy_pie_num
; i
++) {
166 cfg
->reg
= timing_info
->ddrphy_pie
[i
].reg
;
167 cfg
->val
= timing_info
->ddrphy_pie
[i
].val
;