1652f7c2eSAndy Fleming /*
2652f7c2eSAndy Fleming  * Freescale SGMII Riser Card
3652f7c2eSAndy Fleming  *
4652f7c2eSAndy Fleming  * This driver supports the SGMII Riser card found on the
5652f7c2eSAndy Fleming  * "DS" style of development board from Freescale.
6652f7c2eSAndy Fleming  *
7652f7c2eSAndy Fleming  * This software may be used and distributed according to the
8652f7c2eSAndy Fleming  * terms of the GNU Public License, Version 2, incorporated
9652f7c2eSAndy Fleming  * herein by reference.
10652f7c2eSAndy Fleming  *
11652f7c2eSAndy Fleming  * Copyright 2008 Freescale Semiconductor, Inc.
12652f7c2eSAndy Fleming  *
13652f7c2eSAndy Fleming  */
14652f7c2eSAndy Fleming 
15652f7c2eSAndy Fleming #include <config.h>
16652f7c2eSAndy Fleming #include <common.h>
17feede8b0SAndy Fleming #include <net.h>
18*b08c8c48SMasahiro Yamada #include <linux/libfdt.h>
19652f7c2eSAndy Fleming #include <tsec.h>
20308bc61dSHongtao Jia #include <fdt_support.h>
21652f7c2eSAndy Fleming 
fsl_sgmii_riser_init(struct tsec_info_struct * tsec_info,int num)22652f7c2eSAndy Fleming void fsl_sgmii_riser_init(struct tsec_info_struct *tsec_info, int num)
23652f7c2eSAndy Fleming {
24652f7c2eSAndy Fleming 	int i;
25652f7c2eSAndy Fleming 
26652f7c2eSAndy Fleming 	for (i = 0; i < num; i++)
27652f7c2eSAndy Fleming 		if (tsec_info[i].flags & TSEC_SGMII)
28652f7c2eSAndy Fleming 			tsec_info[i].phyaddr += SGMII_RISER_PHY_OFFSET;
29652f7c2eSAndy Fleming }
30feede8b0SAndy Fleming 
fsl_sgmii_riser_fdt_fixup(void * fdt)31feede8b0SAndy Fleming void fsl_sgmii_riser_fdt_fixup(void *fdt)
32feede8b0SAndy Fleming {
33feede8b0SAndy Fleming 	struct eth_device *dev;
34feede8b0SAndy Fleming 	int node;
35308bc61dSHongtao Jia 	int mdio_node;
36feede8b0SAndy Fleming 	int i = -1;
37feede8b0SAndy Fleming 	int etsec_num = 0;
38feede8b0SAndy Fleming 
39feede8b0SAndy Fleming 	node = fdt_path_offset(fdt, "/aliases");
40feede8b0SAndy Fleming 	if (node < 0)
41feede8b0SAndy Fleming 		return;
42feede8b0SAndy Fleming 
43feede8b0SAndy Fleming 	while ((dev = eth_get_dev_by_index(++i)) != NULL) {
44feede8b0SAndy Fleming 		struct tsec_private *priv;
45308bc61dSHongtao Jia 		int phy_node;
46feede8b0SAndy Fleming 		int enet_node;
47308bc61dSHongtao Jia 		uint32_t ph;
48308bc61dSHongtao Jia 		char sgmii_phy[16];
49feede8b0SAndy Fleming 		char enet[16];
50feede8b0SAndy Fleming 		const u32 *phyh;
51feede8b0SAndy Fleming 		const char *model;
52feede8b0SAndy Fleming 		const char *path;
53feede8b0SAndy Fleming 
54feede8b0SAndy Fleming 		if (!strstr(dev->name, "eTSEC"))
55feede8b0SAndy Fleming 			continue;
56feede8b0SAndy Fleming 
57308bc61dSHongtao Jia 		priv = dev->priv;
58308bc61dSHongtao Jia 		if (!(priv->flags & TSEC_SGMII)) {
59308bc61dSHongtao Jia 			etsec_num++;
60308bc61dSHongtao Jia 			continue;
61308bc61dSHongtao Jia 		}
62308bc61dSHongtao Jia 
63308bc61dSHongtao Jia 		mdio_node = fdt_node_offset_by_compatible(fdt, -1,
64308bc61dSHongtao Jia 				"fsl,gianfar-mdio");
65308bc61dSHongtao Jia 		if (mdio_node < 0)
66308bc61dSHongtao Jia 			return;
67308bc61dSHongtao Jia 
68308bc61dSHongtao Jia 		sprintf(sgmii_phy, "sgmii-phy@%d", etsec_num);
69308bc61dSHongtao Jia 		phy_node = fdt_subnode_offset(fdt, mdio_node, sgmii_phy);
70308bc61dSHongtao Jia 		if (phy_node > 0) {
71308bc61dSHongtao Jia 			fdt_increase_size(fdt, 32);
72308bc61dSHongtao Jia 			ph = fdt_create_phandle(fdt, phy_node);
73308bc61dSHongtao Jia 			if (!ph)
74308bc61dSHongtao Jia 				continue;
75308bc61dSHongtao Jia 		}
76308bc61dSHongtao Jia 
77feede8b0SAndy Fleming 		sprintf(enet, "ethernet%d", etsec_num++);
78feede8b0SAndy Fleming 		path = fdt_getprop(fdt, node, enet, NULL);
79feede8b0SAndy Fleming 		if (!path) {
80feede8b0SAndy Fleming 			debug("No alias for %s\n", enet);
81feede8b0SAndy Fleming 			continue;
82feede8b0SAndy Fleming 		}
83feede8b0SAndy Fleming 
84feede8b0SAndy Fleming 		enet_node = fdt_path_offset(fdt, path);
85feede8b0SAndy Fleming 		if (enet_node < 0)
86feede8b0SAndy Fleming 			continue;
87feede8b0SAndy Fleming 
88feede8b0SAndy Fleming 		model = fdt_getprop(fdt, enet_node, "model", NULL);
89feede8b0SAndy Fleming 
90feede8b0SAndy Fleming 		/*
91feede8b0SAndy Fleming 		 * We only want to do this to eTSECs.  On some platforms
92feede8b0SAndy Fleming 		 * there are more than one type of gianfar-style ethernet
93feede8b0SAndy Fleming 		 * controller, and as we are creating an implicit connection
94feede8b0SAndy Fleming 		 * between ethernet nodes and eTSEC devices, it is best to
95feede8b0SAndy Fleming 		 * make the connection use as much explicit information
96feede8b0SAndy Fleming 		 * as exists.
97feede8b0SAndy Fleming 		 */
98feede8b0SAndy Fleming 		if (!strstr(model, "TSEC"))
99feede8b0SAndy Fleming 			continue;
100feede8b0SAndy Fleming 
101308bc61dSHongtao Jia 		if (phy_node < 0) {
102308bc61dSHongtao Jia 			/*
103308bc61dSHongtao Jia 			 * This part is only for old device tree without
104308bc61dSHongtao Jia 			 * sgmii_phy nodes. It's kept just for compatible
105308bc61dSHongtao Jia 			 * reason. Soon to be deprecated if all device tree
106308bc61dSHongtao Jia 			 * get updated.
107308bc61dSHongtao Jia 			 */
108feede8b0SAndy Fleming 			phyh = fdt_getprop(fdt, enet_node, "phy-handle", NULL);
109feede8b0SAndy Fleming 			if (!phyh)
110feede8b0SAndy Fleming 				continue;
111feede8b0SAndy Fleming 
112308bc61dSHongtao Jia 			phy_node = fdt_node_offset_by_phandle(fdt,
113308bc61dSHongtao Jia 					fdt32_to_cpu(*phyh));
114feede8b0SAndy Fleming 
115feede8b0SAndy Fleming 			priv = dev->priv;
116feede8b0SAndy Fleming 
117feede8b0SAndy Fleming 			if (priv->flags & TSEC_SGMII)
118308bc61dSHongtao Jia 				fdt_setprop_cell(fdt, phy_node, "reg",
119308bc61dSHongtao Jia 						priv->phyaddr);
120308bc61dSHongtao Jia 		} else {
121308bc61dSHongtao Jia 			fdt_setprop(fdt, enet_node, "phy-handle", &ph,
122308bc61dSHongtao Jia 					sizeof(ph));
123308bc61dSHongtao Jia 			fdt_setprop_string(fdt, enet_node,
124308bc61dSHongtao Jia 					"phy-connection-type",
125308bc61dSHongtao Jia 					phy_string_for_interface(
126308bc61dSHongtao Jia 						PHY_INTERFACE_MODE_SGMII));
127308bc61dSHongtao Jia 		}
128feede8b0SAndy Fleming 	}
129feede8b0SAndy Fleming }
130