]>
Commit | Line | Data |
---|---|---|
e6f2e902 MB |
1 | /* |
2 | * (C) Copyright 2005 | |
3 | * Wolfgang Denk, DENX Software Engineering, [email protected]. | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
e6f2e902 MB |
6 | */ |
7 | ||
8 | #include <common.h> | |
9 | #include <ioports.h> | |
10 | #include <mpc83xx.h> | |
11 | #include <asm/mpc8349_pci.h> | |
12 | #include <i2c.h> | |
e6f2e902 | 13 | #include <miiphy.h> |
61f2b38a | 14 | #include <asm/mmu.h> |
e6f2e902 | 15 | #include <pci.h> |
ca5def3f SR |
16 | #include <flash.h> |
17 | #include <mtd/cfi_flash.h> | |
e6f2e902 | 18 | |
d87080b7 WD |
19 | DECLARE_GLOBAL_DATA_PTR; |
20 | ||
e6f2e902 MB |
21 | #define IOSYNC asm("eieio") |
22 | #define ISYNC asm("isync") | |
23 | #define SYNC asm("sync") | |
24 | #define FPW FLASH_PORT_WIDTH | |
25 | #define FPWV FLASH_PORT_WIDTHV | |
26 | ||
27 | #define DDR_MAX_SIZE_PER_CS 0x20000000 | |
28 | ||
29 | #if defined(DDR_CASLAT_20) | |
30 | #define TIMING_CASLAT TIMING_CFG1_CASLAT_20 | |
31 | #define MODE_CASLAT DDR_MODE_CASLAT_20 | |
32 | #else | |
33 | #define TIMING_CASLAT TIMING_CFG1_CASLAT_25 | |
34 | #define MODE_CASLAT DDR_MODE_CASLAT_25 | |
35 | #endif | |
36 | ||
37 | #define INITIAL_CS_CONFIG (CSCONFIG_EN | CSCONFIG_ROW_BIT_12 | \ | |
38 | CSCONFIG_COL_BIT_9) | |
39 | ||
e6f2e902 MB |
40 | /* External definitions */ |
41 | ulong flash_get_size (ulong base, int banknum); | |
e6f2e902 MB |
42 | |
43 | /* Local functions */ | |
44 | static int detect_num_flash_banks(void); | |
982db890 | 45 | static long int get_ddr_bank_size(short cs, long *base); |
4019e54d | 46 | static void set_cs_bounds(short cs, ulong base, ulong size); |
e6f2e902 MB |
47 | static void set_cs_config(short cs, long config); |
48 | static void set_ddr_config(void); | |
49 | ||
50 | /* Local variable */ | |
6d0f6bcf | 51 | static volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
e6f2e902 MB |
52 | |
53 | /************************************************************************** | |
54 | * Board initialzation after relocation to RAM. Used to detect the number | |
55 | * of Flash banks on TQM834x. | |
56 | */ | |
57 | int board_early_init_r (void) { | |
58 | /* sanity check, IMMARBAR should be mirrored at offset zero of IMMR */ | |
59 | if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im) | |
60 | return 0; | |
f013dacf | 61 | |
e6f2e902 MB |
62 | /* detect the number of Flash banks */ |
63 | return detect_num_flash_banks(); | |
64 | } | |
65 | ||
66 | /************************************************************************** | |
67 | * DRAM initalization and size detection | |
68 | */ | |
088454cd | 69 | int initdram(void) |
e6f2e902 MB |
70 | { |
71 | long bank_size; | |
72 | long size; | |
73 | int cs; | |
74 | ||
75 | /* during size detection, set up the max DDRLAW size */ | |
6d0f6bcf | 76 | im->sysconf.ddrlaw[0].bar = CONFIG_SYS_DDR_BASE; |
e6f2e902 MB |
77 | im->sysconf.ddrlaw[0].ar = (LAWAR_EN | LAWAR_SIZE_2G); |
78 | ||
79 | /* set CS bounds to maximum size */ | |
80 | for(cs = 0; cs < 4; ++cs) { | |
81 | set_cs_bounds(cs, | |
6d0f6bcf | 82 | CONFIG_SYS_DDR_BASE + (cs * DDR_MAX_SIZE_PER_CS), |
e6f2e902 MB |
83 | DDR_MAX_SIZE_PER_CS); |
84 | ||
85 | set_cs_config(cs, INITIAL_CS_CONFIG); | |
86 | } | |
87 | ||
88 | /* configure ddr controller */ | |
89 | set_ddr_config(); | |
90 | ||
91 | udelay(200); | |
f013dacf | 92 | |
e6f2e902 MB |
93 | /* enable DDR controller */ |
94 | im->ddr.sdram_cfg = (SDRAM_CFG_MEM_EN | | |
95 | SDRAM_CFG_SREN | | |
bbea46f7 | 96 | SDRAM_CFG_SDRAM_TYPE_DDR1); |
e6f2e902 MB |
97 | SYNC; |
98 | ||
99 | /* size detection */ | |
100 | debug("\n"); | |
101 | size = 0; | |
102 | for(cs = 0; cs < 4; ++cs) { | |
103 | debug("\nDetecting Bank%d\n", cs); | |
104 | ||
105 | bank_size = get_ddr_bank_size(cs, | |
982db890 | 106 | (long *)(CONFIG_SYS_DDR_BASE + size)); |
e6f2e902 MB |
107 | size += bank_size; |
108 | ||
3d54639c | 109 | debug("DDR Bank%d size: %ld MiB\n\n", cs, bank_size >> 20); |
e6f2e902 MB |
110 | |
111 | /* exit if less than one bank */ | |
112 | if(size < DDR_MAX_SIZE_PER_CS) break; | |
113 | } | |
114 | ||
088454cd SG |
115 | gd->ram_size = size; |
116 | ||
117 | return 0; | |
e6f2e902 MB |
118 | } |
119 | ||
120 | /************************************************************************** | |
121 | * checkboard() | |
122 | */ | |
123 | int checkboard (void) | |
124 | { | |
125 | puts("Board: TQM834x\n"); | |
126 | ||
127 | #ifdef CONFIG_PCI | |
6902df56 RJ |
128 | volatile immap_t * immr; |
129 | u32 w, f; | |
e6f2e902 | 130 | |
6d0f6bcf | 131 | immr = (immap_t *)CONFIG_SYS_IMMR; |
e080313c | 132 | if (!(immr->reset.rcwh & HRCWH_PCI_HOST)) { |
6902df56 RJ |
133 | printf("PCI: NOT in host mode..?!\n"); |
134 | return 0; | |
135 | } | |
e6f2e902 | 136 | |
6902df56 RJ |
137 | /* get bus width */ |
138 | w = 32; | |
e080313c | 139 | if (immr->reset.rcwh & HRCWH_64_BIT_PCI) |
6902df56 | 140 | w = 64; |
e6f2e902 | 141 | |
6902df56 RJ |
142 | /* get clock */ |
143 | f = gd->pci_clk; | |
e6f2e902 | 144 | |
6902df56 RJ |
145 | printf("PCI1: %d bit, %d MHz\n", w, f / 1000000); |
146 | #else | |
147 | printf("PCI: disabled\n"); | |
148 | #endif | |
149 | return 0; | |
e6f2e902 MB |
150 | } |
151 | ||
6902df56 | 152 | |
e6f2e902 MB |
153 | /************************************************************************** |
154 | * | |
155 | * Local functions | |
156 | * | |
157 | *************************************************************************/ | |
158 | ||
159 | /************************************************************************** | |
160 | * Detect the number of flash banks (1 or 2). Store it in | |
161 | * a global variable tqm834x_num_flash_banks. | |
162 | * Bank detection code based on the Monitor code. | |
163 | */ | |
164 | static int detect_num_flash_banks(void) | |
165 | { | |
166 | typedef unsigned long FLASH_PORT_WIDTH; | |
167 | typedef volatile unsigned long FLASH_PORT_WIDTHV; | |
168 | FPWV *bank1_base; | |
169 | FPWV *bank2_base; | |
170 | FPW bank1_read; | |
171 | FPW bank2_read; | |
172 | ulong bank1_size; | |
173 | ulong bank2_size; | |
174 | ulong total_size; | |
175 | ||
ca5def3f | 176 | cfi_flash_num_flash_banks = 2; /* assume two banks */ |
f013dacf | 177 | |
e6f2e902 | 178 | /* Get bank 1 and 2 information */ |
6d0f6bcf | 179 | bank1_size = flash_get_size(CONFIG_SYS_FLASH_BASE, 0); |
e6f2e902 | 180 | debug("Bank1 size: %lu\n", bank1_size); |
6d0f6bcf | 181 | bank2_size = flash_get_size(CONFIG_SYS_FLASH_BASE + bank1_size, 1); |
e6f2e902 MB |
182 | debug("Bank2 size: %lu\n", bank2_size); |
183 | total_size = bank1_size + bank2_size; | |
184 | ||
185 | if (bank2_size > 0) { | |
186 | /* Seems like we've got bank 2, but maybe it's mirrored 1 */ | |
187 | ||
188 | /* Set the base addresses */ | |
6d0f6bcf JCPV |
189 | bank1_base = (FPWV *) (CONFIG_SYS_FLASH_BASE); |
190 | bank2_base = (FPWV *) (CONFIG_SYS_FLASH_BASE + bank1_size); | |
e6f2e902 MB |
191 | |
192 | /* Put bank 2 into CFI command mode and read */ | |
193 | bank2_base[0x55] = 0x00980098; | |
194 | IOSYNC; | |
195 | ISYNC; | |
196 | bank2_read = bank2_base[0x10]; | |
197 | ||
198 | /* Read from bank 1 (it's in read mode) */ | |
199 | bank1_read = bank1_base[0x10]; | |
200 | ||
201 | /* Reset Flash */ | |
202 | bank1_base[0] = 0x00F000F0; | |
203 | bank2_base[0] = 0x00F000F0; | |
204 | ||
205 | if (bank2_read == bank1_read) { | |
206 | /* | |
207 | * Looks like just one bank, but not sure yet. Let's | |
208 | * read from bank 2 in autosoelect mode. | |
209 | */ | |
210 | bank2_base[0x0555] = 0x00AA00AA; | |
211 | bank2_base[0x02AA] = 0x00550055; | |
212 | bank2_base[0x0555] = 0x00900090; | |
213 | IOSYNC; | |
214 | ISYNC; | |
215 | bank2_read = bank2_base[0x10]; | |
216 | ||
217 | /* Read from bank 1 (it's in read mode) */ | |
218 | bank1_read = bank1_base[0x10]; | |
219 | ||
220 | /* Reset Flash */ | |
221 | bank1_base[0] = 0x00F000F0; | |
222 | bank2_base[0] = 0x00F000F0; | |
223 | ||
224 | if (bank2_read == bank1_read) { | |
225 | /* | |
226 | * In both CFI command and autoselect modes, | |
227 | * we got the some data reading from Flash. | |
228 | * There is only one mirrored bank. | |
229 | */ | |
ca5def3f | 230 | cfi_flash_num_flash_banks = 1; |
e6f2e902 MB |
231 | total_size = bank1_size; |
232 | } | |
233 | } | |
234 | } | |
235 | ||
ca5def3f | 236 | debug("Number of flash banks detected: %d\n", cfi_flash_num_flash_banks); |
e6f2e902 MB |
237 | |
238 | /* set OR0 and BR0 */ | |
f51cdaf1 BB |
239 | set_lbc_or(0, CONFIG_SYS_OR_TIMING_FLASH | |
240 | (-(total_size) & OR_GPCM_AM)); | |
241 | set_lbc_br(0, (CONFIG_SYS_FLASH_BASE & BR_BA) | | |
242 | (BR_MS_GPCM | BR_PS_32 | BR_V)); | |
e6f2e902 MB |
243 | |
244 | return (0); | |
245 | } | |
246 | ||
247 | /************************************************************************* | |
248 | * Detect the size of a ddr bank. Sets CS bounds and CS config accordingly. | |
249 | */ | |
982db890 | 250 | static long int get_ddr_bank_size(short cs, long *base) |
e6f2e902 MB |
251 | { |
252 | /* This array lists all valid DDR SDRAM configurations, with | |
253 | * Bank sizes in bytes. (Refer to Table 9-27 in the MPC8349E RM). | |
254 | * The last entry has to to have size equal 0 and is igonred during | |
255 | * autodection. Bank sizes must be in increasing order of size | |
256 | */ | |
257 | struct { | |
258 | long row; | |
259 | long col; | |
260 | long size; | |
261 | } conf[] = { | |
262 | {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_8, 32 << 20}, | |
263 | {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_9, 64 << 20}, | |
264 | {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_10, 128 << 20}, | |
265 | {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_9, 128 << 20}, | |
266 | {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_10, 256 << 20}, | |
267 | {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_11, 512 << 20}, | |
268 | {CSCONFIG_ROW_BIT_14, CSCONFIG_COL_BIT_10, 512 << 20}, | |
269 | {CSCONFIG_ROW_BIT_14, CSCONFIG_COL_BIT_11, 1024 << 20}, | |
270 | {0, 0, 0} | |
271 | }; | |
272 | ||
273 | int i; | |
274 | int detected; | |
275 | long size; | |
276 | ||
277 | detected = -1; | |
278 | for(i = 0; conf[i].size != 0; ++i) { | |
279 | ||
280 | /* set sdram bank configuration */ | |
281 | set_cs_config(cs, CSCONFIG_EN | conf[i].col | conf[i].row); | |
282 | ||
283 | debug("Getting RAM size...\n"); | |
284 | size = get_ram_size(base, DDR_MAX_SIZE_PER_CS); | |
285 | ||
286 | if((size == conf[i].size) && (i == detected + 1)) | |
287 | detected = i; | |
288 | ||
289 | debug("Trying %ld x %ld (%ld MiB) at addr %p, detected: %ld MiB\n", | |
290 | conf[i].row, | |
291 | conf[i].col, | |
292 | conf[i].size >> 20, | |
293 | base, | |
294 | size >> 20); | |
295 | } | |
296 | ||
297 | if(detected == -1){ | |
298 | /* disable empty cs */ | |
299 | debug("\nNo valid configurations for CS%d, disabling...\n", cs); | |
300 | set_cs_config(cs, 0); | |
301 | return 0; | |
302 | } | |
f013dacf | 303 | |
e6f2e902 MB |
304 | debug("\nDetected configuration %ld x %ld (%ld MiB) at addr %p\n", |
305 | conf[detected].row, conf[detected].col, conf[detected].size >> 20, base); | |
f013dacf | 306 | |
e6f2e902 MB |
307 | /* configure cs ro detected params */ |
308 | set_cs_config(cs, CSCONFIG_EN | conf[detected].row | | |
309 | conf[detected].col); | |
310 | ||
311 | set_cs_bounds(cs, (long)base, conf[detected].size); | |
312 | ||
313 | return(conf[detected].size); | |
314 | } | |
315 | ||
316 | /************************************************************************** | |
317 | * Sets DDR bank CS bounds. | |
318 | */ | |
4019e54d | 319 | static void set_cs_bounds(short cs, ulong base, ulong size) |
e6f2e902 | 320 | { |
3d54639c | 321 | debug("Setting bounds %08lx, %08lx for cs %d\n", base, size, cs); |
e6f2e902 MB |
322 | if(size == 0){ |
323 | im->ddr.csbnds[cs].csbnds = 0x00000000; | |
324 | } else { | |
325 | im->ddr.csbnds[cs].csbnds = | |
326 | ((base >> CSBNDS_SA_SHIFT) & CSBNDS_SA) | | |
327 | (((base + size - 1) >> CSBNDS_EA_SHIFT) & | |
328 | CSBNDS_EA); | |
329 | } | |
330 | SYNC; | |
331 | } | |
332 | ||
333 | /************************************************************************** | |
334 | * Sets DDR banks CS configuration. | |
335 | * config == 0x00000000 disables the CS. | |
336 | */ | |
337 | static void set_cs_config(short cs, long config) | |
338 | { | |
3d54639c | 339 | debug("Setting config %08lx for cs %d\n", config, cs); |
e6f2e902 MB |
340 | im->ddr.cs_config[cs] = config; |
341 | SYNC; | |
342 | } | |
343 | ||
344 | /************************************************************************** | |
345 | * Sets DDR clocks, timings and configuration. | |
346 | */ | |
347 | static void set_ddr_config(void) { | |
348 | /* clock control */ | |
349 | im->ddr.sdram_clk_cntl = DDR_SDRAM_CLK_CNTL_SS_EN | | |
350 | DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05; | |
351 | SYNC; | |
f013dacf | 352 | |
e6f2e902 MB |
353 | /* timing configuration */ |
354 | im->ddr.timing_cfg_1 = | |
355 | (4 << TIMING_CFG1_PRETOACT_SHIFT) | | |
356 | (7 << TIMING_CFG1_ACTTOPRE_SHIFT) | | |
357 | (4 << TIMING_CFG1_ACTTORW_SHIFT) | | |
358 | (5 << TIMING_CFG1_REFREC_SHIFT) | | |
359 | (3 << TIMING_CFG1_WRREC_SHIFT) | | |
360 | (3 << TIMING_CFG1_ACTTOACT_SHIFT) | | |
361 | (1 << TIMING_CFG1_WRTORD_SHIFT) | | |
362 | (TIMING_CFG1_CASLAT & TIMING_CASLAT); | |
363 | ||
364 | im->ddr.timing_cfg_2 = | |
365 | TIMING_CFG2_CPO_DEF | | |
366 | (2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT); | |
367 | SYNC; | |
368 | ||
369 | /* don't enable DDR controller yet */ | |
370 | im->ddr.sdram_cfg = | |
371 | SDRAM_CFG_SREN | | |
bbea46f7 | 372 | SDRAM_CFG_SDRAM_TYPE_DDR1; |
e6f2e902 | 373 | SYNC; |
f013dacf | 374 | |
e6f2e902 MB |
375 | /* Set SDRAM mode */ |
376 | im->ddr.sdram_mode = | |
377 | ((DDR_MODE_EXT_MODEREG | DDR_MODE_WEAK) << | |
378 | SDRAM_MODE_ESD_SHIFT) | | |
379 | ((DDR_MODE_MODEREG | DDR_MODE_BLEN_4) << | |
380 | SDRAM_MODE_SD_SHIFT) | | |
381 | ((DDR_MODE_CASLAT << SDRAM_MODE_SD_SHIFT) & | |
382 | MODE_CASLAT); | |
383 | SYNC; | |
384 | ||
385 | /* Set fast SDRAM refresh rate */ | |
386 | im->ddr.sdram_interval = | |
387 | (DDR_REFINT_166MHZ_7US << SDRAM_INTERVAL_REFINT_SHIFT) | | |
388 | (DDR_BSTOPRE << SDRAM_INTERVAL_BSTOPRE_SHIFT); | |
389 | SYNC; | |
10af6d53 WD |
390 | |
391 | /* Workaround for DDR6 Erratum | |
392 | * see MPC8349E Device Errata Rev.8, 2/2006 | |
393 | * This workaround influences the MPC internal "input enables" | |
394 | * dependent on CAS latency and MPC revision. According to errata | |
395 | * sheet the internal reserved registers for this workaround are | |
396 | * not available from revision 2.0 and up. | |
397 | */ | |
398 | ||
399 | /* Get REVID from register SPRIDR. Skip workaround if rev >= 2.0 | |
400 | * (0x200) | |
401 | */ | |
402 | if ((im->sysconf.spridr & SPRIDR_REVID) < 0x200) { | |
403 | ||
404 | /* There is a internal reserved register at IMMRBAR+0x2F00 | |
405 | * which has to be written with a certain value defined by | |
406 | * errata sheet. | |
407 | */ | |
966083e9 WD |
408 | u32 *reserved_p = (u32 *)((u8 *)im + 0x2f00); |
409 | ||
10af6d53 | 410 | #if defined(DDR_CASLAT_20) |
966083e9 | 411 | *reserved_p = 0x201c0000; |
10af6d53 | 412 | #else |
966083e9 | 413 | *reserved_p = 0x202c0000; |
10af6d53 WD |
414 | #endif |
415 | } | |
e6f2e902 | 416 | } |
4681e673 WD |
417 | |
418 | #ifdef CONFIG_OF_BOARD_SETUP | |
e895a4b0 | 419 | int ft_board_setup(void *blob, bd_t *bd) |
4681e673 WD |
420 | { |
421 | ft_cpu_setup(blob, bd); | |
422 | ||
423 | #ifdef CONFIG_PCI | |
424 | ft_pci_setup(blob, bd); | |
425 | #endif /* CONFIG_PCI */ | |
e895a4b0 SG |
426 | |
427 | return 0; | |
4681e673 WD |
428 | } |
429 | #endif /* CONFIG_OF_BOARD_SETUP */ |