Prepare v2023.10
[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 (phydev->interface != PHY_INTERFACE_MODE_GMII) {
30                 printf("Incorrect interface type\n");
31                 return -EINVAL;
32         }
33
34         if (!ofnode_valid(node))
35                 return -EINVAL;
36
37         phydev->addr = ofnode_read_u32_default(node, "reg", -1);
38         ret = ofnode_parse_phandle_with_args(node, "phy-handle",
39                                              NULL, 0, 0, &phandle);
40         if (ret)
41                 return ret;
42
43         ext_phyaddr = ofnode_read_u32_default(phandle.node, "reg", -1);
44         ext_phydev = phy_find_by_mask(phydev->bus,
45                                       1 << ext_phyaddr);
46         if (!ext_phydev) {
47                 printf("%s, No external phy device found\n", __func__);
48                 return -EINVAL;
49         }
50
51         ext_phydev->interface = ofnode_read_phy_mode(node);
52         if (ext_phydev->interface == PHY_INTERFACE_MODE_NA) {
53                 ext_phydev->interface = PHY_INTERFACE_MODE_RGMII;
54         } else if (!phy_interface_is_rgmii(ext_phydev)) {
55                 printf("Incorrect external interface type\n");
56                 return -EINVAL;
57         }
58
59         ext_phydev->node = phandle.node;
60         phydev->priv = ext_phydev;
61
62         debug("%s, gmii2rgmmi:0x%x, extphy:0x%x\n", __func__, phydev->addr,
63               ext_phyaddr);
64
65         if (ext_phydev->drv->config)
66                 ext_phydev->drv->config(ext_phydev);
67
68         return 0;
69 }
70
71 static int xilinxgmiitorgmii_extread(struct phy_device *phydev, int addr,
72                                      int devaddr, int regnum)
73 {
74         struct phy_device *ext_phydev = phydev->priv;
75
76         debug("%s\n", __func__);
77         if (ext_phydev->drv->readext)
78                 ext_phydev->drv->readext(ext_phydev, addr, devaddr, regnum);
79
80         return 0;
81 }
82
83 static int xilinxgmiitorgmii_extwrite(struct phy_device *phydev, int addr,
84                                       int devaddr, int regnum, u16 val)
85
86 {
87         struct phy_device *ext_phydev = phydev->priv;
88
89         debug("%s\n", __func__);
90         if (ext_phydev->drv->writeext)
91                 ext_phydev->drv->writeext(ext_phydev, addr, devaddr, regnum,
92                                           val);
93
94         return 0;
95 }
96
97 static int xilinxgmiitorgmii_startup(struct phy_device *phydev)
98 {
99         u16 val = 0;
100         struct phy_device *ext_phydev = phydev->priv;
101
102         debug("%s\n", __func__);
103         ext_phydev->dev = phydev->dev;
104         if (ext_phydev->drv->startup)
105                 ext_phydev->drv->startup(ext_phydev);
106
107         val = phy_read(phydev, phydev->addr, ZYNQ_GMII2RGMII_REG);
108         val &= ~ZYNQ_GMII2RGMII_SPEED_MASK;
109
110         if (ext_phydev->speed == SPEED_1000)
111                 val |= BMCR_SPEED1000;
112         else if (ext_phydev->speed == SPEED_100)
113                 val |= BMCR_SPEED100;
114
115         phy_write(phydev, phydev->addr, ZYNQ_GMII2RGMII_REG, val |
116                   BMCR_FULLDPLX);
117
118         phydev->duplex = ext_phydev->duplex;
119         phydev->speed = ext_phydev->speed;
120         phydev->link = ext_phydev->link;
121
122         return 0;
123 }
124
125 static int xilinxgmiitorgmii_probe(struct phy_device *phydev)
126 {
127         debug("%s\n", __func__);
128
129         phydev->flags |= PHY_FLAG_BROKEN_RESET;
130
131         return 0;
132 }
133
134 U_BOOT_PHY_DRIVER(gmii2rgmii) = {
135         .name = "XILINX GMII2RGMII",
136         .uid = PHY_GMII2RGMII_ID,
137         .mask = 0xffffffff,
138         .features = PHY_GBIT_FEATURES,
139         .probe = xilinxgmiitorgmii_probe,
140         .config = xilinxgmiitorgmii_config,
141         .startup = xilinxgmiitorgmii_startup,
142         .writeext = xilinxgmiitorgmii_extwrite,
143         .readext = xilinxgmiitorgmii_extread,
144 };