diff options
Diffstat (limited to 'roms/u-boot/board/freescale/common/sgmii_riser.c')
-rw-r--r-- | roms/u-boot/board/freescale/common/sgmii_riser.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/roms/u-boot/board/freescale/common/sgmii_riser.c b/roms/u-boot/board/freescale/common/sgmii_riser.c new file mode 100644 index 00000000..5c3c5937 --- /dev/null +++ b/roms/u-boot/board/freescale/common/sgmii_riser.c @@ -0,0 +1,129 @@ +/* + * Freescale SGMII Riser Card + * + * This driver supports the SGMII Riser card found on the + * "DS" style of development board from Freescale. + * + * This software may be used and distributed according to the + * terms of the GNU Public License, Version 2, incorporated + * herein by reference. + * + * Copyright 2008 Freescale Semiconductor, Inc. + * + */ + +#include <config.h> +#include <common.h> +#include <net.h> +#include <libfdt.h> +#include <tsec.h> +#include <fdt_support.h> + +void fsl_sgmii_riser_init(struct tsec_info_struct *tsec_info, int num) +{ + int i; + + for (i = 0; i < num; i++) + if (tsec_info[i].flags & TSEC_SGMII) + tsec_info[i].phyaddr += SGMII_RISER_PHY_OFFSET; +} + +void fsl_sgmii_riser_fdt_fixup(void *fdt) +{ + struct eth_device *dev; + int node; + int mdio_node; + int i = -1; + int etsec_num = 0; + + node = fdt_path_offset(fdt, "/aliases"); + if (node < 0) + return; + + while ((dev = eth_get_dev_by_index(++i)) != NULL) { + struct tsec_private *priv; + int phy_node; + int enet_node; + uint32_t ph; + char sgmii_phy[16]; + char enet[16]; + const u32 *phyh; + const char *model; + const char *path; + + if (!strstr(dev->name, "eTSEC")) + continue; + + priv = dev->priv; + if (!(priv->flags & TSEC_SGMII)) { + etsec_num++; + continue; + } + + mdio_node = fdt_node_offset_by_compatible(fdt, -1, + "fsl,gianfar-mdio"); + if (mdio_node < 0) + return; + + sprintf(sgmii_phy, "sgmii-phy@%d", etsec_num); + phy_node = fdt_subnode_offset(fdt, mdio_node, sgmii_phy); + if (phy_node > 0) { + fdt_increase_size(fdt, 32); + ph = fdt_create_phandle(fdt, phy_node); + if (!ph) + continue; + } + + sprintf(enet, "ethernet%d", etsec_num++); + path = fdt_getprop(fdt, node, enet, NULL); + if (!path) { + debug("No alias for %s\n", enet); + continue; + } + + enet_node = fdt_path_offset(fdt, path); + if (enet_node < 0) + continue; + + model = fdt_getprop(fdt, enet_node, "model", NULL); + + /* + * We only want to do this to eTSECs. On some platforms + * there are more than one type of gianfar-style ethernet + * controller, and as we are creating an implicit connection + * between ethernet nodes and eTSEC devices, it is best to + * make the connection use as much explicit information + * as exists. + */ + if (!strstr(model, "TSEC")) + continue; + + if (phy_node < 0) { + /* + * This part is only for old device tree without + * sgmii_phy nodes. It's kept just for compatible + * reason. Soon to be deprecated if all device tree + * get updated. + */ + phyh = fdt_getprop(fdt, enet_node, "phy-handle", NULL); + if (!phyh) + continue; + + phy_node = fdt_node_offset_by_phandle(fdt, + fdt32_to_cpu(*phyh)); + + priv = dev->priv; + + if (priv->flags & TSEC_SGMII) + fdt_setprop_cell(fdt, phy_node, "reg", + priv->phyaddr); + } else { + fdt_setprop(fdt, enet_node, "phy-handle", &ph, + sizeof(ph)); + fdt_setprop_string(fdt, enet_node, + "phy-connection-type", + phy_string_for_interface( + PHY_INTERFACE_MODE_SGMII)); + } + } +} |