blob: e44b7b75bd585c13364dd2f6f6495dc941b855e7 [file] [log] [blame]
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +05301// SPDX-License-Identifier: GPL-2.0
2/*
3 * Xilinx GMII2RGMII phy driver
4 *
5 * Copyright (C) 2018 Xilinx, Inc.
6 */
7
8#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +053010#include <phy.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +053012
13DECLARE_GLOBAL_DATA_PTR;
14
15#define ZYNQ_GMII2RGMII_REG 0x10
16#define ZYNQ_GMII2RGMII_SPEED_MASK (BMCR_SPEED1000 | BMCR_SPEED100)
17
18static int xilinxgmiitorgmii_config(struct phy_device *phydev)
19{
Bin Meng021e7e72021-03-14 20:14:50 +080020 ofnode node = phy_get_ofnode(phydev);
21 struct phy_device *ext_phydev;
22 struct ofnode_phandle_args phandle;
23 int ext_phyaddr = -1;
24 int ret;
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +053025
26 debug("%s\n", __func__);
Bin Meng021e7e72021-03-14 20:14:50 +080027
Marek BehĂșn2141ad42022-04-07 00:33:05 +020028 if (phydev->interface != PHY_INTERFACE_MODE_GMII) {
29 printf("Incorrect interface type\n");
30 return -EINVAL;
31 }
32
Bin Meng021e7e72021-03-14 20:14:50 +080033 if (!ofnode_valid(node))
34 return -EINVAL;
35
36 phydev->addr = ofnode_read_u32_default(node, "reg", -1);
37 ret = ofnode_parse_phandle_with_args(node, "phy-handle",
38 NULL, 0, 0, &phandle);
39 if (ret)
40 return ret;
41
42 ext_phyaddr = ofnode_read_u32_default(phandle.node, "reg", -1);
43 ext_phydev = phy_find_by_mask(phydev->bus,
Marek BehĂșn3927efb2022-04-07 00:33:08 +020044 1 << ext_phyaddr);
Bin Meng021e7e72021-03-14 20:14:50 +080045 if (!ext_phydev) {
46 printf("%s, No external phy device found\n", __func__);
47 return -EINVAL;
48 }
49
Stefan Herbrechtsmeier77765782023-03-22 09:42:47 +010050 ext_phydev->interface = ofnode_read_phy_mode(node);
51 if (ext_phydev->interface == PHY_INTERFACE_MODE_NA) {
52 ext_phydev->interface = PHY_INTERFACE_MODE_RGMII;
53 } else if (!phy_interface_is_rgmii(ext_phydev)) {
54 printf("Incorrect external interface type\n");
55 return -EINVAL;
56 }
57
Bin Meng021e7e72021-03-14 20:14:50 +080058 ext_phydev->node = phandle.node;
59 phydev->priv = ext_phydev;
60
61 debug("%s, gmii2rgmmi:0x%x, extphy:0x%x\n", __func__, phydev->addr,
62 ext_phyaddr);
63
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +053064 if (ext_phydev->drv->config)
65 ext_phydev->drv->config(ext_phydev);
66
67 return 0;
68}
69
70static int xilinxgmiitorgmii_extread(struct phy_device *phydev, int addr,
71 int devaddr, int regnum)
72{
73 struct phy_device *ext_phydev = phydev->priv;
74
75 debug("%s\n", __func__);
76 if (ext_phydev->drv->readext)
77 ext_phydev->drv->readext(ext_phydev, addr, devaddr, regnum);
78
79 return 0;
80}
81
82static int xilinxgmiitorgmii_extwrite(struct phy_device *phydev, int addr,
83 int devaddr, int regnum, u16 val)
84
85{
86 struct phy_device *ext_phydev = phydev->priv;
87
88 debug("%s\n", __func__);
89 if (ext_phydev->drv->writeext)
90 ext_phydev->drv->writeext(ext_phydev, addr, devaddr, regnum,
91 val);
92
93 return 0;
94}
95
96static int xilinxgmiitorgmii_startup(struct phy_device *phydev)
97{
98 u16 val = 0;
99 struct phy_device *ext_phydev = phydev->priv;
100
101 debug("%s\n", __func__);
102 ext_phydev->dev = phydev->dev;
103 if (ext_phydev->drv->startup)
104 ext_phydev->drv->startup(ext_phydev);
105
106 val = phy_read(phydev, phydev->addr, ZYNQ_GMII2RGMII_REG);
107 val &= ~ZYNQ_GMII2RGMII_SPEED_MASK;
108
109 if (ext_phydev->speed == SPEED_1000)
110 val |= BMCR_SPEED1000;
111 else if (ext_phydev->speed == SPEED_100)
112 val |= BMCR_SPEED100;
113
114 phy_write(phydev, phydev->addr, ZYNQ_GMII2RGMII_REG, val |
115 BMCR_FULLDPLX);
116
117 phydev->duplex = ext_phydev->duplex;
118 phydev->speed = ext_phydev->speed;
119 phydev->link = ext_phydev->link;
120
121 return 0;
122}
123
124static int xilinxgmiitorgmii_probe(struct phy_device *phydev)
125{
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530126 debug("%s\n", __func__);
127
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530128 phydev->flags |= PHY_FLAG_BROKEN_RESET;
129
130 return 0;
131}
132
Marek Vasutf5a118f2023-03-19 18:03:11 +0100133U_BOOT_PHY_DRIVER(gmii2rgmii) = {
Siva Durga Prasad Paladugud5c4e1e2018-11-27 11:49:11 +0530134 .name = "XILINX GMII2RGMII",
135 .uid = PHY_GMII2RGMII_ID,
136 .mask = 0xffffffff,
137 .features = PHY_GBIT_FEATURES,
138 .probe = xilinxgmiitorgmii_probe,
139 .config = xilinxgmiitorgmii_config,
140 .startup = xilinxgmiitorgmii_startup,
141 .writeext = xilinxgmiitorgmii_extwrite,
142 .readext = xilinxgmiitorgmii_extread,
143};