Merge tag 'efi-2020-07-rc6' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
[oweals/u-boot.git] / board / freescale / common / sgmii_riser.c
1 /*
2  * Freescale SGMII Riser Card
3  *
4  * This driver supports the SGMII Riser card found on the
5  * "DS" style of development board from Freescale.
6  *
7  * This software may be used and distributed according to the
8  * terms of the GNU Public License, Version 2, incorporated
9  * herein by reference.
10  *
11  * Copyright 2008 Freescale Semiconductor, Inc.
12  *
13  */
14
15 #include <config.h>
16 #include <common.h>
17 #include <log.h>
18 #include <net.h>
19 #include <linux/libfdt.h>
20 #include <tsec.h>
21 #include <fdt_support.h>
22
23 void fsl_sgmii_riser_init(struct tsec_info_struct *tsec_info, int num)
24 {
25         int i;
26
27         for (i = 0; i < num; i++)
28                 if (tsec_info[i].flags & TSEC_SGMII)
29                         tsec_info[i].phyaddr += SGMII_RISER_PHY_OFFSET;
30 }
31
32 void fsl_sgmii_riser_fdt_fixup(void *fdt)
33 {
34         struct eth_device *dev;
35         int node;
36         int mdio_node;
37         int i = -1;
38         int etsec_num = 0;
39
40         node = fdt_path_offset(fdt, "/aliases");
41         if (node < 0)
42                 return;
43
44         while ((dev = eth_get_dev_by_index(++i)) != NULL) {
45                 struct tsec_private *priv;
46                 int phy_node;
47                 int enet_node;
48                 uint32_t ph;
49                 char sgmii_phy[16];
50                 char enet[16];
51                 const u32 *phyh;
52                 const char *model;
53                 const char *path;
54
55                 if (!strstr(dev->name, "eTSEC"))
56                         continue;
57
58                 priv = dev->priv;
59                 if (!(priv->flags & TSEC_SGMII)) {
60                         etsec_num++;
61                         continue;
62                 }
63
64                 mdio_node = fdt_node_offset_by_compatible(fdt, -1,
65                                 "fsl,gianfar-mdio");
66                 if (mdio_node < 0)
67                         return;
68
69                 sprintf(sgmii_phy, "sgmii-phy@%d", etsec_num);
70                 phy_node = fdt_subnode_offset(fdt, mdio_node, sgmii_phy);
71                 if (phy_node > 0) {
72                         fdt_increase_size(fdt, 32);
73                         ph = fdt_create_phandle(fdt, phy_node);
74                         if (!ph)
75                                 continue;
76                 }
77
78                 sprintf(enet, "ethernet%d", etsec_num++);
79                 path = fdt_getprop(fdt, node, enet, NULL);
80                 if (!path) {
81                         debug("No alias for %s\n", enet);
82                         continue;
83                 }
84
85                 enet_node = fdt_path_offset(fdt, path);
86                 if (enet_node < 0)
87                         continue;
88
89                 model = fdt_getprop(fdt, enet_node, "model", NULL);
90
91                 /*
92                  * We only want to do this to eTSECs.  On some platforms
93                  * there are more than one type of gianfar-style ethernet
94                  * controller, and as we are creating an implicit connection
95                  * between ethernet nodes and eTSEC devices, it is best to
96                  * make the connection use as much explicit information
97                  * as exists.
98                  */
99                 if (!strstr(model, "TSEC"))
100                         continue;
101
102                 if (phy_node < 0) {
103                         /*
104                          * This part is only for old device tree without
105                          * sgmii_phy nodes. It's kept just for compatible
106                          * reason. Soon to be deprecated if all device tree
107                          * get updated.
108                          */
109                         phyh = fdt_getprop(fdt, enet_node, "phy-handle", NULL);
110                         if (!phyh)
111                                 continue;
112
113                         phy_node = fdt_node_offset_by_phandle(fdt,
114                                         fdt32_to_cpu(*phyh));
115
116                         priv = dev->priv;
117
118                         if (priv->flags & TSEC_SGMII)
119                                 fdt_setprop_cell(fdt, phy_node, "reg",
120                                                 priv->phyaddr);
121                 } else {
122                         fdt_setprop(fdt, enet_node, "phy-handle", &ph,
123                                         sizeof(ph));
124                         fdt_setprop_string(fdt, enet_node,
125                                         "phy-connection-type",
126                                         phy_string_for_interface(
127                                                 PHY_INTERFACE_MODE_SGMII));
128                 }
129         }
130 }