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_gmii2rgmii.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Xilinx GMII2RGMII phy driver
4  *
5  * Copyright (C) 2018 Xilinx, Inc.
6  */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <log.h>
11 #include <phy.h>
12 #include <asm/global_data.h>
13
14 DECLARE_GLOBAL_DATA_PTR;
15
16 #define ZYNQ_GMII2RGMII_REG             0x10
17 #define ZYNQ_GMII2RGMII_SPEED_MASK      (BMCR_SPEED1000 | BMCR_SPEED100)
18
19 static int xilinxgmiitorgmii_config(struct phy_device *phydev)
20 {
21         ofnode node = phy_get_ofnode(phydev);
22         struct phy_device *ext_phydev;
23         struct ofnode_phandle_args phandle;
24         int ext_phyaddr = -1;
25         int ret;
26
27         debug("%s\n", __func__);
28
29         if (!ofnode_valid(node))
30                 return -EINVAL;
31
32         phydev->addr = ofnode_read_u32_default(node, "reg", -1);
33         ret = ofnode_parse_phandle_with_args(node, "phy-handle",
34                                              NULL, 0, 0, &phandle);
35         if (ret)
36                 return ret;
37
38         ext_phyaddr = ofnode_read_u32_default(phandle.node, "reg", -1);
39         ext_phydev = phy_find_by_mask(phydev->bus,
40                                       1 << ext_phyaddr,
41                                       PHY_INTERFACE_MODE_RGMII);
42         if (!ext_phydev) {
43                 printf("%s, No external phy device found\n", __func__);
44                 return -EINVAL;
45         }
46
47         ext_phydev->node = phandle.node;
48         phydev->priv = ext_phydev;
49
50         debug("%s, gmii2rgmmi:0x%x, extphy:0x%x\n", __func__, phydev->addr,
51               ext_phyaddr);
52
53         if (ext_phydev->drv->config)
54                 ext_phydev->drv->config(ext_phydev);
55
56         return 0;
57 }
58
59 static int xilinxgmiitorgmii_extread(struct phy_device *phydev, int addr,
60                                      int devaddr, int regnum)
61 {
62         struct phy_device *ext_phydev = phydev->priv;
63
64         debug("%s\n", __func__);
65         if (ext_phydev->drv->readext)
66                 ext_phydev->drv->readext(ext_phydev, addr, devaddr, regnum);
67
68         return 0;
69 }
70
71 static int xilinxgmiitorgmii_extwrite(struct phy_device *phydev, int addr,
72                                       int devaddr, int regnum, u16 val)
73
74 {
75         struct phy_device *ext_phydev = phydev->priv;
76
77         debug("%s\n", __func__);
78         if (ext_phydev->drv->writeext)
79                 ext_phydev->drv->writeext(ext_phydev, addr, devaddr, regnum,
80                                           val);
81
82         return 0;
83 }
84
85 static int xilinxgmiitorgmii_startup(struct phy_device *phydev)
86 {
87         u16 val = 0;
88         struct phy_device *ext_phydev = phydev->priv;
89
90         debug("%s\n", __func__);
91         ext_phydev->dev = phydev->dev;
92         if (ext_phydev->drv->startup)
93                 ext_phydev->drv->startup(ext_phydev);
94
95         val = phy_read(phydev, phydev->addr, ZYNQ_GMII2RGMII_REG);
96         val &= ~ZYNQ_GMII2RGMII_SPEED_MASK;
97
98         if (ext_phydev->speed == SPEED_1000)
99                 val |= BMCR_SPEED1000;
100         else if (ext_phydev->speed == SPEED_100)
101                 val |= BMCR_SPEED100;
102
103         phy_write(phydev, phydev->addr, ZYNQ_GMII2RGMII_REG, val |
104                   BMCR_FULLDPLX);
105
106         phydev->duplex = ext_phydev->duplex;
107         phydev->speed = ext_phydev->speed;
108         phydev->link = ext_phydev->link;
109
110         return 0;
111 }
112
113 static int xilinxgmiitorgmii_probe(struct phy_device *phydev)
114 {
115         debug("%s\n", __func__);
116
117         if (phydev->interface != PHY_INTERFACE_MODE_GMII) {
118                 printf("Incorrect interface type\n");
119                 return -EINVAL;
120         }
121
122         phydev->flags |= PHY_FLAG_BROKEN_RESET;
123
124         return 0;
125 }
126
127 static struct phy_driver gmii2rgmii_driver = {
128         .name = "XILINX GMII2RGMII",
129         .uid = PHY_GMII2RGMII_ID,
130         .mask = 0xffffffff,
131         .features = PHY_GBIT_FEATURES,
132         .probe = xilinxgmiitorgmii_probe,
133         .config = xilinxgmiitorgmii_config,
134         .startup = xilinxgmiitorgmii_startup,
135         .writeext = xilinxgmiitorgmii_extwrite,
136         .readext = xilinxgmiitorgmii_extread,
137 };
138
139 int phy_xilinx_gmii2rgmii_init(void)
140 {
141         phy_register(&gmii2rgmii_driver);
142
143         return 0;
144 }