1 /*
2  * Copyright 2021-2022 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <errno.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 
13 #include <common/debug.h>
14 #include <ddr.h>
15 #include <immap.h>
16 #include <lib/mmio.h>
17 
18 #define UL_5POW12	244140625UL
19 #define ULL_2E12	2000000000000ULL
20 #define UL_2POW13	(1UL << 13)
21 #define ULL_8FS		0xFFFFFFFFULL
22 
23 #define do_div(n, base) ({				\
24 	unsigned int __base = (base);			\
25 	unsigned int __rem;				\
26 	__rem = ((unsigned long long)(n)) % __base;	\
27 	(n) = ((unsigned long long)(n)) / __base;	\
28 	__rem;						\
29 })
30 
31 #define CCN_HN_F_SAM_NODEID_MASK	0x7f
32 #ifdef NXP_HAS_CCN504
33 #define CCN_HN_F_SAM_NODEID_DDR0	0x4
34 #define CCN_HN_F_SAM_NODEID_DDR1	0xe
35 #elif defined(NXP_HAS_CCN508)
36 #define CCN_HN_F_SAM_NODEID_DDR0_0	0x3
37 #define CCN_HN_F_SAM_NODEID_DDR0_1	0x8
38 #define CCN_HN_F_SAM_NODEID_DDR1_0	0x13
39 #define CCN_HN_F_SAM_NODEID_DDR1_1	0x18
40 #endif
41 
get_ddr_freq(struct sysinfo * sys,int ctrl_num)42 unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num)
43 {
44 	if (sys->freq_ddr_pll0 == 0) {
45 		get_clocks(sys);
46 	}
47 
48 	switch (ctrl_num) {
49 	case 0:
50 		return sys->freq_ddr_pll0;
51 	case 1:
52 		return sys->freq_ddr_pll0;
53 	case 2:
54 		return sys->freq_ddr_pll1;
55 	}
56 
57 	return 0;
58 }
59 
get_memory_clk_ps(const unsigned long data_rate)60 unsigned int get_memory_clk_ps(const unsigned long data_rate)
61 {
62 	unsigned int result;
63 	/* Round to nearest 10ps, being careful about 64-bit multiply/divide */
64 	unsigned long long rem, mclk_ps = ULL_2E12;
65 
66 	/* Now perform the big divide, the result fits in 32-bits */
67 	rem = do_div(mclk_ps, data_rate);
68 	result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps;
69 
70 	return result;
71 }
72 
picos_to_mclk(unsigned long data_rate,unsigned int picos)73 unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos)
74 {
75 	unsigned long long clks, clks_rem;
76 
77 	/* Short circuit for zero picos */
78 	if ((picos == 0U) || (data_rate == 0UL)) {
79 		return 0U;
80 	}
81 
82 	/* First multiply the time by the data rate (32x32 => 64) */
83 	clks = picos * (unsigned long long)data_rate;
84 	/*
85 	 * Now divide by 5^12 and track the 32-bit remainder, then divide
86 	 * by 2*(2^12) using shifts (and updating the remainder).
87 	 */
88 	clks_rem = do_div(clks, UL_5POW12);
89 	clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12;
90 	clks >>= 13U;
91 
92 	/* If we had a remainder greater than the 1ps error, then round up */
93 	if (clks_rem > data_rate) {
94 		clks++;
95 	}
96 
97 	/* Clamp to the maximum representable value */
98 	if (clks > ULL_8FS) {
99 		clks = ULL_8FS;
100 	}
101 	return (unsigned int) clks;
102 }
103 
104 /* valid_spd_mask has been checked by parse_spd */
disable_unused_ddrc(struct ddr_info * priv,int valid_spd_mask,uintptr_t nxp_ccn_hn_f0_addr)105 int disable_unused_ddrc(struct ddr_info *priv,
106 			int valid_spd_mask, uintptr_t nxp_ccn_hn_f0_addr)
107 {
108 #if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
109 	void *hnf_sam_ctrl = (void *)(nxp_ccn_hn_f0_addr + CCN_HN_F_SAM_CTL);
110 	uint32_t val, nodeid;
111 #ifdef NXP_HAS_CCN504
112 	uint32_t num_hnf_nodes = 4U;
113 #else
114 	uint32_t num_hnf_nodes = 8U;
115 #endif
116 	int disable_ddrc = 0;
117 	int i;
118 
119 	if (priv->num_ctlrs < 2) {
120 		debug("%s: nothing to do.\n", __func__);
121 	}
122 
123 	switch (priv->dimm_on_ctlr) {
124 	case 1:
125 		disable_ddrc = ((valid_spd_mask &0x2) == 0) ? 2 : 0;
126 		disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc;
127 		break;
128 	case 2:
129 		disable_ddrc = ((valid_spd_mask &0x4) == 0) ? 2 : 0;
130 		disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc;
131 		break;
132 	default:
133 		ERROR("Invalid number of DIMMs %d\n", priv->dimm_on_ctlr);
134 		return -EINVAL;
135 	}
136 
137 	if (disable_ddrc != 0) {
138 		debug("valid_spd_mask = 0x%x\n", valid_spd_mask);
139 	}
140 
141 	switch (disable_ddrc) {
142 	case 1:
143 		priv->num_ctlrs = 1;
144 		priv->spd_addr = &priv->spd_addr[priv->dimm_on_ctlr];
145 		priv->ddr[0] = priv->ddr[1];
146 		priv->ddr[1] = NULL;
147 		priv->phy[0] = priv->phy[0];
148 		priv->phy[1] = NULL;
149 		debug("Disable first DDR controller\n");
150 		break;
151 	case 2:
152 		priv->num_ctlrs = 1;
153 		priv->ddr[1] = NULL;
154 		priv->phy[1] = NULL;
155 		debug("Disable second DDR controller\n");
156 		/* fallthrough */
157 	case 0:
158 		break;
159 	default:
160 		ERROR("Program error.\n");
161 		return -EINVAL;
162 	}
163 
164 	if (disable_ddrc == 0) {
165 		debug("Both controllers in use.\n");
166 		return 0;
167 	}
168 
169 	for (i = 0; i < num_hnf_nodes; i++) {
170 		val = mmio_read_64((uintptr_t)hnf_sam_ctrl);
171 #ifdef NXP_HAS_CCN504
172 		nodeid = disable_ddrc == 1 ? CCN_HN_F_SAM_NODEID_DDR1 :
173 			(disable_ddrc == 2 ? CCN_HN_F_SAM_NODEID_DDR0 :
174 			 0x0);   /*Failure condition. never hit */
175 #elif defined(NXP_HAS_CCN508)
176 		if (disable_ddrc == 1) {
177 			nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR1_1 :
178 				CCN_HN_F_SAM_NODEID_DDR1_0;
179 		} else if (disable_ddrc == 2) {
180 			nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR0_0 :
181 				CCN_HN_F_SAM_NODEID_DDR0_1;
182 		} else {
183 			nodeid = 0; /* Failure condition. never hit */
184 		}
185 #endif
186 		if (nodeid != (val & CCN_HN_F_SAM_NODEID_MASK)) {
187 			debug("Setting HN-F node %d\n", i);
188 			debug("nodeid = 0x%x\n", nodeid);
189 			val &= ~CCN_HN_F_SAM_NODEID_MASK;
190 			val |= nodeid;
191 			mmio_write_64((uintptr_t)hnf_sam_ctrl, val);
192 		}
193 		hnf_sam_ctrl += CCN_HN_F_REGION_SIZE;
194 	}
195 #endif
196 	return 0;
197 }
198 
get_ddrc_version(const struct ccsr_ddr * ddr)199 unsigned int get_ddrc_version(const struct ccsr_ddr *ddr)
200 {
201 	unsigned int ver;
202 
203 	ver = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8U;
204 	ver |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8U;
205 
206 	return ver;
207 }
208 
print_ddr_info(struct ccsr_ddr * ddr)209 void print_ddr_info(struct ccsr_ddr *ddr)
210 {
211 	unsigned int cs0_config = ddr_in32(&ddr->csn_cfg[0]);
212 	unsigned int sdram_cfg = ddr_in32(&ddr->sdram_cfg);
213 	int cas_lat;
214 
215 	if ((sdram_cfg & SDRAM_CFG_MEM_EN) == 0U) {
216 		printf(" (DDR not enabled)\n");
217 		return;
218 	}
219 
220 	printf("DDR");
221 	switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
222 		SDRAM_CFG_SDRAM_TYPE_SHIFT) {
223 	case SDRAM_TYPE_DDR4:
224 		printf("4");
225 		break;
226 	default:
227 		printf("?");
228 		break;
229 	}
230 
231 	switch (sdram_cfg & SDRAM_CFG_DBW_MASK) {
232 	case SDRAM_CFG_32_BW:
233 		printf(", 32-bit");
234 		break;
235 	case SDRAM_CFG_16_BW:
236 		printf(", 16-bit");
237 		break;
238 	case SDRAM_CFG_8_BW:
239 		printf(", 8-bit");
240 		break;
241 	default:
242 		printf(", 64-bit");
243 		break;
244 	}
245 
246 	/* Calculate CAS latency based on timing cfg values */
247 	cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
248 	cas_lat += 2;	/* for DDRC newer than 4.4 */
249 	cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4;
250 	printf(", CL=%d", cas_lat >> 1);
251 	if ((cas_lat & 0x1) != 0) {
252 		printf(".5");
253 	}
254 
255 	if ((sdram_cfg & SDRAM_CFG_ECC_EN) != 0) {
256 		printf(", ECC on");
257 	} else {
258 		printf(", ECC off");
259 	}
260 
261 	if ((cs0_config & 0x20000000) != 0) {
262 		printf(", ");
263 		switch ((cs0_config >> 24) & 0xf) {
264 		case DDR_256B_INTLV:
265 			printf("256B");
266 			break;
267 		default:
268 			printf("invalid");
269 			break;
270 		}
271 	}
272 
273 	if (((sdram_cfg >> 8) & 0x7f) != 0) {
274 		printf(", ");
275 		switch (sdram_cfg >> 8 & 0x7f) {
276 		case DDR_BA_INTLV_CS0123:
277 			printf("CS0+CS1+CS2+CS3");
278 			break;
279 		case DDR_BA_INTLV_CS01:
280 			printf("CS0+CS1");
281 			break;
282 		default:
283 			printf("invalid");
284 			break;
285 		}
286 	}
287 	printf("\n");
288 }
289