]>
Commit | Line | Data |
---|---|---|
2915609a AF |
1 | /* |
2 | * Copyright 2009-2011 Freescale Semiconductor, Inc. | |
3 | * | |
1a459660 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
2915609a AF |
5 | */ |
6 | ||
7 | #include <common.h> | |
8 | #include <command.h> | |
9 | #include <netdev.h> | |
10 | #include <asm/mmu.h> | |
11 | #include <asm/processor.h> | |
12 | #include <asm/cache.h> | |
13 | #include <asm/immap_85xx.h> | |
14 | #include <asm/fsl_law.h> | |
5614e71b | 15 | #include <fsl_ddr_sdram.h> |
2915609a AF |
16 | #include <asm/fsl_serdes.h> |
17 | #include <asm/fsl_portals.h> | |
18 | #include <asm/fsl_liodn.h> | |
19 | #include <malloc.h> | |
20 | #include <fm_eth.h> | |
21 | #include <fsl_mdio.h> | |
22 | #include <miiphy.h> | |
23 | #include <phy.h> | |
24 | ||
25 | #include "../common/ngpixis.h" | |
26 | #include "../common/fman.h" | |
27 | #include <asm/fsl_dtsec.h> | |
28 | ||
29 | #define EMI_NONE 0xffffffff | |
30 | #define EMI_MASK 0xf0000000 | |
31 | #define EMI1_RGMII 0x0 | |
32 | #define EMI1_SLOT3 0x80000000 /* bank1 EFGH */ | |
33 | #define EMI1_SLOT4 0x40000000 /* bank2 ABCD */ | |
34 | #define EMI1_SLOT5 0xc0000000 /* bank3 ABCD */ | |
35 | #define EMI2_SLOT4 0x10000000 /* bank2 ABCD */ | |
36 | #define EMI2_SLOT5 0x30000000 /* bank3 ABCD */ | |
37 | #define EMI1_MASK 0xc0000000 | |
38 | #define EMI2_MASK 0x30000000 | |
39 | ||
ffee1dde ZQ |
40 | #define PHY_BASE_ADDR 0x00 |
41 | #define PHY_BASE_ADDR_SLOT5 0x10 | |
42 | ||
2915609a AF |
43 | static int mdio_mux[NUM_FM_PORTS]; |
44 | ||
45 | static char *mdio_names[16] = { | |
46 | "P4080DS_MDIO0", | |
47 | "P4080DS_MDIO1", | |
48 | NULL, | |
49 | "P4080DS_MDIO3", | |
50 | "P4080DS_MDIO4", | |
51 | NULL, NULL, NULL, | |
52 | "P4080DS_MDIO8", | |
53 | NULL, NULL, NULL, | |
54 | "P4080DS_MDIO12", | |
55 | NULL, NULL, NULL, | |
56 | }; | |
57 | ||
61fc52b6 TT |
58 | /* |
59 | * Mapping of all 18 SERDES lanes to board slots. A value of '0' here means | |
60 | * that the mapping must be determined dynamically, or that the lane maps to | |
61 | * something other than a board slot. | |
62 | */ | |
63 | static u8 lane_to_slot[] = { | |
64 | 1, 1, 2, 2, 3, 3, 3, 3, 6, 6, 4, 4, 4, 4, 5, 5, 5, 5 | |
65 | }; | |
66 | ||
2915609a AF |
67 | static char *p4080ds_mdio_name_for_muxval(u32 muxval) |
68 | { | |
69 | return mdio_names[(muxval & EMI_MASK) >> 28]; | |
70 | } | |
71 | ||
72 | struct mii_dev *mii_dev_for_muxval(u32 muxval) | |
73 | { | |
74 | struct mii_dev *bus; | |
75 | char *name = p4080ds_mdio_name_for_muxval(muxval); | |
76 | ||
77 | if (!name) { | |
78 | printf("No bus for muxval %x\n", muxval); | |
79 | return NULL; | |
80 | } | |
81 | ||
82 | bus = miiphy_get_dev_by_name(name); | |
83 | ||
84 | if (!bus) { | |
85 | printf("No bus by name %s\n", name); | |
86 | return NULL; | |
87 | } | |
88 | ||
89 | return bus; | |
90 | } | |
91 | ||
a836626c | 92 | #if defined(CONFIG_SYS_P4080_ERRATUM_SERDES9) && defined(CONFIG_PHY_TERANETICS) |
2915609a AF |
93 | int board_phy_config(struct phy_device *phydev) |
94 | { | |
9fafe7da TK |
95 | if (phydev->drv->config) |
96 | phydev->drv->config(phydev); | |
a836626c TT |
97 | if (phydev->drv->uid == PHY_UID_TN2020) { |
98 | unsigned long timeout = 1 * 1000; /* 1 seconds */ | |
2915609a AF |
99 | enum srds_prtcl device; |
100 | ||
a836626c TT |
101 | /* |
102 | * Wait for the XAUI to come out of reset. This is when it | |
103 | * starts transmitting alignment signals. | |
104 | */ | |
105 | while (--timeout) { | |
106 | int reg = phy_read(phydev, MDIO_MMD_PHYXS, MDIO_CTRL1); | |
107 | if (reg < 0) { | |
108 | printf("TN2020: Error reading from PHY at " | |
109 | "address %u\n", phydev->addr); | |
110 | break; | |
111 | } | |
112 | /* | |
113 | * Note that we've never actually seen | |
114 | * MDIO_CTRL1_RESET set to 1. | |
115 | */ | |
116 | if ((reg & MDIO_CTRL1_RESET) == 0) | |
117 | break; | |
118 | udelay(1000); | |
119 | } | |
120 | ||
121 | if (!timeout) { | |
122 | printf("TN2020: Timeout waiting for PHY at address %u " | |
123 | " to reset.\n", phydev->addr); | |
124 | } | |
125 | ||
2915609a | 126 | switch (phydev->addr) { |
a836626c | 127 | case CONFIG_SYS_FM1_10GEC1_PHY_ADDR: |
2915609a AF |
128 | device = XAUI_FM1; |
129 | break; | |
a836626c | 130 | case CONFIG_SYS_FM2_10GEC1_PHY_ADDR: |
2915609a AF |
131 | device = XAUI_FM2; |
132 | break; | |
133 | default: | |
134 | device = NONE; | |
135 | } | |
136 | ||
137 | serdes_reset_rx(device); | |
138 | } | |
139 | ||
140 | return 0; | |
141 | } | |
142 | #endif | |
143 | ||
144 | struct p4080ds_mdio { | |
145 | u32 muxval; | |
146 | struct mii_dev *realbus; | |
147 | }; | |
148 | ||
149 | static void p4080ds_mux_mdio(u32 muxval) | |
150 | { | |
151 | ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR); | |
152 | uint gpioval = in_be32(&pgpio->gpdat) & ~(EMI_MASK); | |
153 | gpioval |= muxval; | |
154 | ||
155 | out_be32(&pgpio->gpdat, gpioval); | |
156 | } | |
157 | ||
158 | static int p4080ds_mdio_read(struct mii_dev *bus, int addr, int devad, | |
159 | int regnum) | |
160 | { | |
161 | struct p4080ds_mdio *priv = bus->priv; | |
162 | ||
163 | p4080ds_mux_mdio(priv->muxval); | |
164 | ||
165 | return priv->realbus->read(priv->realbus, addr, devad, regnum); | |
166 | } | |
167 | ||
168 | static int p4080ds_mdio_write(struct mii_dev *bus, int addr, int devad, | |
169 | int regnum, u16 value) | |
170 | { | |
171 | struct p4080ds_mdio *priv = bus->priv; | |
172 | ||
173 | p4080ds_mux_mdio(priv->muxval); | |
174 | ||
175 | return priv->realbus->write(priv->realbus, addr, devad, regnum, value); | |
176 | } | |
177 | ||
178 | static int p4080ds_mdio_reset(struct mii_dev *bus) | |
179 | { | |
180 | struct p4080ds_mdio *priv = bus->priv; | |
181 | ||
182 | return priv->realbus->reset(priv->realbus); | |
183 | } | |
184 | ||
185 | static int p4080ds_mdio_init(char *realbusname, u32 muxval) | |
186 | { | |
187 | struct p4080ds_mdio *pmdio; | |
188 | struct mii_dev *bus = mdio_alloc(); | |
189 | ||
190 | if (!bus) { | |
191 | printf("Failed to allocate P4080DS MDIO bus\n"); | |
192 | return -1; | |
193 | } | |
194 | ||
195 | pmdio = malloc(sizeof(*pmdio)); | |
196 | if (!pmdio) { | |
197 | printf("Failed to allocate P4080DS private data\n"); | |
198 | free(bus); | |
199 | return -1; | |
200 | } | |
201 | ||
202 | bus->read = p4080ds_mdio_read; | |
203 | bus->write = p4080ds_mdio_write; | |
204 | bus->reset = p4080ds_mdio_reset; | |
205 | sprintf(bus->name, p4080ds_mdio_name_for_muxval(muxval)); | |
206 | ||
207 | pmdio->realbus = miiphy_get_dev_by_name(realbusname); | |
208 | ||
209 | if (!pmdio->realbus) { | |
210 | printf("No bus with name %s\n", realbusname); | |
211 | free(bus); | |
212 | free(pmdio); | |
213 | return -1; | |
214 | } | |
215 | ||
216 | pmdio->muxval = muxval; | |
217 | bus->priv = pmdio; | |
218 | ||
219 | return mdio_register(bus); | |
220 | } | |
221 | ||
2915609a AF |
222 | void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa, |
223 | enum fm_port port, int offset) | |
224 | { | |
225 | if (mdio_mux[port] == EMI1_RGMII) | |
226 | fdt_set_phy_handle(blob, prop, pa, "phy_rgmii"); | |
227 | ||
228 | if (mdio_mux[port] == EMI1_SLOT3) { | |
229 | int idx = port - FM2_DTSEC1 + 5; | |
230 | char phy[16]; | |
231 | ||
232 | sprintf(phy, "phy%d_slot3", idx); | |
233 | ||
234 | fdt_set_phy_handle(blob, prop, pa, phy); | |
235 | } | |
236 | } | |
237 | ||
238 | void fdt_fixup_board_enet(void *fdt) | |
239 | { | |
240 | int i; | |
241 | ||
242 | /* | |
243 | * P4080DS can be configured in many different ways, supporting a number | |
244 | * of combinations of ethernet devices and phy types. In order to | |
245 | * have just one device tree for all of those configurations, we fix up | |
246 | * the tree here. By default, the device tree configures FM1 and FM2 | |
247 | * for SGMII, and configures XAUI on both 10G interfaces. So we have | |
248 | * a number of different variables to track: | |
249 | * | |
250 | * 1) Whether the device is configured at all. Whichever devices are | |
251 | * not enabled should be disabled by setting the "status" property | |
252 | * to "disabled". | |
253 | * 2) What the PHY interface is. If this is an RGMII connection, | |
254 | * we should change the "phy-connection-type" property to | |
255 | * "rgmii" | |
256 | * 3) Which PHY is being used. Because the MDIO buses are muxed, | |
257 | * we need to redirect the "phy-handle" property to point at the | |
258 | * PHY on the right slot/bus. | |
259 | */ | |
260 | ||
261 | /* We've got six MDIO nodes that may or may not need to exist */ | |
2a523f52 SL |
262 | fdt_status_disabled_by_alias(fdt, "emi1_slot3"); |
263 | fdt_status_disabled_by_alias(fdt, "emi1_slot4"); | |
264 | fdt_status_disabled_by_alias(fdt, "emi1_slot5"); | |
265 | fdt_status_disabled_by_alias(fdt, "emi2_slot4"); | |
266 | fdt_status_disabled_by_alias(fdt, "emi2_slot5"); | |
2915609a AF |
267 | |
268 | for (i = 0; i < NUM_FM_PORTS; i++) { | |
269 | switch (mdio_mux[i]) { | |
270 | case EMI1_SLOT3: | |
2a523f52 | 271 | fdt_status_okay_by_alias(fdt, "emi1_slot3"); |
2915609a AF |
272 | break; |
273 | case EMI1_SLOT4: | |
2a523f52 | 274 | fdt_status_okay_by_alias(fdt, "emi1_slot4"); |
2915609a AF |
275 | break; |
276 | case EMI1_SLOT5: | |
2a523f52 | 277 | fdt_status_okay_by_alias(fdt, "emi1_slot5"); |
2915609a AF |
278 | break; |
279 | case EMI2_SLOT4: | |
2a523f52 | 280 | fdt_status_okay_by_alias(fdt, "emi2_slot4"); |
2915609a AF |
281 | break; |
282 | case EMI2_SLOT5: | |
2a523f52 | 283 | fdt_status_okay_by_alias(fdt, "emi2_slot5"); |
2915609a AF |
284 | break; |
285 | } | |
286 | } | |
287 | } | |
288 | ||
2915609a AF |
289 | int board_eth_init(bd_t *bis) |
290 | { | |
291 | #ifdef CONFIG_FMAN_ENET | |
292 | ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR); | |
2915609a AF |
293 | int i; |
294 | struct fsl_pq_mdio_info dtsec_mdio_info; | |
295 | struct tgec_mdio_info tgec_mdio_info; | |
ffee1dde | 296 | struct mii_dev *bus; |
2915609a | 297 | |
2915609a AF |
298 | /* Initialize the mdio_mux array so we can recognize empty elements */ |
299 | for (i = 0; i < NUM_FM_PORTS; i++) | |
300 | mdio_mux[i] = EMI_NONE; | |
301 | ||
302 | /* The first 4 GPIOs are outputs to control MDIO bus muxing */ | |
303 | out_be32(&pgpio->gpdir, EMI_MASK); | |
304 | ||
305 | dtsec_mdio_info.regs = | |
306 | (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR; | |
307 | dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME; | |
308 | ||
309 | /* Register the 1G MDIO bus */ | |
310 | fsl_pq_mdio_init(bis, &dtsec_mdio_info); | |
311 | ||
312 | tgec_mdio_info.regs = | |
313 | (struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR; | |
314 | tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME; | |
315 | ||
316 | /* Register the 10G MDIO bus */ | |
317 | fm_tgec_mdio_init(bis, &tgec_mdio_info); | |
318 | ||
319 | /* Register the 6 muxing front-ends to the MDIO buses */ | |
320 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII); | |
321 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT3); | |
322 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT4); | |
323 | p4080ds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT5); | |
324 | p4080ds_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, EMI2_SLOT4); | |
325 | p4080ds_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME, EMI2_SLOT5); | |
326 | ||
327 | fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR); | |
328 | fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR); | |
329 | fm_info_set_phy_address(FM1_DTSEC3, CONFIG_SYS_FM1_DTSEC3_PHY_ADDR); | |
330 | fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR); | |
331 | fm_info_set_phy_address(FM1_10GEC1, CONFIG_SYS_FM1_10GEC1_PHY_ADDR); | |
332 | ||
333 | #if (CONFIG_SYS_NUM_FMAN == 2) | |
334 | fm_info_set_phy_address(FM2_DTSEC1, CONFIG_SYS_FM2_DTSEC1_PHY_ADDR); | |
335 | fm_info_set_phy_address(FM2_DTSEC2, CONFIG_SYS_FM2_DTSEC2_PHY_ADDR); | |
336 | fm_info_set_phy_address(FM2_DTSEC3, CONFIG_SYS_FM2_DTSEC3_PHY_ADDR); | |
337 | fm_info_set_phy_address(FM2_DTSEC4, CONFIG_SYS_FM2_DTSEC4_PHY_ADDR); | |
338 | fm_info_set_phy_address(FM2_10GEC1, CONFIG_SYS_FM2_10GEC1_PHY_ADDR); | |
339 | #endif | |
340 | ||
341 | for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { | |
342 | int idx = i - FM1_DTSEC1, lane, slot; | |
343 | switch (fm_info_get_enet_if(i)) { | |
344 | case PHY_INTERFACE_MODE_SGMII: | |
345 | lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx); | |
346 | if (lane < 0) | |
347 | break; | |
348 | slot = lane_to_slot[lane]; | |
349 | switch (slot) { | |
61fc52b6 | 350 | case 3: |
2915609a AF |
351 | mdio_mux[i] = EMI1_SLOT3; |
352 | fm_info_set_mdio(i, | |
353 | mii_dev_for_muxval(mdio_mux[i])); | |
354 | break; | |
61fc52b6 | 355 | case 4: |
2915609a AF |
356 | mdio_mux[i] = EMI1_SLOT4; |
357 | fm_info_set_mdio(i, | |
358 | mii_dev_for_muxval(mdio_mux[i])); | |
359 | break; | |
61fc52b6 | 360 | case 5: |
2915609a AF |
361 | mdio_mux[i] = EMI1_SLOT5; |
362 | fm_info_set_mdio(i, | |
363 | mii_dev_for_muxval(mdio_mux[i])); | |
364 | break; | |
365 | }; | |
366 | break; | |
367 | case PHY_INTERFACE_MODE_RGMII: | |
368 | fm_info_set_phy_address(i, 0); | |
369 | mdio_mux[i] = EMI1_RGMII; | |
370 | fm_info_set_mdio(i, | |
371 | mii_dev_for_muxval(mdio_mux[i])); | |
372 | break; | |
373 | default: | |
374 | break; | |
375 | } | |
376 | } | |
ffee1dde ZQ |
377 | bus = mii_dev_for_muxval(EMI1_SLOT5); |
378 | set_sgmii_phy(bus, FM1_DTSEC1, | |
379 | CONFIG_SYS_NUM_FM1_DTSEC, PHY_BASE_ADDR_SLOT5); | |
2915609a AF |
380 | |
381 | for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) { | |
382 | int idx = i - FM1_10GEC1, lane, slot; | |
383 | switch (fm_info_get_enet_if(i)) { | |
384 | case PHY_INTERFACE_MODE_XGMII: | |
385 | lane = serdes_get_first_lane(XAUI_FM1 + idx); | |
386 | if (lane < 0) | |
387 | break; | |
388 | slot = lane_to_slot[lane]; | |
389 | switch (slot) { | |
61fc52b6 | 390 | case 4: |
2915609a AF |
391 | mdio_mux[i] = EMI2_SLOT4; |
392 | fm_info_set_mdio(i, | |
393 | mii_dev_for_muxval(mdio_mux[i])); | |
394 | break; | |
61fc52b6 | 395 | case 5: |
2915609a AF |
396 | mdio_mux[i] = EMI2_SLOT5; |
397 | fm_info_set_mdio(i, | |
398 | mii_dev_for_muxval(mdio_mux[i])); | |
399 | break; | |
400 | }; | |
401 | break; | |
402 | default: | |
403 | break; | |
404 | } | |
405 | } | |
406 | ||
407 | #if (CONFIG_SYS_NUM_FMAN == 2) | |
408 | for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) { | |
409 | int idx = i - FM2_DTSEC1, lane, slot; | |
410 | switch (fm_info_get_enet_if(i)) { | |
411 | case PHY_INTERFACE_MODE_SGMII: | |
412 | lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx); | |
413 | if (lane < 0) | |
414 | break; | |
415 | slot = lane_to_slot[lane]; | |
416 | switch (slot) { | |
61fc52b6 | 417 | case 3: |
2915609a AF |
418 | mdio_mux[i] = EMI1_SLOT3; |
419 | fm_info_set_mdio(i, | |
420 | mii_dev_for_muxval(mdio_mux[i])); | |
421 | break; | |
61fc52b6 | 422 | case 4: |
2915609a AF |
423 | mdio_mux[i] = EMI1_SLOT4; |
424 | fm_info_set_mdio(i, | |
425 | mii_dev_for_muxval(mdio_mux[i])); | |
426 | break; | |
61fc52b6 | 427 | case 5: |
2915609a AF |
428 | mdio_mux[i] = EMI1_SLOT5; |
429 | fm_info_set_mdio(i, | |
430 | mii_dev_for_muxval(mdio_mux[i])); | |
431 | break; | |
432 | }; | |
433 | break; | |
434 | case PHY_INTERFACE_MODE_RGMII: | |
435 | fm_info_set_phy_address(i, 0); | |
436 | mdio_mux[i] = EMI1_RGMII; | |
437 | fm_info_set_mdio(i, | |
438 | mii_dev_for_muxval(mdio_mux[i])); | |
439 | break; | |
440 | default: | |
441 | break; | |
442 | } | |
443 | } | |
444 | ||
ffee1dde ZQ |
445 | bus = mii_dev_for_muxval(EMI1_SLOT3); |
446 | set_sgmii_phy(bus, FM2_DTSEC1, CONFIG_SYS_NUM_FM2_DTSEC, PHY_BASE_ADDR); | |
447 | bus = mii_dev_for_muxval(EMI1_SLOT4); | |
448 | set_sgmii_phy(bus, FM2_DTSEC1, CONFIG_SYS_NUM_FM2_DTSEC, PHY_BASE_ADDR); | |
449 | ||
2915609a AF |
450 | for (i = FM2_10GEC1; i < FM2_10GEC1 + CONFIG_SYS_NUM_FM2_10GEC; i++) { |
451 | int idx = i - FM2_10GEC1, lane, slot; | |
452 | switch (fm_info_get_enet_if(i)) { | |
453 | case PHY_INTERFACE_MODE_XGMII: | |
454 | lane = serdes_get_first_lane(XAUI_FM2 + idx); | |
455 | if (lane < 0) | |
456 | break; | |
457 | slot = lane_to_slot[lane]; | |
458 | switch (slot) { | |
61fc52b6 | 459 | case 4: |
2915609a AF |
460 | mdio_mux[i] = EMI2_SLOT4; |
461 | fm_info_set_mdio(i, | |
462 | mii_dev_for_muxval(mdio_mux[i])); | |
463 | break; | |
61fc52b6 | 464 | case 5: |
2915609a AF |
465 | mdio_mux[i] = EMI2_SLOT5; |
466 | fm_info_set_mdio(i, | |
467 | mii_dev_for_muxval(mdio_mux[i])); | |
468 | break; | |
469 | }; | |
470 | break; | |
471 | default: | |
472 | break; | |
473 | } | |
474 | } | |
475 | #endif | |
476 | ||
477 | cpu_eth_init(bis); | |
478 | #endif /* CONFIG_FMAN_ENET */ | |
479 | ||
480 | return pci_eth_init(bis); | |
481 | } |