1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#include <common.h>
52#include <netdev.h>
53#include <asm/fsl_serdes.h>
54#include <fm_eth.h>
55#include <fsl_mdio.h>
56#include <malloc.h>
57#include <fdt_support.h>
58#include <asm/fsl_dtsec.h>
59
60#include "../common/ngpixis.h"
61#include "../common/fman.h"
62
63#ifdef CONFIG_FMAN_ENET
64
65#define BRDCFG1_EMI1_SEL_MASK 0x70
66#define BRDCFG1_EMI1_SEL_SLOT1 0x10
67#define BRDCFG1_EMI1_SEL_SLOT2 0x20
68#define BRDCFG1_EMI1_SEL_SLOT5 0x30
69#define BRDCFG1_EMI1_SEL_SLOT6 0x40
70#define BRDCFG1_EMI1_SEL_SLOT7 0x50
71#define BRDCFG1_EMI1_SEL_RGMII 0x00
72#define BRDCFG1_EMI1_EN 0x08
73#define BRDCFG1_EMI2_SEL_MASK 0x06
74#define BRDCFG1_EMI2_SEL_SLOT1 0x00
75#define BRDCFG1_EMI2_SEL_SLOT2 0x02
76
77#define BRDCFG2_REG_GPIO_SEL 0x20
78
79#define PHY_BASE_ADDR 0x00
80
81
82
83
84
85
86
87struct {
88 u8 mask;
89 u8 val;
90} mdio_mux[NUM_FM_PORTS];
91
92
93
94
95
96
97static u8 lane_to_slot[] = {
98 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 0, 0
99};
100
101
102
103
104
105
106void hydra_mux_mdio(u8 mask, u8 val)
107{
108 clrsetbits_8(&pixis->brdcfg1, mask, val);
109}
110
111struct hydra_mdio {
112 u8 mask;
113 u8 val;
114 struct mii_dev *realbus;
115};
116
117static int hydra_mdio_read(struct mii_dev *bus, int addr, int devad,
118 int regnum)
119{
120 struct hydra_mdio *priv = bus->priv;
121
122 hydra_mux_mdio(priv->mask, priv->val);
123
124 return priv->realbus->read(priv->realbus, addr, devad, regnum);
125}
126
127static int hydra_mdio_write(struct mii_dev *bus, int addr, int devad,
128 int regnum, u16 value)
129{
130 struct hydra_mdio *priv = bus->priv;
131
132 hydra_mux_mdio(priv->mask, priv->val);
133
134 return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
135}
136
137static int hydra_mdio_reset(struct mii_dev *bus)
138{
139 struct hydra_mdio *priv = bus->priv;
140
141 return priv->realbus->reset(priv->realbus);
142}
143
144static void hydra_mdio_set_mux(char *name, u8 mask, u8 val)
145{
146 struct mii_dev *bus = miiphy_get_dev_by_name(name);
147 struct hydra_mdio *priv = bus->priv;
148
149 priv->mask = mask;
150 priv->val = val;
151}
152
153static int hydra_mdio_init(char *realbusname, char *fakebusname)
154{
155 struct hydra_mdio *hmdio;
156 struct mii_dev *bus = mdio_alloc();
157
158 if (!bus) {
159 printf("Failed to allocate Hydra MDIO bus\n");
160 return -1;
161 }
162
163 hmdio = malloc(sizeof(*hmdio));
164 if (!hmdio) {
165 printf("Failed to allocate Hydra private data\n");
166 free(bus);
167 return -1;
168 }
169
170 bus->read = hydra_mdio_read;
171 bus->write = hydra_mdio_write;
172 bus->reset = hydra_mdio_reset;
173 sprintf(bus->name, fakebusname);
174
175 hmdio->realbus = miiphy_get_dev_by_name(realbusname);
176
177 if (!hmdio->realbus) {
178 printf("No bus with name %s\n", realbusname);
179 free(bus);
180 free(hmdio);
181 return -1;
182 }
183
184 bus->priv = hmdio;
185
186 return mdio_register(bus);
187}
188
189
190
191
192
193
194
195
196
197
198static void fdt_set_mdio_mux(void *fdt, const char *alias, u32 mux)
199{
200 const char *path = fdt_get_alias(fdt, alias);
201
202 if (!path)
203 path = alias;
204
205 do_fixup_by_path(fdt, path, "fsl,hydra-mdio-muxval",
206 &mux, sizeof(mux), 1);
207}
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
237 enum fm_port port, int offset)
238{
239 unsigned int mux = mdio_mux[port].val & mdio_mux[port].mask;
240 char phy[16];
241
242 if (port == FM1_10GEC1) {
243
244 int lane = serdes_get_first_lane(XAUI_FM1);
245 if (lane >= 0) {
246
247 sprintf(phy, "phy_xgmii_%u", lane_to_slot[lane]);
248 fdt_set_phy_handle(fdt, compat, addr, phy);
249 }
250 return;
251 }
252
253 if (mux == BRDCFG1_EMI1_SEL_RGMII) {
254
255
256 sprintf(phy, "phy_rgmii_%u", port == FM1_DTSEC4 ? 0 : 1);
257 fdt_set_phy_handle(fdt, compat, addr, phy);
258 }
259
260
261 if (mux) {
262
263 sprintf(phy, "phy_sgmii_%x",
264 CONFIG_SYS_FM1_DTSEC1_PHY_ADDR + (port - FM1_DTSEC1));
265 fdt_set_phy_handle(fdt, compat, addr, phy);
266 }
267}
268
269#define PIXIS_SW2_LANE_23_SEL 0x80
270#define PIXIS_SW2_LANE_45_SEL 0x40
271#define PIXIS_SW2_LANE_67_SEL_MASK 0x30
272#define PIXIS_SW2_LANE_67_SEL_5 0x00
273#define PIXIS_SW2_LANE_67_SEL_6 0x20
274#define PIXIS_SW2_LANE_67_SEL_7 0x10
275#define PIXIS_SW2_LANE_8_SEL 0x08
276#define PIXIS_SW2_LANE_1617_SEL 0x04
277
278
279
280
281
282
283
284
285
286static void initialize_lane_to_slot(void)
287{
288 u8 sw2 = in_8(&PIXIS_SW(2));
289
290 lane_to_slot[2] = (sw2 & PIXIS_SW2_LANE_23_SEL) ? 7 : 4;
291 lane_to_slot[3] = lane_to_slot[2];
292
293 lane_to_slot[4] = (sw2 & PIXIS_SW2_LANE_45_SEL) ? 7 : 6;
294 lane_to_slot[5] = lane_to_slot[4];
295
296 switch (sw2 & PIXIS_SW2_LANE_67_SEL_MASK) {
297 case PIXIS_SW2_LANE_67_SEL_5:
298 lane_to_slot[6] = 5;
299 break;
300 case PIXIS_SW2_LANE_67_SEL_6:
301 lane_to_slot[6] = 6;
302 break;
303 case PIXIS_SW2_LANE_67_SEL_7:
304 lane_to_slot[6] = 7;
305 break;
306 }
307 lane_to_slot[7] = lane_to_slot[6];
308
309 lane_to_slot[8] = (sw2 & PIXIS_SW2_LANE_8_SEL) ? 3 : 0;
310
311 lane_to_slot[16] = (sw2 & PIXIS_SW2_LANE_1617_SEL) ? 1 : 0;
312 lane_to_slot[17] = lane_to_slot[16];
313}
314
315#endif
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330void fdt_fixup_board_enet(void *fdt)
331{
332#ifdef CONFIG_FMAN_ENET
333 unsigned int i;
334 int lane;
335
336 for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
337 int idx = i - FM1_DTSEC1;
338
339 switch (fm_info_get_enet_if(i)) {
340 case PHY_INTERFACE_MODE_SGMII:
341 lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
342 if (lane >= 0) {
343 fdt_status_okay_by_alias(fdt, "emi1_sgmii");
344
345 fdt_set_mdio_mux(fdt, "emi1_sgmii",
346 mdio_mux[i].val);
347 }
348 break;
349 case PHY_INTERFACE_MODE_RGMII:
350 fdt_status_okay_by_alias(fdt, "emi1_rgmii");
351 break;
352 default:
353 break;
354 }
355 }
356
357 lane = serdes_get_first_lane(XAUI_FM1);
358 if (lane >= 0)
359 fdt_status_okay_by_alias(fdt, "emi2_xgmii");
360#endif
361}
362
363int board_eth_init(bd_t *bis)
364{
365#ifdef CONFIG_FMAN_ENET
366 struct fsl_pq_mdio_info dtsec_mdio_info;
367 struct tgec_mdio_info tgec_mdio_info;
368 unsigned int i, slot;
369 int lane;
370 struct mii_dev *bus;
371
372 printf("Initializing Fman\n");
373
374 initialize_lane_to_slot();
375
376
377 setbits_8(&pixis->brdcfg2, BRDCFG2_REG_GPIO_SEL);
378
379 memset(mdio_mux, 0, sizeof(mdio_mux));
380
381 dtsec_mdio_info.regs =
382 (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
383 dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
384
385
386 fsl_pq_mdio_init(bis, &dtsec_mdio_info);
387
388 tgec_mdio_info.regs =
389 (struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
390 tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
391
392
393 fm_tgec_mdio_init(bis, &tgec_mdio_info);
394
395
396 hydra_mdio_init(DEFAULT_FM_MDIO_NAME, "HYDRA_RGMII_MDIO");
397 hydra_mdio_init(DEFAULT_FM_MDIO_NAME, "HYDRA_SGMII_MDIO");
398
399
400
401
402
403
404 fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR);
405 fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR);
406 fm_info_set_phy_address(FM1_DTSEC3, CONFIG_SYS_FM1_DTSEC3_PHY_ADDR);
407 fm_info_set_phy_address(FM1_DTSEC4, CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);
408
409 for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
410 int idx = i - FM1_DTSEC1;
411
412 switch (fm_info_get_enet_if(i)) {
413 case PHY_INTERFACE_MODE_SGMII:
414 lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
415 if (lane < 0)
416 break;
417 slot = lane_to_slot[lane];
418 mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK;
419 switch (slot) {
420 case 1:
421
422 mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT1 |
423 BRDCFG1_EMI1_EN;
424 break;
425 case 2:
426 mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT2 |
427 BRDCFG1_EMI1_EN;
428 break;
429 case 5:
430 mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT5 |
431 BRDCFG1_EMI1_EN;
432 break;
433 case 6:
434 mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT6 |
435 BRDCFG1_EMI1_EN;
436 break;
437 case 7:
438 mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT7 |
439 BRDCFG1_EMI1_EN;
440 break;
441 };
442
443 hydra_mdio_set_mux("HYDRA_SGMII_MDIO",
444 mdio_mux[i].mask, mdio_mux[i].val);
445 fm_info_set_mdio(i,
446 miiphy_get_dev_by_name("HYDRA_SGMII_MDIO"));
447 break;
448 case PHY_INTERFACE_MODE_RGMII:
449
450
451
452
453
454
455
456 fm_info_set_phy_address(i, i == FM1_DTSEC4 ? 0 : 1);
457 mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK;
458 mdio_mux[i].val = BRDCFG1_EMI1_SEL_RGMII |
459 BRDCFG1_EMI1_EN;
460 hydra_mdio_set_mux("HYDRA_RGMII_MDIO",
461 mdio_mux[i].mask, mdio_mux[i].val);
462 fm_info_set_mdio(i,
463 miiphy_get_dev_by_name("HYDRA_RGMII_MDIO"));
464 break;
465 case PHY_INTERFACE_MODE_NONE:
466 fm_info_set_phy_address(i, 0);
467 break;
468 default:
469 printf("Fman1: DTSEC%u set to unknown interface %i\n",
470 idx + 1, fm_info_get_enet_if(i));
471 fm_info_set_phy_address(i, 0);
472 break;
473 }
474 }
475
476 bus = miiphy_get_dev_by_name("HYDRA_SGMII_MDIO");
477 set_sgmii_phy(bus, FM1_DTSEC1, CONFIG_SYS_NUM_FM1_DTSEC, PHY_BASE_ADDR);
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492 lane = serdes_get_first_lane(XAUI_FM1);
493 if (lane >= 0) {
494 slot = lane_to_slot[lane];
495 if (slot == 1) {
496
497 clrsetbits_8(&pixis->brdcfg1, BRDCFG1_EMI2_SEL_MASK,
498 BRDCFG1_EMI2_SEL_SLOT1);
499 fm_info_set_phy_address(FM1_10GEC1,
500 CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
501 } else {
502
503 clrsetbits_8(&pixis->brdcfg1, BRDCFG1_EMI2_SEL_MASK,
504 BRDCFG1_EMI2_SEL_SLOT2);
505 fm_info_set_phy_address(FM1_10GEC1,
506 CONFIG_SYS_FM2_10GEC1_PHY_ADDR);
507 }
508 }
509
510 fm_info_set_mdio(FM1_10GEC1,
511 miiphy_get_dev_by_name(DEFAULT_FM_TGEC_MDIO_NAME));
512
513 cpu_eth_init(bis);
514#endif
515
516 return pci_eth_init(bis);
517}
518