1 // SPDX-License-Identifier: GPL-2.0+
3 * Driver for Analog Devices Industrial Ethernet PHYs
5 * Copyright 2019 Analog Devices Inc.
6 * Copyright 2022 Variscite Ltd.
10 #include <linux/bitops.h>
11 #include <linux/bitfield.h>
13 #define PHY_ID_ADIN1300 0x0283bc30
14 #define ADIN1300_EXT_REG_PTR 0x10
15 #define ADIN1300_EXT_REG_DATA 0x11
17 #define ADIN1300_GE_CLK_CFG_REG 0xff1f
18 #define ADIN1300_GE_CLK_CFG_MASK GENMASK(5, 0)
19 #define ADIN1300_GE_CLK_CFG_RCVR_125 BIT(5)
20 #define ADIN1300_GE_CLK_CFG_FREE_125 BIT(4)
21 #define ADIN1300_GE_CLK_CFG_REF_EN BIT(3)
22 #define ADIN1300_GE_CLK_CFG_HRT_RCVR BIT(2)
23 #define ADIN1300_GE_CLK_CFG_HRT_FREE BIT(1)
24 #define ADIN1300_GE_CLK_CFG_25 BIT(0)
26 #define ADIN1300_GE_RGMII_CFG 0xff23
27 #define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6)
28 #define ADIN1300_GE_RGMII_RX_SEL(x) \
29 FIELD_PREP(ADIN1300_GE_RGMII_RX_MSK, x)
30 #define ADIN1300_GE_RGMII_GTX_MSK GENMASK(5, 3)
31 #define ADIN1300_GE_RGMII_GTX_SEL(x) \
32 FIELD_PREP(ADIN1300_GE_RGMII_GTX_MSK, x)
33 #define ADIN1300_GE_RGMII_RXID_EN BIT(2)
34 #define ADIN1300_GE_RGMII_TXID_EN BIT(1)
35 #define ADIN1300_GE_RGMII_EN BIT(0)
37 /* RGMII internal delay settings for rx and tx for ADIN1300 */
38 #define ADIN1300_RGMII_1_60_NS 0x0001
39 #define ADIN1300_RGMII_1_80_NS 0x0002
40 #define ADIN1300_RGMII_2_00_NS 0x0000
41 #define ADIN1300_RGMII_2_20_NS 0x0006
42 #define ADIN1300_RGMII_2_40_NS 0x0007
45 * struct adin_cfg_reg_map - map a config value to aregister value
46 * @cfg value in device configuration
47 * @reg value in the register
49 struct adin_cfg_reg_map {
54 static const struct adin_cfg_reg_map adin_rgmii_delays[] = {
55 { 1600, ADIN1300_RGMII_1_60_NS },
56 { 1800, ADIN1300_RGMII_1_80_NS },
57 { 2000, ADIN1300_RGMII_2_00_NS },
58 { 2200, ADIN1300_RGMII_2_20_NS },
59 { 2400, ADIN1300_RGMII_2_40_NS },
63 static int adin_lookup_reg_value(const struct adin_cfg_reg_map *tbl, int cfg)
67 for (i = 0; tbl[i].cfg; i++) {
68 if (tbl[i].cfg == cfg)
75 static u32 adin_get_reg_value(struct phy_device *phydev,
76 const char *prop_name,
77 const struct adin_cfg_reg_map *tbl,
83 ofnode node = phy_get_ofnode(phydev);
84 if (!ofnode_valid(node)) {
85 printf("%s: failed to get node\n", __func__);
89 if (ofnode_read_u32(node, prop_name, &val)) {
90 printf("%s: failed to find %s, using default %d\n",
91 __func__, prop_name, dflt);
95 debug("%s: %s = '%d'\n", __func__, prop_name, val);
97 rc = adin_lookup_reg_value(tbl, val);
99 printf("%s: Unsupported value %u for %s using default (%u)\n",
100 __func__, val, prop_name, dflt);
108 * adin_get_phy_mode_override - Get phy-mode override for adin PHY
110 * The function gets phy-mode string from property 'adi,phy-mode-override'
111 * and return its index in phy_interface_strings table, or -1 in error case.
113 phy_interface_t adin_get_phy_mode_override(struct phy_device *phydev)
115 ofnode node = phy_get_ofnode(phydev);
116 const char *phy_mode_override;
117 const char *prop_phy_mode_override = "adi,phy-mode-override";
120 phy_mode_override = ofnode_read_string(node, prop_phy_mode_override);
121 if (!phy_mode_override)
122 return PHY_INTERFACE_MODE_NA;
124 debug("%s: %s = '%s'\n",
125 __func__, prop_phy_mode_override, phy_mode_override);
127 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
128 if (!strcmp(phy_mode_override, phy_interface_strings[i]))
129 return (phy_interface_t) i;
131 printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode_override);
133 return PHY_INTERFACE_MODE_NA;
136 static u16 adin_ext_read(struct phy_device *phydev, const u32 regnum)
140 phy_write(phydev, MDIO_DEVAD_NONE, ADIN1300_EXT_REG_PTR, regnum);
141 val = phy_read(phydev, MDIO_DEVAD_NONE, ADIN1300_EXT_REG_DATA);
143 debug("%s: adin@0x%x 0x%x=0x%x\n", __func__, phydev->addr, regnum, val);
148 static int adin_ext_write(struct phy_device *phydev, const u32 regnum, const u16 val)
150 debug("%s: adin@0x%x 0x%x=0x%x\n", __func__, phydev->addr, regnum, val);
152 phy_write(phydev, MDIO_DEVAD_NONE, ADIN1300_EXT_REG_PTR, regnum);
154 return phy_write(phydev, MDIO_DEVAD_NONE, ADIN1300_EXT_REG_DATA, val);
157 static int adin_extread(struct phy_device *phydev, int addr, int devaddr,
160 return adin_ext_read(phydev, regnum);
163 static int adin_extwrite(struct phy_device *phydev, int addr,
164 int devaddr, int regnum, u16 val)
166 return adin_ext_write(phydev, regnum, val);
169 static int adin_config_clk_out(struct phy_device *phydev)
171 ofnode node = phy_get_ofnode(phydev);
172 const char *val = NULL;
175 val = ofnode_read_string(node, "adi,phy-output-clock");
177 /* property not present, do not enable GP_CLK pin */
178 } else if (strcmp(val, "25mhz-reference") == 0) {
179 sel |= ADIN1300_GE_CLK_CFG_25;
180 } else if (strcmp(val, "125mhz-free-running") == 0) {
181 sel |= ADIN1300_GE_CLK_CFG_FREE_125;
182 } else if (strcmp(val, "adaptive-free-running") == 0) {
183 sel |= ADIN1300_GE_CLK_CFG_HRT_FREE;
185 pr_err("%s: invalid adi,phy-output-clock\n", __func__);
189 if (ofnode_read_bool(node, "adi,phy-output-reference-clock"))
190 sel |= ADIN1300_GE_CLK_CFG_REF_EN;
192 return adin_ext_write(phydev, ADIN1300_GE_CLK_CFG_REG,
193 ADIN1300_GE_CLK_CFG_MASK & sel);
196 static int adin_config_rgmii_mode(struct phy_device *phydev)
200 phy_interface_t phy_mode_override = adin_get_phy_mode_override(phydev);
202 if (phy_mode_override != PHY_INTERFACE_MODE_NA) {
203 phydev->interface = phy_mode_override;
206 reg_val = adin_ext_read(phydev, ADIN1300_GE_RGMII_CFG);
208 if (!phy_interface_is_rgmii(phydev)) {
210 reg_val &= ~ADIN1300_GE_RGMII_EN;
211 return adin_ext_write(phydev, ADIN1300_GE_RGMII_CFG, reg_val);
215 reg_val |= ADIN1300_GE_RGMII_EN;
217 /* Enable / Disable RGMII RX Delay */
218 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
219 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
220 reg_val |= ADIN1300_GE_RGMII_RXID_EN;
222 val = adin_get_reg_value(phydev, "adi,rx-internal-delay-ps",
224 ADIN1300_RGMII_2_00_NS);
225 reg_val &= ~ADIN1300_GE_RGMII_RX_MSK;
226 reg_val |= ADIN1300_GE_RGMII_RX_SEL(val);
228 reg_val &= ~ADIN1300_GE_RGMII_RXID_EN;
231 /* Enable / Disable RGMII RX Delay */
232 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
233 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
234 reg_val |= ADIN1300_GE_RGMII_TXID_EN;
236 val = adin_get_reg_value(phydev, "adi,tx-internal-delay-ps",
238 ADIN1300_RGMII_2_00_NS);
239 reg_val &= ~ADIN1300_GE_RGMII_GTX_MSK;
240 reg_val |= ADIN1300_GE_RGMII_GTX_SEL(val);
242 reg_val &= ~ADIN1300_GE_RGMII_TXID_EN;
245 return adin_ext_write(phydev, ADIN1300_GE_RGMII_CFG, reg_val);
248 static int adin1300_config(struct phy_device *phydev)
252 printf("ADIN1300 PHY detected at addr %d\n", phydev->addr);
254 ret = adin_config_clk_out(phydev);
258 ret = adin_config_rgmii_mode(phydev);
263 return genphy_config(phydev);
266 U_BOOT_PHY_DRIVER(ADIN1300) = {
268 .uid = PHY_ID_ADIN1300,
270 .features = PHY_GBIT_FEATURES,
271 .config = adin1300_config,
272 .startup = genphy_startup,
273 .shutdown = genphy_shutdown,
274 .readext = adin_extread,
275 .writeext = adin_extwrite,