• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * lowlevel_init_v300.c
3  *
4  * The file is Hardware initialization.
5  *
6  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 #include <compiler.h>
23 #include <asm/arch/platform.h>
24 #include <config.h>
25 #include <ddr_training_impl.h>
26 
delay(unsigned int num)27 static inline void delay(unsigned int num)
28 {
29 	volatile unsigned int i;
30 
31 	for (i = 0; i < (100 * num); i++) /* 100: Cycle */
32 		__asm__ __volatile__("nop");
33 }
34 
dwb(void)35 static inline void dwb(void) /* drain write buffer */
36 {
37 }
38 
readl(unsigned addr)39 static inline unsigned int readl(unsigned addr)
40 {
41 	unsigned int val;
42 
43 	val = (*(volatile unsigned int *)((uintptr_t)(addr)));
44 	return val;
45 }
46 
writel(unsigned val,unsigned addr)47 static inline void writel(unsigned val, unsigned addr)
48 {
49 	dwb();
50 	(*(volatile unsigned *)((uintptr_t)(addr))) = (val);
51 	dwb();
52 }
53 
54 #define REG_BASE_RNG_GEN            0x10090000
55 #define TRNG_DSTA_FIFO_DATA_OFST    0x204
56 #define TRNG_DATA_ST_OFST           0x208
57 #define BIT_TRNG_FIFO_DATA_CNT      0x8
58 #define TRNG_FIFO_DATA_CNT_MASK     0xff
59 #define REG_PERI_CRG104             0x1a0
60 #define TRNG_CLK_ENABLE             (0x1<<3)
61 #define TRNG_CLK_DISABLE            ~(0x1<<3)
62 #define TRNG_CTRL_DEF_VAL           0xa
63 #define HISEC_COM_TRNG_CTRL_OFST    0x200
64 
65 #define REG_BASE_MISC               0x12030000
66 #define DDR_CA0_OFST                0x28
67 #define DDR_CA1_OFST                0x2C
68 #define DDR_CA2_OFST                0x30
69 
70 #define REG_BASE_DDRC               0x120d0000
71 #define DDRC_CTRL_SREF_OFST         (0x8000 + 0x0)
72 #define DDRC_CFG_DDRMODE_OFST       (0x8000 + 0x50)
73 #define DDRC_CURR_FUNC_OFST         (0x8000 + 0x294)
74 
75 #define DDRC_CHANNEL_VALID_MASK     0xf
76 #define DDRC_SELF_REFURBISH_MASK    0x1
77 
78 #define DDRC_SELF_REFURBISH_EN      0x1
79 #define DDRC_SELF_REFURBISH_EXIT    (0x1 << 1)
80 
81 #define HPM_CORE_MIN 150
82 #define HPM_CORE_MAX 350
83 #define TEMPERATURE_MIN 117
84 #define TEMPERATURE_MAX 841
85 #define HPM_CORE_VALUE_MIN  190
86 #define HPM_CORE_VALUE_MAX  310
87 
88 #undef reg_get
89 #undef reg_set
90 #define reg_get(addr) readl(addr)
91 #define reg_set(addr, val) writel(val, (unsigned int)(addr))
92 
93 #define temperature_formula(val) (((((val) - 117) * 212) >> 10) - 40)
94 #define hpm_formula(hpm, temp)  ((hpm) + 4 + ((((temp) - 70) * 205) >> 10))
95 #define volt_formula(val) (1287 - ((1514 * (val)) >> 10))
96 #define duty_formula(val)  (((unsigned int)((1099 - (val)) * 460) >> 10) - 1)
97 #define svb_pwm_reg_val(val) ((((val) << 16) & 0XFFFF0000) + 0x0c75)
98 
trng_init(void)99 void trng_init(void)
100 {
101 	unsigned int reg_val;
102 	/* open rsa and trng clock */
103 	reg_val = reg_get(CRG_REG_BASE + REG_PERI_CRG104);
104 	reg_val |= TRNG_CLK_ENABLE;
105 	reg_set(CRG_REG_BASE + REG_PERI_CRG104, reg_val);
106 
107 	/* set trng ctrl register */
108 	reg_set(REG_BASE_RNG_GEN + HISEC_COM_TRNG_CTRL_OFST,
109 			TRNG_CTRL_DEF_VAL);
110 }
111 
trng_deinit(void)112 void trng_deinit(void)
113 {
114 	unsigned int reg_val;
115 
116 	/* close rsa and trng clock */
117 	reg_val = reg_get(CRG_REG_BASE + REG_PERI_CRG104);
118 	reg_val &= TRNG_CLK_DISABLE;
119 	reg_set(CRG_REG_BASE + REG_PERI_CRG104, reg_val);
120 }
121 
122 /* svb */
123 #define SVB_VER_16EV300             0x10
124 
125 #define CYCLE_NUM 4
126 #define  HPM_CORE_REG0 0x120280d8
127 #define  HPM_CORE_REG1 0x120280dc
128 
129 #define SVB_PWM_REG 0X120280b0
130 
131 #define SVB_VER_REG         0x12020168
132 #define  HPM_CHECK_REG 0x1202015c
133 #define SYS_CTRL_VOLT_REG 0x12020158
134 
135 #define TSENSOR_STATUS0 0x120280bc
136 #define OTP_HPM_CORE_REG 0x100a002c
137 
hpm_value_avg(unsigned int * val,int num)138 static unsigned hpm_value_avg(unsigned int *val, int num)
139 {
140 	unsigned int i;
141 	unsigned tmp = 0;
142 
143 	for (i = 0; i < num; i++)
144 		tmp += val[i] >> NUM_2;
145 
146 	return tmp >> NUM_2;
147 }
148 
get_hpm_value(unsigned int * hpm_core)149 static void get_hpm_value(unsigned int *hpm_core)
150 {
151 	int i;
152 	unsigned int temp;
153 	unsigned int core_value[NUM_4];
154 
155 	core_value[NUM_0] = 0;
156 	core_value[NUM_1] = 0;
157 	core_value[NUM_2] = 0;
158 	core_value[NUM_3] = 0;
159 
160 	for (i = 0; i < CYCLE_NUM; i++) {
161 		delay(10); /* delay 10ms */
162 
163 		temp = readl(HPM_CORE_REG0);
164 		core_value[NUM_1] += (temp >> 16) & 0x3ff; /* get hight 16 bits */
165 		core_value[NUM_0] += temp & 0x3ff;
166 		temp = readl(HPM_CORE_REG1);
167 		core_value[NUM_3] += (temp >> 16) & 0x3ff; /* get hight 16 bits */
168 		core_value[NUM_2] += temp & 0x3ff;
169 	}
170 
171 	*hpm_core = hpm_value_avg(core_value, NUM_4);
172 }
173 
start_hpm(unsigned int * hpm_core)174 static void start_hpm(unsigned int *hpm_core)
175 {
176 	get_hpm_value(hpm_core);
177 }
178 
hpm_check(unsigned int * hpm_core)179 static void hpm_check(unsigned int *hpm_core)
180 {
181 	union {
182 		struct {
183 			unsigned int reserved_0 : 16; /* [15..0] */
184 			unsigned int sys_hpm_core : 9; /* [24..16] */
185 			unsigned int reserved_1 : 1; /* [25] */
186 			unsigned int hpm_core_err : 1; /* [26] */
187 			unsigned int reserved_2 : 5; /* [27..31] */
188 		} bits;
189 
190 		unsigned int u32;
191 	} sysboot10;
192 	sysboot10.u32 = readl(HPM_CHECK_REG);
193 	sysboot10.bits.sys_hpm_core = 0;
194 	sysboot10.bits.hpm_core_err = 0;
195 
196 	if (*hpm_core < HPM_CORE_MIN) {
197 		*hpm_core = HPM_CORE_MIN;
198 		sysboot10.bits.hpm_core_err = 1;
199 	}
200 	if (*hpm_core > HPM_CORE_MAX) {
201 		*hpm_core = HPM_CORE_MAX;
202 		sysboot10.bits.hpm_core_err = 1;
203 	}
204 
205 	sysboot10.bits.sys_hpm_core = *hpm_core;
206 
207 	writel(sysboot10.u32, HPM_CHECK_REG);
208 }
209 
get_temperature(unsigned int * temperature)210 static void get_temperature(unsigned int *temperature)
211 {
212 	unsigned int value;
213 
214 	value = readl(TSENSOR_STATUS0);
215 	value = value & 0x3ff; /* 0x3ff: mask */
216 
217 	if (value <= TEMPERATURE_MIN)
218 		*temperature = -40; /* -40: temperature val */
219 	else if (value >= TEMPERATURE_MAX)
220 		*temperature = 110; /* 110: temperature val */
221 	else
222 		*temperature = temperature_formula(value);
223 }
224 
adjust_hpm(unsigned int * hpm_core,unsigned int temperature)225 static void adjust_hpm(unsigned int *hpm_core, unsigned int temperature)
226 {
227 	/* 283 70: hpm_core and temperature Threshold */
228 	if ((*hpm_core >= 283) && (temperature >= 70))
229 		*hpm_core = hpm_formula(*hpm_core, temperature);
230 	/* 222 70: hpm_core and temperature Threshold */
231 	else if ((*hpm_core <= 222) && (temperature >= 70))
232 		*hpm_core = *hpm_core - NUM_4;
233 }
234 
set_hpm_core_volt(unsigned int hpm_core_value)235 static void set_hpm_core_volt(unsigned int hpm_core_value)
236 {
237 	unsigned int volt;
238 	unsigned int duty;
239 	unsigned int otp_vmin_core = readl(OTP_HPM_CORE_REG);
240 
241 	if (hpm_core_value <= HPM_CORE_VALUE_MIN)
242 		volt = 1006; /* 1006: volt value */
243 	else if (hpm_core_value >= HPM_CORE_VALUE_MAX)
244 		volt = 829; /* 829: volt value */
245 	else
246 		volt = volt_formula(hpm_core_value);
247 
248 	volt = volt + (int)((short int)(otp_vmin_core >> 16)); /* get hight 16 bits */
249 
250 	writel(volt, SYS_CTRL_VOLT_REG);
251 	duty = duty_formula(volt);
252 
253 	writel(svb_pwm_reg_val(duty), SVB_PWM_REG);
254 }
255 
start_svb(void)256 void start_svb(void)
257 {
258 	unsigned int hpm_core = 0;
259 	unsigned int temperature = 0;
260 
261 	unsigned int tmp_reg = readl(SVB_VER_REG);
262 	tmp_reg = (tmp_reg & 0xff00ffff) | (SVB_VER_16EV300 << 16); /* Move Left 16 bit */
263 	writel(tmp_reg, SVB_VER_REG);
264 
265 	get_temperature(&temperature);
266 	start_hpm(&hpm_core);
267 	adjust_hpm(&hpm_core, temperature);
268 	hpm_check(&hpm_core);
269 
270 	set_hpm_core_volt(hpm_core);
271 	delay(200); /* delay 200ms */
272 }
273 
274 
275 /* [CUSTOM] DDR PHY0-PHY1 base register */
276 #define DDR_REG_BASE_PHY0       0x120dc000
277 
278 /* [CUSTOM] DDR DMC0-DMC3 base register */
279 #define DDR_REG_BASE_DMC0       0x120d8000
280 #define DDR_REG_BASE_DMC1       0x120d8000
281 
282 #ifdef DDR_REG_BASE_PHY1
283 #define DDR_REG_BASE_DMC2       0x120d9000
284 #define DDR_REG_BASE_DMC3       0x120d9000
285 #endif
286 
287 #define CRG_REG_BASE            0x12010000
288 #define PERI_CRG_DDRT           0x198
289 
290 #define DDR_REG_BASE_SYSCTRL    0x12020000
291 /* [SYSCTRL]RAM Retention control register 0 */
292 #define SYSCTRL_MISC_CTRL4      0x8010
293 
294 #define DDR_PHY_DRAMCFG         0x2c    /* DRAM config register */
295 #define PHY_DRAMCFG_TYPE_MASK   0xf /* [3:0] */
296 #define PHY_DRAMCFG_TYPE_LPDDR4 0x6   /* [2:0] 110 LPDDR4 */
297 
298 #define BYTE_NUM  2
299 
300 /**
301  * ddr_boot_prepare
302  * @void
303  *
304  * Do some prepare before ddr training.
305  * Keep empty when nothing to do.
306  */
ddr_boot_prepare(struct tr_relate_reg * reg)307 static void ddr_boot_prepare(struct tr_relate_reg *reg)
308 {
309 	/* select ddrt bus path */
310 	reg->custom.ive_ddrt_mst_sel = readl(DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4);
311 	writel(reg->custom.ive_ddrt_mst_sel & 0xffffffdf,
312 		   DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4);
313 
314 	/* turn on ddrt clock */
315 	reg->custom.ddrt_clk_reg = readl(CRG_REG_BASE + PERI_CRG_DDRT);
316 	/* enable ddrt0 clock */
317 	writel(reg->custom.ddrt_clk_reg | (0x1 << 1), CRG_REG_BASE + PERI_CRG_DDRT);
318 	__asm__ __volatile__("nop");
319 	/* disable ddrt0 soft reset */
320 	writel(readl(CRG_REG_BASE + PERI_CRG_DDRT) & (~(0x1 << 0)),
321 		   CRG_REG_BASE + PERI_CRG_DDRT);
322 
323 	/* disable rdqs anti-aging */
324 	reg->custom.phy0_age_compst_en = readl(DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
325 	writel((reg->custom.phy0_age_compst_en & 0x7fffffff),
326 		   DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
327 #ifdef DDR_REG_BASE_PHY1
328 	reg->custom.phy1_age_compst_en = readl(DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
329 	writel((reg->custom.phy1_age_compst_en & 0x7fffffff),
330 		   DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
331 #endif
332 }
333 
334 /**
335  * ddr_boot_restore
336  * @void
337  *
338  * Restore register config after ddr training.
339  * Keep empty when nothing to do.
340  */
ddr_boot_restore(struct tr_relate_reg * reg)341 static void ddr_boot_restore(struct tr_relate_reg *reg)
342 {
343 	/* restore ddrt bus path */
344 	writel(reg->custom.ive_ddrt_mst_sel, DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4);
345 
346 	/* restore ddrt clock */
347 	writel(reg->custom.ddrt_clk_reg, CRG_REG_BASE + PERI_CRG_DDRT);
348 
349 	/* restore rdqs anti-aging */
350 	writel(reg->custom.phy0_age_compst_en, DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
351 #ifdef DDR_REG_BASE_PHY1
352 	writel(reg->custom.phy1_age_compst_en, DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
353 #endif
354 }
355 
356 /**
357  * ddr_rdqs_bdl_adj
358  * @void
359  *
360  * Adjust rdqs/rdq/rdm bdl to avoid problem cause by ddr anti-aging.
361  */
ddr_rdqs_bdl_adj(void)362 static void ddr_rdqs_bdl_adj(void)
363 {
364 	int i;
365 	unsigned int rdqs;
366 	unsigned int rdq03, rdq47;
367 	unsigned int rdm;
368 	unsigned int tmp;
369 
370 	for (i = 0; i < BYTE_NUM; i++) {
371 		rdqs = readl(DDR_REG_BASE_PHY0 + 0x22c + i * 0x80);
372 		rdq03 = readl(DDR_REG_BASE_PHY0 + 0x21c + i * 0x80);
373 		rdq47 = readl(DDR_REG_BASE_PHY0 + 0x220 + i * 0x80);
374 		rdm = readl(DDR_REG_BASE_PHY0 + 0x224 + i * 0x80);
375 
376 		/* rdqs bdl lower two bit shoud be 0x11 */
377 		while ((rdqs & 0x3) < 0x3) {
378 			/* rdqs/rdq/rdm bdl + 1 */
379 			rdqs = rdqs + 0x1;
380 			rdq03 = rdq03 + 0x01010101;
381 			rdq47 = rdq47 + 0x01010101;
382 			rdm = rdm + 0x1;
383 
384 			writel(rdqs, DDR_REG_BASE_PHY0 + 0x22c + i * 0x80);
385 			writel(rdq03, DDR_REG_BASE_PHY0 + 0x21c + i * 0x80);
386 			writel(rdq47, DDR_REG_BASE_PHY0 + 0x220 + i * 0x80);
387 			writel(rdm, DDR_REG_BASE_PHY0 + 0x224 + i * 0x80);
388 		}
389 	}
390 
391 	tmp = readl(DDR_REG_BASE_PHY0 + DDR_PHY_MISC);
392 	tmp |= (1 << PHY_MISC_UPDATE_BIT);
393 	/* update new config to PHY */
394 	writel(tmp, DDR_REG_BASE_PHY0 + DDR_PHY_MISC);
395 	tmp &= ~(1 << PHY_MISC_UPDATE_BIT);
396 	writel(tmp, DDR_REG_BASE_PHY0 + DDR_PHY_MISC);
397 	tmp = readl(DDR_REG_BASE_PHY0 + DDR_PHY_PHYINITCTRL);
398 	/* set 1 to issue PHY counter reset signal */
399 	tmp |= (1 << PHY_PHYCONN_RST_BIT);
400 	writel(tmp, DDR_REG_BASE_PHY0 + DDR_PHY_PHYINITCTRL);
401 	/* set 0 to end the reset signal */
402 	tmp &= ~(1 << PHY_PHYCONN_RST_BIT);
403 	writel(tmp, DDR_REG_BASE_PHY0 + DDR_PHY_PHYINITCTRL);
404 }
405 
start_ddr_training(unsigned int base)406 void start_ddr_training(unsigned int base)
407 {
408 	struct tr_relate_reg relate_reg;
409 	struct tr_relate_reg *reg = &relate_reg;
410 
411 	start_svb();
412 
413 	ddr_boot_prepare(reg);
414 
415 	/* ddr pcode training */
416 	ddr_pcode_training_if();
417 	/* ddr hw training */
418 	ddr_hw_training_if();
419 	/* ddr sw training */
420 	ddr_sw_training_if();
421 
422 	ddr_rdqs_bdl_adj();
423 
424 	ddr_boot_restore(reg);
425 
426 	/* the value should config after trainning, or
427 	  it will cause chip compatibility problems */
428 	if ((readl(DDR_REG_BASE_PHY0 + DDR_PHY_DRAMCFG) &
429 		PHY_DRAMCFG_TYPE_MASK) == PHY_DRAMCFG_TYPE_LPDDR4) {
430 		writel(0x401, DDR_REG_BASE_DMC0 + 0x28);
431 		writel(0x401, DDR_REG_BASE_DMC1 + 0x28);
432 	} else {
433 		writel(0x401, DDR_REG_BASE_DMC0 + 0x28);
434 	}
435 #ifdef DDR_REG_BASE_PHY1
436 	if ((readl(DDR_REG_BASE_PHY1 + DDR_PHY_DRAMCFG) &
437 		PHY_DRAMCFG_TYPE_MASK) == PHY_DRAMCFG_TYPE_LPDDR4) {
438 		writel(0x401, DDR_REG_BASE_DMC2 + 0x28);
439 		writel(0x401, DDR_REG_BASE_DMC3 + 0x28);
440 	} else {
441 		writel(0x401, DDR_REG_BASE_DMC1 + 0x28);
442 	}
443 #endif
444 	/* enable ddr scramb */
445 }
446