]>
Commit | Line | Data |
---|---|---|
f41e588c SDPP |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Xilinx GMII2RGMII phy driver | |
4 | * | |
5 | * Copyright (C) 2018 Xilinx, Inc. | |
6 | */ | |
7 | ||
d678a59d | 8 | #include <common.h> |
f41e588c | 9 | #include <dm.h> |
f7ae49fc | 10 | #include <log.h> |
f41e588c | 11 | #include <phy.h> |
401d1c4f | 12 | #include <asm/global_data.h> |
f41e588c SDPP |
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 | { | |
6c993815 BM |
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; | |
f41e588c SDPP |
26 | |
27 | debug("%s\n", __func__); | |
6c993815 | 28 | |
f961b3ab MB |
29 | if (phydev->interface != PHY_INTERFACE_MODE_GMII) { |
30 | printf("Incorrect interface type\n"); | |
31 | return -EINVAL; | |
32 | } | |
33 | ||
6c993815 BM |
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, | |
e24b58f5 | 45 | 1 << ext_phyaddr); |
6c993815 BM |
46 | if (!ext_phydev) { |
47 | printf("%s, No external phy device found\n", __func__); | |
48 | return -EINVAL; | |
49 | } | |
50 | ||
29003429 SH |
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 | ||
6c993815 BM |
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 | ||
f41e588c SDPP |
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 | { | |
f41e588c SDPP |
127 | debug("%s\n", __func__); |
128 | ||
f41e588c SDPP |
129 | phydev->flags |= PHY_FLAG_BROKEN_RESET; |
130 | ||
131 | return 0; | |
132 | } | |
133 | ||
53ef8d79 | 134 | U_BOOT_PHY_DRIVER(gmii2rgmii) = { |
f41e588c SDPP |
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 | }; |