blob: 23157930101f401f332b3a9e94948a34899de62b [file] [log] [blame]
Andy Fleming3d19fad2008-08-31 16:33:28 -05001/*
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>
Simon Glass0f2af882020-05-10 11:40:05 -060017#include <log.h>
Andy Flemingacaccae2008-12-05 20:10:22 -060018#include <net.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090019#include <linux/libfdt.h>
Andy Fleming3d19fad2008-08-31 16:33:28 -050020#include <tsec.h>
Hongtao Jiad9c2f362012-07-11 23:39:53 +000021#include <fdt_support.h>
Andy Fleming3d19fad2008-08-31 16:33:28 -050022
23void 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}
Andy Flemingacaccae2008-12-05 20:10:22 -060031
32void fsl_sgmii_riser_fdt_fixup(void *fdt)
33{
34 struct eth_device *dev;
35 int node;
Hongtao Jiad9c2f362012-07-11 23:39:53 +000036 int mdio_node;
Andy Flemingacaccae2008-12-05 20:10:22 -060037 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;
Hongtao Jiad9c2f362012-07-11 23:39:53 +000046 int phy_node;
Andy Flemingacaccae2008-12-05 20:10:22 -060047 int enet_node;
Hongtao Jiad9c2f362012-07-11 23:39:53 +000048 uint32_t ph;
49 char sgmii_phy[16];
Andy Flemingacaccae2008-12-05 20:10:22 -060050 char enet[16];
51 const u32 *phyh;
Andy Flemingacaccae2008-12-05 20:10:22 -060052 const char *model;
53 const char *path;
54
Andy Flemingacaccae2008-12-05 20:10:22 -060055 if (!strstr(dev->name, "eTSEC"))
56 continue;
57
Hongtao Jiad9c2f362012-07-11 23:39:53 +000058 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
Andy Flemingacaccae2008-12-05 20:10:22 -060078 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
Andy Flemingacaccae2008-12-05 20:10:22 -060091 /*
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
Hongtao Jiad9c2f362012-07-11 23:39:53 +0000102 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;
Andy Flemingacaccae2008-12-05 20:10:22 -0600112
Hongtao Jiad9c2f362012-07-11 23:39:53 +0000113 phy_node = fdt_node_offset_by_phandle(fdt,
114 fdt32_to_cpu(*phyh));
Andy Flemingacaccae2008-12-05 20:10:22 -0600115
Hongtao Jiad9c2f362012-07-11 23:39:53 +0000116 priv = dev->priv;
Andy Flemingacaccae2008-12-05 20:10:22 -0600117
Hongtao Jiad9c2f362012-07-11 23:39:53 +0000118 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 }
Andy Flemingacaccae2008-12-05 20:10:22 -0600129 }
130}