1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #include "ddr_interface.h"
20 #include "ddr_training_impl.h"
21
22 #define CRG_REG_BASE 0x12010000U
23 #define PERI_CRG_DDRT 0x198U
24 #define PERI_CRG_DDRCKSEL 0x80U
25 /* [SYSCTRL]RAM Retention control register 0 */
26 #define SYSCTRL_MISC_CTRL4 0x8010U
27
28 static struct tr_relate_reg relate_reg;
29 static struct tr_relate_reg *reg = &relate_reg;
30
31 /**
32 * Do some prepare before copy code from DDR to SRAM.
33 * Keep empty when nothing to do.
34 */
ddr_cmd_prepare_copy(void)35 void ddr_cmd_prepare_copy(void) { return; }
36
37 /**
38 * Save site before DDR training command execute .
39 * Keep empty when nothing to do.
40 */
ddr_cmd_site_save(void)41 void ddr_cmd_site_save(void)
42 {
43 /* select ddrt bus path */
44 reg->custom.ive_ddrt_mst_sel = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4);
45 ddr_write(reg->custom.ive_ddrt_mst_sel & 0xffffffdf, DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4);
46
47 /* turn on ddrt clock */
48 reg->custom.ddrt_clk_reg = ddr_read(CRG_REG_BASE + PERI_CRG_DDRT);
49 /* enable ddrt0 clock */
50 ddr_write(reg->custom.ddrt_clk_reg | (1U << 1), CRG_REG_BASE + PERI_CRG_DDRT);
51 __asm__ __volatile__("nop");
52 /* disable ddrt0 soft reset */
53 ddr_write(ddr_read(CRG_REG_BASE + PERI_CRG_DDRT) & (~(1U << 0)), CRG_REG_BASE + PERI_CRG_DDRT);
54
55 /* disable rdqs anti-aging */
56 reg->custom.phy0_age_compst_en = ddr_read(DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
57 ddr_write((reg->custom.phy0_age_compst_en & 0x7fffffff), DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
58 #ifdef DDR_REG_BASE_PHY1
59 reg->custom.phy1_age_compst_en = ddr_read(DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
60 ddr_write((reg->custom.phy1_age_compst_en & 0x7fffffff), DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
61 #endif
62 }
63
64 /**
65 * Restore site after DDR training command execute.
66 * Keep empty when nothing to do.
67 */
ddr_cmd_site_restore(void)68 void ddr_cmd_site_restore(void)
69 {
70 /* restore ddrt bus path */
71 ddr_write(reg->custom.ive_ddrt_mst_sel, DDR_REG_BASE_SYSCTRL + SYSCTRL_MISC_CTRL4);
72
73 /* restore ddrt clock */
74 ddr_write(reg->custom.ddrt_clk_reg, CRG_REG_BASE + PERI_CRG_DDRT);
75
76 /* restore rdqs anti-aging */
77 ddr_write(reg->custom.phy0_age_compst_en, DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
78 #ifdef DDR_REG_BASE_PHY1
79 ddr_write(reg->custom.phy1_age_compst_en, DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
80 #endif
81 }
82
ddr_training_save_reg_custom(void * reg,unsigned int mask)83 void ddr_training_save_reg_custom(void *reg, unsigned int mask) { return; }
ddr_training_restore_reg_custom(void * reg)84 void ddr_training_restore_reg_custom(void *reg) { return; }
85
86 /**
87 * DDR clock select.
88 * For ddr osc training.
89 */
90 #ifdef DDR_PCODE_TRAINING_CONFIG
ddr_get_cksel(void)91 int ddr_get_cksel(void)
92 {
93 int freq;
94 unsigned int ddr_cksel;
95 ddr_cksel = (ddr_read(CRG_REG_BASE + PERI_CRG_DDRCKSEL) >> 0x3) & 0x7;
96 switch (ddr_cksel) {
97 case 0x000:
98 /* 24MHz */
99 freq = 24;
100 break;
101 case 0x001:
102 /* 450MHz */
103 freq = 450;
104 break;
105 case 0x011:
106 /* 300MHz */
107 freq = 300;
108 break;
109 case 0x100:
110 /* 297MHz */
111 freq = 297;
112 break;
113 default:
114 freq = 300;
115 break;
116 }
117 return freq;
118 }
119 #endif
120