]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/freescale/b4860qds/eth_b4860qds.c
Merge branch 'u-boot-samsung/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / board / freescale / b4860qds / eth_b4860qds.c
1 /*
2  * Copyright 2012 Freescale Semiconductor, Inc.
3  * Author: Sandeep Kumar Singh <sandeep@freescale.com>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /* This file is based on board/freescale/corenet_ds/eth_superhydra.c */
25
26 /*
27  * This file handles the board muxing between the Fman Ethernet MACs and
28  * the RGMII/SGMII/XGMII PHYs on a Freescale B4860 "Centaur". The SGMII
29  * PHYs are the two on-board 1Gb ports. There are no RGMII PHY on board.
30  * The 10Gb XGMII PHY is provided via the XAUI riser card. There is only
31  * one Fman device on B4860. The SERDES configuration is used to determine
32  * where the SGMII and XAUI cards exist, and also which Fman MACs are routed
33  * to which PHYs. So for a given Fman MAC, there is one and only PHY it
34  * connects to. MACs cannot be routed to PHYs dynamically. This configuration
35  * is done at boot time by reading SERDES protocol from RCW.
36  */
37
38 #include <common.h>
39 #include <netdev.h>
40 #include <asm/fsl_serdes.h>
41 #include <fm_eth.h>
42 #include <fsl_mdio.h>
43 #include <malloc.h>
44 #include <fdt_support.h>
45 #include <asm/fsl_dtsec.h>
46
47 #include "../common/ngpixis.h"
48 #include "../common/fman.h"
49 #include "../common/qixis.h"
50 #include "b4860qds_qixis.h"
51
52 #define EMI_NONE       0xFFFFFFFF
53
54 #ifdef CONFIG_FMAN_ENET
55
56 /*
57  * Mapping of all 16 SERDES lanes to board slots. A value n(>0) will mean that
58  * lane at index is mapped to slot number n. A value of '0' will mean
59  * that the mapping must be determined dynamically, or that the lane maps to
60  * something other than a board slot
61  */
62 static u8 lane_to_slot[] = {
63         0, 0, 0, 0,
64         0, 0, 0, 0,
65         1, 1, 1, 1,
66         0, 0, 0, 0
67 };
68
69 /*
70  * This function initializes the lane_to_slot[] array. It reads RCW to check
71  * if Serdes2{E,F,G,H} is configured as slot 2 or as SFP and initializes
72  * lane_to_slot[] accordingly
73  */
74 static void initialize_lane_to_slot(void)
75 {
76         unsigned int  serdes2_prtcl;
77         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
78         serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
79                 FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
80         serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
81         debug("Initializing lane to slot: Serdes2 protocol: %x\n",
82                         serdes2_prtcl);
83
84         switch (serdes2_prtcl) {
85         case 0x18:
86                 /*
87                  * Configuration:
88                  * SERDES: 2
89                  * Lanes: A,B,C,D: SGMII
90                  * Lanes: E,F: Aur
91                  * Lanes: G,H: SRIO
92                  */
93         case 0x91:
94                 /*
95                  * Configuration:
96                  * SERDES: 2
97                  * Lanes: A,B: SGMII
98                  * Lanes: C,D: SRIO2
99                  * Lanes: E,F,G,H: XAUI2
100                  */
101         case 0x93:
102                 /*
103                  * Configuration:
104                  * SERDES: 2
105                  * Lanes: A,B,C,D: SGMII
106                  * Lanes: E,F,G,H: XAUI2
107                  */
108         case 0x98:
109                 /*
110                  * Configuration:
111                  * SERDES: 2
112                  * Lanes: A,B,C,D: XAUI2
113                  * Lanes: E,F,G,H: XAUI2
114                  */
115         case 0x9a:
116                 /*
117                  * Configuration:
118                  * SERDES: 2
119                  * Lanes: A,B: PCI
120                  * Lanes: C,D: SGMII
121                  * Lanes: E,F,G,H: XAUI2
122                  */
123         case 0x9e:
124                 /*
125                  * Configuration:
126                  * SERDES: 2
127                  * Lanes: A,B,C,D: PCI
128                  * Lanes: E,F,G,H: XAUI2
129                  */
130         case 0xb2:
131                 /*
132                  * Configuration:
133                  * SERDES: 2
134                  * Lanes: A,B,C,D: PCI
135                  * Lanes: E,F: SGMII 3&4
136                  * Lanes: G,H: XFI
137                  */
138         case 0xc2:
139                 /*
140                  * Configuration:
141                  * SERDES: 2
142                  * Lanes: A,B: SGMII
143                  * Lanes: C,D: SRIO2
144                  * Lanes: E,F,G,H: XAUI2
145                  */
146                 lane_to_slot[12] = 2;
147                 lane_to_slot[13] = lane_to_slot[12];
148                 lane_to_slot[14] = lane_to_slot[12];
149                 lane_to_slot[15] = lane_to_slot[12];
150                 break;
151
152         default:
153                 printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n",
154                                 serdes2_prtcl);
155                         break;
156         }
157         return;
158 }
159
160 #endif /* #ifdef CONFIG_FMAN_ENET */
161
162 int board_eth_init(bd_t *bis)
163 {
164 #ifdef CONFIG_FMAN_ENET
165         struct memac_mdio_info memac_mdio_info;
166         struct memac_mdio_info tg_memac_mdio_info;
167         unsigned int i;
168         unsigned int  serdes1_prtcl, serdes2_prtcl;
169         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
170         serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
171                 FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
172         if (!serdes1_prtcl) {
173                 printf("SERDES1 is not enabled\n");
174                 return 0;
175         }
176         serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
177         debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
178
179         serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
180                 FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
181         if (!serdes2_prtcl) {
182                 printf("SERDES2 is not enabled\n");
183                 return 0;
184         }
185         serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
186         debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
187
188         printf("Initializing Fman\n");
189
190         initialize_lane_to_slot();
191
192         memac_mdio_info.regs =
193                 (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
194         memac_mdio_info.name = DEFAULT_FM_MDIO_NAME;
195
196         /* Register the real 1G MDIO bus */
197         fm_memac_mdio_init(bis, &memac_mdio_info);
198
199         tg_memac_mdio_info.regs =
200                 (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
201         tg_memac_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
202
203         /* Register the real 10G MDIO bus */
204         fm_memac_mdio_init(bis, &tg_memac_mdio_info);
205
206         /*
207          * Program the two on board DTSEC PHY addresses assuming that they are
208          * all SGMII. RGMII is not supported on this board. Setting SGMII 5 and
209          * 6 to on board SGMII phys
210          */
211         fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_DTSEC5_PHY_ADDR);
212         fm_info_set_phy_address(FM1_DTSEC6, CONFIG_SYS_FM1_DTSEC6_PHY_ADDR);
213
214         switch (serdes1_prtcl) {
215         case 0x2a:
216                 /* Serdes 1: A-B SGMII, Configuring DTSEC 5 and 6 */
217                 debug("Setting phy addresses for FM1_DTSEC5: %x and"
218                         "FM1_DTSEC6: %x\n", CONFIG_SYS_FM1_DTSEC5_PHY_ADDR,
219                         CONFIG_SYS_FM1_DTSEC6_PHY_ADDR);
220                 /* Fixing Serdes clock by programming FPGA register */
221                 QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125);
222                 fm_info_set_phy_address(FM1_DTSEC5,
223                                 CONFIG_SYS_FM1_DTSEC5_PHY_ADDR);
224                 fm_info_set_phy_address(FM1_DTSEC6,
225                                 CONFIG_SYS_FM1_DTSEC6_PHY_ADDR);
226                 break;
227 #ifdef CONFIG_PPC_B4420
228         case 0x18:
229                 /* Serdes 1: A-D SGMII, Configuring on board dual SGMII Phy */
230                 debug("Setting phy addresses for FM1_DTSEC3: %x and"
231                         "FM1_DTSEC4: %x\n", CONFIG_SYS_FM1_DTSEC5_PHY_ADDR,
232                         CONFIG_SYS_FM1_DTSEC6_PHY_ADDR);
233                 /* Fixing Serdes clock by programming FPGA register */
234                 QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125);
235                 fm_info_set_phy_address(FM1_DTSEC3,
236                                 CONFIG_SYS_FM1_DTSEC5_PHY_ADDR);
237                 fm_info_set_phy_address(FM1_DTSEC4,
238                                 CONFIG_SYS_FM1_DTSEC6_PHY_ADDR);
239                 break;
240 #endif
241         default:
242                 printf("Fman:  Unsupported SerDes1 Protocol 0x%02x\n",
243                                 serdes1_prtcl);
244                 break;
245         }
246         switch (serdes2_prtcl) {
247         case 0x18:
248                 debug("Setting phy addresses on SGMII Riser card for"
249                                 "FM1_DTSEC ports: \n");
250                 fm_info_set_phy_address(FM1_DTSEC1,
251                                 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
252                 fm_info_set_phy_address(FM1_DTSEC2,
253                                 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
254                 fm_info_set_phy_address(FM1_DTSEC3,
255                                 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR);
256                 fm_info_set_phy_address(FM1_DTSEC4,
257                                 CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR);
258                 break;
259         case 0x49:
260                 debug("Setting phy addresses on SGMII Riser card for"
261                                 "FM1_DTSEC ports: \n");
262                 fm_info_set_phy_address(FM1_DTSEC1,
263                                 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
264                 fm_info_set_phy_address(FM1_DTSEC2,
265                                 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
266                 fm_info_set_phy_address(FM1_DTSEC3,
267                                 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR);
268                 break;
269         case 0x8d:
270         case 0xb2:
271                 debug("Setting phy addresses on SGMII Riser card for"
272                                 "FM1_DTSEC ports: \n");
273                 fm_info_set_phy_address(FM1_DTSEC3,
274                                 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
275                 fm_info_set_phy_address(FM1_DTSEC4,
276                                 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
277                 break;
278         case 0x98:
279                 /* XAUI in Slot1 and Slot2 */
280                 debug("Setting phy addresses on B4860 QDS AMC2PEX-2S for FM1_10GEC1: %x\n",
281                       CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
282                 fm_info_set_phy_address(FM1_10GEC1,
283                                         CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
284                 debug("Setting phy addresses on B4860 QDS AMC2PEX-2S for FM1_10GEC2: %x\n",
285                       CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
286                 fm_info_set_phy_address(FM1_10GEC2,
287                                         CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
288                 break;
289         case 0x9E:
290                 /* XAUI in Slot2 */
291                 debug("Setting phy addresses on B4860 QDS AMC2PEX-2S for FM1_10GEC2: %x\n",
292                       CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
293                 fm_info_set_phy_address(FM1_10GEC2,
294                                         CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
295                 break;
296         default:
297                 printf("Fman:  Unsupported SerDes2 Protocol 0x%02x\n",
298                                 serdes2_prtcl);
299                 break;
300         }
301
302         for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
303                 int idx = i - FM1_DTSEC1;
304
305                 switch (fm_info_get_enet_if(i)) {
306                 case PHY_INTERFACE_MODE_SGMII:
307                         fm_info_set_mdio(i,
308                                 miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
309                         break;
310                 case PHY_INTERFACE_MODE_NONE:
311                         fm_info_set_phy_address(i, 0);
312                         break;
313                 default:
314                         printf("Fman1: DTSEC%u set to unknown interface %i\n",
315                                         idx + 1, fm_info_get_enet_if(i));
316                         fm_info_set_phy_address(i, 0);
317                         break;
318                 }
319         }
320
321         for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) {
322                 int idx = i - FM1_10GEC1;
323
324                 switch (fm_info_get_enet_if(i)) {
325                 case PHY_INTERFACE_MODE_XGMII:
326                         fm_info_set_mdio(i,
327                                          miiphy_get_dev_by_name(DEFAULT_FM_TGEC_MDIO_NAME));
328                         break;
329                 default:
330                         printf("Fman1: 10GSEC%u set to unknown interface %i\n",
331                                idx + 1, fm_info_get_enet_if(i));
332                         fm_info_set_phy_address(i, 0);
333                         break;
334                 }
335         }
336
337
338         cpu_eth_init(bis);
339 #endif
340
341         return pci_eth_init(bis);
342 }
343
344 void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
345                               enum fm_port port, int offset)
346 {
347         int phy;
348         char alias[32];
349
350         if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) {
351                 phy = fm_info_get_phy_address(port);
352
353                 sprintf(alias, "phy_sgmii_%x", phy);
354                 fdt_set_phy_handle(fdt, compat, addr, alias);
355         }
356 }
357
358 void fdt_fixup_board_enet(void *fdt)
359 {
360         int i;
361         char alias[32];
362
363         for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
364                 switch (fm_info_get_enet_if(i)) {
365                 case PHY_INTERFACE_MODE_NONE:
366                         sprintf(alias, "ethernet%u", i);
367                         fdt_status_disabled_by_alias(fdt, alias);
368                         break;
369                 default:
370                         break;
371                 }
372         }
373 }