]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/p3060qds/eth.c
Merge branch 'master' of git://git.denx.de/u-boot-mpc83xx
[karo-tx-uboot.git] / board / freescale / p3060qds / eth.c
1 /*
2  * Copyright 2011 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 #include <common.h>
24 #include <command.h>
25 #include <netdev.h>
26 #include <asm/mmu.h>
27 #include <asm/processor.h>
28 #include <asm/cache.h>
29 #include <asm/immap_85xx.h>
30 #include <asm/fsl_law.h>
31 #include <asm/fsl_ddr_sdram.h>
32 #include <asm/fsl_serdes.h>
33 #include <asm/fsl_portals.h>
34 #include <asm/fsl_liodn.h>
35 #include <malloc.h>
36 #include <fm_eth.h>
37 #include <fsl_mdio.h>
38 #include <miiphy.h>
39 #include <phy.h>
40 #include <asm/fsl_dtsec.h>
41
42 #include "../common/qixis.h"
43 #include "../common/fman.h"
44
45 #include "p3060qds_qixis.h"
46
47 #define EMI_NONE       0xffffffff
48 #define EMI1_RGMII1    0
49 #define EMI1_SLOT1     1
50 #define EMI1_SLOT2     2
51 #define EMI1_SLOT3     3
52 #define EMI1_RGMII2    4
53
54 static int mdio_mux[NUM_FM_PORTS];
55
56 static char *mdio_names[5] = {
57         "P3060QDS_MDIO0",
58         "P3060QDS_MDIO1",
59         "P3060QDS_MDIO2",
60         "P3060QDS_MDIO3",
61         "P3060QDS_MDIO4",
62 };
63
64 /*
65  * Mapping of all 18 SERDES lanes to board slots.
66  * A value of '0' here means that the mapping must be determined
67  * dynamically, Lane 8/9/16/17 map to Slot1 or Aurora debug
68  */
69 static u8 lane_to_slot[] = {
70         4, 4, 4, 4, 3, 3, 3, 3, 0, 0, 2, 2, 2, 2, 1, 1, 0, 0
71 };
72
73 static char *p3060qds_mdio_name_for_muxval(u32 muxval)
74 {
75         return mdio_names[muxval];
76 }
77
78 struct mii_dev *mii_dev_for_muxval(u32 muxval)
79 {
80         struct mii_dev *bus;
81         char *name = p3060qds_mdio_name_for_muxval(muxval);
82
83         if (!name) {
84                 printf("No bus for muxval %x\n", muxval);
85                 return NULL;
86         }
87
88         bus = miiphy_get_dev_by_name(name);
89
90         if (!bus) {
91                 printf("No bus by name %s\n", name);
92                 return NULL;
93         }
94
95         return bus;
96 }
97
98 struct p3060qds_mdio {
99         u32 muxval;
100         struct mii_dev *realbus;
101 };
102
103 static void p3060qds_mux_mdio(u32 muxval)
104 {
105         u8 brdcfg4;
106
107         brdcfg4 = QIXIS_READ(brdcfg[4]);
108         brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
109         brdcfg4 |= (muxval << 4);
110         QIXIS_WRITE(brdcfg[4], brdcfg4);
111 }
112
113 static int p3060qds_mdio_read(struct mii_dev *bus, int addr, int devad,
114                                 int regnum)
115 {
116         struct p3060qds_mdio *priv = bus->priv;
117
118         p3060qds_mux_mdio(priv->muxval);
119
120         return priv->realbus->read(priv->realbus, addr, devad, regnum);
121 }
122
123 static int p3060qds_mdio_write(struct mii_dev *bus, int addr, int devad,
124                                 int regnum, u16 value)
125 {
126         struct p3060qds_mdio *priv = bus->priv;
127
128         p3060qds_mux_mdio(priv->muxval);
129
130         return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
131 }
132
133 static int p3060qds_mdio_reset(struct mii_dev *bus)
134 {
135         struct p3060qds_mdio *priv = bus->priv;
136
137         return priv->realbus->reset(priv->realbus);
138 }
139
140 static int p3060qds_mdio_init(char *realbusname, u32 muxval)
141 {
142         struct p3060qds_mdio *pmdio;
143         struct mii_dev *bus = mdio_alloc();
144
145         if (!bus) {
146                 printf("Failed to allocate P3060QDS MDIO bus\n");
147                 return -1;
148         }
149
150         pmdio = malloc(sizeof(*pmdio));
151         if (!pmdio) {
152                 printf("Failed to allocate P3060QDS private data\n");
153                 free(bus);
154                 return -1;
155         }
156
157         bus->read = p3060qds_mdio_read;
158         bus->write = p3060qds_mdio_write;
159         bus->reset = p3060qds_mdio_reset;
160         sprintf(bus->name, p3060qds_mdio_name_for_muxval(muxval));
161
162         pmdio->realbus = miiphy_get_dev_by_name(realbusname);
163
164         if (!pmdio->realbus) {
165                 printf("No bus with name %s\n", realbusname);
166                 free(bus);
167                 free(pmdio);
168                 return -1;
169         }
170
171         pmdio->muxval = muxval;
172         bus->priv = pmdio;
173
174         return mdio_register(bus);
175 }
176
177 void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
178                                 enum fm_port port, int offset)
179 {
180         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
181         int srds_prtcl = (in_be32(&gur->rcwsr[4]) &
182                           FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
183
184         if (mdio_mux[port] == EMI1_RGMII1)
185                 fdt_set_phy_handle(blob, prop, pa, "phy_rgmii1");
186
187         if (mdio_mux[port] == EMI1_RGMII2)
188                 fdt_set_phy_handle(blob, prop, pa, "phy_rgmii2");
189
190         if ((mdio_mux[port] == EMI1_SLOT1) && ((srds_prtcl == 0x3)
191                 || (srds_prtcl == 0x6))) {
192                 switch (port) {
193                 case FM2_DTSEC4:
194                         fdt_set_phy_handle(blob, prop, pa, "phy2_slot1");
195                         break;
196                 case FM1_DTSEC4:
197                         fdt_set_phy_handle(blob, prop, pa, "phy3_slot1");
198                         break;
199                 default:
200                         break;
201                 }
202         }
203
204         if (mdio_mux[port] == EMI1_SLOT3) {
205                 switch (port) {
206                 case FM2_DTSEC3:
207                         fdt_set_phy_handle(blob, prop, pa, "phy0_slot3");
208                         break;
209                 case FM1_DTSEC3:
210                         fdt_set_phy_handle(blob, prop, pa, "phy1_slot3");
211                         break;
212                 default:
213                         break;
214                 }
215         }
216 }
217
218 void fdt_fixup_board_enet(void *fdt)
219 {
220         int i, lane, idx;
221
222         for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
223                 idx = i - FM1_DTSEC1;
224                 switch (fm_info_get_enet_if(i)) {
225                 case PHY_INTERFACE_MODE_SGMII:
226                         lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
227                         if (lane < 0)
228                                 break;
229
230                         switch (mdio_mux[i]) {
231                         case EMI1_SLOT1:
232                                 if (lane >= 14) {
233                                         fdt_status_okay_by_alias(fdt,
234                                                 "emi1_slot1");
235                                         fdt_status_disabled_by_alias(fdt,
236                                                 "emi1_slot1_bk1");
237                                 } else {
238                                         fdt_status_disabled_by_alias(fdt,
239                                                 "emi1_slot1");
240                                         fdt_status_okay_by_alias(fdt,
241                                                 "emi1_slot1_bk1");
242                                 }
243                                 break;
244                         case EMI1_SLOT2:
245                                 fdt_status_okay_by_alias(fdt, "emi1_slot2");
246                                 break;
247                         case EMI1_SLOT3:
248                                 fdt_status_okay_by_alias(fdt, "emi1_slot3");
249                                 break;
250                         }
251                 break;
252                 case PHY_INTERFACE_MODE_RGMII:
253                         if (i == FM1_DTSEC1)
254                                 fdt_status_okay_by_alias(fdt, "emi1_rgmii1");
255
256                         if (i == FM1_DTSEC2)
257                                 fdt_status_okay_by_alias(fdt, "emi1_rgmii2");
258                         break;
259                 default:
260                         break;
261                 }
262         }
263 #if (CONFIG_SYS_NUM_FMAN == 2)
264         for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) {
265                 idx = i - FM2_DTSEC1;
266                 switch (fm_info_get_enet_if(i)) {
267                 case PHY_INTERFACE_MODE_SGMII:
268                         lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx);
269                         if (lane >= 0) {
270                                 switch (mdio_mux[i]) {
271                                 case EMI1_SLOT1:
272                                         if (lane >= 14)
273                                                 fdt_status_okay_by_alias(fdt,
274                                                         "emi1_slot1");
275                                         else
276                                                 fdt_status_okay_by_alias(fdt,
277                                                         "emi1_slot1_bk1");
278                                         break;
279                                 case EMI1_SLOT2:
280                                         fdt_status_okay_by_alias(fdt,
281                                                 "emi1_slot2");
282                                         break;
283                                 case EMI1_SLOT3:
284                                         fdt_status_okay_by_alias(fdt,
285                                                 "emi1_slot3");
286                                         break;
287                                 }
288                         }
289                         break;
290                 default:
291                         break;
292                 }
293         }
294 #endif
295 }
296
297 static void initialize_lane_to_slot(void)
298 {
299         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
300         int sdprtl = (in_be32(&gur->rcwsr[4]) &
301                                 FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
302
303         switch (sdprtl) {
304         case 0x03:
305         case 0x06:
306                 lane_to_slot[8] = 1;
307                 lane_to_slot[9] = lane_to_slot[8];
308                 lane_to_slot[16] = 5;
309                 lane_to_slot[17] = lane_to_slot[16];
310                 break;
311         case 0x16:
312         case 0x19:
313         case 0x1C:
314                 lane_to_slot[8] = 5;
315                 lane_to_slot[9] = lane_to_slot[8];
316                 lane_to_slot[16] = 1;
317                 lane_to_slot[17] = lane_to_slot[16];
318                 break;
319         default:
320                 puts("Invalid SerDes protocol for P3060QDS\n");
321                 break;
322         }
323 }
324
325 int board_eth_init(bd_t *bis)
326 {
327 #ifdef CONFIG_FMAN_ENET
328         struct dtsec *tsec = (void *)CONFIG_SYS_FSL_FM1_DTSEC1_ADDR;
329         int i;
330         struct fsl_pq_mdio_info dtsec_mdio_info;
331         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
332         int srds_cfg = (in_be32(&gur->rcwsr[4]) &
333                                 FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
334
335         initialize_lane_to_slot();
336
337         /*
338          * Set TBIPA on FM1@DTSEC1.  This is needed for configurations
339          * where FM1@DTSEC1 isn't used directly, since it provides
340          * MDIO for other ports.
341          */
342         out_be32(&tsec->tbipa, CONFIG_SYS_TBIPA_VALUE);
343
344         /* Initialize the mdio_mux array so we can recognize empty elements */
345         for (i = 0; i < NUM_FM_PORTS; i++)
346                 mdio_mux[i] = EMI_NONE;
347
348         dtsec_mdio_info.regs =
349                 (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
350         dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
351
352         /* Register the 1G MDIO bus */
353         fsl_pq_mdio_init(bis, &dtsec_mdio_info);
354
355         /* Register the 5 muxing front-ends to the MDIO buses */
356         if (fm_info_get_enet_if(FM1_DTSEC1) == PHY_INTERFACE_MODE_RGMII)
357                 p3060qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII1);
358
359         if (fm_info_get_enet_if(FM1_DTSEC2) == PHY_INTERFACE_MODE_RGMII)
360                 p3060qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_RGMII2);
361         p3060qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT1);
362         p3060qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT2);
363         p3060qds_mdio_init(DEFAULT_FM_MDIO_NAME, EMI1_SLOT3);
364
365         if (fm_info_get_enet_if(FM1_DTSEC1) == PHY_INTERFACE_MODE_RGMII)
366                 fm_info_set_phy_address(FM1_DTSEC1, 1); /* RGMII1 */
367         else if (fm_info_get_enet_if(FM1_DTSEC1) == PHY_INTERFACE_MODE_SGMII)
368                 fm_info_set_phy_address(FM1_DTSEC1, SGMII_CARD_PORT2_PHY_ADDR);
369
370         if (fm_info_get_enet_if(FM1_DTSEC2) == PHY_INTERFACE_MODE_RGMII)
371                 fm_info_set_phy_address(FM1_DTSEC2, 2); /* RGMII2 */
372         else if (fm_info_get_enet_if(FM1_DTSEC2) == PHY_INTERFACE_MODE_SGMII)
373                 fm_info_set_phy_address(FM1_DTSEC2, SGMII_CARD_PORT4_PHY_ADDR);
374
375         fm_info_set_phy_address(FM2_DTSEC1, SGMII_CARD_PORT1_PHY_ADDR);
376         fm_info_set_phy_address(FM2_DTSEC2, SGMII_CARD_PORT3_PHY_ADDR);
377
378         switch (srds_cfg) {
379         case 0x03:
380         case 0x06:
381                 fm_info_set_phy_address(FM2_DTSEC3, SGMII_CARD_PORT3_PHY_ADDR);
382                 fm_info_set_phy_address(FM1_DTSEC3, SGMII_CARD_PORT4_PHY_ADDR);
383                 fm_info_set_phy_address(FM2_DTSEC4, SGMII_CARD_PORT1_PHY_ADDR);
384                 fm_info_set_phy_address(FM1_DTSEC4, SGMII_CARD_PORT2_PHY_ADDR);
385                 break;
386         case 0x16:
387         case 0x19:
388         case 0x1C:
389                 fm_info_set_phy_address(FM2_DTSEC3, SGMII_CARD_PORT1_PHY_ADDR);
390                 fm_info_set_phy_address(FM1_DTSEC3, SGMII_CARD_PORT2_PHY_ADDR);
391                 fm_info_set_phy_address(FM2_DTSEC4, SGMII_CARD_PORT3_PHY_ADDR);
392                 fm_info_set_phy_address(FM1_DTSEC4, SGMII_CARD_PORT4_PHY_ADDR);
393                 break;
394         default:
395                 puts("Invalid SerDes protocol for P3060QDS\n");
396                 break;
397         }
398
399         for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
400                 int idx = i - FM1_DTSEC1, lane, slot;
401                 switch (fm_info_get_enet_if(i)) {
402                 case PHY_INTERFACE_MODE_SGMII:
403                         lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
404                         if (lane < 0)
405                                 break;
406                         slot = lane_to_slot[lane];
407                         if (QIXIS_READ(present) & (1 << (slot - 1)))
408                                 fm_disable_port(i);
409                         switch (slot) {
410                         case 1:
411                                 mdio_mux[i] = EMI1_SLOT1;
412                                 fm_info_set_mdio(i,
413                                         mii_dev_for_muxval(mdio_mux[i]));
414                                 break;
415                         case 2:
416                                 mdio_mux[i] = EMI1_SLOT2;
417                                 fm_info_set_mdio(i,
418                                         mii_dev_for_muxval(mdio_mux[i]));
419                                 break;
420                         case 3:
421                                 mdio_mux[i] = EMI1_SLOT3;
422                                 fm_info_set_mdio(i,
423                                         mii_dev_for_muxval(mdio_mux[i]));
424                                 break;
425                         };
426                         break;
427                 case PHY_INTERFACE_MODE_RGMII:
428                         if (i == FM1_DTSEC1) {
429                                 mdio_mux[i] = EMI1_RGMII1;
430                                 fm_info_set_mdio(i,
431                                         mii_dev_for_muxval(mdio_mux[i]));
432                         } else if (i == FM1_DTSEC2) {
433                                 mdio_mux[i] = EMI1_RGMII2;
434                                 fm_info_set_mdio(i,
435                                         mii_dev_for_muxval(mdio_mux[i]));
436                         }
437                         break;
438                 default:
439                         break;
440                 }
441         }
442
443 #if (CONFIG_SYS_NUM_FMAN == 2)
444         for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) {
445                 int idx = i - FM2_DTSEC1, lane, slot;
446                 switch (fm_info_get_enet_if(i)) {
447                 case PHY_INTERFACE_MODE_SGMII:
448                         lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx);
449                         if (lane < 0)
450                                 break;
451                         slot = lane_to_slot[lane];
452                         if (QIXIS_READ(present) & (1 << (slot - 1)))
453                                 fm_disable_port(i);
454                         switch (slot) {
455                         case 1:
456                                 mdio_mux[i] = EMI1_SLOT1;
457                                 fm_info_set_mdio(i,
458                                         mii_dev_for_muxval(mdio_mux[i]));
459                                 break;
460                         case 2:
461                                 mdio_mux[i] = EMI1_SLOT2;
462                                 fm_info_set_mdio(i,
463                                         mii_dev_for_muxval(mdio_mux[i]));
464                                 break;
465                         case 3:
466                                 mdio_mux[i] = EMI1_SLOT3;
467                                 fm_info_set_mdio(i,
468                                         mii_dev_for_muxval(mdio_mux[i]));
469                                 break;
470                         };
471                         break;
472                 default:
473                         break;
474                 }
475         }
476 #endif /* CONFIG_SYS_NUM_FMAN */
477
478         cpu_eth_init(bis);
479 #endif /* CONFIG_FMAN_ENET */
480
481         return pci_eth_init(bis);
482 }