Merge git://git.denx.de/u-boot-sunxi
[oweals/u-boot.git] / board / freescale / b4860qds / eth_b4860qds.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2012 Freescale Semiconductor, Inc.
4  * Author: Sandeep Kumar Singh <sandeep@freescale.com>
5  */
6
7 /* This file is based on board/freescale/corenet_ds/eth_superhydra.c */
8
9 /*
10  * This file handles the board muxing between the Fman Ethernet MACs and
11  * the RGMII/SGMII/XGMII PHYs on a Freescale B4860 "Centaur". The SGMII
12  * PHYs are the two on-board 1Gb ports. There are no RGMII PHY on board.
13  * The 10Gb XGMII PHY is provided via the XAUI riser card. There is only
14  * one Fman device on B4860. The SERDES configuration is used to determine
15  * where the SGMII and XAUI cards exist, and also which Fman MACs are routed
16  * to which PHYs. So for a given Fman MAC, there is one and only PHY it
17  * connects to. MACs cannot be routed to PHYs dynamically. This configuration
18  * is done at boot time by reading SERDES protocol from RCW.
19  */
20
21 #include <common.h>
22 #include <netdev.h>
23 #include <asm/fsl_serdes.h>
24 #include <fm_eth.h>
25 #include <fsl_mdio.h>
26 #include <malloc.h>
27 #include <fdt_support.h>
28 #include <fsl_dtsec.h>
29
30 #include "../common/ngpixis.h"
31 #include "../common/fman.h"
32 #include "../common/qixis.h"
33 #include "b4860qds_qixis.h"
34
35 #define EMI_NONE       0xFFFFFFFF
36
37 #ifdef CONFIG_FMAN_ENET
38
39 /*
40  * Mapping of all 16 SERDES lanes to board slots. A value n(>0) will mean that
41  * lane at index is mapped to slot number n. A value of '0' will mean
42  * that the mapping must be determined dynamically, or that the lane maps to
43  * something other than a board slot
44  */
45 static u8 lane_to_slot[] = {
46         0, 0, 0, 0,
47         0, 0, 0, 0,
48         1, 1, 1, 1,
49         0, 0, 0, 0
50 };
51
52 /*
53  * This function initializes the lane_to_slot[] array. It reads RCW to check
54  * if Serdes2{E,F,G,H} is configured as slot 2 or as SFP and initializes
55  * lane_to_slot[] accordingly
56  */
57 static void initialize_lane_to_slot(void)
58 {
59         unsigned int  serdes2_prtcl;
60         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
61         serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
62                 FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
63         serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
64         debug("Initializing lane to slot: Serdes2 protocol: %x\n",
65                         serdes2_prtcl);
66
67         switch (serdes2_prtcl) {
68         case 0x17:
69         case 0x18:
70                 /*
71                  * Configuration:
72                  * SERDES: 2
73                  * Lanes: A,B,C,D: SGMII
74                  * Lanes: E,F: Aur
75                  * Lanes: G,H: SRIO
76                  */
77         case 0x91:
78                 /*
79                  * Configuration:
80                  * SERDES: 2
81                  * Lanes: A,B: SGMII
82                  * Lanes: C,D: SRIO2
83                  * Lanes: E,F,G,H: XAUI2
84                  */
85         case 0x93:
86                 /*
87                  * Configuration:
88                  * SERDES: 2
89                  * Lanes: A,B,C,D: SGMII
90                  * Lanes: E,F,G,H: XAUI2
91                  */
92         case 0x98:
93                 /*
94                  * Configuration:
95                  * SERDES: 2
96                  * Lanes: A,B,C,D: XAUI2
97                  * Lanes: E,F,G,H: XAUI2
98                  */
99         case 0x9a:
100                 /*
101                  * Configuration:
102                  * SERDES: 2
103                  * Lanes: A,B: PCI
104                  * Lanes: C,D: SGMII
105                  * Lanes: E,F,G,H: XAUI2
106                  */
107         case 0x9e:
108                 /*
109                  * Configuration:
110                  * SERDES: 2
111                  * Lanes: A,B,C,D: PCI
112                  * Lanes: E,F,G,H: XAUI2
113                  */
114         case 0xb1:
115         case 0xb2:
116         case 0x8c:
117         case 0x8d:
118                 /*
119                  * Configuration:
120                  * SERDES: 2
121                  * Lanes: A,B,C,D: PCI
122                  * Lanes: E,F: SGMII 3&4
123                  * Lanes: G,H: XFI
124                  */
125         case 0xc2:
126                 /*
127                  * Configuration:
128                  * SERDES: 2
129                  * Lanes: A,B: SGMII
130                  * Lanes: C,D: SRIO2
131                  * Lanes: E,F,G,H: XAUI2
132                  */
133                 lane_to_slot[12] = 2;
134                 lane_to_slot[13] = lane_to_slot[12];
135                 lane_to_slot[14] = lane_to_slot[12];
136                 lane_to_slot[15] = lane_to_slot[12];
137                 break;
138
139         default:
140                 printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n",
141                                 serdes2_prtcl);
142                         break;
143         }
144         return;
145 }
146
147 #endif /* #ifdef CONFIG_FMAN_ENET */
148
149 int board_eth_init(bd_t *bis)
150 {
151 #ifdef CONFIG_FMAN_ENET
152         struct memac_mdio_info memac_mdio_info;
153         struct memac_mdio_info tg_memac_mdio_info;
154         unsigned int i;
155         unsigned int  serdes1_prtcl, serdes2_prtcl;
156         int qsgmii;
157         struct mii_dev *bus;
158         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
159         serdes1_prtcl = in_be32(&gur->rcwsr[4]) &
160                 FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
161         if (!serdes1_prtcl) {
162                 printf("SERDES1 is not enabled\n");
163                 return 0;
164         }
165         serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
166         debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl);
167
168         serdes2_prtcl = in_be32(&gur->rcwsr[4]) &
169                 FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
170         if (!serdes2_prtcl) {
171                 printf("SERDES2 is not enabled\n");
172                 return 0;
173         }
174         serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
175         debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl);
176
177         printf("Initializing Fman\n");
178
179         initialize_lane_to_slot();
180
181         memac_mdio_info.regs =
182                 (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
183         memac_mdio_info.name = DEFAULT_FM_MDIO_NAME;
184
185         /* Register the real 1G MDIO bus */
186         fm_memac_mdio_init(bis, &memac_mdio_info);
187
188         tg_memac_mdio_info.regs =
189                 (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
190         tg_memac_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
191
192         /* Register the real 10G MDIO bus */
193         fm_memac_mdio_init(bis, &tg_memac_mdio_info);
194
195         /*
196          * Program the two on board DTSEC PHY addresses assuming that they are
197          * all SGMII. RGMII is not supported on this board. Setting SGMII 5 and
198          * 6 to on board SGMII phys
199          */
200         fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
201         fm_info_set_phy_address(FM1_DTSEC6, CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
202
203         switch (serdes1_prtcl) {
204         case 0x29:
205         case 0x2a:
206                 /* Serdes 1: A-B SGMII, Configuring DTSEC 5 and 6 */
207                 debug("Set phy addresses for FM1_DTSEC5:%x, FM1_DTSEC6:%x\n",
208                       CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR,
209                       CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
210                 fm_info_set_phy_address(FM1_DTSEC5,
211                                 CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
212                 fm_info_set_phy_address(FM1_DTSEC6,
213                                 CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
214                 break;
215 #ifdef CONFIG_ARCH_B4420
216         case 0x17:
217         case 0x18:
218                 /* Serdes 1: A-D SGMII, Configuring on board dual SGMII Phy */
219                 debug("Set phy addresses for FM1_DTSEC3:%x, FM1_DTSEC4:%x\n",
220                       CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR,
221                       CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
222                 /* Fixing Serdes clock by programming FPGA register */
223                 QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125);
224                 fm_info_set_phy_address(FM1_DTSEC3,
225                                 CONFIG_SYS_FM1_ONBOARD_PHY1_ADDR);
226                 fm_info_set_phy_address(FM1_DTSEC4,
227                                 CONFIG_SYS_FM1_ONBOARD_PHY2_ADDR);
228                 break;
229 #endif
230         default:
231                 printf("Fman:  Unsupported SerDes1 Protocol 0x%02x\n",
232                                 serdes1_prtcl);
233                 break;
234         }
235         switch (serdes2_prtcl) {
236         case 0x17:
237         case 0x18:
238                 debug("Set phy address on SGMII Riser for FM1_DTSEC1:%x\n",
239                       CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
240                 fm_info_set_phy_address(FM1_DTSEC1,
241                                 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
242                 fm_info_set_phy_address(FM1_DTSEC2,
243                                 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
244                 fm_info_set_phy_address(FM1_DTSEC3,
245                                 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR);
246                 fm_info_set_phy_address(FM1_DTSEC4,
247                                 CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR);
248                 break;
249         case 0x48:
250         case 0x49:
251                 debug("Set phy address on SGMII Riser for FM1_DTSEC1:%x\n",
252                       CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
253                 fm_info_set_phy_address(FM1_DTSEC1,
254                                 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
255                 fm_info_set_phy_address(FM1_DTSEC2,
256                                 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
257                 fm_info_set_phy_address(FM1_DTSEC3,
258                                 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR);
259                 break;
260         case 0xb1:
261         case 0xb2:
262         case 0x8c:
263         case 0x8d:
264                 debug("Set phy addresses on SGMII Riser for FM1_DTSEC1:%x\n",
265                       CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
266                 fm_info_set_phy_address(FM1_DTSEC3,
267                                 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR);
268                 fm_info_set_phy_address(FM1_DTSEC4,
269                                 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR);
270                 /*
271                  * XFI does not need a PHY to work, but to make U-Boot
272                  * happy, assign a fake PHY address for a XFI port.
273                  */
274                 fm_info_set_phy_address(FM1_10GEC1, 0);
275                 fm_info_set_phy_address(FM1_10GEC2, 1);
276                 break;
277         case 0x98:
278                 /* XAUI in Slot1 and Slot2 */
279                 debug("Set phy address of AMC2PEX-2S for FM1_10GEC1:%x\n",
280                       CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
281                 fm_info_set_phy_address(FM1_10GEC1,
282                                         CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
283                 debug("Set phy address of AMC2PEX-2S for FM1_10GEC2:%x\n",
284                       CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
285                 fm_info_set_phy_address(FM1_10GEC2,
286                                         CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
287                 break;
288         case 0x9E:
289                 /* XAUI in Slot2 */
290                 debug("Sett phy address of AMC2PEX-2S for FM1_10GEC2:%x\n",
291                       CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
292                 fm_info_set_phy_address(FM1_10GEC2,
293                                         CONFIG_SYS_FM1_10GEC2_PHY_ADDR);
294                 break;
295         default:
296                 printf("Fman:  Unsupported SerDes2 Protocol 0x%02x\n",
297                                 serdes2_prtcl);
298                 break;
299         }
300
301         /*set PHY address for QSGMII Riser Card on slot2*/
302         bus = miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME);
303         qsgmii = is_qsgmii_riser_card(bus, PHY_BASE_ADDR, PORT_NUM, REGNUM);
304
305         if (qsgmii) {
306                 switch (serdes2_prtcl) {
307                 case 0xb2:
308                 case 0x8d:
309                         fm_info_set_phy_address(FM1_DTSEC3, PHY_BASE_ADDR);
310                         fm_info_set_phy_address(FM1_DTSEC4, PHY_BASE_ADDR + 1);
311                         break;
312                 default:
313                         break;
314                 }
315         }
316
317         for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
318                 int idx = i - FM1_DTSEC1;
319
320                 switch (fm_info_get_enet_if(i)) {
321                 case PHY_INTERFACE_MODE_SGMII:
322                         fm_info_set_mdio(i,
323                                 miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME));
324                         break;
325                 case PHY_INTERFACE_MODE_NONE:
326                         fm_info_set_phy_address(i, 0);
327                         break;
328                 default:
329                         printf("Fman1: DTSEC%u set to unknown interface %i\n",
330                                         idx + 1, fm_info_get_enet_if(i));
331                         fm_info_set_phy_address(i, 0);
332                         break;
333                 }
334         }
335
336         for (i = FM1_10GEC1; i < FM1_10GEC1 + CONFIG_SYS_NUM_FM1_10GEC; i++) {
337                 int idx = i - FM1_10GEC1;
338
339                 switch (fm_info_get_enet_if(i)) {
340                 case PHY_INTERFACE_MODE_XGMII:
341                         fm_info_set_mdio(i,
342                                          miiphy_get_dev_by_name
343                                          (DEFAULT_FM_TGEC_MDIO_NAME));
344                         break;
345                 case PHY_INTERFACE_MODE_NONE:
346                         fm_info_set_phy_address(i, 0);
347                         break;
348                 default:
349                         printf("Fman1: TGEC%u set to unknown interface %i\n",
350                                idx + 1, fm_info_get_enet_if(i));
351                         fm_info_set_phy_address(i, 0);
352                         break;
353                 }
354         }
355
356         cpu_eth_init(bis);
357 #endif
358
359         return pci_eth_init(bis);
360 }
361
362 void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
363                               enum fm_port port, int offset)
364 {
365         int phy;
366         char alias[32];
367         struct fixed_link f_link;
368         ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
369         u32 prtcl2 = in_be32(&gur->rcwsr[4]) & FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
370
371         prtcl2 >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
372
373         if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) {
374                 phy = fm_info_get_phy_address(port);
375
376                 sprintf(alias, "phy_sgmii_%x", phy);
377                 fdt_set_phy_handle(fdt, compat, addr, alias);
378                 fdt_status_okay_by_alias(fdt, alias);
379         } else if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_XGMII) {
380                 /* check if it's XFI interface for 10g */
381                 switch (prtcl2) {
382                 case 0x80:
383                 case 0x81:
384                 case 0x82:
385                 case 0x83:
386                 case 0x84:
387                 case 0x85:
388                 case 0x86:
389                 case 0x87:
390                 case 0x88:
391                 case 0x89:
392                 case 0x8a:
393                 case 0x8b:
394                 case 0x8c:
395                 case 0x8d:
396                 case 0x8e:
397                 case 0xb1:
398                 case 0xb2:
399                         f_link.phy_id = port;
400                         f_link.duplex = 1;
401                         f_link.link_speed = 10000;
402                         f_link.pause = 0;
403                         f_link.asym_pause = 0;
404
405                         fdt_delprop(fdt, offset, "phy-handle");
406                         fdt_setprop(fdt, offset, "fixed-link", &f_link,
407                                     sizeof(f_link));
408                         break;
409                 case 0x98: /* XAUI interface */
410                         strcpy(alias, "phy_xaui_slot1");
411                         fdt_status_okay_by_alias(fdt, alias);
412
413                         strcpy(alias, "phy_xaui_slot2");
414                         fdt_status_okay_by_alias(fdt, alias);
415                         break;
416                 case 0x9e: /* XAUI interface */
417                 case 0x9a:
418                 case 0x93:
419                 case 0x91:
420                         strcpy(alias, "phy_xaui_slot1");
421                         fdt_status_okay_by_alias(fdt, alias);
422                         break;
423                 case 0x97: /* XAUI interface */
424                 case 0xc3:
425                         strcpy(alias, "phy_xaui_slot2");
426                         fdt_status_okay_by_alias(fdt, alias);
427                         break;
428                 default:
429                         break;
430                 }
431         }
432 }
433
434 /*
435  * Set status to disabled for unused ethernet node
436  */
437 void fdt_fixup_board_enet(void *fdt)
438 {
439         int i;
440         char alias[32];
441
442         for (i = FM1_DTSEC1; i <= FM1_10GEC2; i++) {
443                 switch (fm_info_get_enet_if(i)) {
444                 case PHY_INTERFACE_MODE_NONE:
445                         sprintf(alias, "ethernet%u", i);
446                         fdt_status_disabled_by_alias(fdt, alias);
447                         break;
448                 default:
449                         break;
450                 }
451         }
452 }