hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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 <linux/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));
       }
   }
}