xref: /openbmc/linux/drivers/net/phy/realtek.c (revision 3557b3fd)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * drivers/net/phy/realtek.c
4  *
5  * Driver for Realtek PHYs
6  *
7  * Author: Johnson Leung <r58129@freescale.com>
8  *
9  * Copyright (c) 2004 Freescale Semiconductor, Inc.
10  */
11 #include <linux/bitops.h>
12 #include <linux/phy.h>
13 #include <linux/module.h>
14 
15 #define RTL821x_PHYSR				0x11
16 #define RTL821x_PHYSR_DUPLEX			BIT(13)
17 #define RTL821x_PHYSR_SPEED			GENMASK(15, 14)
18 
19 #define RTL821x_INER				0x12
20 #define RTL8211B_INER_INIT			0x6400
21 #define RTL8211E_INER_LINK_STATUS		BIT(10)
22 #define RTL8211F_INER_LINK_STATUS		BIT(4)
23 
24 #define RTL821x_INSR				0x13
25 
26 #define RTL821x_PAGE_SELECT			0x1f
27 
28 #define RTL8211F_INSR				0x1d
29 
30 #define RTL8211F_TX_DELAY			BIT(8)
31 
32 #define RTL8201F_ISR				0x1e
33 #define RTL8201F_IER				0x13
34 
35 #define RTL8366RB_POWER_SAVE			0x15
36 #define RTL8366RB_POWER_SAVE_ON			BIT(12)
37 
38 MODULE_DESCRIPTION("Realtek PHY driver");
39 MODULE_AUTHOR("Johnson Leung");
40 MODULE_LICENSE("GPL");
41 
42 static int rtl821x_read_page(struct phy_device *phydev)
43 {
44 	return __phy_read(phydev, RTL821x_PAGE_SELECT);
45 }
46 
47 static int rtl821x_write_page(struct phy_device *phydev, int page)
48 {
49 	return __phy_write(phydev, RTL821x_PAGE_SELECT, page);
50 }
51 
52 static int rtl8201_ack_interrupt(struct phy_device *phydev)
53 {
54 	int err;
55 
56 	err = phy_read(phydev, RTL8201F_ISR);
57 
58 	return (err < 0) ? err : 0;
59 }
60 
61 static int rtl821x_ack_interrupt(struct phy_device *phydev)
62 {
63 	int err;
64 
65 	err = phy_read(phydev, RTL821x_INSR);
66 
67 	return (err < 0) ? err : 0;
68 }
69 
70 static int rtl8211f_ack_interrupt(struct phy_device *phydev)
71 {
72 	int err;
73 
74 	err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR);
75 
76 	return (err < 0) ? err : 0;
77 }
78 
79 static int rtl8201_config_intr(struct phy_device *phydev)
80 {
81 	u16 val;
82 
83 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
84 		val = BIT(13) | BIT(12) | BIT(11);
85 	else
86 		val = 0;
87 
88 	return phy_write_paged(phydev, 0x7, RTL8201F_IER, val);
89 }
90 
91 static int rtl8211b_config_intr(struct phy_device *phydev)
92 {
93 	int err;
94 
95 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
96 		err = phy_write(phydev, RTL821x_INER,
97 				RTL8211B_INER_INIT);
98 	else
99 		err = phy_write(phydev, RTL821x_INER, 0);
100 
101 	return err;
102 }
103 
104 static int rtl8211e_config_intr(struct phy_device *phydev)
105 {
106 	int err;
107 
108 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
109 		err = phy_write(phydev, RTL821x_INER,
110 				RTL8211E_INER_LINK_STATUS);
111 	else
112 		err = phy_write(phydev, RTL821x_INER, 0);
113 
114 	return err;
115 }
116 
117 static int rtl8211f_config_intr(struct phy_device *phydev)
118 {
119 	u16 val;
120 
121 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
122 		val = RTL8211F_INER_LINK_STATUS;
123 	else
124 		val = 0;
125 
126 	return phy_write_paged(phydev, 0xa42, RTL821x_INER, val);
127 }
128 
129 static int rtl8211_config_aneg(struct phy_device *phydev)
130 {
131 	int ret;
132 
133 	ret = genphy_config_aneg(phydev);
134 	if (ret < 0)
135 		return ret;
136 
137 	/* Quirk was copied from vendor driver. Unfortunately it includes no
138 	 * description of the magic numbers.
139 	 */
140 	if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) {
141 		phy_write(phydev, 0x17, 0x2138);
142 		phy_write(phydev, 0x0e, 0x0260);
143 	} else {
144 		phy_write(phydev, 0x17, 0x2108);
145 		phy_write(phydev, 0x0e, 0x0000);
146 	}
147 
148 	return 0;
149 }
150 
151 static int rtl8211c_config_init(struct phy_device *phydev)
152 {
153 	/* RTL8211C has an issue when operating in Gigabit slave mode */
154 	return phy_set_bits(phydev, MII_CTRL1000,
155 			    CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER);
156 }
157 
158 static int rtl8211f_config_init(struct phy_device *phydev)
159 {
160 	u16 val = 0;
161 
162 	/* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */
163 	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
164 	    phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
165 		val = RTL8211F_TX_DELAY;
166 
167 	return phy_modify_paged(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, val);
168 }
169 
170 static int rtl8211b_suspend(struct phy_device *phydev)
171 {
172 	phy_write(phydev, MII_MMD_DATA, BIT(9));
173 
174 	return genphy_suspend(phydev);
175 }
176 
177 static int rtl8211b_resume(struct phy_device *phydev)
178 {
179 	phy_write(phydev, MII_MMD_DATA, 0);
180 
181 	return genphy_resume(phydev);
182 }
183 
184 static int rtl8366rb_config_init(struct phy_device *phydev)
185 {
186 	int ret;
187 
188 	ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE,
189 			   RTL8366RB_POWER_SAVE_ON);
190 	if (ret) {
191 		dev_err(&phydev->mdio.dev,
192 			"error enabling power management\n");
193 	}
194 
195 	return ret;
196 }
197 
198 static struct phy_driver realtek_drvs[] = {
199 	{
200 		PHY_ID_MATCH_EXACT(0x00008201),
201 		.name           = "RTL8201CP Ethernet",
202 	}, {
203 		PHY_ID_MATCH_EXACT(0x001cc816),
204 		.name		= "RTL8201F Fast Ethernet",
205 		.ack_interrupt	= &rtl8201_ack_interrupt,
206 		.config_intr	= &rtl8201_config_intr,
207 		.suspend	= genphy_suspend,
208 		.resume		= genphy_resume,
209 		.read_page	= rtl821x_read_page,
210 		.write_page	= rtl821x_write_page,
211 	}, {
212 		PHY_ID_MATCH_EXACT(0x001cc910),
213 		.name		= "RTL8211 Gigabit Ethernet",
214 		.config_aneg	= rtl8211_config_aneg,
215 		.read_mmd	= &genphy_read_mmd_unsupported,
216 		.write_mmd	= &genphy_write_mmd_unsupported,
217 	}, {
218 		PHY_ID_MATCH_EXACT(0x001cc912),
219 		.name		= "RTL8211B Gigabit Ethernet",
220 		.ack_interrupt	= &rtl821x_ack_interrupt,
221 		.config_intr	= &rtl8211b_config_intr,
222 		.read_mmd	= &genphy_read_mmd_unsupported,
223 		.write_mmd	= &genphy_write_mmd_unsupported,
224 		.suspend	= rtl8211b_suspend,
225 		.resume		= rtl8211b_resume,
226 	}, {
227 		PHY_ID_MATCH_EXACT(0x001cc913),
228 		.name		= "RTL8211C Gigabit Ethernet",
229 		.config_init	= rtl8211c_config_init,
230 		.read_mmd	= &genphy_read_mmd_unsupported,
231 		.write_mmd	= &genphy_write_mmd_unsupported,
232 	}, {
233 		PHY_ID_MATCH_EXACT(0x001cc914),
234 		.name		= "RTL8211DN Gigabit Ethernet",
235 		.ack_interrupt	= rtl821x_ack_interrupt,
236 		.config_intr	= rtl8211e_config_intr,
237 		.suspend	= genphy_suspend,
238 		.resume		= genphy_resume,
239 	}, {
240 		PHY_ID_MATCH_EXACT(0x001cc915),
241 		.name		= "RTL8211E Gigabit Ethernet",
242 		.ack_interrupt	= &rtl821x_ack_interrupt,
243 		.config_intr	= &rtl8211e_config_intr,
244 		.suspend	= genphy_suspend,
245 		.resume		= genphy_resume,
246 	}, {
247 		PHY_ID_MATCH_EXACT(0x001cc916),
248 		.name		= "RTL8211F Gigabit Ethernet",
249 		.config_init	= &rtl8211f_config_init,
250 		.ack_interrupt	= &rtl8211f_ack_interrupt,
251 		.config_intr	= &rtl8211f_config_intr,
252 		.suspend	= genphy_suspend,
253 		.resume		= genphy_resume,
254 		.read_page	= rtl821x_read_page,
255 		.write_page	= rtl821x_write_page,
256 	}, {
257 		PHY_ID_MATCH_EXACT(0x001cc800),
258 		.name		= "Generic Realtek PHY",
259 		.suspend	= genphy_suspend,
260 		.resume		= genphy_resume,
261 		.read_page	= rtl821x_read_page,
262 		.write_page	= rtl821x_write_page,
263 	}, {
264 		PHY_ID_MATCH_EXACT(0x001cc961),
265 		.name		= "RTL8366RB Gigabit Ethernet",
266 		.config_init	= &rtl8366rb_config_init,
267 		/* These interrupts are handled by the irq controller
268 		 * embedded inside the RTL8366RB, they get unmasked when the
269 		 * irq is requested and ACKed by reading the status register,
270 		 * which is done by the irqchip code.
271 		 */
272 		.ack_interrupt	= genphy_no_ack_interrupt,
273 		.config_intr	= genphy_no_config_intr,
274 		.suspend	= genphy_suspend,
275 		.resume		= genphy_resume,
276 	},
277 };
278 
279 module_phy_driver(realtek_drvs);
280 
281 static const struct mdio_device_id __maybe_unused realtek_tbl[] = {
282 	{ PHY_ID_MATCH_VENDOR(0x001cc800) },
283 	{ }
284 };
285 
286 MODULE_DEVICE_TABLE(mdio, realtek_tbl);
287