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