xref: /openbmc/u-boot/arch/arm/mach-imx/mx7/ddr.c (revision 2f07a9a6)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2258bad41SUri Mashiach /*
3258bad41SUri Mashiach  * DDR controller configuration for the i.MX7 architecture
4258bad41SUri Mashiach  *
5258bad41SUri Mashiach  * (C) Copyright 2017 CompuLab, Ltd. http://www.compulab.com
6258bad41SUri Mashiach  *
7258bad41SUri Mashiach  * Author: Uri Mashiach <uri.mashiach@compulab.co.il>
8258bad41SUri Mashiach  */
9258bad41SUri Mashiach 
10258bad41SUri Mashiach #include <linux/types.h>
11258bad41SUri Mashiach #include <asm/io.h>
12258bad41SUri Mashiach #include <asm/arch/imx-regs.h>
13258bad41SUri Mashiach #include <asm/arch/crm_regs.h>
14258bad41SUri Mashiach #include <asm/arch/mx7-ddr.h>
15258bad41SUri Mashiach #include <common.h>
16258bad41SUri Mashiach 
17258bad41SUri Mashiach /*
18258bad41SUri Mashiach  * Routine: mx7_dram_cfg
19258bad41SUri Mashiach  * Description: DDR controller configuration
20258bad41SUri Mashiach  *
21258bad41SUri Mashiach  * @ddrc_regs_val: DDRC registers value
22258bad41SUri Mashiach  * @ddrc_mp_val: DDRC_MP registers value
23258bad41SUri Mashiach  * @ddr_phy_regs_val: DDR_PHY registers value
24258bad41SUri Mashiach  * @calib_param: calibration parameters
25258bad41SUri Mashiach  *
26258bad41SUri Mashiach  */
mx7_dram_cfg(struct ddrc * ddrc_regs_val,struct ddrc_mp * ddrc_mp_val,struct ddr_phy * ddr_phy_regs_val,struct mx7_calibration * calib_param)27258bad41SUri Mashiach void mx7_dram_cfg(struct ddrc *ddrc_regs_val, struct ddrc_mp *ddrc_mp_val,
28258bad41SUri Mashiach 		  struct ddr_phy *ddr_phy_regs_val,
29258bad41SUri Mashiach 		  struct mx7_calibration *calib_param)
30258bad41SUri Mashiach {
31258bad41SUri Mashiach 	struct src *const src_regs = (struct src *)SRC_BASE_ADDR;
32258bad41SUri Mashiach 	struct ddrc *const ddrc_regs = (struct ddrc *)DDRC_IPS_BASE_ADDR;
33258bad41SUri Mashiach 	struct ddrc_mp *const ddrc_mp_reg = (struct ddrc_mp *)DDRC_MP_BASE_ADDR;
34258bad41SUri Mashiach 	struct ddr_phy *const ddr_phy_regs =
35258bad41SUri Mashiach 		(struct ddr_phy *)DDRPHY_IPS_BASE_ADDR;
36258bad41SUri Mashiach 	struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs =
37258bad41SUri Mashiach 		(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
38258bad41SUri Mashiach 	int i;
39258bad41SUri Mashiach 
40258bad41SUri Mashiach 	/* Assert DDR Controller preset and DDR PHY reset */
41258bad41SUri Mashiach 	writel(SRC_DDRC_RCR_DDRC_CORE_RST_MASK, &src_regs->ddrc_rcr);
42258bad41SUri Mashiach 
43258bad41SUri Mashiach 	/* DDR controller configuration */
44258bad41SUri Mashiach 	writel(ddrc_regs_val->mstr, &ddrc_regs->mstr);
45258bad41SUri Mashiach 	writel(ddrc_regs_val->rfshtmg, &ddrc_regs->rfshtmg);
46258bad41SUri Mashiach 	writel(ddrc_mp_val->pctrl_0, &ddrc_mp_reg->pctrl_0);
47258bad41SUri Mashiach 	writel(ddrc_regs_val->init1, &ddrc_regs->init1);
48258bad41SUri Mashiach 	writel(ddrc_regs_val->init0, &ddrc_regs->init0);
49258bad41SUri Mashiach 	writel(ddrc_regs_val->init3, &ddrc_regs->init3);
50258bad41SUri Mashiach 	writel(ddrc_regs_val->init4, &ddrc_regs->init4);
51258bad41SUri Mashiach 	writel(ddrc_regs_val->init5, &ddrc_regs->init5);
52258bad41SUri Mashiach 	writel(ddrc_regs_val->rankctl, &ddrc_regs->rankctl);
53258bad41SUri Mashiach 	writel(ddrc_regs_val->dramtmg0, &ddrc_regs->dramtmg0);
54258bad41SUri Mashiach 	writel(ddrc_regs_val->dramtmg1, &ddrc_regs->dramtmg1);
55258bad41SUri Mashiach 	writel(ddrc_regs_val->dramtmg2, &ddrc_regs->dramtmg2);
56258bad41SUri Mashiach 	writel(ddrc_regs_val->dramtmg3, &ddrc_regs->dramtmg3);
57258bad41SUri Mashiach 	writel(ddrc_regs_val->dramtmg4, &ddrc_regs->dramtmg4);
58258bad41SUri Mashiach 	writel(ddrc_regs_val->dramtmg5, &ddrc_regs->dramtmg5);
59258bad41SUri Mashiach 	writel(ddrc_regs_val->dramtmg8, &ddrc_regs->dramtmg8);
60258bad41SUri Mashiach 	writel(ddrc_regs_val->zqctl0, &ddrc_regs->zqctl0);
61258bad41SUri Mashiach 	writel(ddrc_regs_val->dfitmg0, &ddrc_regs->dfitmg0);
62258bad41SUri Mashiach 	writel(ddrc_regs_val->dfitmg1, &ddrc_regs->dfitmg1);
63258bad41SUri Mashiach 	writel(ddrc_regs_val->dfiupd0, &ddrc_regs->dfiupd0);
64258bad41SUri Mashiach 	writel(ddrc_regs_val->dfiupd1, &ddrc_regs->dfiupd1);
65258bad41SUri Mashiach 	writel(ddrc_regs_val->dfiupd2, &ddrc_regs->dfiupd2);
66258bad41SUri Mashiach 	writel(ddrc_regs_val->addrmap0, &ddrc_regs->addrmap0);
67258bad41SUri Mashiach 	writel(ddrc_regs_val->addrmap1, &ddrc_regs->addrmap1);
68258bad41SUri Mashiach 	writel(ddrc_regs_val->addrmap4, &ddrc_regs->addrmap4);
69258bad41SUri Mashiach 	writel(ddrc_regs_val->addrmap5, &ddrc_regs->addrmap5);
70258bad41SUri Mashiach 	writel(ddrc_regs_val->addrmap6, &ddrc_regs->addrmap6);
71258bad41SUri Mashiach 	writel(ddrc_regs_val->odtcfg, &ddrc_regs->odtcfg);
72258bad41SUri Mashiach 	writel(ddrc_regs_val->odtmap, &ddrc_regs->odtmap);
73258bad41SUri Mashiach 
74258bad41SUri Mashiach 	/* De-assert DDR Controller preset and DDR PHY reset */
75258bad41SUri Mashiach 	clrbits_le32(&src_regs->ddrc_rcr, SRC_DDRC_RCR_DDRC_CORE_RST_MASK);
76258bad41SUri Mashiach 
77258bad41SUri Mashiach 	/* PHY configuration */
78258bad41SUri Mashiach 	writel(ddr_phy_regs_val->phy_con0, &ddr_phy_regs->phy_con0);
79258bad41SUri Mashiach 	writel(ddr_phy_regs_val->phy_con1, &ddr_phy_regs->phy_con1);
80258bad41SUri Mashiach 	writel(ddr_phy_regs_val->phy_con4, &ddr_phy_regs->phy_con4);
81258bad41SUri Mashiach 	writel(ddr_phy_regs_val->mdll_con0, &ddr_phy_regs->mdll_con0);
82258bad41SUri Mashiach 	writel(ddr_phy_regs_val->drvds_con0, &ddr_phy_regs->drvds_con0);
83258bad41SUri Mashiach 	writel(ddr_phy_regs_val->offset_wr_con0, &ddr_phy_regs->offset_wr_con0);
84258bad41SUri Mashiach 	writel(ddr_phy_regs_val->offset_rd_con0, &ddr_phy_regs->offset_rd_con0);
85258bad41SUri Mashiach 	writel(ddr_phy_regs_val->cmd_sdll_con0 |
86258bad41SUri Mashiach 	       DDR_PHY_CMD_SDLL_CON0_CTRL_RESYNC_MASK,
87258bad41SUri Mashiach 	       &ddr_phy_regs->cmd_sdll_con0);
88258bad41SUri Mashiach 	writel(ddr_phy_regs_val->cmd_sdll_con0 &
89258bad41SUri Mashiach 	       ~DDR_PHY_CMD_SDLL_CON0_CTRL_RESYNC_MASK,
90258bad41SUri Mashiach 	       &ddr_phy_regs->cmd_sdll_con0);
91258bad41SUri Mashiach 	writel(ddr_phy_regs_val->offset_lp_con0, &ddr_phy_regs->offset_lp_con0);
92258bad41SUri Mashiach 
93258bad41SUri Mashiach 	/* calibration */
94258bad41SUri Mashiach 	for (i = 0; i < calib_param->num_val; i++)
95258bad41SUri Mashiach 		writel(calib_param->values[i], &ddr_phy_regs->zq_con0);
96258bad41SUri Mashiach 
97258bad41SUri Mashiach 	/* Wake_up DDR PHY */
98258bad41SUri Mashiach 	HW_CCM_CCGR_WR(CCGR_IDX_DDR, CCM_CLK_ON_N_N);
99258bad41SUri Mashiach 	writel(IOMUXC_GPR_GPR8_ddr_phy_ctrl_wake_up(0xf) |
100258bad41SUri Mashiach 	       IOMUXC_GPR_GPR8_ddr_phy_dfi_init_start_MASK,
101258bad41SUri Mashiach 	       &iomuxc_gpr_regs->gpr[8]);
102258bad41SUri Mashiach 	HW_CCM_CCGR_WR(CCGR_IDX_DDR, CCM_CLK_ON_R_W);
103258bad41SUri Mashiach }
104258bad41SUri Mashiach 
105258bad41SUri Mashiach /*
106258bad41SUri Mashiach  * Routine: imx_ddr_size
107258bad41SUri Mashiach  * Description: extract the current DRAM size from the DDRC registers
108258bad41SUri Mashiach  *
109258bad41SUri Mashiach  * @return: DRAM size
110258bad41SUri Mashiach  */
imx_ddr_size(void)111258bad41SUri Mashiach unsigned int imx_ddr_size(void)
112258bad41SUri Mashiach {
113258bad41SUri Mashiach 	struct ddrc *const ddrc_regs = (struct ddrc *)DDRC_IPS_BASE_ADDR;
114258bad41SUri Mashiach 	u32 reg_val, field_val;
115258bad41SUri Mashiach 	int bits = 0;/* Number of address bits */
116258bad41SUri Mashiach 
117258bad41SUri Mashiach 	/* Count data bus width bits */
118258bad41SUri Mashiach 	reg_val = readl(&ddrc_regs->mstr);
119258bad41SUri Mashiach 	field_val = (reg_val & MSTR_DATA_BUS_WIDTH_MASK) >> MSTR_DATA_BUS_WIDTH_SHIFT;
120258bad41SUri Mashiach 	bits += 2 - field_val;
121258bad41SUri Mashiach 	/* Count rank address bits */
122258bad41SUri Mashiach 	field_val = (reg_val & MSTR_DATA_ACTIVE_RANKS_MASK) >> MSTR_DATA_ACTIVE_RANKS_SHIFT;
123258bad41SUri Mashiach 	if (field_val > 1)
124258bad41SUri Mashiach 		bits += field_val - 1;
125258bad41SUri Mashiach 	/* Count column address bits */
126258bad41SUri Mashiach 	bits += 2;/* Column address 0 and 1 are fixed mapped */
127258bad41SUri Mashiach 	reg_val = readl(&ddrc_regs->addrmap2);
128258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP2_COL_B2_MASK) >> ADDRMAP2_COL_B2_SHIFT;
129258bad41SUri Mashiach 	if (field_val <= 7)
130258bad41SUri Mashiach 		bits++;
131258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP2_COL_B3_MASK) >> ADDRMAP2_COL_B3_SHIFT;
132258bad41SUri Mashiach 	if (field_val <= 7)
133258bad41SUri Mashiach 		bits++;
134258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP2_COL_B4_MASK) >> ADDRMAP2_COL_B4_SHIFT;
135258bad41SUri Mashiach 	if (field_val <= 7)
136258bad41SUri Mashiach 		bits++;
137258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP2_COL_B5_MASK) >> ADDRMAP2_COL_B5_SHIFT;
138258bad41SUri Mashiach 	if (field_val <= 7)
139258bad41SUri Mashiach 		bits++;
140258bad41SUri Mashiach 	reg_val = readl(&ddrc_regs->addrmap3);
141258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP3_COL_B6_MASK) >> ADDRMAP3_COL_B6_SHIFT;
142258bad41SUri Mashiach 	if (field_val <= 7)
143258bad41SUri Mashiach 		bits++;
144258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP3_COL_B7_MASK) >> ADDRMAP3_COL_B7_SHIFT;
145258bad41SUri Mashiach 	if (field_val <= 7)
146258bad41SUri Mashiach 		bits++;
147258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP3_COL_B8_MASK) >> ADDRMAP3_COL_B8_SHIFT;
148258bad41SUri Mashiach 	if (field_val <= 7)
149258bad41SUri Mashiach 		bits++;
150258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP3_COL_B9_MASK) >> ADDRMAP3_COL_B9_SHIFT;
151258bad41SUri Mashiach 	if (field_val <= 7)
152258bad41SUri Mashiach 		bits++;
153258bad41SUri Mashiach 	reg_val = readl(&ddrc_regs->addrmap4);
154258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP4_COL_B10_MASK) >> ADDRMAP4_COL_B10_SHIFT;
155258bad41SUri Mashiach 	if (field_val <= 7)
156258bad41SUri Mashiach 		bits++;
157258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP4_COL_B11_MASK) >> ADDRMAP4_COL_B11_SHIFT;
158258bad41SUri Mashiach 	if (field_val <= 7)
159258bad41SUri Mashiach 		bits++;
160258bad41SUri Mashiach 	/* Count row address bits */
161258bad41SUri Mashiach 	reg_val = readl(&ddrc_regs->addrmap5);
162258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP5_ROW_B0_MASK) >> ADDRMAP5_ROW_B0_SHIFT;
163258bad41SUri Mashiach 	if (field_val <= 11)
164258bad41SUri Mashiach 		bits++;
165258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP5_ROW_B1_MASK) >> ADDRMAP5_ROW_B1_SHIFT;
166258bad41SUri Mashiach 	if (field_val <= 11)
167258bad41SUri Mashiach 		bits++;
168258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP5_ROW_B2_10_MASK) >> ADDRMAP5_ROW_B2_10_SHIFT;
169258bad41SUri Mashiach 	if (field_val <= 11)
170258bad41SUri Mashiach 		bits += 9;
171258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP5_ROW_B11_MASK) >> ADDRMAP5_ROW_B11_SHIFT;
172258bad41SUri Mashiach 	if (field_val <= 11)
173258bad41SUri Mashiach 		bits++;
174258bad41SUri Mashiach 	reg_val = readl(&ddrc_regs->addrmap6);
175258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP6_ROW_B12_MASK) >> ADDRMAP6_ROW_B12_SHIFT;
176258bad41SUri Mashiach 	if (field_val <= 11)
177258bad41SUri Mashiach 		bits++;
178258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP6_ROW_B13_MASK) >> ADDRMAP6_ROW_B13_SHIFT;
179258bad41SUri Mashiach 	if (field_val <= 11)
180258bad41SUri Mashiach 		bits++;
181258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP6_ROW_B14_MASK) >> ADDRMAP6_ROW_B14_SHIFT;
182258bad41SUri Mashiach 	if (field_val <= 11)
183258bad41SUri Mashiach 		bits++;
184258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP6_ROW_B15_MASK) >> ADDRMAP6_ROW_B15_SHIFT;
185258bad41SUri Mashiach 	if (field_val <= 11)
186258bad41SUri Mashiach 		bits++;
187258bad41SUri Mashiach 	/* Count bank bits */
188258bad41SUri Mashiach 	reg_val = readl(&ddrc_regs->addrmap1);
189258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP1_BANK_B0_MASK) >> ADDRMAP1_BANK_B0_SHIFT;
190258bad41SUri Mashiach 	if (field_val <= 30)
191258bad41SUri Mashiach 		bits++;
192258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP1_BANK_B1_MASK) >> ADDRMAP1_BANK_B1_SHIFT;
193258bad41SUri Mashiach 	if (field_val <= 30)
194258bad41SUri Mashiach 		bits++;
195258bad41SUri Mashiach 	field_val = (reg_val & ADDRMAP1_BANK_B2_MASK) >> ADDRMAP1_BANK_B2_SHIFT;
196258bad41SUri Mashiach 	if (field_val <= 29)
197258bad41SUri Mashiach 		bits++;
198258bad41SUri Mashiach 
199*2cea8d74SMarcel Ziswiler 	/* cap to max 2 GB */
200*2cea8d74SMarcel Ziswiler 	if (bits > 31)
201*2cea8d74SMarcel Ziswiler 		bits = 31;
202*2cea8d74SMarcel Ziswiler 
203258bad41SUri Mashiach 	return 1 << bits;
204258bad41SUri Mashiach }
205