1// SPDX-License-Identifier: GPL-2.0+ OR MIT
2/*
3 * Copyright 2021 NXP
4 */
5#include <common.h>
6#include <asm/io.h>
7#include <asm/arch/clock.h>
8#include <asm/arch/ddr.h>
9#include <asm/arch/imx-regs.h>
10
11#define DENALI_CTL_00		(DDR_CTL_BASE_ADDR + 4 * 0)
12#define CTL_START		0x1
13
14#define DENALI_CTL_03		(DDR_CTL_BASE_ADDR + 4 * 3)
15#define DENALI_CTL_197		(DDR_CTL_BASE_ADDR + 4 * 197)
16#define DENALI_CTL_250		(DDR_CTL_BASE_ADDR + 4 * 250)
17#define DENALI_CTL_251		(DDR_CTL_BASE_ADDR + 4 * 251)
18#define DENALI_CTL_266		(DDR_CTL_BASE_ADDR + 4 * 266)
19#define DFI_INIT_COMPLETE	0x2
20
21#define DENALI_CTL_614		(DDR_CTL_BASE_ADDR + 4 * 614)
22#define DENALI_CTL_615		(DDR_CTL_BASE_ADDR + 4 * 615)
23
24#define DENALI_PI_00		(DDR_PI_BASE_ADDR + 4 * 0)
25#define PI_START		0x1
26
27#define DENALI_PI_04		(DDR_PI_BASE_ADDR + 4 * 4)
28#define DENALI_PI_11		(DDR_PI_BASE_ADDR + 4 * 11)
29#define DENALI_PI_12		(DDR_PI_BASE_ADDR + 4 * 12)
30#define DENALI_CTL_23		(DDR_CTL_BASE_ADDR + 4 * 23)
31#define DENALI_CTL_25		(DDR_CTL_BASE_ADDR + 4 * 25)
32
33#define DENALI_PHY_1624		(DDR_PHY_BASE_ADDR + 4 * 1624)
34#define DENALI_PHY_1625  	(DDR_PHY_BASE_ADDR + 4 * 1625)
35#define DENALI_PHY_1537		(DDR_PHY_BASE_ADDR + 4 * 1537)
36#define PHY_FREQ_SEL_MULTICAST_EN(X)	((X) << 8)
37#define PHY_FREQ_SEL_INDEX(X)		((X) << 16)
38
39#define DENALI_PHY_1547		(DDR_PHY_BASE_ADDR + 4 * 1547)
40#define DENALI_PHY_1555		(DDR_PHY_BASE_ADDR + 4 * 1555)
41#define DENALI_PHY_1564		(DDR_PHY_BASE_ADDR + 4 * 1564)
42#define DENALI_PHY_1565		(DDR_PHY_BASE_ADDR + 4 * 1565)
43
44static void ddr_enable_pll_bypass(void)
45{
46	u32 reg_val;
47
48	/* PI_INIT_LVL_EN=0x0  (DENALI_PI_04) */
49	reg_val = readl(DENALI_PI_04) & ~0x1;
50	writel(reg_val, DENALI_PI_04);
51
52	/* PI_FREQ_MAP=0x1  (DENALI_PI_12) */
53	writel(0x1, DENALI_PI_12);
54
55	/* PI_INIT_WORK_FREQ=0x0  (DENALI_PI_11) */
56	reg_val = readl(DENALI_PI_11) & ~(0x1f << 8);
57	writel(reg_val, DENALI_PI_11);
58
59	/* DFIBUS_FREQ_INIT=0x0  (DENALI_CTL_23) */
60	reg_val = readl(DENALI_CTL_23) & ~(0x3 << 24);
61	writel(reg_val, DENALI_CTL_23);
62
63	/* PHY_LP4_BOOT_DISABLE=0x0 (DENALI_PHY_1547) */
64	reg_val = readl(DENALI_PHY_1547) & ~(0x1 << 8);
65	writel(reg_val, DENALI_PHY_1547);
66
67	/* PHY_PLL_BYPASS=0x1 (DENALI_PHY_1624) */
68	reg_val = readl(DENALI_PHY_1624) | 0x1;
69	writel(reg_val, DENALI_PHY_1624);
70
71	/* PHY_LP4_BOOT_PLL_BYPASS to 0x1 (DENALI_PHY_1555) */
72	reg_val = readl(DENALI_PHY_1555) | 0x1;
73	writel(reg_val, DENALI_PHY_1555);
74
75	/* FREQ_CHANGE_TYPE_F0 = 0x0/FREQ_CHANGE_TYPE_F1 = 0x1/FREQ_CHANGE_TYPE_F2 = 0x2 */
76	reg_val = 0x020100;
77	writel(reg_val, DENALI_CTL_25);
78}
79
80int ddr_calibration(unsigned int fsp_table[3])
81{
82	u32 reg_val;
83	u32 int_status_init, phy_freq_req, phy_freq_type;
84	u32 lock_0, lock_1, lock_2;
85	u32 freq_chg_pt, freq_chg_cnt;
86	u32 is_lpddr4 = 0;
87
88	if (IS_ENABLED(CONFIG_IMX8ULP_DRAM_PHY_PLL_BYPASS)) {
89		ddr_enable_pll_bypass();
90		freq_chg_cnt = 0;
91		freq_chg_pt = 0;
92	} else {
93		reg_val = (readl(DENALI_CTL_00)>>8)&0xf;
94		if(reg_val == 0x7) {
95			/* LPDDR3 type */
96			set_ddr_clk(fsp_table[1] >> 1);
97			freq_chg_cnt = 0;
98			freq_chg_pt = 0;
99		} else if(reg_val == 0xb) {
100			/* LPDDR4/4x type */
101			is_lpddr4 = 1;
102			reg_val = readl(DENALI_CTL_250);
103			if (((reg_val >> 16) & 0x3) == 1)
104				freq_chg_cnt = 2;
105			else
106				freq_chg_cnt = 3;
107
108			reg_val = readl(DENALI_PI_12);
109			if(reg_val == 0x3)
110				freq_chg_pt = 1;
111			else if(reg_val == 0x7)
112				freq_chg_pt = 2;
113			else {
114				printf("frequency map(0x%x) is wrong, please check!\r\n", reg_val);
115				return -1;
116			}
117		} else {
118			printf("Incorrect DDR type configured!\r\n");
119			return -1;
120		}
121	}
122
123	/* Assert PI_START parameter and then assert START parameter in Controller. */
124	reg_val = readl(DENALI_PI_00) | PI_START;
125	writel(reg_val, DENALI_PI_00);
126
127	reg_val = readl(DENALI_CTL_00) | CTL_START;
128	writel(reg_val, DENALI_CTL_00);
129
130	/* Poll for init_done_bit in Controller interrupt status register (INT_STATUS_INIT) */
131	do {
132		if (!freq_chg_cnt) {
133			int_status_init = (readl(DENALI_CTL_266) >> 8) & 0xff;
134			/* DDR subsystem is ready for traffic. */
135			if (int_status_init & DFI_INIT_COMPLETE) {
136				debug("complete\n");
137				break;
138			}
139		}
140
141		/*
142		 * During leveling, PHY will request for freq change and SoC clock logic
143		 * should provide requested frequency
144		 * Polling SIM LPDDR_CTRL2 Bit phy_freq_chg_req until be 1'b1
145		 */
146		reg_val = readl(AVD_SIM_LPDDR_CTRL2);
147		/* DFS interrupt is set */
148		phy_freq_req = ((reg_val >> 7) & 0x1) && ((reg_val >> 15) & 0x1);
149		if (phy_freq_req) {
150			phy_freq_type = reg_val & 0x1F;
151			if (phy_freq_type == 0x00) {
152				debug("Poll for freq_chg_req on SIM register and change to F0 frequency.\n");
153				set_ddr_clk(fsp_table[phy_freq_type] >> 1);
154
155				/* Write 1'b1 at LPDDR_CTRL2 bit phy_freq_cfg_ack */
156				reg_val = readl(AVD_SIM_LPDDR_CTRL2);
157				writel(reg_val | (0x1 << 6), AVD_SIM_LPDDR_CTRL2);
158			} else if (phy_freq_type == 0x01) {
159				debug("Poll for freq_chg_req on SIM register and change to F1 frequency.\n");
160				set_ddr_clk(fsp_table[phy_freq_type] >> 1);
161
162				/* Write 1'b1 at LPDDR_CTRL2 bit phy_freq_cfg_ack */
163				reg_val = readl(AVD_SIM_LPDDR_CTRL2);
164				writel(reg_val | (0x1 << 6), AVD_SIM_LPDDR_CTRL2);
165				if (freq_chg_pt == 1)
166					freq_chg_cnt--;
167			} else if (phy_freq_type == 0x02) {
168				debug("Poll for freq_chg_req on SIM register and change to F2 frequency.\n");
169				set_ddr_clk(fsp_table[phy_freq_type] >> 1);
170
171				/* Write 1'b1 at LPDDR_CTRL2 bit phy_freq_cfg_ack */
172				reg_val = readl(AVD_SIM_LPDDR_CTRL2);
173				writel(reg_val | (0x1 << 6), AVD_SIM_LPDDR_CTRL2);
174				if (freq_chg_pt == 2)
175					freq_chg_cnt--;
176			}
177
178			/* Hardware clear the ack on falling edge of LPDDR_CTRL2:phy_freq_chg_reg */
179			/* Ensure the ack is clear before starting to poll request again */
180			while ((readl(AVD_SIM_LPDDR_CTRL2) & BIT(6)))
181				;
182		}
183	} while (1);
184
185	/* Check PLL lock status */
186	lock_0 = readl(DENALI_PHY_1564) & 0xffff;
187	lock_1 = (readl(DENALI_PHY_1564) >> 16) & 0xffff;
188	lock_2 = readl(DENALI_PHY_1565) & 0xffff;
189
190	if ((lock_0 & 0x3) != 0x3 || (lock_1 & 0x3) != 0x3 || (lock_2 & 0x3) != 0x3) {
191		debug("De-Skew PLL failed to lock\n");
192		debug("lock_0=0x%x, lock_1=0x%x, lock_2=0x%x\n", lock_0, lock_1, lock_2);
193		return -1;
194	}
195
196	debug("De-Skew PLL is locked and ready\n");
197
198	/* Change LPDDR4 FREQ1 to bypass mode if it is lower than 200MHz */
199	if(is_lpddr4 && fsp_table[1] < 400) {
200		/* Set FREQ1 to bypass mode */
201		reg_val = PHY_FREQ_SEL_MULTICAST_EN(0) | PHY_FREQ_SEL_INDEX(0);
202		writel(reg_val, DENALI_PHY_1537);
203
204		/* PHY_PLL_BYPASS=0x1 (DENALI_PHY_1624) */
205		reg_val =readl(DENALI_PHY_1624) | 0x1;
206		writel(reg_val, DENALI_PHY_1624);
207
208		/* DENALI_PHY_1625: bypass mode in PHY PLL */
209		reg_val =readl(DENALI_PHY_1625) & ~0xf;
210		writel(reg_val, DENALI_PHY_1625);
211	}
212
213	return 0;
214}
215
216static void save_dram_config(struct dram_timing_info2 *timing_info, unsigned long saved_timing_base)
217{
218	int i = 0;
219	struct dram_timing_info2 *saved_timing = (struct dram_timing_info2 *)saved_timing_base;
220	struct dram_cfg_param *cfg;
221
222	saved_timing->ctl_cfg_num = timing_info->ctl_cfg_num;
223	saved_timing->phy_f1_cfg_num = timing_info->phy_f1_cfg_num;
224	saved_timing->phy_f2_cfg_num = timing_info->phy_f2_cfg_num;
225
226	/* save the fsp table */
227	for (i = 0; i < 3; i++)
228		saved_timing->fsp_table[i] = timing_info->fsp_table[i];
229
230	cfg = (struct dram_cfg_param *)(saved_timing_base +
231					sizeof(*timing_info));
232
233	/* save ctl config */
234	saved_timing->ctl_cfg = cfg;
235	for (i = 0; i < timing_info->ctl_cfg_num; i++) {
236		cfg->reg = timing_info->ctl_cfg[i].reg;
237		cfg->val = timing_info->ctl_cfg[i].val;
238		cfg++;
239	}
240
241	/* save phy f1 config */
242	saved_timing->phy_f1_cfg = cfg;
243	for (i = 0; i < timing_info->phy_f1_cfg_num; i++) {
244		cfg->reg = timing_info->phy_f1_cfg[i].reg;
245		cfg->val = timing_info->phy_f1_cfg[i].val;
246		cfg++;
247	}
248
249	/* save phy f2 config */
250	saved_timing->phy_f2_cfg = cfg;
251	for (i = 0; i < timing_info->phy_f2_cfg_num; i++) {
252		cfg->reg = timing_info->phy_f2_cfg[i].reg;
253		cfg->val = timing_info->phy_f2_cfg[i].val;
254		cfg++;
255	}
256}
257
258int ddr_init(struct dram_timing_info2 *dram_timing)
259{
260	int i;
261
262	if (IS_ENABLED(CONFIG_IMX8ULP_DRAM_PHY_PLL_BYPASS)) {
263		/* Use PLL bypass for boot freq */
264		/* Since PLL can't generate the double freq, Need ddr clock to generate it. */
265		set_ddr_clk(dram_timing->fsp_table[0]); /* Set to boot freq */
266		setbits_le32(AVD_SIM_BASE_ADDR, 0x1); /* SIM_DDR_CTRL_DIV2_EN */
267	} else {
268		set_ddr_clk(dram_timing->fsp_table[0] >> 1); /* Set to boot freq */
269		clrbits_le32(AVD_SIM_BASE_ADDR, 0x1); /* SIM_DDR_CTRL_DIV2_EN */
270	}
271
272	/* save the dram config into sram for low power mode */
273	save_dram_config(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE);
274
275	/* Initialize CTL registers */
276	for (i = 0; i < dram_timing->ctl_cfg_num; i++)
277		writel(dram_timing->ctl_cfg[i].val, (ulong)dram_timing->ctl_cfg[i].reg);
278
279	/* Initialize PI registers */
280	for (i = 0; i < dram_timing->pi_cfg_num; i++)
281		writel(dram_timing->pi_cfg[i].val, (ulong)dram_timing->pi_cfg[i].reg);
282
283	/* Write PHY regiters for all 3 frequency points (48Mhz/384Mhz/528Mhz): f1_index=0 */
284	writel(PHY_FREQ_SEL_MULTICAST_EN(1) | PHY_FREQ_SEL_INDEX(0), DENALI_PHY_1537);
285	for (i = 0; i < dram_timing->phy_f1_cfg_num; i++)
286		writel(dram_timing->phy_f1_cfg[i].val, (ulong)dram_timing->phy_f1_cfg[i].reg);
287
288	/* Write PHY regiters for freqency point 2 (528Mhz): f2_index=1 */
289	writel(PHY_FREQ_SEL_MULTICAST_EN(0) | PHY_FREQ_SEL_INDEX(1), DENALI_PHY_1537);
290	for (i = 0; i < dram_timing->phy_f2_cfg_num; i++)
291		writel(dram_timing->phy_f2_cfg[i].val, (ulong)dram_timing->phy_f2_cfg[i].reg);
292
293	/* Re-enable MULTICAST mode */
294	writel(PHY_FREQ_SEL_MULTICAST_EN(1) | PHY_FREQ_SEL_INDEX(0), DENALI_PHY_1537);
295
296	return ddr_calibration(dram_timing->fsp_table);
297}
298