]>
Commit | Line | Data |
---|---|---|
4387cf1a AG |
1 | /* |
2 | * Partially derived from board code for digsyMTC, | |
3 | * (C) Copyright 2009 | |
4 | * Grzegorz Bernacki, Semihalf, gjb@semihalf.com | |
5 | * | |
6 | * (C) Copyright 2012 | |
7 | * DENX Software Engineering, Anatolij Gustschin <agust@denx.de> | |
8 | * | |
1a459660 | 9 | * SPDX-License-Identifier: GPL-2.0+ |
4387cf1a AG |
10 | */ |
11 | ||
12 | #include <common.h> | |
13 | #include <mpc5xxx.h> | |
14 | #include <asm/processor.h> | |
15 | #include <asm/io.h> | |
16 | #include <libfdt.h> | |
17 | #include <fdt_support.h> | |
18 | #include <i2c.h> | |
19 | #include <miiphy.h> | |
20 | #include <net.h> | |
21 | #include <pci.h> | |
22 | ||
23 | DECLARE_GLOBAL_DATA_PTR; | |
24 | ||
25 | #define SDRAM_MODE 0x00CD0000 | |
26 | #define SDRAM_CONTROL 0x504F0000 | |
27 | #define SDRAM_CONFIG1 0xD2322800 | |
28 | #define SDRAM_CONFIG2 0x8AD70000 | |
29 | ||
30 | enum ifm_sensor_type { | |
31 | O2DNT = 0x00, /* !< O2DNT 32MB */ | |
32 | O2DNT2 = 0x01, /* !< O2DNT2 64MB */ | |
33 | O3DNT = 0x02, /* !< O3DNT 32MB */ | |
34 | O3DNT_MIN = 0x40, /* !< O3DNT Minerva 32MB */ | |
35 | UNKNOWN = 0xff, /* !< Unknow sensor */ | |
36 | }; | |
37 | ||
38 | static enum ifm_sensor_type gt_ifm_sensor_type; | |
39 | ||
40 | #ifndef CONFIG_SYS_RAMBOOT | |
41 | static void sdram_start(int hi_addr) | |
42 | { | |
43 | struct mpc5xxx_sdram *sdram = (struct mpc5xxx_sdram *)MPC5XXX_SDRAM; | |
44 | long hi_addr_bit = hi_addr ? 0x01000000 : 0; | |
45 | long control = SDRAM_CONTROL | hi_addr_bit; | |
46 | ||
47 | /* unlock mode register */ | |
48 | out_be32(&sdram->ctrl, control | 0x80000000); | |
49 | ||
50 | /* precharge all banks */ | |
51 | out_be32(&sdram->ctrl, control | 0x80000002); | |
52 | ||
53 | /* auto refresh */ | |
54 | out_be32(&sdram->ctrl, control | 0x80000004); | |
55 | ||
56 | /* set mode register */ | |
57 | out_be32(&sdram->mode, SDRAM_MODE); | |
58 | ||
59 | /* normal operation */ | |
60 | out_be32(&sdram->ctrl, control); | |
61 | } | |
62 | #endif | |
63 | ||
64 | /* | |
f1683aa7 | 65 | * ATTENTION: Although partially referenced dram_init does NOT make real use |
4387cf1a AG |
66 | * use of CONFIG_SYS_SDRAM_BASE. The code does not work if |
67 | * CONFIG_SYS_SDRAM_BASE is something else than 0x00000000. | |
68 | */ | |
f1683aa7 | 69 | int dram_init(void) |
4387cf1a AG |
70 | { |
71 | struct mpc5xxx_mmap_ctl *mmap_ctl = | |
72 | (struct mpc5xxx_mmap_ctl *)CONFIG_SYS_MBAR; | |
73 | struct mpc5xxx_sdram *sdram = (struct mpc5xxx_sdram *)MPC5XXX_SDRAM; | |
74 | ulong dramsize = 0; | |
75 | ulong dramsize2 = 0; | |
76 | uint svr, pvr; | |
77 | ||
78 | if (gt_ifm_sensor_type == O2DNT2) { | |
79 | /* activate SDRAM CS1 */ | |
80 | setbits_be32((void *)MPC5XXX_GPS_PORT_CONFIG, 0x80000000); | |
81 | } | |
82 | ||
83 | #ifndef CONFIG_SYS_RAMBOOT | |
84 | ulong test1, test2; | |
85 | ||
86 | /* setup SDRAM chip selects */ | |
87 | out_be32(&mmap_ctl->sdram0, 0x0000001E); /* 2 GB at 0x0 */ | |
88 | out_be32(&mmap_ctl->sdram1, 0x00000000); /* disabled */ | |
89 | ||
90 | /* setup config registers */ | |
91 | out_be32(&sdram->config1, SDRAM_CONFIG1); | |
92 | out_be32(&sdram->config2, SDRAM_CONFIG2); | |
93 | ||
94 | /* find RAM size using SDRAM CS0 only */ | |
95 | sdram_start(0); | |
96 | test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x08000000); | |
97 | sdram_start(1); | |
98 | test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x08000000); | |
99 | if (test1 > test2) { | |
100 | sdram_start(0); | |
101 | dramsize = test1; | |
102 | } else { | |
103 | dramsize = test2; | |
104 | } | |
105 | ||
106 | /* memory smaller than 1MB is impossible */ | |
107 | if (dramsize < (1 << 20)) | |
108 | dramsize = 0; | |
109 | ||
110 | /* set SDRAM CS0 size according to the amount of RAM found */ | |
111 | if (dramsize > 0) { | |
112 | out_be32(&mmap_ctl->sdram0, | |
113 | (0x13 + __builtin_ffs(dramsize >> 20) - 1)); | |
114 | } else { | |
115 | out_be32(&mmap_ctl->sdram0, 0); /* disabled */ | |
116 | } | |
117 | ||
118 | /* let SDRAM CS1 start right after CS0 */ | |
119 | out_be32(&mmap_ctl->sdram1, dramsize + 0x0000001E); /* 2G */ | |
120 | ||
121 | /* find RAM size using SDRAM CS1 only */ | |
122 | if (!dramsize) | |
123 | sdram_start(0); | |
124 | ||
125 | test2 = test1 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), | |
126 | 0x80000000); | |
127 | if (!dramsize) { | |
128 | sdram_start(1); | |
129 | test2 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), | |
130 | 0x80000000); | |
131 | } | |
132 | ||
133 | if (test1 > test2) { | |
134 | sdram_start(0); | |
135 | dramsize2 = test1; | |
136 | } else { | |
137 | dramsize2 = test2; | |
138 | } | |
139 | ||
140 | /* memory smaller than 1MB is impossible */ | |
141 | if (dramsize2 < (1 << 20)) | |
142 | dramsize2 = 0; | |
143 | ||
144 | /* set SDRAM CS1 size according to the amount of RAM found */ | |
145 | if (dramsize2 > 0) { | |
146 | out_be32(&mmap_ctl->sdram1, (dramsize | | |
147 | (0x13 + __builtin_ffs(dramsize2 >> 20) - 1))); | |
148 | } else { | |
149 | out_be32(&mmap_ctl->sdram1, dramsize); /* disabled */ | |
150 | } | |
151 | ||
152 | #else /* CONFIG_SYS_RAMBOOT */ | |
153 | /* retrieve size of memory connected to SDRAM CS0 */ | |
154 | dramsize = in_be32(&mmap_ctl->sdram0) & 0xFF; | |
155 | if (dramsize >= 0x13) | |
156 | dramsize = (1 << (dramsize - 0x13)) << 20; | |
157 | else | |
158 | dramsize = 0; | |
159 | ||
160 | /* retrieve size of memory connected to SDRAM CS1 */ | |
161 | dramsize2 = in_be32(&mmap_ctl->sdram1) & 0xFF; | |
162 | if (dramsize2 >= 0x13) | |
163 | dramsize2 = (1 << (dramsize2 - 0x13)) << 20; | |
164 | else | |
165 | dramsize2 = 0; | |
166 | ||
167 | #endif /* CONFIG_SYS_RAMBOOT */ | |
168 | ||
169 | /* | |
170 | * On MPC5200B we need to set the special configuration delay in the | |
171 | * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM | |
172 | * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190: | |
173 | * | |
174 | * "The SDelay should be written to a value of 0x00000004. It is | |
175 | * required to account for changes caused by normal wafer processing | |
176 | * parameters." | |
177 | */ | |
178 | svr = get_svr(); | |
179 | pvr = get_pvr(); | |
180 | if ((SVR_MJREV(svr) >= 2) && | |
181 | (PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4)) | |
182 | out_be32(&sdram->sdelay, 0x04); | |
183 | ||
088454cd SG |
184 | gd->ram_size = dramsize + dramsize2; |
185 | ||
186 | return 0; | |
4387cf1a AG |
187 | } |
188 | ||
189 | ||
190 | #define GPT_GPIO_IN 0x4 | |
191 | ||
192 | int checkboard(void) | |
193 | { | |
194 | struct mpc5xxx_gpt *gpt = (struct mpc5xxx_gpt *)MPC5XXX_GPT; | |
195 | unsigned char board_config = 0; | |
196 | int i; | |
197 | ||
198 | /* switch gpt0 - gpt7 to input */ | |
199 | for (i = 0; i < 7; i++) | |
200 | out_be32(&gpt[i].emsr, GPT_GPIO_IN); | |
201 | ||
202 | /* get configuration byte on timer-port */ | |
203 | for (i = 0; i < 7; i++) | |
204 | board_config |= (in_be32(&gpt[i].sr) & 0x100) >> (8 - i); | |
205 | ||
206 | puts("Board: "); | |
207 | ||
208 | switch (board_config) { | |
209 | case 0: | |
210 | puts("O2DNT\n"); | |
211 | gt_ifm_sensor_type = O2DNT; | |
212 | break; | |
213 | case 1: | |
214 | puts("O3DNT\n"); | |
215 | gt_ifm_sensor_type = O3DNT; | |
216 | break; | |
217 | case 2: | |
218 | puts("O2DNT2\n"); | |
219 | gt_ifm_sensor_type = O2DNT2; | |
220 | break; | |
221 | case 64: | |
222 | puts("O3DNT Minerva\n"); | |
223 | gt_ifm_sensor_type = O3DNT_MIN; | |
224 | break; | |
225 | default: | |
226 | puts("Unknown\n"); | |
227 | gt_ifm_sensor_type = UNKNOWN; | |
228 | break; | |
229 | } | |
230 | ||
231 | return 0; | |
232 | } | |
233 | ||
234 | int board_early_init_r(void) | |
235 | { | |
236 | struct mpc5xxx_lpb *lpb_regs = (struct mpc5xxx_lpb *)MPC5XXX_LPB; | |
237 | ||
238 | /* | |
239 | * Now, when we are in RAM, enable flash write access for detection | |
240 | * process. Note that CS_BOOT cannot be cleared when executing in flash. | |
241 | */ | |
242 | clrbits_be32(&lpb_regs->cs0_cfg, 1); /* clear RO */ | |
243 | /* disable CS_BOOT */ | |
244 | clrbits_be32((void *)MPC5XXX_ADDECR, (1 << 25)); | |
245 | /* enable CS0 */ | |
246 | setbits_be32((void *)MPC5XXX_ADDECR, (1 << 16)); | |
247 | ||
248 | return 0; | |
249 | } | |
250 | ||
251 | #define MIIM_LXT971_LED_CFG_REG 0x14 | |
252 | #define LXT971_LED_CFG_LINK_STATUS 0x4000 | |
253 | #define LXT971_LED_CFG_RX_TX_ACTIVITY 0x0700 | |
254 | #define LXT971_LED_CFG_LINK_ACTIVITY 0x00D0 | |
255 | #define LXT971_LED_CFG_PULSE_STRETCH 0x0002 | |
256 | /* | |
257 | * Additional PHY intialization after reset in mpc5xxx_fec_init_phy() | |
258 | */ | |
259 | void reset_phy(void) | |
260 | { | |
261 | /* | |
262 | * Set LED configuration bits. | |
263 | * It can't be done in misc_init_r() since FEC is not | |
264 | * initialized at this time. Therefore we do it here. | |
265 | */ | |
266 | miiphy_write("FEC", CONFIG_PHY_ADDR, MIIM_LXT971_LED_CFG_REG, | |
267 | LXT971_LED_CFG_LINK_STATUS | | |
268 | LXT971_LED_CFG_RX_TX_ACTIVITY | | |
269 | LXT971_LED_CFG_LINK_ACTIVITY | | |
270 | LXT971_LED_CFG_PULSE_STRETCH); | |
271 | } | |
272 | ||
273 | #if defined(CONFIG_POST) | |
274 | /* | |
275 | * Reads GPIO pin PSC6_3. A keypress is reported, if PSC6_3 is low. If PSC6_3 | |
276 | * is left open, no keypress is detected. | |
277 | */ | |
278 | int post_hotkeys_pressed(void) | |
279 | { | |
280 | struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *) MPC5XXX_GPIO; | |
281 | ||
282 | /* | |
283 | * Configure PSC6_1 and PSC6_3 as GPIO. PSC6 then couldn't be used in | |
284 | * CODEC or UART mode. Consumer IrDA should still be possible. | |
285 | */ | |
286 | clrbits_be32(&gpio->port_config, 0x07000000); | |
287 | setbits_be32(&gpio->port_config, 0x03000000); | |
288 | ||
289 | /* Enable GPIO for GPIO_IRDA_1 (IR_USB_CLK pin) = PSC6_3 */ | |
290 | setbits_be32(&gpio->simple_gpioe, 0x20000000); | |
291 | ||
292 | /* Configure GPIO_IRDA_1 as input */ | |
293 | clrbits_be32(&gpio->simple_ddr, 0x20000000); | |
294 | ||
295 | return (in_be32(&gpio->simple_ival) & 0x20000000) ? 0 : 1; | |
296 | } | |
297 | #endif | |
298 | ||
299 | #ifdef CONFIG_PCI | |
300 | static struct pci_controller hose; | |
301 | ||
302 | void pci_init_board(void) | |
303 | { | |
304 | pci_mpc5xxx_init(&hose); | |
305 | } | |
306 | #endif | |
307 | ||
7ffe3cd6 | 308 | #ifdef CONFIG_OF_BOARD_SETUP |
4387cf1a AG |
309 | #if defined(CONFIG_SYS_UPDATE_FLASH_SIZE) |
310 | static void ft_adapt_flash_base(void *blob) | |
311 | { | |
312 | flash_info_t *dev = &flash_info[0]; | |
313 | int off; | |
314 | struct fdt_property *prop; | |
315 | int len; | |
316 | u32 *reg, *reg2; | |
317 | ||
318 | off = fdt_node_offset_by_compatible(blob, -1, "fsl,mpc5200b-lpb"); | |
319 | if (off < 0) { | |
320 | printf("Could not find fsl,mpc5200b-lpb node.\n"); | |
321 | return; | |
322 | } | |
323 | ||
324 | /* found compatible property */ | |
325 | prop = fdt_get_property_w(blob, off, "ranges", &len); | |
326 | if (prop) { | |
327 | reg = reg2 = (u32 *)&prop->data[0]; | |
328 | ||
329 | reg[2] = dev->start[0]; | |
330 | reg[3] = dev->size; | |
331 | fdt_setprop(blob, off, "ranges", reg2, len); | |
332 | } else | |
333 | printf("Could not find ranges\n"); | |
334 | } | |
335 | ||
336 | extern ulong flash_get_size(phys_addr_t base, int banknum); | |
337 | ||
338 | /* Update the flash baseaddr settings */ | |
339 | int update_flash_size(int flash_size) | |
340 | { | |
341 | struct mpc5xxx_mmap_ctl *mm = | |
342 | (struct mpc5xxx_mmap_ctl *) CONFIG_SYS_MBAR; | |
343 | flash_info_t *dev; | |
344 | int i; | |
345 | int size = 0; | |
346 | unsigned long base = 0x0; | |
347 | u32 *cs_reg = (u32 *)&mm->cs0_start; | |
348 | ||
349 | for (i = 0; i < 2; i++) { | |
350 | dev = &flash_info[i]; | |
351 | ||
352 | if (dev->size) { | |
353 | /* calculate new base addr for this chipselect */ | |
354 | base -= dev->size; | |
355 | out_be32(cs_reg, START_REG(base)); | |
356 | cs_reg++; | |
357 | out_be32(cs_reg, STOP_REG(base, dev->size)); | |
358 | cs_reg++; | |
359 | /* recalculate the sectoraddr in the cfi driver */ | |
360 | size += flash_get_size(base, i); | |
361 | } | |
362 | } | |
363 | flash_protect_default(); | |
364 | gd->bd->bi_flashstart = base; | |
365 | return 0; | |
366 | } | |
367 | #endif /* defined(CONFIG_SYS_UPDATE_FLASH_SIZE) */ | |
368 | ||
e895a4b0 | 369 | int ft_board_setup(void *blob, bd_t *bd) |
4387cf1a AG |
370 | { |
371 | int phy_addr = CONFIG_PHY_ADDR; | |
372 | char eth_path[] = "/soc5200@f0000000/mdio@3000/ethernet-phy@0"; | |
373 | ||
374 | ft_cpu_setup(blob, bd); | |
375 | ||
376 | #if defined(CONFIG_SYS_UPDATE_FLASH_SIZE) | |
377 | #ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE | |
378 | /* Update reg property in all nor flash nodes too */ | |
379 | fdt_fixup_nor_flash_size(blob); | |
380 | #endif | |
381 | ft_adapt_flash_base(blob); | |
382 | #endif | |
383 | /* fix up the phy address */ | |
384 | do_fixup_by_path(blob, eth_path, "reg", &phy_addr, sizeof(int), 0); | |
e895a4b0 SG |
385 | |
386 | return 0; | |
4387cf1a | 387 | } |
7ffe3cd6 | 388 | #endif /* CONFIG_OF_BOARD_SETUP */ |