blob: b6dffc872b4eafbd116662da5bc91c6192c6747a [file] [log] [blame]
Pankaj Guptac518de42020-12-09 14:02:39 +05301/*
Maninder Singh6be80352021-12-30 00:09:32 -07002 * Copyright 2021-2022 NXP
Pankaj Guptac518de42020-12-09 14:02:39 +05303 *
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)
Maninder Singh6be80352021-12-30 00:09:32 -070036#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
Pankaj Guptac518de42020-12-09 14:02:39 +053040#endif
41
42unsigned 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
60unsigned 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
73unsigned 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 */
105int 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);
Maninder Singh6be80352021-12-30 00:09:32 -0700171#ifdef NXP_HAS_CCN504
Pankaj Guptac518de42020-12-09 14:02:39 +0530172 nodeid = disable_ddrc == 1 ? CCN_HN_F_SAM_NODEID_DDR1 :
Maninder Singh6be80352021-12-30 00:09:32 -0700173 (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
Pankaj Guptac518de42020-12-09 14:02:39 +0530186 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
199unsigned 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
209void 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}