xref: /arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright 2021 NXP
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  *
6*91f16700Schasinglulu  */
7*91f16700Schasinglulu 
8*91f16700Schasinglulu /*
9*91f16700Schasinglulu  * Generic driver for Freescale MMDC(Multi Mode DDR Controller).
10*91f16700Schasinglulu  */
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include <errno.h>
13*91f16700Schasinglulu #include <stdint.h>
14*91f16700Schasinglulu #include <stdio.h>
15*91f16700Schasinglulu #include <stdlib.h>
16*91f16700Schasinglulu #include <string.h>
17*91f16700Schasinglulu 
18*91f16700Schasinglulu #include <common/debug.h>
19*91f16700Schasinglulu #include "ddr_io.h"
20*91f16700Schasinglulu #include <drivers/delay_timer.h>
21*91f16700Schasinglulu #include <fsl_mmdc.h>
22*91f16700Schasinglulu 
23*91f16700Schasinglulu static void set_wait_for_bits_clear(void *ptr, unsigned int value,
24*91f16700Schasinglulu 				    unsigned int bits)
25*91f16700Schasinglulu {
26*91f16700Schasinglulu 	int timeout = 1000;
27*91f16700Schasinglulu 
28*91f16700Schasinglulu 	ddr_out32(ptr, value);
29*91f16700Schasinglulu 
30*91f16700Schasinglulu 	while ((ddr_in32(ptr) & bits) != 0) {
31*91f16700Schasinglulu 		udelay(100);
32*91f16700Schasinglulu 		timeout--;
33*91f16700Schasinglulu 	}
34*91f16700Schasinglulu 	if (timeout <= 0) {
35*91f16700Schasinglulu 		INFO("Error: %llx", (unsigned long long)ptr);
36*91f16700Schasinglulu 		INFO(" wait for clear timeout.\n");
37*91f16700Schasinglulu 	}
38*91f16700Schasinglulu }
39*91f16700Schasinglulu 
40*91f16700Schasinglulu void mmdc_init(const struct fsl_mmdc_info *priv, uintptr_t nxp_ddr_addr)
41*91f16700Schasinglulu {
42*91f16700Schasinglulu 	struct mmdc_regs *mmdc = (struct mmdc_regs *)nxp_ddr_addr;
43*91f16700Schasinglulu 	unsigned int tmp;
44*91f16700Schasinglulu 
45*91f16700Schasinglulu 	/* 1. set configuration request */
46*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ);
47*91f16700Schasinglulu 
48*91f16700Schasinglulu 	/* 2. configure the desired timing parameters */
49*91f16700Schasinglulu 	ddr_out32(&mmdc->mdotc, priv->mdotc);
50*91f16700Schasinglulu 	ddr_out32(&mmdc->mdcfg0, priv->mdcfg0);
51*91f16700Schasinglulu 	ddr_out32(&mmdc->mdcfg1, priv->mdcfg1);
52*91f16700Schasinglulu 	ddr_out32(&mmdc->mdcfg2, priv->mdcfg2);
53*91f16700Schasinglulu 
54*91f16700Schasinglulu 	/* 3. configure DDR type and other miscellaneous parameters */
55*91f16700Schasinglulu 	ddr_out32(&mmdc->mdmisc, priv->mdmisc);
56*91f16700Schasinglulu 	ddr_out32(&mmdc->mpmur0, MMDC_MPMUR0_FRC_MSR);
57*91f16700Schasinglulu 	ddr_out32(&mmdc->mdrwd, priv->mdrwd);
58*91f16700Schasinglulu 	ddr_out32(&mmdc->mpodtctrl, priv->mpodtctrl);
59*91f16700Schasinglulu 
60*91f16700Schasinglulu 	/* 4. configure the required delay while leaving reset */
61*91f16700Schasinglulu 	ddr_out32(&mmdc->mdor, priv->mdor);
62*91f16700Schasinglulu 
63*91f16700Schasinglulu 	/* 5. configure DDR physical parameters */
64*91f16700Schasinglulu 	/* set row/column address width, burst length, data bus width */
65*91f16700Schasinglulu 	tmp = priv->mdctl & ~(MDCTL_SDE0 | MDCTL_SDE1);
66*91f16700Schasinglulu 	ddr_out32(&mmdc->mdctl, tmp);
67*91f16700Schasinglulu 	/* configure address space partition */
68*91f16700Schasinglulu 	ddr_out32(&mmdc->mdasp, priv->mdasp);
69*91f16700Schasinglulu 
70*91f16700Schasinglulu 	/* 6. perform a ZQ calibration - not needed here, doing in #8b */
71*91f16700Schasinglulu 
72*91f16700Schasinglulu 	/* 7. enable MMDC with the desired chip select */
73*91f16700Schasinglulu #if (DDRC_NUM_CS == 1)
74*91f16700Schasinglulu 	ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0);
75*91f16700Schasinglulu #elif (DDRC_NUM_CS == 2)
76*91f16700Schasinglulu 	ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0 | MDCTL_SDE1);
77*91f16700Schasinglulu #else
78*91f16700Schasinglulu #error "Unsupported DDRC_NUM_CS"
79*91f16700Schasinglulu #endif
80*91f16700Schasinglulu 
81*91f16700Schasinglulu 	/* 8a. dram init sequence: update MRs for ZQ, ODT, PRE, etc */
82*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(8) |
83*91f16700Schasinglulu 				MDSCR_ENABLE_CON_REQ |
84*91f16700Schasinglulu 				CMD_LOAD_MODE_REG |
85*91f16700Schasinglulu 				CMD_BANK_ADDR_2);
86*91f16700Schasinglulu 
87*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0) |
88*91f16700Schasinglulu 				MDSCR_ENABLE_CON_REQ |
89*91f16700Schasinglulu 				CMD_LOAD_MODE_REG |
90*91f16700Schasinglulu 				CMD_BANK_ADDR_3);
91*91f16700Schasinglulu 
92*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) |
93*91f16700Schasinglulu 				MDSCR_ENABLE_CON_REQ |
94*91f16700Schasinglulu 				CMD_LOAD_MODE_REG |
95*91f16700Schasinglulu 				CMD_BANK_ADDR_1);
96*91f16700Schasinglulu 
97*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x19) |
98*91f16700Schasinglulu 				CMD_ADDR_LSB_MR_ADDR(0x30) |
99*91f16700Schasinglulu 				MDSCR_ENABLE_CON_REQ |
100*91f16700Schasinglulu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0);
101*91f16700Schasinglulu 
102*91f16700Schasinglulu 	/* 8b. ZQ calibration */
103*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x4) |
104*91f16700Schasinglulu 				MDSCR_ENABLE_CON_REQ |
105*91f16700Schasinglulu 				CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0);
106*91f16700Schasinglulu 
107*91f16700Schasinglulu 	set_wait_for_bits_clear(&mmdc->mpzqhwctrl, priv->mpzqhwctrl,
108*91f16700Schasinglulu 				MPZQHWCTRL_ZQ_HW_FORCE);
109*91f16700Schasinglulu 
110*91f16700Schasinglulu 	/* 9a. calibrations now, wr lvl */
111*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr,  CMD_ADDR_LSB_MR_ADDR(0x84) | MDSCR_WL_EN |
112*91f16700Schasinglulu 				MDSCR_ENABLE_CON_REQ |
113*91f16700Schasinglulu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1);
114*91f16700Schasinglulu 
115*91f16700Schasinglulu 	set_wait_for_bits_clear(&mmdc->mpwlgcr, MPWLGCR_HW_WL_EN,
116*91f16700Schasinglulu 				MPWLGCR_HW_WL_EN);
117*91f16700Schasinglulu 
118*91f16700Schasinglulu 	mdelay(1);
119*91f16700Schasinglulu 
120*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) |
121*91f16700Schasinglulu 				MDSCR_ENABLE_CON_REQ |
122*91f16700Schasinglulu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1);
123*91f16700Schasinglulu 
124*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ);
125*91f16700Schasinglulu 
126*91f16700Schasinglulu 	mdelay(1);
127*91f16700Schasinglulu 
128*91f16700Schasinglulu 	/* 9b. read DQS gating calibration */
129*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ |
130*91f16700Schasinglulu 				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0);
131*91f16700Schasinglulu 
132*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ |
133*91f16700Schasinglulu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3);
134*91f16700Schasinglulu 
135*91f16700Schasinglulu 	ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN);
136*91f16700Schasinglulu 
137*91f16700Schasinglulu 	/* set absolute read delay offset */
138*91f16700Schasinglulu 	if (priv->mprddlctl != 0) {
139*91f16700Schasinglulu 		ddr_out32(&mmdc->mprddlctl, priv->mprddlctl);
140*91f16700Schasinglulu 	} else {
141*91f16700Schasinglulu 		ddr_out32(&mmdc->mprddlctl, MMDC_MPRDDLCTL_DEFAULT_DELAY);
142*91f16700Schasinglulu 	}
143*91f16700Schasinglulu 
144*91f16700Schasinglulu 	set_wait_for_bits_clear(&mmdc->mpdgctrl0,
145*91f16700Schasinglulu 				AUTO_RD_DQS_GATING_CALIBRATION_EN,
146*91f16700Schasinglulu 				AUTO_RD_DQS_GATING_CALIBRATION_EN);
147*91f16700Schasinglulu 
148*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr,  MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG |
149*91f16700Schasinglulu 				CMD_BANK_ADDR_3);
150*91f16700Schasinglulu 
151*91f16700Schasinglulu 	/* 9c. read calibration */
152*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ |
153*91f16700Schasinglulu 				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0);
154*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ |
155*91f16700Schasinglulu 				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3);
156*91f16700Schasinglulu 	ddr_out32(&mmdc->mppdcmpr2,  MPPDCMPR2_MPR_COMPARE_EN);
157*91f16700Schasinglulu 	set_wait_for_bits_clear(&mmdc->mprddlhwctl,
158*91f16700Schasinglulu 				MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN,
159*91f16700Schasinglulu 				MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN);
160*91f16700Schasinglulu 
161*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG |
162*91f16700Schasinglulu 				CMD_BANK_ADDR_3);
163*91f16700Schasinglulu 
164*91f16700Schasinglulu 	/* 10. configure power-down, self-refresh entry, exit parameters */
165*91f16700Schasinglulu 	ddr_out32(&mmdc->mdpdc, priv->mdpdc);
166*91f16700Schasinglulu 	ddr_out32(&mmdc->mapsr, MMDC_MAPSR_PWR_SAV_CTRL_STAT);
167*91f16700Schasinglulu 
168*91f16700Schasinglulu 	/* 11. ZQ config again? do nothing here */
169*91f16700Schasinglulu 
170*91f16700Schasinglulu 	/* 12. refresh scheme */
171*91f16700Schasinglulu 	set_wait_for_bits_clear(&mmdc->mdref, priv->mdref,
172*91f16700Schasinglulu 				MDREF_START_REFRESH);
173*91f16700Schasinglulu 
174*91f16700Schasinglulu 	/* 13. disable CON_REQ */
175*91f16700Schasinglulu 	ddr_out32(&mmdc->mdscr, MDSCR_DISABLE_CFG_REQ);
176*91f16700Schasinglulu }
177