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