Merge tag 'u-boot-at91-2022.07-a' of https://source.denx.de/u-boot/custodians/u-boot...
[platform/kernel/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 <log.h>
11 #include <phy.h>
12 #include <dm.h>
13
14 #define MII_PHY_STATUS_SPD_MASK         0x0C00
15 #define MII_PHY_STATUS_FULLDUPLEX       0x1000
16 #define MII_PHY_STATUS_1000             0x0800
17 #define MII_PHY_STATUS_100              0x0400
18 #define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF
19
20 /* Mask used for ID comparisons */
21 #define XILINX_PHY_ID_MASK              0xfffffff0
22
23 /* Known PHY IDs */
24 #define XILINX_PHY_ID                   0x01740c00
25
26 /* struct phy_device dev_flags definitions */
27 #define XAE_PHY_TYPE_MII                0
28 #define XAE_PHY_TYPE_GMII               1
29 #define XAE_PHY_TYPE_RGMII_1_3          2
30 #define XAE_PHY_TYPE_RGMII_2_0          3
31 #define XAE_PHY_TYPE_SGMII              4
32 #define XAE_PHY_TYPE_1000BASE_X         5
33
34 static int xilinxphy_startup(struct phy_device *phydev)
35 {
36         int err;
37         int status = 0;
38
39         debug("%s\n", __func__);
40         /* Update the link, but return if there
41          * was an error
42          */
43         err = genphy_update_link(phydev);
44         if (err)
45                 return err;
46
47         if (AUTONEG_ENABLE == phydev->autoneg) {
48                 status = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
49                 status = status & MII_PHY_STATUS_SPD_MASK;
50
51                 if (status & MII_PHY_STATUS_FULLDUPLEX)
52                         phydev->duplex = DUPLEX_FULL;
53                 else
54                         phydev->duplex = DUPLEX_HALF;
55
56                 switch (status) {
57                 case MII_PHY_STATUS_1000:
58                         phydev->speed = SPEED_1000;
59                         break;
60
61                 case MII_PHY_STATUS_100:
62                         phydev->speed = SPEED_100;
63                         break;
64
65                 default:
66                         phydev->speed = SPEED_10;
67                         break;
68                 }
69         } else {
70                 int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
71
72                 if (bmcr < 0)
73                         return bmcr;
74
75                 if (bmcr & BMCR_FULLDPLX)
76                         phydev->duplex = DUPLEX_FULL;
77                 else
78                         phydev->duplex = DUPLEX_HALF;
79
80                 if (bmcr & BMCR_SPEED1000)
81                         phydev->speed = SPEED_1000;
82                 else if (bmcr & BMCR_SPEED100)
83                         phydev->speed = SPEED_100;
84                 else
85                         phydev->speed = SPEED_10;
86         }
87
88         /*
89          * For 1000BASE-X Phy Mode the speed/duplex will always be
90          * 1000Mbps/fullduplex
91          */
92         if (phydev->flags == XAE_PHY_TYPE_1000BASE_X) {
93                 phydev->duplex = DUPLEX_FULL;
94                 phydev->speed = SPEED_1000;
95         }
96
97         return 0;
98 }
99
100 static int xilinxphy_of_init(struct phy_device *phydev)
101 {
102         u32 phytype;
103         ofnode node;
104
105         debug("%s\n", __func__);
106         node = phy_get_ofnode(phydev);
107         if (!ofnode_valid(node))
108                 return -EINVAL;
109
110         phytype = ofnode_read_u32_default(node, "xlnx,phy-type", -1);
111         if (phytype == XAE_PHY_TYPE_1000BASE_X)
112                 phydev->flags |= XAE_PHY_TYPE_1000BASE_X;
113
114         return 0;
115 }
116
117 static int xilinxphy_config(struct phy_device *phydev)
118 {
119         int temp;
120
121         debug("%s\n", __func__);
122         xilinxphy_of_init(phydev);
123         temp = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
124         temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE;
125         phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, temp);
126
127         return 0;
128 }
129
130 static struct phy_driver xilinxphy_driver = {
131         .uid = XILINX_PHY_ID,
132         .mask = XILINX_PHY_ID_MASK,
133         .name = "Xilinx PCS/PMA PHY",
134         .features = PHY_GBIT_FEATURES,
135         .config = &xilinxphy_config,
136         .startup = &xilinxphy_startup,
137         .shutdown = &genphy_shutdown,
138 };
139
140 int phy_xilinx_init(void)
141 {
142         debug("%s\n", __func__);
143         phy_register(&xilinxphy_driver);
144
145         return 0;
146 }