1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2020 Rockchip Electronics Co., Ltd
4 */
5
6 #include <common.h>
7 #include <debug_uart.h>
8 #include <dm.h>
9 #include <dm/root.h>
10 #include <dt-structs.h>
11 #include <regmap.h>
12 #include <asm/io.h>
13 #include <asm/types.h>
14 #include <asm/arch/hardware.h>
15 #include <asm/arch/sdram_rv1108.h>
16 #include <asm/arch/timer.h>
17 #include <asm/arch/sdram.h>
18
19 struct dram_info info;
20
21 struct rockchip_dmc_plat {
22 #if CONFIG_IS_ENABLED(OF_PLATDATA)
23 struct dtd_rockchip_rv1108_dmc dtplat;
24 #else
25 struct sdram_params params;
26 #endif
27 struct regmap *map;
28 };
29
enable_ddr_io_ret(struct dram_info * priv)30 void enable_ddr_io_ret(struct dram_info *priv)
31 {
32 writel(DDR_IO_RET_EN, &priv->pmu->sft_con);
33 rk_clrsetreg(&priv->pmu_grf->soc_con[0],
34 DDRPHY_BUFFEREN_CORE_MASK,
35 DDRPHY_BUFFEREN_CORE_EN);
36 }
37
rkdclk_init(struct dram_info * priv,struct sdram_params * params_priv)38 void rkdclk_init(struct dram_info *priv,
39 struct sdram_params *params_priv)
40 {
41 rk_clrsetreg(&priv->cru->pll[1].con3, WORK_MODE_MASK,
42 WORK_MODE_SLOW << WORK_MODE_SHIFT);
43 rk_clrsetreg(&priv->cru->pll[1].con3, GLOBAL_POWER_DOWN_MASK,
44 GLOBAL_POWER_DOWN << GLOBAL_POWER_DOWN_SHIFT);
45 rk_clrsetreg(&priv->cru->pll[1].con3, DSMPD_MASK,
46 INTEGER_MODE << DSMPD_SHIFT);
47 rk_clrsetreg(&priv->cru->pll[1].con0, FBDIV_MASK,
48 params_priv->dpll_init_cfg.fbdiv << FBDIV_SHIFT);
49 rk_clrsetreg(&priv->cru->pll[1].con1,
50 POSTDIV2_MASK | POSTDIV1_MASK | REFDIV_MASK,
51 params_priv->dpll_init_cfg.postdiv2 << POSTDIV2_SHIFT |
52 params_priv->dpll_init_cfg.postdiv1 << POSTDIV1_SHIFT |
53 params_priv->dpll_init_cfg.refdiv << REFDIV_SHIFT);
54 rk_clrsetreg(&priv->cru->pll[1].con3, GLOBAL_POWER_DOWN_MASK,
55 GLOBAL_POWER_UP << GLOBAL_POWER_DOWN_SHIFT);
56 while (!(readl(&priv->cru->pll[1].con2) & (1u << LOCK_STA_SHIFT)))
57 udelay(1);
58
59 rk_clrsetreg(&priv->cru->clksel_con[4], CLK_DDR_PLL_SEL_MASK |
60 CLK_DDR_DIV_CON_MASK, 0 << CLK_DDR_PLL_SEL_SHIFT |
61 0 << CLK_DDR_DIV_CON_SHIFT);
62 rk_clrsetreg(&priv->cru->pll[1].con3, WORK_MODE_MASK,
63 WORK_MODE_NORMAL << WORK_MODE_SHIFT);
64 }
65
phy_pctrl_reset_cru(struct dram_info * priv)66 void phy_pctrl_reset_cru(struct dram_info *priv)
67 {
68 rk_clrsetreg(&priv->cru->softrst_con[2], DDRUPCTL_PSRSTN_REQ_MASK |
69 DDRUPCTL_NSRSTN_REQ_MASK,
70 DDRUPCTL_PSRSTN_REQ << DDRUPCTL_PSRSTN_REQ_SHIFT |
71 DDRUPCTL_NSRSTN_REQ << DDRUPCTL_NSRSTN_REQ_SHIFT);
72 rk_clrsetreg(&priv->cru->softrst_con[1],
73 DDRPHY_SRSTN_CLKDIV_REQ_MASK | DDRPHY_SRSTN_REQ_MASK |
74 DDRPHY_PSRSTN_REQ_MASK,
75 DDRPHY_SRSTN_CLKDIV_REQ << DDRPHY_SRSTN_CLKDIV_REQ_SHIFT |
76 DDRPHY_SRSTN_REQ << DDRPHY_SRSTN_REQ_SHIFT |
77 DDRPHY_PSRSTN_REQ << DDRPHY_PSRSTN_REQ_SHIFT);
78
79 udelay(10);
80
81 rk_clrsetreg(&priv->cru->softrst_con[1],
82 DDRPHY_SRSTN_CLKDIV_REQ_MASK | DDRPHY_SRSTN_REQ_MASK |
83 DDRPHY_PSRSTN_REQ_MASK,
84 DDRPHY_SRSTN_CLKDIV_DIS << DDRPHY_SRSTN_CLKDIV_REQ_SHIFT |
85 DDRPHY_PSRSTN_DIS << DDRPHY_PSRSTN_REQ_SHIFT |
86 DDRPHY_SRSTN_DIS << DDRPHY_SRSTN_REQ_SHIFT);
87 udelay(10);
88
89 rk_clrsetreg(&priv->cru->softrst_con[2], DDRUPCTL_PSRSTN_REQ_MASK |
90 DDRUPCTL_NSRSTN_REQ_MASK,
91 DDRUPCTL_PSRSTN_DIS << DDRUPCTL_PSRSTN_REQ_SHIFT |
92 DDRUPCTL_NSRSTN_DIS << DDRUPCTL_NSRSTN_REQ_SHIFT);
93 udelay(10);
94 }
95
pctl_cfg_grf(struct dram_info * priv,struct sdram_params * params_priv)96 void pctl_cfg_grf(struct dram_info *priv,
97 struct sdram_params *params_priv)
98 {
99 writel(RK_SETBITS(MSCH_MAINDDR3 | MSCH_MAINPARTIALPOP),
100 &priv->grf->soc_con0);
101 }
102
ddr_msch_cfg(struct dram_info * priv,struct sdram_params * params_priv)103 void ddr_msch_cfg(struct dram_info *priv,
104 struct sdram_params *params_priv)
105 {
106 writel((readl(&priv->service_msch->ddrtiming) & BWRATIO_HALF_BW) |
107 params_priv->ddr_timing_t.noc_timing.d32,
108 &priv->service_msch->ddrtiming);
109 writel(params_priv->ddr_timing_t.readlatency,
110 &priv->service_msch->readlatency);
111 writel(params_priv->ddr_timing_t.activate.d32,
112 &priv->service_msch->activate);
113 writel(params_priv->ddr_timing_t.devtodev,
114 &priv->service_msch->devtodev);
115 }
116
ddr_msch_cfg_rbc(struct sdram_params * params_priv,struct dram_info * priv)117 void ddr_msch_cfg_rbc(struct sdram_params *params_priv,
118 struct dram_info *priv)
119 {
120 int i = 0;
121
122 if (params_priv->ddr_config_t.col == 10)
123 i = 2;
124 else
125 i = 3;
126 writel(i, &priv->service_msch->ddrconf);
127 }
128
ddr_phy_skew_cfg(struct dram_info * priv)129 void ddr_phy_skew_cfg(struct dram_info *priv)
130 {
131 }
132
set_ds_odt(struct dram_info * priv,struct sdram_params * params_priv)133 void set_ds_odt(struct dram_info *priv,
134 struct sdram_params *params_priv)
135 {
136 /* set phy drive impedance */
137 writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg11);
138 clrsetbits_le32(&priv->phy->phy_reg12, CMD_PRCOMP_MASK,
139 PHY_RON_RTT_34OHM << CMD_PRCOMP_SHIFT);
140
141 writel(PHY_RON_RTT_45OHM, &priv->phy->phy_reg16);
142 writel(PHY_RON_RTT_45OHM, &priv->phy->phy_reg18);
143 writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg20);
144 writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg2f);
145 writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg30);
146 writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg3f);
147
148 /*set phy odt*/
149 writel(PHY_RON_RTT_225OHM, &priv->phy->phy_reg21);
150 writel(PHY_RON_RTT_225OHM, &priv->phy->phy_reg2e);
151 writel(PHY_RON_RTT_225OHM, &priv->phy->phy_reg31);
152 writel(PHY_RON_RTT_225OHM, &priv->phy->phy_reg3e);
153 }
154
ddr_phy_dqs_rx_dll_cfg(struct dram_info * priv,u32 freq)155 void ddr_phy_dqs_rx_dll_cfg(struct dram_info *priv, u32 freq)
156 {
157 /* 45 degree delay */
158 writel(LEFT_CHN_A_READ_DQS_45_DELAY, &priv->phy->phy_reg28);
159 writel(RIGHT_CHN_A_READ_DQS_45_DELAY, &priv->phy->phy_reg38);
160 }
161
ddr_msch_get_max_col(struct dram_info * priv,struct ddr_schedule * sch_priv)162 void ddr_msch_get_max_col(struct dram_info *priv,
163 struct ddr_schedule *sch_priv)
164 {
165 writel(1, &priv->service_msch->ddrconf);
166 sch_priv->col = 11;
167 sch_priv->bank = 3;
168 }
169
ddr_msch_get_max_row(struct dram_info * priv,struct ddr_schedule * sch_priv)170 void ddr_msch_get_max_row(struct dram_info *priv,
171 struct ddr_schedule *sch_priv)
172 {
173 writel(1, &priv->service_msch->ddrconf);
174 sch_priv->row = 16;
175 sch_priv->col = 11;
176 sch_priv->bank = 3;
177 }
178
get_base_addr(unsigned int * reg,unsigned int offset)179 void *get_base_addr(unsigned int *reg, unsigned int offset)
180 {
181 u32 p = *(reg + 2 * offset);
182
183 return (void *)p;
184 }
185
modify_data_training(struct dram_info * priv,struct sdram_params * params_priv)186 void modify_data_training(struct dram_info *priv,
187 struct sdram_params *params_priv)
188 {
189 printascii("REGFB: 0x");
190 printhex8(readl(&priv->phy->phy_regfb));
191 printascii(", 0x");
192 printhex8(readl(&priv->phy->phy_regfc));
193 printascii("\n");
194 }
195
check_rd_gate(struct dram_info * priv)196 int check_rd_gate(struct dram_info *priv)
197 {
198 return 0;
199 }
200
enable_low_power(struct dram_info * priv,struct sdram_params * params_priv)201 void enable_low_power(struct dram_info *priv,
202 struct sdram_params *params_priv)
203 {
204 move_to_config_state(priv);
205
206 clrsetbits_le32(&priv->pctl->mcfg, PD_IDLE_MASK,
207 PD_IDLE << PD_IDLE_SHIFT);
208 clrsetbits_le32(&priv->pctl->mcfg1,
209 SR_IDLE_MASK | HW_EXIT_IDLE_EN_MASK,
210 SR_IDLE | HW_EXIT_IDLE_EN);
211
212 /* uPCTL in low_power status because of auto self-refresh */
213 writel(GO_STATE, &priv->pctl->sctl);
214 }
215
get_ddr_param(struct dram_info * sdram_priv,struct ddr_param * ddr_param)216 void get_ddr_param(struct dram_info *sdram_priv,
217 struct ddr_param *ddr_param)
218 {
219 size_t ram_size =
220 rockchip_sdram_size((phys_addr_t)&sdram_priv->grf->os_reg2);
221
222 ddr_param->count = 1;
223 ddr_param->para[0] = CONFIG_SYS_SDRAM_BASE;
224 ddr_param->para[1] = ram_size;
225 }
226
sdram_init(void)227 int sdram_init(void)
228 {
229 int ret;
230 struct ddr_param ddr_param;
231 struct dram_info *sdram_priv = &info;
232 struct driver_info *info =
233 ll_entry_start(struct driver_info, driver_info);
234 #if CONFIG_IS_ENABLED(OF_PLATDATA)
235 struct dtd_rockchip_rv1108_dmc *dtplat = (void *)info->platdata;
236 struct sdram_params *params = (void *)dtplat->rockchip_sdram_params;
237
238 sdram_priv->pctl = get_base_addr((void *)dtplat->reg, 0);
239 sdram_priv->phy = get_base_addr((void *)dtplat->reg, 1);
240 sdram_priv->service_msch = get_base_addr((void *)dtplat->reg, 2);
241 sdram_priv->grf = get_base_addr((void *)dtplat->reg, 3);
242 sdram_priv->pmu_grf = get_base_addr((void *)dtplat->reg, 4);
243 sdram_priv->cru = get_base_addr((void *)dtplat->reg, 5);
244 sdram_priv->pmu = get_base_addr((void *)dtplat->reg, 6);
245 #else
246 struct sdram_params *params = (void *)info->platdata;
247 #endif
248 ret = rv1108_sdram_init(sdram_priv, params);
249 if (ret)
250 debug("rv1108_sdram_init() fail!");
251
252 get_ddr_param(sdram_priv, &ddr_param);
253 rockchip_setup_ddr_param(&ddr_param);
254
255 return ret;
256 }
257