]>
Commit | Line | Data |
---|---|---|
19580e66 | 1 | /* |
a1964ea5 | 2 | * Copyright (C) 2007,2010 Freescale Semiconductor, Inc. |
19580e66 DL |
3 | * Dave Liu <daveliu@freescale.com> |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
19580e66 DL |
6 | */ |
7 | ||
8 | #include <common.h> | |
c78c6783 | 9 | #include <hwconfig.h> |
19580e66 | 10 | #include <i2c.h> |
6f8c85e8 | 11 | #include <asm/io.h> |
7e1afb62 | 12 | #include <asm/fsl_mpc83xx_serdes.h> |
19580e66 | 13 | #include <spd_sdram.h> |
1da83a63 | 14 | #include <tsec.h> |
19580e66 | 15 | #include <libfdt.h> |
3bf1be3c | 16 | #include <fdt_support.h> |
c78c6783 | 17 | #include <fsl_esdhc.h> |
063c1263 | 18 | #include <fsl_mdio.h> |
865ff856 | 19 | #include <phy.h> |
8b34557c | 20 | #include "pci.h" |
19580e66 | 21 | #include "../common/pq-mds-pib.h" |
19580e66 | 22 | |
088454cd SG |
23 | DECLARE_GLOBAL_DATA_PTR; |
24 | ||
19580e66 DL |
25 | int board_early_init_f(void) |
26 | { | |
6d0f6bcf | 27 | u8 *bcsr = (u8 *)CONFIG_SYS_BCSR; |
19580e66 DL |
28 | |
29 | /* Enable flash write */ | |
30 | bcsr[0x9] &= ~0x04; | |
31 | /* Clear all of the interrupt of BCSR */ | |
32 | bcsr[0xe] = 0xff; | |
33 | ||
6f8c85e8 | 34 | #ifdef CONFIG_FSL_SERDES |
6d0f6bcf | 35 | immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; |
6f8c85e8 DL |
36 | u32 spridr = in_be32(&immr->sysconf.spridr); |
37 | ||
38 | /* we check only part num, and don't look for CPU revisions */ | |
5fb5a689 | 39 | switch (PARTID_NO_E(spridr)) { |
e5c4ade4 | 40 | case SPR_8377: |
6f8c85e8 | 41 | fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA, |
e1ac387f | 42 | FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); |
6f8c85e8 | 43 | break; |
e5c4ade4 | 44 | case SPR_8378: |
1da83a63 | 45 | fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SGMII, |
e1ac387f | 46 | FSL_SERDES_CLK_125, FSL_SERDES_VDD_1V); |
6f8c85e8 | 47 | break; |
e5c4ade4 | 48 | case SPR_8379: |
6f8c85e8 | 49 | fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SATA, |
e1ac387f | 50 | FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); |
e5c4ade4 | 51 | fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_SATA, |
e1ac387f | 52 | FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); |
6f8c85e8 DL |
53 | break; |
54 | default: | |
55 | printf("serdes not configured: unknown CPU part number: " | |
e1ac387f | 56 | "%04x\n", spridr >> 16); |
6f8c85e8 DL |
57 | break; |
58 | } | |
59 | #endif /* CONFIG_FSL_SERDES */ | |
19580e66 DL |
60 | return 0; |
61 | } | |
62 | ||
c78c6783 AV |
63 | #ifdef CONFIG_FSL_ESDHC |
64 | int board_mmc_init(bd_t *bd) | |
65 | { | |
66 | struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR; | |
67 | u8 *bcsr = (u8 *)CONFIG_SYS_BCSR; | |
68 | ||
69 | if (!hwconfig("esdhc")) | |
70 | return 0; | |
71 | ||
72 | /* Set SPI_SD, SER_SD, and IRQ4_WP so that SD signals go through */ | |
73 | bcsr[0xc] |= 0x4c; | |
74 | ||
75 | /* Set proper bits in SICR to allow SD signals through */ | |
76 | clrsetbits_be32(&im->sysconf.sicrl, SICRL_USB_B, SICRL_USB_B_SD); | |
77 | clrsetbits_be32(&im->sysconf.sicrh, SICRH_GPIO2_E | SICRH_SPI, | |
78 | SICRH_GPIO2_E_SD | SICRH_SPI_SD); | |
79 | ||
80 | return fsl_esdhc_mmc_init(bd); | |
81 | } | |
82 | #endif | |
83 | ||
1da83a63 AV |
84 | #if defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) |
85 | int board_eth_init(bd_t *bd) | |
86 | { | |
063c1263 | 87 | struct fsl_pq_mdio_info mdio_info; |
1da83a63 AV |
88 | struct tsec_info_struct tsec_info[2]; |
89 | struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR; | |
90 | u32 rcwh = in_be32(&im->reset.rcwh); | |
91 | u32 tsec_mode; | |
92 | int num = 0; | |
93 | ||
94 | /* New line after Net: */ | |
95 | printf("\n"); | |
96 | ||
97 | #ifdef CONFIG_TSEC1 | |
98 | SET_STD_TSEC_INFO(tsec_info[num], 1); | |
99 | ||
100 | printf(CONFIG_TSEC1_NAME ": "); | |
101 | ||
102 | tsec_mode = rcwh & HRCWH_TSEC1M_MASK; | |
103 | if (tsec_mode == HRCWH_TSEC1M_IN_RGMII) { | |
104 | printf("RGMII\n"); | |
105 | /* this is default, no need to fixup */ | |
106 | } else if (tsec_mode == HRCWH_TSEC1M_IN_SGMII) { | |
107 | printf("SGMII\n"); | |
108 | tsec_info[num].phyaddr = TSEC1_PHY_ADDR_SGMII; | |
109 | tsec_info[num].flags = TSEC_GIGABIT; | |
110 | } else { | |
111 | printf("unsupported PHY type\n"); | |
112 | } | |
113 | num++; | |
114 | #endif | |
115 | #ifdef CONFIG_TSEC2 | |
116 | SET_STD_TSEC_INFO(tsec_info[num], 2); | |
117 | ||
118 | printf(CONFIG_TSEC2_NAME ": "); | |
119 | ||
120 | tsec_mode = rcwh & HRCWH_TSEC2M_MASK; | |
121 | if (tsec_mode == HRCWH_TSEC2M_IN_RGMII) { | |
122 | printf("RGMII\n"); | |
123 | /* this is default, no need to fixup */ | |
124 | } else if (tsec_mode == HRCWH_TSEC2M_IN_SGMII) { | |
125 | printf("SGMII\n"); | |
126 | tsec_info[num].phyaddr = TSEC2_PHY_ADDR_SGMII; | |
127 | tsec_info[num].flags = TSEC_GIGABIT; | |
128 | } else { | |
129 | printf("unsupported PHY type\n"); | |
130 | } | |
131 | num++; | |
132 | #endif | |
063c1263 AF |
133 | |
134 | mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR; | |
135 | mdio_info.name = DEFAULT_MII_NAME; | |
136 | fsl_pq_mdio_init(bd, &mdio_info); | |
137 | ||
1da83a63 AV |
138 | return tsec_eth_init(bd, tsec_info, num); |
139 | } | |
140 | ||
141 | static void __ft_tsec_fixup(void *blob, bd_t *bd, const char *alias, | |
142 | int phy_addr) | |
143 | { | |
1da83a63 AV |
144 | const u32 *ph; |
145 | int off; | |
146 | int err; | |
147 | ||
148 | off = fdt_path_offset(blob, alias); | |
149 | if (off < 0) { | |
150 | printf("WARNING: could not find %s alias: %s.\n", alias, | |
151 | fdt_strerror(off)); | |
152 | return; | |
153 | } | |
154 | ||
865ff856 | 155 | err = fdt_fixup_phy_connection(blob, off, PHY_INTERFACE_MODE_SGMII); |
a1964ea5 | 156 | |
1da83a63 AV |
157 | if (err) { |
158 | printf("WARNING: could not set phy-connection-type for %s: " | |
159 | "%s.\n", alias, fdt_strerror(err)); | |
160 | return; | |
161 | } | |
162 | ||
163 | ph = (u32 *)fdt_getprop(blob, off, "phy-handle", 0); | |
164 | if (!ph) { | |
165 | printf("WARNING: could not get phy-handle for %s.\n", | |
166 | alias); | |
167 | return; | |
168 | } | |
169 | ||
170 | off = fdt_node_offset_by_phandle(blob, *ph); | |
171 | if (off < 0) { | |
172 | printf("WARNING: could not get phy node for %s: %s\n", alias, | |
173 | fdt_strerror(off)); | |
174 | return; | |
175 | } | |
176 | ||
177 | phy_addr = cpu_to_fdt32(phy_addr); | |
178 | err = fdt_setprop(blob, off, "reg", &phy_addr, sizeof(phy_addr)); | |
179 | if (err < 0) { | |
180 | printf("WARNING: could not set phy node's reg for %s: " | |
181 | "%s.\n", alias, fdt_strerror(err)); | |
182 | return; | |
183 | } | |
184 | } | |
185 | ||
186 | static void ft_tsec_fixup(void *blob, bd_t *bd) | |
187 | { | |
188 | struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR; | |
189 | u32 rcwh = in_be32(&im->reset.rcwh); | |
190 | u32 tsec_mode; | |
191 | ||
192 | #ifdef CONFIG_TSEC1 | |
193 | tsec_mode = rcwh & HRCWH_TSEC1M_MASK; | |
194 | if (tsec_mode == HRCWH_TSEC1M_IN_SGMII) | |
195 | __ft_tsec_fixup(blob, bd, "ethernet0", TSEC1_PHY_ADDR_SGMII); | |
196 | #endif | |
197 | ||
198 | #ifdef CONFIG_TSEC2 | |
199 | tsec_mode = rcwh & HRCWH_TSEC2M_MASK; | |
200 | if (tsec_mode == HRCWH_TSEC2M_IN_SGMII) | |
201 | __ft_tsec_fixup(blob, bd, "ethernet1", TSEC2_PHY_ADDR_SGMII); | |
202 | #endif | |
203 | } | |
204 | #else | |
205 | static inline void ft_tsec_fixup(void *blob, bd_t *bd) {} | |
206 | #endif /* defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) */ | |
207 | ||
19580e66 DL |
208 | int board_early_init_r(void) |
209 | { | |
210 | #ifdef CONFIG_PQ_MDS_PIB | |
211 | pib_init(); | |
212 | #endif | |
213 | return 0; | |
214 | } | |
215 | ||
9adda545 | 216 | #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) |
19580e66 DL |
217 | extern void ddr_enable_ecc(unsigned int dram_size); |
218 | #endif | |
219 | int fixed_sdram(void); | |
220 | ||
088454cd | 221 | int initdram(void) |
19580e66 | 222 | { |
6d0f6bcf | 223 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
19580e66 DL |
224 | u32 msize = 0; |
225 | ||
226 | if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im) | |
088454cd | 227 | return -ENXIO; |
19580e66 DL |
228 | |
229 | #if defined(CONFIG_SPD_EEPROM) | |
230 | msize = spd_sdram(); | |
231 | #else | |
232 | msize = fixed_sdram(); | |
233 | #endif | |
234 | ||
9adda545 | 235 | #if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER) |
19580e66 DL |
236 | /* Initialize DDR ECC byte */ |
237 | ddr_enable_ecc(msize * 1024 * 1024); | |
238 | #endif | |
239 | ||
240 | /* return total bus DDR size(bytes) */ | |
088454cd SG |
241 | gd->ram_size = msize * 1024 * 1024; |
242 | ||
243 | return 0; | |
19580e66 DL |
244 | } |
245 | ||
246 | #if !defined(CONFIG_SPD_EEPROM) | |
247 | /************************************************************************* | |
248 | * fixed sdram init -- doesn't use serial presence detect. | |
249 | ************************************************************************/ | |
250 | int fixed_sdram(void) | |
251 | { | |
6d0f6bcf JCPV |
252 | volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR; |
253 | u32 msize = CONFIG_SYS_DDR_SIZE * 1024 * 1024; | |
19580e66 DL |
254 | u32 msize_log2 = __ilog2(msize); |
255 | ||
6d0f6bcf | 256 | im->sysconf.ddrlaw[0].bar = CONFIG_SYS_DDR_SDRAM_BASE & 0xfffff000; |
19580e66 DL |
257 | im->sysconf.ddrlaw[0].ar = LBLAWAR_EN | (msize_log2 - 1); |
258 | ||
6d0f6bcf | 259 | #if (CONFIG_SYS_DDR_SIZE != 512) |
19580e66 DL |
260 | #warning Currenly any ddr size other than 512 is not supported |
261 | #endif | |
6d0f6bcf | 262 | im->sysconf.ddrcdr = CONFIG_SYS_DDRCDR_VALUE; |
19580e66 DL |
263 | udelay(50000); |
264 | ||
6d0f6bcf | 265 | im->ddr.sdram_clk_cntl = CONFIG_SYS_DDR_SDRAM_CLK_CNTL; |
19580e66 DL |
266 | udelay(1000); |
267 | ||
6d0f6bcf JCPV |
268 | im->ddr.csbnds[0].csbnds = CONFIG_SYS_DDR_CS0_BNDS; |
269 | im->ddr.cs_config[0] = CONFIG_SYS_DDR_CS0_CONFIG; | |
19580e66 DL |
270 | udelay(1000); |
271 | ||
6d0f6bcf JCPV |
272 | im->ddr.timing_cfg_0 = CONFIG_SYS_DDR_TIMING_0; |
273 | im->ddr.timing_cfg_1 = CONFIG_SYS_DDR_TIMING_1; | |
274 | im->ddr.timing_cfg_2 = CONFIG_SYS_DDR_TIMING_2; | |
275 | im->ddr.timing_cfg_3 = CONFIG_SYS_DDR_TIMING_3; | |
276 | im->ddr.sdram_cfg = CONFIG_SYS_DDR_SDRAM_CFG; | |
277 | im->ddr.sdram_cfg2 = CONFIG_SYS_DDR_SDRAM_CFG2; | |
278 | im->ddr.sdram_mode = CONFIG_SYS_DDR_MODE; | |
279 | im->ddr.sdram_mode2 = CONFIG_SYS_DDR_MODE2; | |
280 | im->ddr.sdram_interval = CONFIG_SYS_DDR_INTERVAL; | |
19580e66 DL |
281 | __asm__ __volatile__("sync"); |
282 | udelay(1000); | |
283 | ||
284 | im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; | |
285 | udelay(2000); | |
6d0f6bcf | 286 | return CONFIG_SYS_DDR_SIZE; |
19580e66 | 287 | } |
6d0f6bcf | 288 | #endif /*!CONFIG_SYS_SPD_EEPROM */ |
19580e66 DL |
289 | |
290 | int checkboard(void) | |
291 | { | |
292 | puts("Board: Freescale MPC837xEMDS\n"); | |
293 | return 0; | |
294 | } | |
295 | ||
00f7bbae AV |
296 | #ifdef CONFIG_PCI |
297 | int board_pci_host_broken(void) | |
298 | { | |
299 | struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR; | |
300 | const u32 rcw_mask = HRCWH_PCI1_ARBITER_ENABLE | HRCWH_PCI_HOST; | |
00f7bbae AV |
301 | |
302 | /* It's always OK in case of external arbiter. */ | |
bfadb17f | 303 | if (hwconfig_subarg_cmp("pci", "arbiter", "external")) |
00f7bbae AV |
304 | return 0; |
305 | ||
306 | if ((in_be32(&im->reset.rcwh) & rcw_mask) != rcw_mask) | |
307 | return 1; | |
308 | ||
309 | return 0; | |
310 | } | |
311 | ||
312 | static void ft_pci_fixup(void *blob, bd_t *bd) | |
313 | { | |
314 | const char *status = "broken (no arbiter)"; | |
315 | int off; | |
316 | int err; | |
317 | ||
318 | off = fdt_path_offset(blob, "pci0"); | |
319 | if (off < 0) { | |
320 | printf("WARNING: could not find pci0 alias: %s.\n", | |
321 | fdt_strerror(off)); | |
322 | return; | |
323 | } | |
324 | ||
325 | err = fdt_setprop(blob, off, "status", status, strlen(status) + 1); | |
326 | if (err) { | |
327 | printf("WARNING: could not set status for pci0: %s.\n", | |
328 | fdt_strerror(err)); | |
329 | return; | |
330 | } | |
331 | } | |
332 | #endif | |
333 | ||
19580e66 | 334 | #if defined(CONFIG_OF_BOARD_SETUP) |
e895a4b0 | 335 | int ft_board_setup(void *blob, bd_t *bd) |
19580e66 | 336 | { |
19580e66 | 337 | ft_cpu_setup(blob, bd); |
1da83a63 | 338 | ft_tsec_fixup(blob, bd); |
a5c289b9 | 339 | fsl_fdt_fixup_dr_usb(blob, bd); |
c78c6783 | 340 | fdt_fixup_esdhc(blob, bd); |
19580e66 DL |
341 | #ifdef CONFIG_PCI |
342 | ft_pci_setup(blob, bd); | |
00f7bbae AV |
343 | if (board_pci_host_broken()) |
344 | ft_pci_fixup(blob, bd); | |
8b34557c | 345 | ft_pcie_fixup(blob, bd); |
19580e66 | 346 | #endif |
e895a4b0 SG |
347 | |
348 | return 0; | |
19580e66 DL |
349 | } |
350 | #endif /* CONFIG_OF_BOARD_SETUP */ |