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 0x11010000U
23 #define PERI_CRG_DDRT 0x22A0U
24 #define PERI_CRG_DDRCKSEL 0x2280U
25
26 /* sysctrl offset address */
27 #define DDRT_CTRL 0x4030 /* DDRT control register */
28
29 /* register bit */
30 #define DDRTEST0_CKEN_BIT 4 /* DDRTEST0 clock gating configuration register */
31 #define DDRTEST0_SRST_REQ_BIT 0 /* soft reset request for DDRTEST0 */
32 #define DDRT0_MST_SEL_BIT 0 /* ddr p0 bus path selection control */
33
34 /*
35 * Do some prepare before copy code from DDR to SRAM.
36 * Keep empty when nothing to do.
37 */
ddr_cmd_prepare_copy(void)38 void ddr_cmd_prepare_copy(void)
39 {
40 return;
41 }
42
43 /*
44 * Save site before DDR training command execute .
45 * Keep empty when nothing to do.
46 */
ddr_cmd_site_save(void)47 void ddr_cmd_site_save(void)
48 {
49 return;
50 }
51
52 /*
53 * Restore site after DDR training command execute.
54 * Keep empty when nothing to do.
55 */
ddr_cmd_site_restore(void)56 void ddr_cmd_site_restore(void)
57 {
58 return;
59 }
60
ddr_training_save_reg_custom(void * reg,unsigned int mask)61 void ddr_training_save_reg_custom(void *reg, unsigned int mask)
62 {
63 return;
64 }
ddr_training_restore_reg_custom(void * reg)65 void ddr_training_restore_reg_custom(void *reg)
66 {
67 return;
68 }
69
70 /*
71 * Save site before DDR training:include boot and command execute.
72 * Keep empty when nothing to do.
73 */
ddr_boot_cmd_save(void * reg)74 void ddr_boot_cmd_save(void *reg)
75 {
76 struct tr_relate_reg *relate_reg = (struct tr_relate_reg *)reg;
77
78 /* ddr bus path selection control */
79 relate_reg->custom.ddr_ctrl = ddr_read(DDR_REG_BASE_SYSCTRL + DDRT_CTRL);
80 ddr_write(relate_reg->custom.ddr_ctrl | (0x1 << DDRT0_MST_SEL_BIT), DDR_REG_BASE_SYSCTRL + DDRT_CTRL);
81
82 /* turn on ddrt clock */
83 relate_reg->custom.ddrt_clk_reg = ddr_read(CRG_REG_BASE + PERI_CRG_DDRT);
84 /* enable ddrt0 clock */
85 ddr_write(relate_reg->custom.ddrt_clk_reg | (0x1 << DDRTEST0_CKEN_BIT), CRG_REG_BASE + PERI_CRG_DDRT);
86 __asm__ __volatile__("nop");
87 /* disable ddrt0 soft reset */
88 ddr_write(ddr_read(CRG_REG_BASE + PERI_CRG_DDRT) & (~(0x1 << DDRTEST0_SRST_REQ_BIT)), CRG_REG_BASE + PERI_CRG_DDRT);
89
90 /* disable rdqs anti-aging */
91 relate_reg->custom.phy0_age_compst_en = ddr_read(DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
92 ddr_write((relate_reg->custom.phy0_age_compst_en & (~(0x1 << PHY_CFG_RX_AGE_COMPST_EN_BIT))),
93 DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
94 #ifdef DDR_REG_BASE_PHY1
95 relate_reg->custom.phy1_age_compst_en = ddr_read(DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
96 ddr_write((relate_reg->custom.phy1_age_compst_en & (~(0x1 << PHY_CFG_RX_AGE_COMPST_EN_BIT))),
97 DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
98 #endif
99 }
100
101 /*
102 * Restore site after DDR training:include boot and command execute.
103 * Keep empty when nothing to do.
104 */
ddr_boot_cmd_restore(void * reg)105 void ddr_boot_cmd_restore(void *reg)
106 {
107 struct tr_relate_reg *relate_reg = (struct tr_relate_reg *)reg;
108
109 /* restore ddr bus path selection */
110 ddr_write(relate_reg->custom.ddr_ctrl, DDR_REG_BASE_SYSCTRL + DDRT_CTRL);
111 /* restore ddrt clock */
112 ddr_write(relate_reg->custom.ddrt_clk_reg, CRG_REG_BASE + PERI_CRG_DDRT);
113
114 /* restore rdqs anti-aging */
115 ddr_write(relate_reg->custom.phy0_age_compst_en, DDR_REG_BASE_PHY0 + DDR_PHY_PHYRSCTRL);
116 #ifdef DDR_REG_BASE_PHY1
117 ddr_write(relate_reg->custom.phy1_age_compst_en, DDR_REG_BASE_PHY1 + DDR_PHY_PHYRSCTRL);
118 #endif
119 }
120
121 /*
122 * DDR clock select.
123 * For ddr osc training.
124 */
125 #ifdef DDR_PCODE_TRAINING_CONFIG
ddr_get_cksel(void)126 int ddr_get_cksel(void)
127 {
128 int freq;
129 unsigned int ddr_cksel;
130 ddr_cksel = (ddr_read(CRG_REG_BASE + PERI_CRG_DDRCKSEL) >> 0x3) & 0x7;
131 switch (ddr_cksel) {
132 case 0x000:
133 freq = 24; /* 24MHz */
134 break;
135 case 0x001:
136 freq = 450; /* 450MHz */
137 break;
138 case 0x011:
139 freq = 300; /* 300MHz */
140 break;
141 case 0x100:
142 freq = 297; /* 297MHz */
143 break;
144 default:
145 freq = 300; /* 300MHz */
146 break;
147 }
148 return freq;
149 }
150 #endif
151