1*d90265e7SArtem Shimko // SPDX-License-Identifier: GPL-2.0
2*d90265e7SArtem Shimko /*
3*d90265e7SArtem Shimko * Driver for the DAPU Telecom DAP8211R(I) Gigabit Ethernet PHY.
4*d90265e7SArtem Shimko *
5*d90265e7SArtem Shimko * Specifications:
6*d90265e7SArtem Shimko * - IEEE 802.3 10BASE-Te, 100BASE-TX, 1000BASE-T
7*d90265e7SArtem Shimko * - IEEE 802.3az-2010 Energy Efficient Ethernet
8*d90265e7SArtem Shimko * - IEEE 1588 SyncE support
9*d90265e7SArtem Shimko * - RGMII
10*d90265e7SArtem Shimko *
11*d90265e7SArtem Shimko * Author: Artem Shimko <a.shimko.dev@gmail.com>
12*d90265e7SArtem Shimko */
13*d90265e7SArtem Shimko
14*d90265e7SArtem Shimko #include <linux/bitfield.h>
15*d90265e7SArtem Shimko #include <linux/errno.h>
16*d90265e7SArtem Shimko #include <linux/ethtool.h>
17*d90265e7SArtem Shimko #include <linux/kernel.h>
18*d90265e7SArtem Shimko #include <linux/iopoll.h>
19*d90265e7SArtem Shimko #include <linux/mii.h>
20*d90265e7SArtem Shimko #include <linux/module.h>
21*d90265e7SArtem Shimko #include <linux/netdevice.h>
22*d90265e7SArtem Shimko #include <linux/phy.h>
23*d90265e7SArtem Shimko
24*d90265e7SArtem Shimko #define DAP8211R_PHY_ID 0x0008011B
25*d90265e7SArtem Shimko #define DAP8211R_PHY_ID_MASK 0xFFFFFFFF
26*d90265e7SArtem Shimko
27*d90265e7SArtem Shimko #define DAP8211R_EXT_ADD 0x1E
28*d90265e7SArtem Shimko #define DAP8211R_EXT_DATA 0x1F
29*d90265e7SArtem Shimko
30*d90265e7SArtem Shimko #define DAP8211R_PHY_CON 0xA001
31*d90265e7SArtem Shimko #define DAP8211R_PHY_SW_RST BIT(15)
32*d90265e7SArtem Shimko
33*d90265e7SArtem Shimko #define DAP8211R_RGMII_CON 0xA003
34*d90265e7SArtem Shimko #define DAP8211R_RGMII_TX_DEL_MASK GENMASK(3, 0)
35*d90265e7SArtem Shimko #define DAP8211R_RGMII_RX_DEL_MASK GENMASK(13, 10)
36*d90265e7SArtem Shimko
37*d90265e7SArtem Shimko #define DAP8211R_RGMII_CONFIG_MASK (DAP8211R_RGMII_RX_DEL_MASK | DAP8211R_RGMII_TX_DEL_MASK)
38*d90265e7SArtem Shimko
39*d90265e7SArtem Shimko /*
40*d90265e7SArtem Shimko * Hardware reset RX RGMII default delay from the datasheet: 0 * 150ps == 0.00ns
41*d90265e7SArtem Shimko * Used when rx-internal-delay-ps is not specified in DT for RGMII mode and
42*d90265e7SArtem Shimko * in RGMII_TXID to set rx delay.
43*d90265e7SArtem Shimko */
44*d90265e7SArtem Shimko #define DAP8211R_INITIAL_RX_DEL_VAL 0
45*d90265e7SArtem Shimko
46*d90265e7SArtem Shimko /*
47*d90265e7SArtem Shimko * Hardware reset TX RGMII default delay from the datasheet: 1 * 150ps == 0.15ns
48*d90265e7SArtem Shimko * Used when tx-internal-delay-ps is not specified in DT for RGMII mode and
49*d90265e7SArtem Shimko * in RGMII_RXID to set tx delay.
50*d90265e7SArtem Shimko */
51*d90265e7SArtem Shimko #define DAP8211R_INITIAL_TX_DEL_VAL 1
52*d90265e7SArtem Shimko
53*d90265e7SArtem Shimko /*
54*d90265e7SArtem Shimko * Default RGMII delay: 13 * 150 == 1.95ns
55*d90265e7SArtem Shimko * Used when rx-internal-delay-ps or tx-internal-delay-ps are not specified in DT
56*d90265e7SArtem Shimko * for RGMII ID modes to set tx or rx delay.
57*d90265e7SArtem Shimko */
58*d90265e7SArtem Shimko #define DAP8211R_DEFAULT_DEL_SEL 0xD
59*d90265e7SArtem Shimko
60*d90265e7SArtem Shimko static const int dap8211r_internal_delay[] = {0, 150, 300, 450, 600, 750, 900,
61*d90265e7SArtem Shimko 1050, 1200, 1350, 1500, 1650, 1800,
62*d90265e7SArtem Shimko 1950, 2100, 2250};
63*d90265e7SArtem Shimko
64*d90265e7SArtem Shimko #define DAP8211R_DELAY_SIZE ARRAY_SIZE(dap8211r_internal_delay)
65*d90265e7SArtem Shimko
66*d90265e7SArtem Shimko /**
67*d90265e7SArtem Shimko * dap8211r_read_ext() - Read extended register
68*d90265e7SArtem Shimko * @phydev: PHY device structure
69*d90265e7SArtem Shimko * @reg: Extended register address
70*d90265e7SArtem Shimko *
71*d90265e7SArtem Shimko * Reads a PHY extended register using the indirect access method.
72*d90265e7SArtem Shimko * The caller must hold the MDIO bus lock.
73*d90265e7SArtem Shimko *
74*d90265e7SArtem Shimko * Return: Register value on success, or negative error code
75*d90265e7SArtem Shimko */
dap8211r_read_ext(struct phy_device * phydev,u16 reg)76*d90265e7SArtem Shimko static int dap8211r_read_ext(struct phy_device *phydev, u16 reg)
77*d90265e7SArtem Shimko {
78*d90265e7SArtem Shimko int ret;
79*d90265e7SArtem Shimko
80*d90265e7SArtem Shimko phy_lock_mdio_bus(phydev);
81*d90265e7SArtem Shimko ret = __phy_write(phydev, DAP8211R_EXT_ADD, reg);
82*d90265e7SArtem Shimko if (ret < 0)
83*d90265e7SArtem Shimko goto out;
84*d90265e7SArtem Shimko
85*d90265e7SArtem Shimko ret = __phy_read(phydev, DAP8211R_EXT_DATA);
86*d90265e7SArtem Shimko out:
87*d90265e7SArtem Shimko phy_unlock_mdio_bus(phydev);
88*d90265e7SArtem Shimko return ret;
89*d90265e7SArtem Shimko }
90*d90265e7SArtem Shimko
91*d90265e7SArtem Shimko /**
92*d90265e7SArtem Shimko * dap8211r_modify_ext() - Modify extended register bits
93*d90265e7SArtem Shimko * @phydev: PHY device structure
94*d90265e7SArtem Shimko * @reg: Extended register address
95*d90265e7SArtem Shimko * @mask: Bit mask of bits to clear
96*d90265e7SArtem Shimko * @set: Bit mask of bits to set
97*d90265e7SArtem Shimko *
98*d90265e7SArtem Shimko * Modifies a PHY extended register using the indirect access method.
99*d90265e7SArtem Shimko * New value = (old value & ~mask) | set.
100*d90265e7SArtem Shimko * The caller must hold the MDIO bus lock.
101*d90265e7SArtem Shimko *
102*d90265e7SArtem Shimko * Return: 0 on success, or negative error code
103*d90265e7SArtem Shimko */
dap8211r_modify_ext(struct phy_device * phydev,u16 reg,u16 mask,u16 set)104*d90265e7SArtem Shimko static int dap8211r_modify_ext(struct phy_device *phydev, u16 reg, u16 mask, u16 set)
105*d90265e7SArtem Shimko {
106*d90265e7SArtem Shimko int ret;
107*d90265e7SArtem Shimko
108*d90265e7SArtem Shimko phy_lock_mdio_bus(phydev);
109*d90265e7SArtem Shimko ret = __phy_write(phydev, DAP8211R_EXT_ADD, reg);
110*d90265e7SArtem Shimko if (ret < 0)
111*d90265e7SArtem Shimko goto out;
112*d90265e7SArtem Shimko
113*d90265e7SArtem Shimko ret = __phy_modify(phydev, DAP8211R_EXT_DATA, mask, set);
114*d90265e7SArtem Shimko out:
115*d90265e7SArtem Shimko phy_unlock_mdio_bus(phydev);
116*d90265e7SArtem Shimko return ret;
117*d90265e7SArtem Shimko }
118*d90265e7SArtem Shimko
119*d90265e7SArtem Shimko /**
120*d90265e7SArtem Shimko * dap8211r_config_init() - Initialize PHY
121*d90265e7SArtem Shimko * @phydev: PHY device structure
122*d90265e7SArtem Shimko *
123*d90265e7SArtem Shimko * Configures the PHY during initialization:
124*d90265e7SArtem Shimko * - RGMII delays based on interface mode
125*d90265e7SArtem Shimko * - Software reset to apply settings (low active, self clear)
126*d90265e7SArtem Shimko *
127*d90265e7SArtem Shimko * Return: 0 on success, or negative error code
128*d90265e7SArtem Shimko */
dap8211r_config_init(struct phy_device * phydev)129*d90265e7SArtem Shimko static int dap8211r_config_init(struct phy_device *phydev)
130*d90265e7SArtem Shimko {
131*d90265e7SArtem Shimko u16 set = 0;
132*d90265e7SArtem Shimko int ret, val;
133*d90265e7SArtem Shimko s32 rx_internal_delay = DAP8211R_INITIAL_RX_DEL_VAL;
134*d90265e7SArtem Shimko s32 tx_internal_delay = DAP8211R_INITIAL_TX_DEL_VAL;
135*d90265e7SArtem Shimko
136*d90265e7SArtem Shimko if (!phy_interface_is_rgmii(phydev))
137*d90265e7SArtem Shimko return 0;
138*d90265e7SArtem Shimko
139*d90265e7SArtem Shimko if (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)
140*d90265e7SArtem Shimko rx_internal_delay = phy_get_internal_delay(phydev, dap8211r_internal_delay,
141*d90265e7SArtem Shimko DAP8211R_DELAY_SIZE, true);
142*d90265e7SArtem Shimko
143*d90265e7SArtem Shimko if (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)
144*d90265e7SArtem Shimko tx_internal_delay = phy_get_internal_delay(phydev, dap8211r_internal_delay,
145*d90265e7SArtem Shimko DAP8211R_DELAY_SIZE, false);
146*d90265e7SArtem Shimko
147*d90265e7SArtem Shimko switch (phydev->interface) {
148*d90265e7SArtem Shimko case PHY_INTERFACE_MODE_RGMII:
149*d90265e7SArtem Shimko if (rx_internal_delay < 0)
150*d90265e7SArtem Shimko rx_internal_delay = DAP8211R_INITIAL_RX_DEL_VAL;
151*d90265e7SArtem Shimko
152*d90265e7SArtem Shimko if (tx_internal_delay < 0)
153*d90265e7SArtem Shimko tx_internal_delay = DAP8211R_INITIAL_TX_DEL_VAL;
154*d90265e7SArtem Shimko break;
155*d90265e7SArtem Shimko case PHY_INTERFACE_MODE_RGMII_RXID:
156*d90265e7SArtem Shimko if (rx_internal_delay < 0)
157*d90265e7SArtem Shimko rx_internal_delay = DAP8211R_DEFAULT_DEL_SEL;
158*d90265e7SArtem Shimko break;
159*d90265e7SArtem Shimko case PHY_INTERFACE_MODE_RGMII_ID:
160*d90265e7SArtem Shimko if (rx_internal_delay < 0)
161*d90265e7SArtem Shimko rx_internal_delay = DAP8211R_DEFAULT_DEL_SEL;
162*d90265e7SArtem Shimko fallthrough;
163*d90265e7SArtem Shimko case PHY_INTERFACE_MODE_RGMII_TXID:
164*d90265e7SArtem Shimko if (tx_internal_delay < 0)
165*d90265e7SArtem Shimko tx_internal_delay = DAP8211R_DEFAULT_DEL_SEL;
166*d90265e7SArtem Shimko break;
167*d90265e7SArtem Shimko default:
168*d90265e7SArtem Shimko phydev_err(phydev, "Unsupported interface: %d\n",
169*d90265e7SArtem Shimko phydev->interface);
170*d90265e7SArtem Shimko return -EINVAL;
171*d90265e7SArtem Shimko }
172*d90265e7SArtem Shimko
173*d90265e7SArtem Shimko set |= FIELD_PREP(DAP8211R_RGMII_RX_DEL_MASK, rx_internal_delay);
174*d90265e7SArtem Shimko set |= FIELD_PREP(DAP8211R_RGMII_TX_DEL_MASK, tx_internal_delay);
175*d90265e7SArtem Shimko
176*d90265e7SArtem Shimko ret = dap8211r_modify_ext(phydev, DAP8211R_PHY_CON, DAP8211R_PHY_SW_RST, 0);
177*d90265e7SArtem Shimko if (ret)
178*d90265e7SArtem Shimko return ret;
179*d90265e7SArtem Shimko
180*d90265e7SArtem Shimko /* Wait for reset self-clear (from low active to high) */
181*d90265e7SArtem Shimko ret = read_poll_timeout(dap8211r_read_ext, val,
182*d90265e7SArtem Shimko (val & DAP8211R_PHY_SW_RST),
183*d90265e7SArtem Shimko 20, 200, false, phydev, DAP8211R_PHY_CON);
184*d90265e7SArtem Shimko if (ret)
185*d90265e7SArtem Shimko return ret;
186*d90265e7SArtem Shimko if (val < 0)
187*d90265e7SArtem Shimko return val;
188*d90265e7SArtem Shimko
189*d90265e7SArtem Shimko ret = dap8211r_modify_ext(phydev, DAP8211R_RGMII_CON, DAP8211R_RGMII_CONFIG_MASK, set);
190*d90265e7SArtem Shimko if (ret)
191*d90265e7SArtem Shimko return ret;
192*d90265e7SArtem Shimko
193*d90265e7SArtem Shimko return 0;
194*d90265e7SArtem Shimko }
195*d90265e7SArtem Shimko
196*d90265e7SArtem Shimko static struct phy_driver dap8211r_driver[] = {
197*d90265e7SArtem Shimko {
198*d90265e7SArtem Shimko PHY_ID_MATCH_EXACT(DAP8211R_PHY_ID),
199*d90265e7SArtem Shimko .name = "DAP8211R Gigabit Ethernet",
200*d90265e7SArtem Shimko .soft_reset = genphy_soft_reset,
201*d90265e7SArtem Shimko .config_init = dap8211r_config_init,
202*d90265e7SArtem Shimko .read_status = genphy_read_status,
203*d90265e7SArtem Shimko .set_loopback = genphy_loopback,
204*d90265e7SArtem Shimko .config_aneg = genphy_config_aneg,
205*d90265e7SArtem Shimko .suspend = genphy_suspend,
206*d90265e7SArtem Shimko .resume = genphy_resume,
207*d90265e7SArtem Shimko },
208*d90265e7SArtem Shimko };
209*d90265e7SArtem Shimko module_phy_driver(dap8211r_driver);
210*d90265e7SArtem Shimko
211*d90265e7SArtem Shimko MODULE_DESCRIPTION("DAP8211R Gigabit Ethernet PHY driver");
212*d90265e7SArtem Shimko MODULE_AUTHOR("Artem Shimko <a.shimko.dev@gmail.com>");
213*d90265e7SArtem Shimko MODULE_LICENSE("GPL");
214*d90265e7SArtem Shimko
215*d90265e7SArtem Shimko static const struct mdio_device_id __maybe_unused dap8211r_tb[] = {
216*d90265e7SArtem Shimko { DAP8211R_PHY_ID, DAP8211R_PHY_ID_MASK },
217*d90265e7SArtem Shimko { /* sentinel */ }
218*d90265e7SArtem Shimko };
219*d90265e7SArtem Shimko MODULE_DEVICE_TABLE(mdio, dap8211r_tb);
220*d90265e7SArtem Shimko
221