xref: /rk3399_rockchip-uboot/drivers/ram/rockchip/dmc_fsp.c (revision 3bbe0d2f9129303e9f36d3ddfa3485653e188ecd)
1 // SPDX-License-Identifier:     GPL-2.0+
2 /*
3  * (C) Copyright 2021 Rockchip Electronics Co., Ltd.
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <syscon.h>
9 #include <asm/io.h>
10 #include <dm/of_access.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/rockchip_smccc.h>
13 #include <asm/arch/sdram.h>
14 #include <asm/arch/sdram_common.h>
15 
16 #define DDR2_PARAMS_PHANDLE_NAME		"ddr2_params"
17 #define DDR3_PARAMS_PHANDLE_NAME		"ddr3_params"
18 #define DDR4_PARAMS_PHANDLE_NAME		"ddr4_params"
19 #define LPDDR2_PARAMS_PHANDLE_NAME		"lpddr2_params"
20 #define LPDDR3_PARAMS_PHANDLE_NAME		"lpddr3_params"
21 #define LPDDR4_PARAMS_PHANDLE_NAME		"lpddr4_params"
22 #define LPDDR4X_PARAMS_PHANDLE_NAME		"lpddr4x_params"
23 #define LPDDR5_PARAMS_PHANDLE_NAME		"lpddr5_params"
24 
25 #define DTS_PAR_OFFSET				(4096)
26 #define PARAMS_INVALID_VAL			(0xff00aa99)
27 
28 #define PMUGRF_OS_REG(n)			(0x200 + (n) * 4)
29 
30 /* there is a matching relationship, modify it with caution */
31 static char *dmc_fsp_params[] = {
32 	"debug_print_level",
33 	/* if need, add parameter after */
34 };
35 
36 /* there is a matching relationship, modify it with caution */
37 static char *ddr_params_v1[] = {
38 	/* version information V1.00 */
39 	"version",
40 	"expanded_version",
41 	"reserved",
42 	/* freq info, freq_0 is final frequency, unit: MHz */
43 	"freq_0",
44 	"freq_1",
45 	"freq_2",
46 	"freq_3",
47 	"freq_4",
48 	"freq_5",
49 	/* power save setting */
50 	"pd_idle",
51 	"sr_idle",
52 	"sr_mc_gate_idle",
53 	"srpd_lite_idle",
54 	"standby_idle",
55 	"pd_dis_freq",
56 	"sr_dis_freq",
57 	"dram_dll_dis_freq",
58 	"phy_dll_dis_freq",
59 	/* drv when odt on */
60 	"phy_dq_drv_odten",
61 	"phy_ca_drv_odten",
62 	"phy_clk_drv_odten",
63 	"dram_dq_drv_odten",
64 	/* drv when odt off */
65 	"phy_dq_drv_odtoff",
66 	"phy_ca_drv_odtoff",
67 	"phy_clk_drv_odtoff",
68 	"dram_dq_drv_odtoff",
69 	/* odt info */
70 	"dram_odt",
71 	"phy_odt",
72 	"phy_odt_puup_en",
73 	"phy_odt_pudn_en",
74 	/* odt enable freq */
75 	"dram_dq_odt_en_freq",
76 	"phy_odt_en_freq",
77 	/* slew rate when odt enable */
78 	"phy_dq_sr_odten",
79 	"phy_ca_sr_odten",
80 	"phy_clk_sr_odten",
81 	/* slew rate when odt disable */
82 	"phy_dq_sr_odtoff",
83 	"phy_ca_sr_odtoff",
84 	"phy_clk_sr_odtoff",
85 	/* ssmod setting*/
86 	"ssmod_downspread",
87 	"ssmod_div",
88 	"ssmod_spread",
89 	/* 2T mode */
90 	"mode_2t",
91 	/* speed bin */
92 	"speed_bin",
93 	/* dram extended temperature support */
94 	"dram_ext_temp",
95 	/* byte map */
96 	"byte_map",
97 	/* dq map */
98 	"dq_map_cs0_dq_l",
99 	"dq_map_cs0_dq_h",
100 	"dq_map_cs1_dq_l",
101 	"dq_map_cs1_dq_h",
102 	/* for LPDDR4 and LPDDR4X */
103 	/* odt info */
104 	"lp4_ca_odt",
105 	"lp4_drv_pu_cal_odten",
106 	"lp4_drv_pu_cal_odtoff",
107 	"phy_lp4_drv_pulldown_en_odten",
108 	"phy_lp4_drv_pulldown_en_odtoff",
109 	/* odt enable freq */
110 	"lp4_ca_odt_en_freq",
111 	/* lp4 cs drv info and ca odt info */
112 	"phy_lp4_cs_drv_odten",
113 	"phy_lp4_cs_drv_odtoff",
114 	"lp4_odte_ck_en",
115 	"lp4_odte_cs_en",
116 	"lp4_odtd_ca_en",
117 	/* lp4 vref info when odt enable */
118 	"phy_lp4_dq_vref_odten",
119 	"lp4_dq_vref_odten",
120 	"lp4_ca_vref_odten",
121 	/* lp4 vref info when odt disable */
122 	"phy_lp4_dq_vref_odtoff",
123 	"lp4_dq_vref_odtoff",
124 	"lp4_ca_vref_odtoff",
125 	/* if need, add parameter after and change the minor version. */
126 };
127 
128 static int get_atf_version(void)
129 {
130 	struct arm_smccc_res res;
131 
132 	res = sip_smc_dram(0, 0, ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION);
133 
134 	if (res.a0)
135 		return -ENOMEM;
136 	else
137 		return res.a1;
138 }
139 
140 static int dmc_fsp_probe(struct udevice *dev)
141 {
142 	struct device_node *np_params;
143 	struct arm_smccc_res res;
144 	void *pmugrf_base;
145 	int *p = NULL;
146 	char *phandle_name = NULL;
147 	char **ddr_params;
148 	int ddr_params_version;
149 	u32 dram_type, os_reg2_val, os_reg3_val;
150 	u32 i = 0, count = 0, size = 0;
151 	ulong atf_version_limit;
152 
153 	atf_version_limit = dev_get_driver_data(dev);
154 	if (get_atf_version() < atf_version_limit) {
155 		printf("%s: trusted firmware need to update or is invalid!\n", __func__);
156 		printf("%s: current ATF version 0x%x, required version 0x%lx\n",
157 		       __func__, get_atf_version(), atf_version_limit);
158 		return 0;
159 	}
160 
161 	pmugrf_base = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
162 	os_reg2_val = readl(pmugrf_base + PMUGRF_OS_REG(2));
163 	os_reg3_val = readl(pmugrf_base + PMUGRF_OS_REG(3));
164 	dram_type = SYS_REG_DEC_DDRTYPE_V3(os_reg2_val, os_reg3_val);
165 
166 	if (dram_type == DDR2)
167 		phandle_name = DDR2_PARAMS_PHANDLE_NAME;
168 	else if (dram_type == DDR3)
169 		phandle_name = DDR3_PARAMS_PHANDLE_NAME;
170 	else if (dram_type == DDR4)
171 		phandle_name = DDR4_PARAMS_PHANDLE_NAME;
172 	else if (dram_type == LPDDR2)
173 		phandle_name = LPDDR2_PARAMS_PHANDLE_NAME;
174 	else if (dram_type == LPDDR3)
175 		phandle_name = LPDDR3_PARAMS_PHANDLE_NAME;
176 	else if (dram_type == LPDDR4)
177 		phandle_name = LPDDR4_PARAMS_PHANDLE_NAME;
178 	else if (dram_type == LPDDR4X)
179 		phandle_name = LPDDR4X_PARAMS_PHANDLE_NAME;
180 	else if (dram_type == LPDDR5)
181 		phandle_name = LPDDR5_PARAMS_PHANDLE_NAME;
182 	else
183 		printf("%s: dram_type unsupported\n", __func__);
184 
185 	np_params = of_parse_phandle(ofnode_to_np(dev_ofnode(dev)), phandle_name, 0);
186 	if (!np_params) {
187 		printf("%s: of_parse_phandle %s error!\n", __func__, phandle_name);
188 		return -EINVAL;
189 	}
190 
191 	ddr_params_version = ofnode_read_u32_default(np_to_ofnode(np_params), "version", -1);
192 	if (ddr_params_version < 0) {
193 		printf("%s: get ddr_params_version error\n", __func__);
194 		return -EINVAL;
195 	}
196 
197 	if ((ddr_params_version & 0xff00) == 0x100 &&
198 	    (ddr_params_version & 0xffff) <= 0x100) {
199 		count = ARRAY_SIZE(ddr_params_v1);
200 		ddr_params = ddr_params_v1;
201 	} else {
202 		printf("%s: ddr_params_version=0x%x unsupported\n", __func__, ddr_params_version);
203 		return -EINVAL;
204 	}
205 
206 	size = count * 4;
207 	res = sip_smc_request_share_mem(DIV_ROUND_UP(size, 4096) + 1, SHARE_PAGE_TYPE_DDRFSP);
208 	if (res.a0 != 0) {
209 		printf("%s:no share memory for init\n", __func__);
210 		return -ENOMEM;
211 	}
212 
213 	/* fill share memory and pass to the atf */
214 	p = (int *)(res.a1);
215 	for (i = 0; i < ARRAY_SIZE(dmc_fsp_params); i++)
216 		p[i] = dev_read_u32_default(dev, dmc_fsp_params[i], PARAMS_INVALID_VAL);
217 
218 	p = (int *)(res.a1 + DTS_PAR_OFFSET / 4);
219 	for (i = 0; i < count; i++) {
220 		p[i] = ofnode_read_u32_default(np_to_ofnode(np_params), ddr_params[i],
221 					       PARAMS_INVALID_VAL);
222 	}
223 
224 	flush_cache((unsigned long)(res.a1), (DIV_ROUND_UP(size, 4096) + 1) * 0x1000);
225 	res = sip_smc_dram(SHARE_PAGE_TYPE_DDRFSP, 0, ROCKCHIP_SIP_CONFIG_DRAM_FSP_INIT);
226 	if (res.a0) {
227 		printf("%s: rockchip_sip_config_dram_fsp_init error:%lx\n", __func__, res.a0);
228 		return -ENOMEM;
229 	}
230 
231 	return 0;
232 }
233 
234 static const struct udevice_id rockchip_dmc_fsp_ids[] = {
235 	{ .compatible = "rockchip,rk3568-dmc-fsp", .data = 0x102},
236 	{ }
237 };
238 
239 U_BOOT_DRIVER(dmc_fsp) = {
240 	.name = "rockchip_dmc_fsp",
241 	.id = UCLASS_DMC,
242 	.probe = dmc_fsp_probe,
243 	.of_match = rockchip_dmc_fsp_ids,
244 };
245