1b86c816cSZhihuan He // SPDX-License-Identifier: GPL-2.0+
295b95808SZhihuan He /*
3b86c816cSZhihuan He * Copyright (C) 2020 Rockchip Electronics Co., Ltd
495b95808SZhihuan He */
5b86c816cSZhihuan He
695b95808SZhihuan He #include <common.h>
7b86c816cSZhihuan He #include <debug_uart.h>
895b95808SZhihuan He #include <dm.h>
995b95808SZhihuan He #include <dm/root.h>
1095b95808SZhihuan He #include <dt-structs.h>
1195b95808SZhihuan He #include <regmap.h>
1295b95808SZhihuan He #include <asm/io.h>
1395b95808SZhihuan He #include <asm/types.h>
1495b95808SZhihuan He #include <asm/arch/hardware.h>
1595b95808SZhihuan He #include <asm/arch/sdram_rv1108.h>
1695b95808SZhihuan He #include <asm/arch/timer.h>
17e1f97ec3SYouMin Chen #include <asm/arch/sdram.h>
1895b95808SZhihuan He
1995b95808SZhihuan He struct dram_info info;
2095b95808SZhihuan He
2195b95808SZhihuan He struct rockchip_dmc_plat {
2295b95808SZhihuan He #if CONFIG_IS_ENABLED(OF_PLATDATA)
2395b95808SZhihuan He struct dtd_rockchip_rv1108_dmc dtplat;
2495b95808SZhihuan He #else
2595b95808SZhihuan He struct sdram_params params;
2695b95808SZhihuan He #endif
2795b95808SZhihuan He struct regmap *map;
2895b95808SZhihuan He };
2995b95808SZhihuan He
enable_ddr_io_ret(struct dram_info * priv)3095b95808SZhihuan He void enable_ddr_io_ret(struct dram_info *priv)
3195b95808SZhihuan He {
3295b95808SZhihuan He writel(DDR_IO_RET_EN, &priv->pmu->sft_con);
3395b95808SZhihuan He rk_clrsetreg(&priv->pmu_grf->soc_con[0],
3495b95808SZhihuan He DDRPHY_BUFFEREN_CORE_MASK,
3595b95808SZhihuan He DDRPHY_BUFFEREN_CORE_EN);
3695b95808SZhihuan He }
3795b95808SZhihuan He
rkdclk_init(struct dram_info * priv,struct sdram_params * params_priv)3895b95808SZhihuan He void rkdclk_init(struct dram_info *priv,
3995b95808SZhihuan He struct sdram_params *params_priv)
4095b95808SZhihuan He {
4195b95808SZhihuan He rk_clrsetreg(&priv->cru->pll[1].con3, WORK_MODE_MASK,
4295b95808SZhihuan He WORK_MODE_SLOW << WORK_MODE_SHIFT);
4395b95808SZhihuan He rk_clrsetreg(&priv->cru->pll[1].con3, GLOBAL_POWER_DOWN_MASK,
4495b95808SZhihuan He GLOBAL_POWER_DOWN << GLOBAL_POWER_DOWN_SHIFT);
4595b95808SZhihuan He rk_clrsetreg(&priv->cru->pll[1].con3, DSMPD_MASK,
4695b95808SZhihuan He INTEGER_MODE << DSMPD_SHIFT);
4795b95808SZhihuan He rk_clrsetreg(&priv->cru->pll[1].con0, FBDIV_MASK,
4895b95808SZhihuan He params_priv->dpll_init_cfg.fbdiv << FBDIV_SHIFT);
4995b95808SZhihuan He rk_clrsetreg(&priv->cru->pll[1].con1,
5095b95808SZhihuan He POSTDIV2_MASK | POSTDIV1_MASK | REFDIV_MASK,
5195b95808SZhihuan He params_priv->dpll_init_cfg.postdiv2 << POSTDIV2_SHIFT |
5295b95808SZhihuan He params_priv->dpll_init_cfg.postdiv1 << POSTDIV1_SHIFT |
5395b95808SZhihuan He params_priv->dpll_init_cfg.refdiv << REFDIV_SHIFT);
5495b95808SZhihuan He rk_clrsetreg(&priv->cru->pll[1].con3, GLOBAL_POWER_DOWN_MASK,
5595b95808SZhihuan He GLOBAL_POWER_UP << GLOBAL_POWER_DOWN_SHIFT);
5695b95808SZhihuan He while (!(readl(&priv->cru->pll[1].con2) & (1u << LOCK_STA_SHIFT)))
5795b95808SZhihuan He udelay(1);
5895b95808SZhihuan He
5995b95808SZhihuan He rk_clrsetreg(&priv->cru->clksel_con[4], CLK_DDR_PLL_SEL_MASK |
6095b95808SZhihuan He CLK_DDR_DIV_CON_MASK, 0 << CLK_DDR_PLL_SEL_SHIFT |
6195b95808SZhihuan He 0 << CLK_DDR_DIV_CON_SHIFT);
6295b95808SZhihuan He rk_clrsetreg(&priv->cru->pll[1].con3, WORK_MODE_MASK,
6395b95808SZhihuan He WORK_MODE_NORMAL << WORK_MODE_SHIFT);
6495b95808SZhihuan He }
6595b95808SZhihuan He
phy_pctrl_reset_cru(struct dram_info * priv)6695b95808SZhihuan He void phy_pctrl_reset_cru(struct dram_info *priv)
6795b95808SZhihuan He {
6895b95808SZhihuan He rk_clrsetreg(&priv->cru->softrst_con[2], DDRUPCTL_PSRSTN_REQ_MASK |
6995b95808SZhihuan He DDRUPCTL_NSRSTN_REQ_MASK,
7095b95808SZhihuan He DDRUPCTL_PSRSTN_REQ << DDRUPCTL_PSRSTN_REQ_SHIFT |
7195b95808SZhihuan He DDRUPCTL_NSRSTN_REQ << DDRUPCTL_NSRSTN_REQ_SHIFT);
7295b95808SZhihuan He rk_clrsetreg(&priv->cru->softrst_con[1],
7395b95808SZhihuan He DDRPHY_SRSTN_CLKDIV_REQ_MASK | DDRPHY_SRSTN_REQ_MASK |
7495b95808SZhihuan He DDRPHY_PSRSTN_REQ_MASK,
7595b95808SZhihuan He DDRPHY_SRSTN_CLKDIV_REQ << DDRPHY_SRSTN_CLKDIV_REQ_SHIFT |
7695b95808SZhihuan He DDRPHY_SRSTN_REQ << DDRPHY_SRSTN_REQ_SHIFT |
7795b95808SZhihuan He DDRPHY_PSRSTN_REQ << DDRPHY_PSRSTN_REQ_SHIFT);
7895b95808SZhihuan He
7995b95808SZhihuan He udelay(10);
8095b95808SZhihuan He
8195b95808SZhihuan He rk_clrsetreg(&priv->cru->softrst_con[1],
8295b95808SZhihuan He DDRPHY_SRSTN_CLKDIV_REQ_MASK | DDRPHY_SRSTN_REQ_MASK |
8395b95808SZhihuan He DDRPHY_PSRSTN_REQ_MASK,
8495b95808SZhihuan He DDRPHY_SRSTN_CLKDIV_DIS << DDRPHY_SRSTN_CLKDIV_REQ_SHIFT |
8595b95808SZhihuan He DDRPHY_PSRSTN_DIS << DDRPHY_PSRSTN_REQ_SHIFT |
8695b95808SZhihuan He DDRPHY_SRSTN_DIS << DDRPHY_SRSTN_REQ_SHIFT);
8795b95808SZhihuan He udelay(10);
8895b95808SZhihuan He
8995b95808SZhihuan He rk_clrsetreg(&priv->cru->softrst_con[2], DDRUPCTL_PSRSTN_REQ_MASK |
9095b95808SZhihuan He DDRUPCTL_NSRSTN_REQ_MASK,
9195b95808SZhihuan He DDRUPCTL_PSRSTN_DIS << DDRUPCTL_PSRSTN_REQ_SHIFT |
9295b95808SZhihuan He DDRUPCTL_NSRSTN_DIS << DDRUPCTL_NSRSTN_REQ_SHIFT);
9395b95808SZhihuan He udelay(10);
9495b95808SZhihuan He }
9595b95808SZhihuan He
pctl_cfg_grf(struct dram_info * priv,struct sdram_params * params_priv)96b86c816cSZhihuan He void pctl_cfg_grf(struct dram_info *priv,
97b86c816cSZhihuan He struct sdram_params *params_priv)
9895b95808SZhihuan He {
9995b95808SZhihuan He writel(RK_SETBITS(MSCH_MAINDDR3 | MSCH_MAINPARTIALPOP),
10095b95808SZhihuan He &priv->grf->soc_con0);
10195b95808SZhihuan He }
10295b95808SZhihuan He
ddr_msch_cfg(struct dram_info * priv,struct sdram_params * params_priv)103b86c816cSZhihuan He void ddr_msch_cfg(struct dram_info *priv,
104b86c816cSZhihuan He struct sdram_params *params_priv)
105b86c816cSZhihuan He {
106b86c816cSZhihuan He writel((readl(&priv->service_msch->ddrtiming) & BWRATIO_HALF_BW) |
107b86c816cSZhihuan He params_priv->ddr_timing_t.noc_timing.d32,
108b86c816cSZhihuan He &priv->service_msch->ddrtiming);
109b86c816cSZhihuan He writel(params_priv->ddr_timing_t.readlatency,
110b86c816cSZhihuan He &priv->service_msch->readlatency);
111b86c816cSZhihuan He writel(params_priv->ddr_timing_t.activate.d32,
112b86c816cSZhihuan He &priv->service_msch->activate);
113b86c816cSZhihuan He writel(params_priv->ddr_timing_t.devtodev,
114b86c816cSZhihuan He &priv->service_msch->devtodev);
115b86c816cSZhihuan He }
116b86c816cSZhihuan He
ddr_msch_cfg_rbc(struct sdram_params * params_priv,struct dram_info * priv)117b86c816cSZhihuan He void ddr_msch_cfg_rbc(struct sdram_params *params_priv,
118b86c816cSZhihuan He struct dram_info *priv)
119b86c816cSZhihuan He {
120b86c816cSZhihuan He int i = 0;
121b86c816cSZhihuan He
122b86c816cSZhihuan He if (params_priv->ddr_config_t.col == 10)
123b86c816cSZhihuan He i = 2;
124b86c816cSZhihuan He else
125b86c816cSZhihuan He i = 3;
126b86c816cSZhihuan He writel(i, &priv->service_msch->ddrconf);
127b86c816cSZhihuan He }
128b86c816cSZhihuan He
ddr_phy_skew_cfg(struct dram_info * priv)129b86c816cSZhihuan He void ddr_phy_skew_cfg(struct dram_info *priv)
130b86c816cSZhihuan He {
131b86c816cSZhihuan He }
132b86c816cSZhihuan He
set_ds_odt(struct dram_info * priv,struct sdram_params * params_priv)133b86c816cSZhihuan He void set_ds_odt(struct dram_info *priv,
134b86c816cSZhihuan He struct sdram_params *params_priv)
135b86c816cSZhihuan He {
136b86c816cSZhihuan He /* set phy drive impedance */
137b86c816cSZhihuan He writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg11);
138b86c816cSZhihuan He clrsetbits_le32(&priv->phy->phy_reg12, CMD_PRCOMP_MASK,
139b86c816cSZhihuan He PHY_RON_RTT_34OHM << CMD_PRCOMP_SHIFT);
140b86c816cSZhihuan He
141b86c816cSZhihuan He writel(PHY_RON_RTT_45OHM, &priv->phy->phy_reg16);
142b86c816cSZhihuan He writel(PHY_RON_RTT_45OHM, &priv->phy->phy_reg18);
143b86c816cSZhihuan He writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg20);
144b86c816cSZhihuan He writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg2f);
145b86c816cSZhihuan He writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg30);
146b86c816cSZhihuan He writel(PHY_RON_RTT_34OHM, &priv->phy->phy_reg3f);
147b86c816cSZhihuan He
148b86c816cSZhihuan He /*set phy odt*/
149b86c816cSZhihuan He writel(PHY_RON_RTT_225OHM, &priv->phy->phy_reg21);
150b86c816cSZhihuan He writel(PHY_RON_RTT_225OHM, &priv->phy->phy_reg2e);
151b86c816cSZhihuan He writel(PHY_RON_RTT_225OHM, &priv->phy->phy_reg31);
152b86c816cSZhihuan He writel(PHY_RON_RTT_225OHM, &priv->phy->phy_reg3e);
153b86c816cSZhihuan He }
154b86c816cSZhihuan He
ddr_phy_dqs_rx_dll_cfg(struct dram_info * priv,u32 freq)155b86c816cSZhihuan He void ddr_phy_dqs_rx_dll_cfg(struct dram_info *priv, u32 freq)
156b86c816cSZhihuan He {
157b86c816cSZhihuan He /* 45 degree delay */
158b86c816cSZhihuan He writel(LEFT_CHN_A_READ_DQS_45_DELAY, &priv->phy->phy_reg28);
159b86c816cSZhihuan He writel(RIGHT_CHN_A_READ_DQS_45_DELAY, &priv->phy->phy_reg38);
160b86c816cSZhihuan He }
161b86c816cSZhihuan He
ddr_msch_get_max_col(struct dram_info * priv,struct ddr_schedule * sch_priv)162b86c816cSZhihuan He void ddr_msch_get_max_col(struct dram_info *priv,
163b86c816cSZhihuan He struct ddr_schedule *sch_priv)
164b86c816cSZhihuan He {
165b86c816cSZhihuan He writel(1, &priv->service_msch->ddrconf);
166b86c816cSZhihuan He sch_priv->col = 11;
167b86c816cSZhihuan He sch_priv->bank = 3;
168b86c816cSZhihuan He }
169b86c816cSZhihuan He
ddr_msch_get_max_row(struct dram_info * priv,struct ddr_schedule * sch_priv)170b86c816cSZhihuan He void ddr_msch_get_max_row(struct dram_info *priv,
171b86c816cSZhihuan He struct ddr_schedule *sch_priv)
172b86c816cSZhihuan He {
173b86c816cSZhihuan He writel(1, &priv->service_msch->ddrconf);
174b86c816cSZhihuan He sch_priv->row = 16;
175b86c816cSZhihuan He sch_priv->col = 11;
176b86c816cSZhihuan He sch_priv->bank = 3;
177b86c816cSZhihuan He }
178b86c816cSZhihuan He
get_base_addr(unsigned int * reg,unsigned int offset)17995b95808SZhihuan He void *get_base_addr(unsigned int *reg, unsigned int offset)
18095b95808SZhihuan He {
18195b95808SZhihuan He u32 p = *(reg + 2 * offset);
18295b95808SZhihuan He
18395b95808SZhihuan He return (void *)p;
18495b95808SZhihuan He }
18595b95808SZhihuan He
modify_data_training(struct dram_info * priv,struct sdram_params * params_priv)186b86c816cSZhihuan He void modify_data_training(struct dram_info *priv,
187b86c816cSZhihuan He struct sdram_params *params_priv)
188b86c816cSZhihuan He {
189b86c816cSZhihuan He printascii("REGFB: 0x");
190b86c816cSZhihuan He printhex8(readl(&priv->phy->phy_regfb));
191b86c816cSZhihuan He printascii(", 0x");
192b86c816cSZhihuan He printhex8(readl(&priv->phy->phy_regfc));
193b86c816cSZhihuan He printascii("\n");
194b86c816cSZhihuan He }
195b86c816cSZhihuan He
check_rd_gate(struct dram_info * priv)196b86c816cSZhihuan He int check_rd_gate(struct dram_info *priv)
197b86c816cSZhihuan He {
198b86c816cSZhihuan He return 0;
199b86c816cSZhihuan He }
200b86c816cSZhihuan He
enable_low_power(struct dram_info * priv,struct sdram_params * params_priv)201b86c816cSZhihuan He void enable_low_power(struct dram_info *priv,
202b86c816cSZhihuan He struct sdram_params *params_priv)
203b86c816cSZhihuan He {
204b86c816cSZhihuan He move_to_config_state(priv);
205b86c816cSZhihuan He
206b86c816cSZhihuan He clrsetbits_le32(&priv->pctl->mcfg, PD_IDLE_MASK,
207b86c816cSZhihuan He PD_IDLE << PD_IDLE_SHIFT);
208b86c816cSZhihuan He clrsetbits_le32(&priv->pctl->mcfg1,
209b86c816cSZhihuan He SR_IDLE_MASK | HW_EXIT_IDLE_EN_MASK,
210b86c816cSZhihuan He SR_IDLE | HW_EXIT_IDLE_EN);
211b86c816cSZhihuan He
212*5d4a323cSTang Yun ping /* DDRCTL in low_power status because of auto self-refresh */
213b86c816cSZhihuan He writel(GO_STATE, &priv->pctl->sctl);
214b86c816cSZhihuan He }
215b86c816cSZhihuan He
get_ddr_param(struct dram_info * sdram_priv,struct ddr_param * ddr_param)216e5f39383SZhihuan He void get_ddr_param(struct dram_info *sdram_priv,
217e5f39383SZhihuan He struct ddr_param *ddr_param)
218e5f39383SZhihuan He {
219e5f39383SZhihuan He size_t ram_size =
220e5f39383SZhihuan He rockchip_sdram_size((phys_addr_t)&sdram_priv->grf->os_reg2);
221e5f39383SZhihuan He
222e5f39383SZhihuan He ddr_param->count = 1;
223e5f39383SZhihuan He ddr_param->para[0] = CONFIG_SYS_SDRAM_BASE;
224e5f39383SZhihuan He ddr_param->para[1] = ram_size;
225e5f39383SZhihuan He }
226e5f39383SZhihuan He
sdram_init(void)227891b189dSYouMin Chen int sdram_init(void)
22895b95808SZhihuan He {
22995b95808SZhihuan He int ret;
230e5f39383SZhihuan He struct ddr_param ddr_param;
23195b95808SZhihuan He struct dram_info *sdram_priv = &info;
23295b95808SZhihuan He struct driver_info *info =
23395b95808SZhihuan He ll_entry_start(struct driver_info, driver_info);
23495b95808SZhihuan He #if CONFIG_IS_ENABLED(OF_PLATDATA)
23595b95808SZhihuan He struct dtd_rockchip_rv1108_dmc *dtplat = (void *)info->platdata;
23695b95808SZhihuan He struct sdram_params *params = (void *)dtplat->rockchip_sdram_params;
23795b95808SZhihuan He
23895b95808SZhihuan He sdram_priv->pctl = get_base_addr((void *)dtplat->reg, 0);
23995b95808SZhihuan He sdram_priv->phy = get_base_addr((void *)dtplat->reg, 1);
24095b95808SZhihuan He sdram_priv->service_msch = get_base_addr((void *)dtplat->reg, 2);
24195b95808SZhihuan He sdram_priv->grf = get_base_addr((void *)dtplat->reg, 3);
24295b95808SZhihuan He sdram_priv->pmu_grf = get_base_addr((void *)dtplat->reg, 4);
24395b95808SZhihuan He sdram_priv->cru = get_base_addr((void *)dtplat->reg, 5);
24495b95808SZhihuan He sdram_priv->pmu = get_base_addr((void *)dtplat->reg, 6);
24595b95808SZhihuan He #else
24695b95808SZhihuan He struct sdram_params *params = (void *)info->platdata;
24795b95808SZhihuan He #endif
24895b95808SZhihuan He ret = rv1108_sdram_init(sdram_priv, params);
24995b95808SZhihuan He if (ret)
25095b95808SZhihuan He debug("rv1108_sdram_init() fail!");
251891b189dSYouMin Chen
252e5f39383SZhihuan He get_ddr_param(sdram_priv, &ddr_param);
253e5f39383SZhihuan He rockchip_setup_ddr_param(&ddr_param);
254e5f39383SZhihuan He
255891b189dSYouMin Chen return ret;
25695b95808SZhihuan He }
257