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