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 <net.h> 18 #include <linux/libfdt.h> 19 #include <tsec.h> 20 #include <fdt_support.h> 21 22 void fsl_sgmii_riser_init(struct tsec_info_struct *tsec_info, int num) 23 { 24 int i; 25 26 for (i = 0; i < num; i++) 27 if (tsec_info[i].flags & TSEC_SGMII) 28 tsec_info[i].phyaddr += SGMII_RISER_PHY_OFFSET; 29 } 30 31 void fsl_sgmii_riser_fdt_fixup(void *fdt) 32 { 33 struct eth_device *dev; 34 int node; 35 int mdio_node; 36 int i = -1; 37 int etsec_num = 0; 38 39 node = fdt_path_offset(fdt, "/aliases"); 40 if (node < 0) 41 return; 42 43 while ((dev = eth_get_dev_by_index(++i)) != NULL) { 44 struct tsec_private *priv; 45 int phy_node; 46 int enet_node; 47 uint32_t ph; 48 char sgmii_phy[16]; 49 char enet[16]; 50 const u32 *phyh; 51 const char *model; 52 const char *path; 53 54 if (!strstr(dev->name, "eTSEC")) 55 continue; 56 57 priv = dev->priv; 58 if (!(priv->flags & TSEC_SGMII)) { 59 etsec_num++; 60 continue; 61 } 62 63 mdio_node = fdt_node_offset_by_compatible(fdt, -1, 64 "fsl,gianfar-mdio"); 65 if (mdio_node < 0) 66 return; 67 68 sprintf(sgmii_phy, "sgmii-phy@%d", etsec_num); 69 phy_node = fdt_subnode_offset(fdt, mdio_node, sgmii_phy); 70 if (phy_node > 0) { 71 fdt_increase_size(fdt, 32); 72 ph = fdt_create_phandle(fdt, phy_node); 73 if (!ph) 74 continue; 75 } 76 77 sprintf(enet, "ethernet%d", etsec_num++); 78 path = fdt_getprop(fdt, node, enet, NULL); 79 if (!path) { 80 debug("No alias for %s\n", enet); 81 continue; 82 } 83 84 enet_node = fdt_path_offset(fdt, path); 85 if (enet_node < 0) 86 continue; 87 88 model = fdt_getprop(fdt, enet_node, "model", NULL); 89 90 /* 91 * We only want to do this to eTSECs. On some platforms 92 * there are more than one type of gianfar-style ethernet 93 * controller, and as we are creating an implicit connection 94 * between ethernet nodes and eTSEC devices, it is best to 95 * make the connection use as much explicit information 96 * as exists. 97 */ 98 if (!strstr(model, "TSEC")) 99 continue; 100 101 if (phy_node < 0) { 102 /* 103 * This part is only for old device tree without 104 * sgmii_phy nodes. It's kept just for compatible 105 * reason. Soon to be deprecated if all device tree 106 * get updated. 107 */ 108 phyh = fdt_getprop(fdt, enet_node, "phy-handle", NULL); 109 if (!phyh) 110 continue; 111 112 phy_node = fdt_node_offset_by_phandle(fdt, 113 fdt32_to_cpu(*phyh)); 114 115 priv = dev->priv; 116 117 if (priv->flags & TSEC_SGMII) 118 fdt_setprop_cell(fdt, phy_node, "reg", 119 priv->phyaddr); 120 } else { 121 fdt_setprop(fdt, enet_node, "phy-handle", &ph, 122 sizeof(ph)); 123 fdt_setprop_string(fdt, enet_node, 124 "phy-connection-type", 125 phy_string_for_interface( 126 PHY_INTERFACE_MODE_SGMII)); 127 } 128 } 129 } 130