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