]>
Commit | Line | Data |
---|---|---|
e6f2e902 MB |
1 | /* |
2 | * (C) Copyright 2005 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
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); |
e6f2e902 MB |
46 | static void set_cs_bounds(short cs, long base, long size); |
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 | */ | |
9973e3c6 | 69 | phys_size_t initdram (int board_type) |
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 | ||
115 | return size; | |
116 | } | |
117 | ||
118 | /************************************************************************** | |
119 | * checkboard() | |
120 | */ | |
121 | int checkboard (void) | |
122 | { | |
123 | puts("Board: TQM834x\n"); | |
124 | ||
125 | #ifdef CONFIG_PCI | |
6902df56 RJ |
126 | volatile immap_t * immr; |
127 | u32 w, f; | |
e6f2e902 | 128 | |
6d0f6bcf | 129 | immr = (immap_t *)CONFIG_SYS_IMMR; |
e080313c | 130 | if (!(immr->reset.rcwh & HRCWH_PCI_HOST)) { |
6902df56 RJ |
131 | printf("PCI: NOT in host mode..?!\n"); |
132 | return 0; | |
133 | } | |
e6f2e902 | 134 | |
6902df56 RJ |
135 | /* get bus width */ |
136 | w = 32; | |
e080313c | 137 | if (immr->reset.rcwh & HRCWH_64_BIT_PCI) |
6902df56 | 138 | w = 64; |
e6f2e902 | 139 | |
6902df56 RJ |
140 | /* get clock */ |
141 | f = gd->pci_clk; | |
e6f2e902 | 142 | |
6902df56 RJ |
143 | printf("PCI1: %d bit, %d MHz\n", w, f / 1000000); |
144 | #else | |
145 | printf("PCI: disabled\n"); | |
146 | #endif | |
147 | return 0; | |
e6f2e902 MB |
148 | } |
149 | ||
6902df56 | 150 | |
e6f2e902 MB |
151 | /************************************************************************** |
152 | * | |
153 | * Local functions | |
154 | * | |
155 | *************************************************************************/ | |
156 | ||
157 | /************************************************************************** | |
158 | * Detect the number of flash banks (1 or 2). Store it in | |
159 | * a global variable tqm834x_num_flash_banks. | |
160 | * Bank detection code based on the Monitor code. | |
161 | */ | |
162 | static int detect_num_flash_banks(void) | |
163 | { | |
164 | typedef unsigned long FLASH_PORT_WIDTH; | |
165 | typedef volatile unsigned long FLASH_PORT_WIDTHV; | |
166 | FPWV *bank1_base; | |
167 | FPWV *bank2_base; | |
168 | FPW bank1_read; | |
169 | FPW bank2_read; | |
170 | ulong bank1_size; | |
171 | ulong bank2_size; | |
172 | ulong total_size; | |
173 | ||
ca5def3f | 174 | cfi_flash_num_flash_banks = 2; /* assume two banks */ |
f013dacf | 175 | |
e6f2e902 | 176 | /* Get bank 1 and 2 information */ |
6d0f6bcf | 177 | bank1_size = flash_get_size(CONFIG_SYS_FLASH_BASE, 0); |
e6f2e902 | 178 | debug("Bank1 size: %lu\n", bank1_size); |
6d0f6bcf | 179 | bank2_size = flash_get_size(CONFIG_SYS_FLASH_BASE + bank1_size, 1); |
e6f2e902 MB |
180 | debug("Bank2 size: %lu\n", bank2_size); |
181 | total_size = bank1_size + bank2_size; | |
182 | ||
183 | if (bank2_size > 0) { | |
184 | /* Seems like we've got bank 2, but maybe it's mirrored 1 */ | |
185 | ||
186 | /* Set the base addresses */ | |
6d0f6bcf JCPV |
187 | bank1_base = (FPWV *) (CONFIG_SYS_FLASH_BASE); |
188 | bank2_base = (FPWV *) (CONFIG_SYS_FLASH_BASE + bank1_size); | |
e6f2e902 MB |
189 | |
190 | /* Put bank 2 into CFI command mode and read */ | |
191 | bank2_base[0x55] = 0x00980098; | |
192 | IOSYNC; | |
193 | ISYNC; | |
194 | bank2_read = bank2_base[0x10]; | |
195 | ||
196 | /* Read from bank 1 (it's in read mode) */ | |
197 | bank1_read = bank1_base[0x10]; | |
198 | ||
199 | /* Reset Flash */ | |
200 | bank1_base[0] = 0x00F000F0; | |
201 | bank2_base[0] = 0x00F000F0; | |
202 | ||
203 | if (bank2_read == bank1_read) { | |
204 | /* | |
205 | * Looks like just one bank, but not sure yet. Let's | |
206 | * read from bank 2 in autosoelect mode. | |
207 | */ | |
208 | bank2_base[0x0555] = 0x00AA00AA; | |
209 | bank2_base[0x02AA] = 0x00550055; | |
210 | bank2_base[0x0555] = 0x00900090; | |
211 | IOSYNC; | |
212 | ISYNC; | |
213 | bank2_read = bank2_base[0x10]; | |
214 | ||
215 | /* Read from bank 1 (it's in read mode) */ | |
216 | bank1_read = bank1_base[0x10]; | |
217 | ||
218 | /* Reset Flash */ | |
219 | bank1_base[0] = 0x00F000F0; | |
220 | bank2_base[0] = 0x00F000F0; | |
221 | ||
222 | if (bank2_read == bank1_read) { | |
223 | /* | |
224 | * In both CFI command and autoselect modes, | |
225 | * we got the some data reading from Flash. | |
226 | * There is only one mirrored bank. | |
227 | */ | |
ca5def3f | 228 | cfi_flash_num_flash_banks = 1; |
e6f2e902 MB |
229 | total_size = bank1_size; |
230 | } | |
231 | } | |
232 | } | |
233 | ||
ca5def3f | 234 | debug("Number of flash banks detected: %d\n", cfi_flash_num_flash_banks); |
e6f2e902 MB |
235 | |
236 | /* set OR0 and BR0 */ | |
f51cdaf1 BB |
237 | set_lbc_or(0, CONFIG_SYS_OR_TIMING_FLASH | |
238 | (-(total_size) & OR_GPCM_AM)); | |
239 | set_lbc_br(0, (CONFIG_SYS_FLASH_BASE & BR_BA) | | |
240 | (BR_MS_GPCM | BR_PS_32 | BR_V)); | |
e6f2e902 MB |
241 | |
242 | return (0); | |
243 | } | |
244 | ||
245 | /************************************************************************* | |
246 | * Detect the size of a ddr bank. Sets CS bounds and CS config accordingly. | |
247 | */ | |
982db890 | 248 | static long int get_ddr_bank_size(short cs, long *base) |
e6f2e902 MB |
249 | { |
250 | /* This array lists all valid DDR SDRAM configurations, with | |
251 | * Bank sizes in bytes. (Refer to Table 9-27 in the MPC8349E RM). | |
252 | * The last entry has to to have size equal 0 and is igonred during | |
253 | * autodection. Bank sizes must be in increasing order of size | |
254 | */ | |
255 | struct { | |
256 | long row; | |
257 | long col; | |
258 | long size; | |
259 | } conf[] = { | |
260 | {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_8, 32 << 20}, | |
261 | {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_9, 64 << 20}, | |
262 | {CSCONFIG_ROW_BIT_12, CSCONFIG_COL_BIT_10, 128 << 20}, | |
263 | {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_9, 128 << 20}, | |
264 | {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_10, 256 << 20}, | |
265 | {CSCONFIG_ROW_BIT_13, CSCONFIG_COL_BIT_11, 512 << 20}, | |
266 | {CSCONFIG_ROW_BIT_14, CSCONFIG_COL_BIT_10, 512 << 20}, | |
267 | {CSCONFIG_ROW_BIT_14, CSCONFIG_COL_BIT_11, 1024 << 20}, | |
268 | {0, 0, 0} | |
269 | }; | |
270 | ||
271 | int i; | |
272 | int detected; | |
273 | long size; | |
274 | ||
275 | detected = -1; | |
276 | for(i = 0; conf[i].size != 0; ++i) { | |
277 | ||
278 | /* set sdram bank configuration */ | |
279 | set_cs_config(cs, CSCONFIG_EN | conf[i].col | conf[i].row); | |
280 | ||
281 | debug("Getting RAM size...\n"); | |
282 | size = get_ram_size(base, DDR_MAX_SIZE_PER_CS); | |
283 | ||
284 | if((size == conf[i].size) && (i == detected + 1)) | |
285 | detected = i; | |
286 | ||
287 | debug("Trying %ld x %ld (%ld MiB) at addr %p, detected: %ld MiB\n", | |
288 | conf[i].row, | |
289 | conf[i].col, | |
290 | conf[i].size >> 20, | |
291 | base, | |
292 | size >> 20); | |
293 | } | |
294 | ||
295 | if(detected == -1){ | |
296 | /* disable empty cs */ | |
297 | debug("\nNo valid configurations for CS%d, disabling...\n", cs); | |
298 | set_cs_config(cs, 0); | |
299 | return 0; | |
300 | } | |
f013dacf | 301 | |
e6f2e902 MB |
302 | debug("\nDetected configuration %ld x %ld (%ld MiB) at addr %p\n", |
303 | conf[detected].row, conf[detected].col, conf[detected].size >> 20, base); | |
f013dacf | 304 | |
e6f2e902 MB |
305 | /* configure cs ro detected params */ |
306 | set_cs_config(cs, CSCONFIG_EN | conf[detected].row | | |
307 | conf[detected].col); | |
308 | ||
309 | set_cs_bounds(cs, (long)base, conf[detected].size); | |
310 | ||
311 | return(conf[detected].size); | |
312 | } | |
313 | ||
314 | /************************************************************************** | |
315 | * Sets DDR bank CS bounds. | |
316 | */ | |
317 | static void set_cs_bounds(short cs, long base, long size) | |
318 | { | |
3d54639c | 319 | debug("Setting bounds %08lx, %08lx for cs %d\n", base, size, cs); |
e6f2e902 MB |
320 | if(size == 0){ |
321 | im->ddr.csbnds[cs].csbnds = 0x00000000; | |
322 | } else { | |
323 | im->ddr.csbnds[cs].csbnds = | |
324 | ((base >> CSBNDS_SA_SHIFT) & CSBNDS_SA) | | |
325 | (((base + size - 1) >> CSBNDS_EA_SHIFT) & | |
326 | CSBNDS_EA); | |
327 | } | |
328 | SYNC; | |
329 | } | |
330 | ||
331 | /************************************************************************** | |
332 | * Sets DDR banks CS configuration. | |
333 | * config == 0x00000000 disables the CS. | |
334 | */ | |
335 | static void set_cs_config(short cs, long config) | |
336 | { | |
3d54639c | 337 | debug("Setting config %08lx for cs %d\n", config, cs); |
e6f2e902 MB |
338 | im->ddr.cs_config[cs] = config; |
339 | SYNC; | |
340 | } | |
341 | ||
342 | /************************************************************************** | |
343 | * Sets DDR clocks, timings and configuration. | |
344 | */ | |
345 | static void set_ddr_config(void) { | |
346 | /* clock control */ | |
347 | im->ddr.sdram_clk_cntl = DDR_SDRAM_CLK_CNTL_SS_EN | | |
348 | DDR_SDRAM_CLK_CNTL_CLK_ADJUST_05; | |
349 | SYNC; | |
f013dacf | 350 | |
e6f2e902 MB |
351 | /* timing configuration */ |
352 | im->ddr.timing_cfg_1 = | |
353 | (4 << TIMING_CFG1_PRETOACT_SHIFT) | | |
354 | (7 << TIMING_CFG1_ACTTOPRE_SHIFT) | | |
355 | (4 << TIMING_CFG1_ACTTORW_SHIFT) | | |
356 | (5 << TIMING_CFG1_REFREC_SHIFT) | | |
357 | (3 << TIMING_CFG1_WRREC_SHIFT) | | |
358 | (3 << TIMING_CFG1_ACTTOACT_SHIFT) | | |
359 | (1 << TIMING_CFG1_WRTORD_SHIFT) | | |
360 | (TIMING_CFG1_CASLAT & TIMING_CASLAT); | |
361 | ||
362 | im->ddr.timing_cfg_2 = | |
363 | TIMING_CFG2_CPO_DEF | | |
364 | (2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT); | |
365 | SYNC; | |
366 | ||
367 | /* don't enable DDR controller yet */ | |
368 | im->ddr.sdram_cfg = | |
369 | SDRAM_CFG_SREN | | |
bbea46f7 | 370 | SDRAM_CFG_SDRAM_TYPE_DDR1; |
e6f2e902 | 371 | SYNC; |
f013dacf | 372 | |
e6f2e902 MB |
373 | /* Set SDRAM mode */ |
374 | im->ddr.sdram_mode = | |
375 | ((DDR_MODE_EXT_MODEREG | DDR_MODE_WEAK) << | |
376 | SDRAM_MODE_ESD_SHIFT) | | |
377 | ((DDR_MODE_MODEREG | DDR_MODE_BLEN_4) << | |
378 | SDRAM_MODE_SD_SHIFT) | | |
379 | ((DDR_MODE_CASLAT << SDRAM_MODE_SD_SHIFT) & | |
380 | MODE_CASLAT); | |
381 | SYNC; | |
382 | ||
383 | /* Set fast SDRAM refresh rate */ | |
384 | im->ddr.sdram_interval = | |
385 | (DDR_REFINT_166MHZ_7US << SDRAM_INTERVAL_REFINT_SHIFT) | | |
386 | (DDR_BSTOPRE << SDRAM_INTERVAL_BSTOPRE_SHIFT); | |
387 | SYNC; | |
10af6d53 WD |
388 | |
389 | /* Workaround for DDR6 Erratum | |
390 | * see MPC8349E Device Errata Rev.8, 2/2006 | |
391 | * This workaround influences the MPC internal "input enables" | |
392 | * dependent on CAS latency and MPC revision. According to errata | |
393 | * sheet the internal reserved registers for this workaround are | |
394 | * not available from revision 2.0 and up. | |
395 | */ | |
396 | ||
397 | /* Get REVID from register SPRIDR. Skip workaround if rev >= 2.0 | |
398 | * (0x200) | |
399 | */ | |
400 | if ((im->sysconf.spridr & SPRIDR_REVID) < 0x200) { | |
401 | ||
402 | /* There is a internal reserved register at IMMRBAR+0x2F00 | |
403 | * which has to be written with a certain value defined by | |
404 | * errata sheet. | |
405 | */ | |
966083e9 WD |
406 | u32 *reserved_p = (u32 *)((u8 *)im + 0x2f00); |
407 | ||
10af6d53 | 408 | #if defined(DDR_CASLAT_20) |
966083e9 | 409 | *reserved_p = 0x201c0000; |
10af6d53 | 410 | #else |
966083e9 | 411 | *reserved_p = 0x202c0000; |
10af6d53 WD |
412 | #endif |
413 | } | |
e6f2e902 | 414 | } |
4681e673 WD |
415 | |
416 | #ifdef CONFIG_OF_BOARD_SETUP | |
417 | void ft_board_setup(void *blob, bd_t *bd) | |
418 | { | |
419 | ft_cpu_setup(blob, bd); | |
420 | ||
421 | #ifdef CONFIG_PCI | |
422 | ft_pci_setup(blob, bd); | |
423 | #endif /* CONFIG_PCI */ | |
424 | } | |
425 | #endif /* CONFIG_OF_BOARD_SETUP */ |