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