SPDX: Convert all of our single license tags to Linux Kernel style
[oweals/u-boot.git] / drivers / net / phy / xilinx_phy.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Xilinx PCS/PMA Core phy driver
4  *
5  * Copyright (C) 2015 - 2016 Xilinx, Inc.
6  */
7
8 #include <config.h>
9 #include <common.h>
10 #include <phy.h>
11 #include <dm.h>
12
13 DECLARE_GLOBAL_DATA_PTR;
14
15 #define MII_PHY_STATUS_SPD_MASK         0x0C00
16 #define MII_PHY_STATUS_FULLDUPLEX       0x1000
17 #define MII_PHY_STATUS_1000             0x0800
18 #define MII_PHY_STATUS_100              0x0400
19 #define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF
20
21 /* Mask used for ID comparisons */
22 #define XILINX_PHY_ID_MASK              0xfffffff0
23
24 /* Known PHY IDs */
25 #define XILINX_PHY_ID                   0x01740c00
26
27 /* struct phy_device dev_flags definitions */
28 #define XAE_PHY_TYPE_MII                0
29 #define XAE_PHY_TYPE_GMII               1
30 #define XAE_PHY_TYPE_RGMII_1_3          2
31 #define XAE_PHY_TYPE_RGMII_2_0          3
32 #define XAE_PHY_TYPE_SGMII              4
33 #define XAE_PHY_TYPE_1000BASE_X         5
34
35 static int xilinxphy_startup(struct phy_device *phydev)
36 {
37         int err;
38         int status = 0;
39
40         debug("%s\n", __func__);
41         /* Update the link, but return if there
42          * was an error
43          */
44         err = genphy_update_link(phydev);
45         if (err)
46                 return err;
47
48         if (AUTONEG_ENABLE == phydev->autoneg) {
49                 status = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
50                 status = status & MII_PHY_STATUS_SPD_MASK;
51
52                 if (status & MII_PHY_STATUS_FULLDUPLEX)
53                         phydev->duplex = DUPLEX_FULL;
54                 else
55                         phydev->duplex = DUPLEX_HALF;
56
57                 switch (status) {
58                 case MII_PHY_STATUS_1000:
59                         phydev->speed = SPEED_1000;
60                         break;
61
62                 case MII_PHY_STATUS_100:
63                         phydev->speed = SPEED_100;
64                         break;
65
66                 default:
67                         phydev->speed = SPEED_10;
68                         break;
69                 }
70         } else {
71                 int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
72
73                 if (bmcr < 0)
74                         return bmcr;
75
76                 if (bmcr & BMCR_FULLDPLX)
77                         phydev->duplex = DUPLEX_FULL;
78                 else
79                         phydev->duplex = DUPLEX_HALF;
80
81                 if (bmcr & BMCR_SPEED1000)
82                         phydev->speed = SPEED_1000;
83                 else if (bmcr & BMCR_SPEED100)
84                         phydev->speed = SPEED_100;
85                 else
86                         phydev->speed = SPEED_10;
87         }
88
89         /*
90          * For 1000BASE-X Phy Mode the speed/duplex will always be
91          * 1000Mbps/fullduplex
92          */
93         if (phydev->flags == XAE_PHY_TYPE_1000BASE_X) {
94                 phydev->duplex = DUPLEX_FULL;
95                 phydev->speed = SPEED_1000;
96         }
97
98         return 0;
99 }
100
101 static int xilinxphy_of_init(struct phy_device *phydev)
102 {
103         u32 phytype;
104
105         debug("%s\n", __func__);
106         phytype = fdtdec_get_int(gd->fdt_blob, dev_of_offset(phydev->dev),
107                                  "xlnx,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
114 static 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
127 static 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
137 int phy_xilinx_init(void)
138 {
139         debug("%s\n", __func__);
140         phy_register(&xilinxphy_driver);
141
142         return 0;
143 }