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