1
2
3
4
5
6
7
8
9#include <config.h>
10#include <common.h>
11#include <phy.h>
12#include <dm.h>
13
14DECLARE_GLOBAL_DATA_PTR;
15
16#define MII_PHY_STATUS_SPD_MASK 0x0C00
17#define MII_PHY_STATUS_FULLDUPLEX 0x1000
18#define MII_PHY_STATUS_1000 0x0800
19#define MII_PHY_STATUS_100 0x0400
20#define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF
21
22
23#define XILINX_PHY_ID_MASK 0xfffffff0
24
25
26#define XILINX_PHY_ID 0x01740c00
27
28
29#define XAE_PHY_TYPE_MII 0
30#define XAE_PHY_TYPE_GMII 1
31#define XAE_PHY_TYPE_RGMII_1_3 2
32#define XAE_PHY_TYPE_RGMII_2_0 3
33#define XAE_PHY_TYPE_SGMII 4
34#define XAE_PHY_TYPE_1000BASE_X 5
35
36static int xilinxphy_startup(struct phy_device *phydev)
37{
38 int err;
39 int status = 0;
40
41 debug("%s\n", __func__);
42
43
44
45 err = genphy_update_link(phydev);
46 if (err)
47 return err;
48
49 if (AUTONEG_ENABLE == phydev->autoneg) {
50 status = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
51 status = status & MII_PHY_STATUS_SPD_MASK;
52
53 if (status & MII_PHY_STATUS_FULLDUPLEX)
54 phydev->duplex = DUPLEX_FULL;
55 else
56 phydev->duplex = DUPLEX_HALF;
57
58 switch (status) {
59 case MII_PHY_STATUS_1000:
60 phydev->speed = SPEED_1000;
61 break;
62
63 case MII_PHY_STATUS_100:
64 phydev->speed = SPEED_100;
65 break;
66
67 default:
68 phydev->speed = SPEED_10;
69 break;
70 }
71 } else {
72 int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
73
74 if (bmcr < 0)
75 return bmcr;
76
77 if (bmcr & BMCR_FULLDPLX)
78 phydev->duplex = DUPLEX_FULL;
79 else
80 phydev->duplex = DUPLEX_HALF;
81
82 if (bmcr & BMCR_SPEED1000)
83 phydev->speed = SPEED_1000;
84 else if (bmcr & BMCR_SPEED100)
85 phydev->speed = SPEED_100;
86 else
87 phydev->speed = SPEED_10;
88 }
89
90
91
92
93
94 if (phydev->flags == XAE_PHY_TYPE_1000BASE_X) {
95 phydev->duplex = DUPLEX_FULL;
96 phydev->speed = SPEED_1000;
97 }
98
99 return 0;
100}
101
102static int xilinxphy_of_init(struct phy_device *phydev)
103{
104 u32 phytype;
105
106 debug("%s\n", __func__);
107 phytype = fdtdec_get_int(gd->fdt_blob, phydev->dev->of_offset, "phy-type", -1);
108 if (phytype == XAE_PHY_TYPE_1000BASE_X)
109 phydev->flags |= XAE_PHY_TYPE_1000BASE_X;
110
111 return 0;
112}
113
114static int xilinxphy_config(struct phy_device *phydev)
115{
116 int temp;
117
118 debug("%s\n", __func__);
119 xilinxphy_of_init(phydev);
120 temp = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
121 temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE;
122 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, temp);
123
124 return 0;
125}
126
127static struct phy_driver xilinxphy_driver = {
128 .uid = XILINX_PHY_ID,
129 .mask = XILINX_PHY_ID_MASK,
130 .name = "Xilinx PCS/PMA PHY",
131 .features = PHY_GBIT_FEATURES,
132 .config = &xilinxphy_config,
133 .startup = &xilinxphy_startup,
134 .shutdown = &genphy_shutdown,
135};
136
137int phy_xilinx_init(void)
138{
139 debug("%s\n", __func__);
140 phy_register(&xilinxphy_driver);
141
142 return 0;
143}
144