Blame view
drivers/net/phy/realtek.c
18.3 KB
a2443fd1a net: phy: Convert... |
1 |
// SPDX-License-Identifier: GPL-2.0+ |
bbc4d71d6 net: phy: realtek... |
2 |
/* drivers/net/phy/realtek.c |
097c2aa89 phylib: Add Realt... |
3 4 5 6 7 8 |
* * Driver for Realtek PHYs * * Author: Johnson Leung <r58129@freescale.com> * * Copyright (c) 2004 Freescale Semiconductor, Inc. |
097c2aa89 phylib: Add Realt... |
9 |
*/ |
8cc5baefb net: phy: realtek... |
10 |
#include <linux/bitops.h> |
83430a4ff MLK-24295 net: ph... |
11 |
#include <linux/of.h> |
097c2aa89 phylib: Add Realt... |
12 |
#include <linux/phy.h> |
9d9779e72 drivers/net: Add ... |
13 |
#include <linux/module.h> |
fee698d62 net: phy: realtek... |
14 |
#include <linux/delay.h> |
097c2aa89 phylib: Add Realt... |
15 |
|
f609ab0ed net: phy: realtek... |
16 17 18 |
#define RTL821x_PHYSR 0x11 #define RTL821x_PHYSR_DUPLEX BIT(13) #define RTL821x_PHYSR_SPEED GENMASK(15, 14) |
a82f266d2 net: phy: realtek... |
19 |
|
f609ab0ed net: phy: realtek... |
20 21 22 23 |
#define RTL821x_INER 0x12 #define RTL8211B_INER_INIT 0x6400 #define RTL8211E_INER_LINK_STATUS BIT(10) #define RTL8211F_INER_LINK_STATUS BIT(4) |
a82f266d2 net: phy: realtek... |
24 |
|
f609ab0ed net: phy: realtek... |
25 |
#define RTL821x_INSR 0x13 |
a82f266d2 net: phy: realtek... |
26 |
|
f81dadbcf net: phy: realtek... |
27 |
#define RTL821x_EXT_PAGE_SELECT 0x1e |
f609ab0ed net: phy: realtek... |
28 |
#define RTL821x_PAGE_SELECT 0x1f |
097c2aa89 phylib: Add Realt... |
29 |
|
66e22932e net: phy: realtek... |
30 |
#define RTL8211F_PHYCR1 0x18 |
f609ab0ed net: phy: realtek... |
31 |
#define RTL8211F_INSR 0x1d |
ef3d90491 net: phy: realtek... |
32 |
|
f609ab0ed net: phy: realtek... |
33 |
#define RTL8211F_TX_DELAY BIT(8) |
1b3047b52 net: phy: realtek... |
34 |
#define RTL8211F_RX_DELAY BIT(3) |
66e22932e net: phy: realtek... |
35 36 37 |
#define RTL8211F_ALDPS_PLL_OFF BIT(1) #define RTL8211F_ALDPS_ENABLE BIT(2) #define RTL8211F_ALDPS_XTAL_OFF BIT(12) |
bbc4d71d6 net: phy: realtek... |
38 39 40 |
#define RTL8211E_CTRL_DELAY BIT(13) #define RTL8211E_TX_DELAY BIT(12) #define RTL8211E_RX_DELAY BIT(11) |
f609ab0ed net: phy: realtek... |
41 42 43 |
#define RTL8201F_ISR 0x1e #define RTL8201F_IER 0x13 |
513588dd4 net: phy: realtek... |
44 |
|
d85458256 net: phy: realtek... |
45 46 |
#define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) |
5181b473d net: phy: realtek... |
47 48 49 |
#define RTL_SUPPORTS_5000FULL BIT(14) #define RTL_SUPPORTS_2500FULL BIT(13) #define RTL_SUPPORTS_10000FULL BIT(0) |
087f5b875 net: phy: realtek... |
50 51 52 53 |
#define RTL_ADV_2500FULL BIT(7) #define RTL_LPADV_10000FULL BIT(11) #define RTL_LPADV_5000FULL BIT(6) #define RTL_LPADV_2500FULL BIT(5) |
d445dff2d net: phy: realtek... |
54 |
#define RTLGEN_SPEED_MASK 0x0630 |
5181b473d net: phy: realtek... |
55 |
#define RTL_GENERIC_PHYID 0x001cc800 |
83430a4ff MLK-24295 net: ph... |
56 57 58 59 60 |
/* page 0xa43, register 0x19 */ #define RTL8211F_PHYCR2 0x19 #define RTL8211F_CLKOUT_EN BIT(0) #define RTL821X_CLKOUT_EN_FEATURE (1 << 0) |
097c2aa89 phylib: Add Realt... |
61 62 63 |
MODULE_DESCRIPTION("Realtek PHY driver"); MODULE_AUTHOR("Johnson Leung"); MODULE_LICENSE("GPL"); |
83430a4ff MLK-24295 net: ph... |
64 65 66 |
struct rtl821x_priv { u32 quirks; }; |
d98c8ccde phy: realtek: use... |
67 |
static int rtl821x_read_page(struct phy_device *phydev) |
136819a6e net: phy: realtek... |
68 |
{ |
d98c8ccde phy: realtek: use... |
69 |
return __phy_read(phydev, RTL821x_PAGE_SELECT); |
136819a6e net: phy: realtek... |
70 |
} |
d98c8ccde phy: realtek: use... |
71 |
static int rtl821x_write_page(struct phy_device *phydev, int page) |
136819a6e net: phy: realtek... |
72 |
{ |
d98c8ccde phy: realtek: use... |
73 |
return __phy_write(phydev, RTL821x_PAGE_SELECT, page); |
136819a6e net: phy: realtek... |
74 |
} |
83430a4ff MLK-24295 net: ph... |
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
static int rtl821x_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; struct rtl821x_priv *priv; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; if (of_property_read_bool(dev->of_node, "rtl821x,clkout_en")) priv->quirks |= RTL821X_CLKOUT_EN_FEATURE; phydev->priv = priv; return 0; } |
513588dd4 net: phy: realtek... |
91 92 93 94 95 96 97 98 |
static int rtl8201_ack_interrupt(struct phy_device *phydev) { int err; err = phy_read(phydev, RTL8201F_ISR); return (err < 0) ? err : 0; } |
097c2aa89 phylib: Add Realt... |
99 100 101 102 103 104 105 106 |
static int rtl821x_ack_interrupt(struct phy_device *phydev) { int err; err = phy_read(phydev, RTL821x_INSR); return (err < 0) ? err : 0; } |
3447cf2e9 net/phy: Add supp... |
107 108 109 |
static int rtl8211f_ack_interrupt(struct phy_device *phydev) { int err; |
d98c8ccde phy: realtek: use... |
110 |
err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR); |
3447cf2e9 net/phy: Add supp... |
111 112 113 |
return (err < 0) ? err : 0; } |
513588dd4 net: phy: realtek... |
114 115 |
static int rtl8201_config_intr(struct phy_device *phydev) { |
136819a6e net: phy: realtek... |
116 |
u16 val; |
513588dd4 net: phy: realtek... |
117 118 |
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) |
136819a6e net: phy: realtek... |
119 |
val = BIT(13) | BIT(12) | BIT(11); |
513588dd4 net: phy: realtek... |
120 |
else |
136819a6e net: phy: realtek... |
121 |
val = 0; |
513588dd4 net: phy: realtek... |
122 |
|
d98c8ccde phy: realtek: use... |
123 |
return phy_write_paged(phydev, 0x7, RTL8201F_IER, val); |
513588dd4 net: phy: realtek... |
124 |
} |
ef3d90491 net: phy: realtek... |
125 |
static int rtl8211b_config_intr(struct phy_device *phydev) |
097c2aa89 phylib: Add Realt... |
126 127 128 129 130 |
{ int err; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_write(phydev, RTL821x_INER, |
69021e32e net: phy: realtek... |
131 |
RTL8211B_INER_INIT); |
097c2aa89 phylib: Add Realt... |
132 133 134 135 136 |
else err = phy_write(phydev, RTL821x_INER, 0); return err; } |
ef3d90491 net: phy: realtek... |
137 138 139 140 141 142 |
static int rtl8211e_config_intr(struct phy_device *phydev) { int err; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_write(phydev, RTL821x_INER, |
8b64fd614 net: phy: rtl8211... |
143 |
RTL8211E_INER_LINK_STATUS); |
ef3d90491 net: phy: realtek... |
144 145 146 147 148 |
else err = phy_write(phydev, RTL821x_INER, 0); return err; } |
3447cf2e9 net/phy: Add supp... |
149 150 |
static int rtl8211f_config_intr(struct phy_device *phydev) { |
136819a6e net: phy: realtek... |
151 |
u16 val; |
3447cf2e9 net/phy: Add supp... |
152 153 |
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) |
136819a6e net: phy: realtek... |
154 |
val = RTL8211F_INER_LINK_STATUS; |
3447cf2e9 net/phy: Add supp... |
155 |
else |
136819a6e net: phy: realtek... |
156 |
val = 0; |
3447cf2e9 net/phy: Add supp... |
157 |
|
d98c8ccde phy: realtek: use... |
158 |
return phy_write_paged(phydev, 0xa42, RTL821x_INER, val); |
3447cf2e9 net/phy: Add supp... |
159 |
} |
d241d4aac net: phy: realtek... |
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
static int rtl8211_config_aneg(struct phy_device *phydev) { int ret; ret = genphy_config_aneg(phydev); if (ret < 0) return ret; /* Quirk was copied from vendor driver. Unfortunately it includes no * description of the magic numbers. */ if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) { phy_write(phydev, 0x17, 0x2138); phy_write(phydev, 0x0e, 0x0260); } else { phy_write(phydev, 0x17, 0x2108); phy_write(phydev, 0x0e, 0x0000); } return 0; } |
cf87915cb net: phy: realtek... |
181 182 183 |
static int rtl8211c_config_init(struct phy_device *phydev) { /* RTL8211C has an issue when operating in Gigabit slave mode */ |
48e4adf9a net: phy: realtek... |
184 185 |
return phy_set_bits(phydev, MII_CTRL1000, CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); |
cf87915cb net: phy: realtek... |
186 |
} |
3447cf2e9 net/phy: Add supp... |
187 188 |
static int rtl8211f_config_init(struct phy_device *phydev) { |
3aec743d6 net: phy: realtek... |
189 |
struct device *dev = &phydev->mdio.dev; |
1b3047b52 net: phy: realtek... |
190 |
u16 val_txdly, val_rxdly; |
66e22932e net: phy: realtek... |
191 |
u16 val; |
3aec743d6 net: phy: realtek... |
192 |
int ret; |
83430a4ff MLK-24295 net: ph... |
193 |
struct rtl821x_priv *priv = phydev->priv; |
3447cf2e9 net/phy: Add supp... |
194 |
|
66e22932e net: phy: realtek... |
195 196 |
val = RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_XTAL_OFF; phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, val, val); |
1da7756e6 net: phy: realtek... |
197 198 |
switch (phydev->interface) { case PHY_INTERFACE_MODE_RGMII: |
1b3047b52 net: phy: realtek... |
199 200 201 |
val_txdly = 0; val_rxdly = 0; break; |
1da7756e6 net: phy: realtek... |
202 |
case PHY_INTERFACE_MODE_RGMII_RXID: |
1b3047b52 net: phy: realtek... |
203 204 |
val_txdly = 0; val_rxdly = RTL8211F_RX_DELAY; |
1da7756e6 net: phy: realtek... |
205 |
break; |
1b3047b52 net: phy: realtek... |
206 |
|
1da7756e6 net: phy: realtek... |
207 |
case PHY_INTERFACE_MODE_RGMII_TXID: |
1b3047b52 net: phy: realtek... |
208 209 210 211 212 213 214 |
val_txdly = RTL8211F_TX_DELAY; val_rxdly = 0; break; case PHY_INTERFACE_MODE_RGMII_ID: val_txdly = RTL8211F_TX_DELAY; val_rxdly = RTL8211F_RX_DELAY; |
1da7756e6 net: phy: realtek... |
215 |
break; |
1b3047b52 net: phy: realtek... |
216 |
|
1da7756e6 net: phy: realtek... |
217 218 219 |
default: /* the rest of the modes imply leaving delay as is. */ return 0; } |
3447cf2e9 net/phy: Add supp... |
220 |
|
c4aa46bd3 Make changes to h... |
221 222 223 224 |
/* Set green LED for Link, yellow LED for Active */ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd04); phy_write(phydev, 0x10, 0x617f); phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); |
3aec743d6 net: phy: realtek... |
225 |
ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, |
1b3047b52 net: phy: realtek... |
226 |
val_txdly); |
3aec743d6 net: phy: realtek... |
227 228 229 230 231 232 233 234 |
if (ret < 0) { dev_err(dev, "Failed to update the TX delay register "); return ret; } else if (ret) { dev_dbg(dev, "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader) ", |
1b3047b52 net: phy: realtek... |
235 |
val_txdly ? "Enabling" : "Disabling"); |
3aec743d6 net: phy: realtek... |
236 237 238 239 |
} else { dev_dbg(dev, "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration) ", |
1b3047b52 net: phy: realtek... |
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
val_txdly ? "enabled" : "disabled"); } ret = phy_modify_paged_changed(phydev, 0xd08, 0x15, RTL8211F_RX_DELAY, val_rxdly); if (ret < 0) { dev_err(dev, "Failed to update the RX delay register "); return ret; } else if (ret) { dev_dbg(dev, "%s 2ns RX delay (and changing the value from pin-strapping RXD0 or the bootloader) ", val_rxdly ? "Enabling" : "Disabling"); } else { dev_dbg(dev, "2ns RX delay was already %s (by pin-strapping RXD0 or bootloader configuration) ", val_rxdly ? "enabled" : "disabled"); |
3aec743d6 net: phy: realtek... |
259 |
} |
83430a4ff MLK-24295 net: ph... |
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
if (priv->quirks & RTL821X_CLKOUT_EN_FEATURE) { ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, RTL8211F_CLKOUT_EN); if (ret < 0) { dev_err(&phydev->mdio.dev, "clkout enable failed "); return ret; } } else { ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0); if (ret < 0) { dev_err(&phydev->mdio.dev, "clkout disable failed "); return ret; } } |
3aec743d6 net: phy: realtek... |
277 |
return 0; |
3447cf2e9 net/phy: Add supp... |
278 |
} |
f81dadbcf net: phy: realtek... |
279 280 281 282 283 284 285 286 |
static int rtl8211e_config_init(struct phy_device *phydev) { int ret = 0, oldpage; u16 val; /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */ switch (phydev->interface) { case PHY_INTERFACE_MODE_RGMII: |
bbc4d71d6 net: phy: realtek... |
287 |
val = RTL8211E_CTRL_DELAY | 0; |
f81dadbcf net: phy: realtek... |
288 289 |
break; case PHY_INTERFACE_MODE_RGMII_ID: |
bbc4d71d6 net: phy: realtek... |
290 |
val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY; |
f81dadbcf net: phy: realtek... |
291 292 |
break; case PHY_INTERFACE_MODE_RGMII_RXID: |
bbc4d71d6 net: phy: realtek... |
293 |
val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY; |
f81dadbcf net: phy: realtek... |
294 295 |
break; case PHY_INTERFACE_MODE_RGMII_TXID: |
bbc4d71d6 net: phy: realtek... |
296 |
val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY; |
f81dadbcf net: phy: realtek... |
297 298 299 300 301 302 303 |
break; default: /* the rest of the modes imply leaving delays as is. */ return 0; } /* According to a sample driver there is a 0x1c config register on the * 0xa4 extension page (0x7) layout. It can be used to disable/enable |
bbc4d71d6 net: phy: realtek... |
304 305 306 307 308 309 |
* the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. * The configuration register definition: * 14 = reserved * 13 = Force Tx RX Delay controlled by bit12 bit11, * 12 = RX Delay, 11 = TX Delay * 10:0 = Test && debug settings reserved by realtek |
f81dadbcf net: phy: realtek... |
310 311 312 313 |
*/ oldpage = phy_select_page(phydev, 0x7); if (oldpage < 0) goto err_restore_page; |
dffe7d2e0 net: phy: realtek... |
314 |
ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4); |
f81dadbcf net: phy: realtek... |
315 316 |
if (ret) goto err_restore_page; |
bbc4d71d6 net: phy: realtek... |
317 318 |
ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY, |
dffe7d2e0 net: phy: realtek... |
319 |
val); |
f81dadbcf net: phy: realtek... |
320 321 322 323 |
err_restore_page: return phy_restore_page(phydev, oldpage, ret); } |
049ff57a2 net: phy: realtek... |
324 325 326 327 328 329 330 331 332 333 334 335 336 |
static int rtl8211b_suspend(struct phy_device *phydev) { phy_write(phydev, MII_MMD_DATA, BIT(9)); return genphy_suspend(phydev); } static int rtl8211b_resume(struct phy_device *phydev) { phy_write(phydev, MII_MMD_DATA, 0); return genphy_resume(phydev); } |
d85458256 net: phy: realtek... |
337 338 339 |
static int rtl8366rb_config_init(struct phy_device *phydev) { int ret; |
d85458256 net: phy: realtek... |
340 341 342 343 344 345 346 347 348 349 |
ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE, RTL8366RB_POWER_SAVE_ON); if (ret) { dev_err(&phydev->mdio.dev, "error enabling power management "); } return ret; } |
d445dff2d net: phy: realtek... |
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
/* get actual speed to cover the downshift case */ static int rtlgen_get_speed(struct phy_device *phydev) { int val; if (!phydev->link) return 0; val = phy_read_paged(phydev, 0xa43, 0x12); if (val < 0) return val; switch (val & RTLGEN_SPEED_MASK) { case 0x0000: phydev->speed = SPEED_10; break; case 0x0010: phydev->speed = SPEED_100; break; case 0x0020: phydev->speed = SPEED_1000; break; case 0x0200: phydev->speed = SPEED_10000; break; case 0x0210: phydev->speed = SPEED_2500; break; case 0x0220: phydev->speed = SPEED_5000; break; default: break; } return 0; } static int rtlgen_read_status(struct phy_device *phydev) { int ret; ret = genphy_read_status(phydev); if (ret < 0) return ret; return rtlgen_get_speed(phydev); } |
5b3f13950 net: phy: realtek... |
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) { int ret; if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) { rtl821x_write_page(phydev, 0xa5c); ret = __phy_read(phydev, 0x12); rtl821x_write_page(phydev, 0); } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { rtl821x_write_page(phydev, 0xa5d); ret = __phy_read(phydev, 0x10); rtl821x_write_page(phydev, 0); } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) { rtl821x_write_page(phydev, 0xa5d); ret = __phy_read(phydev, 0x11); rtl821x_write_page(phydev, 0); } else { ret = -EOPNOTSUPP; } return ret; } static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, u16 val) { int ret; if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { rtl821x_write_page(phydev, 0xa5d); ret = __phy_write(phydev, 0x10, val); rtl821x_write_page(phydev, 0); } else { ret = -EOPNOTSUPP; } return ret; } |
7a333af6b net: phy: realtek... |
436 |
static int rtl822x_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) |
edde25e55 net: phy: realtek... |
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 |
{ int ret = rtlgen_read_mmd(phydev, devnum, regnum); if (ret != -EOPNOTSUPP) return ret; if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) { rtl821x_write_page(phydev, 0xa6e); ret = __phy_read(phydev, 0x16); rtl821x_write_page(phydev, 0); } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { rtl821x_write_page(phydev, 0xa6d); ret = __phy_read(phydev, 0x12); rtl821x_write_page(phydev, 0); } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) { rtl821x_write_page(phydev, 0xa6d); ret = __phy_read(phydev, 0x10); rtl821x_write_page(phydev, 0); } return ret; } |
7a333af6b net: phy: realtek... |
459 |
static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, |
edde25e55 net: phy: realtek... |
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
u16 val) { int ret = rtlgen_write_mmd(phydev, devnum, regnum, val); if (ret != -EOPNOTSUPP) return ret; if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) { rtl821x_write_page(phydev, 0xa6d); ret = __phy_write(phydev, 0x12, val); rtl821x_write_page(phydev, 0); } return ret; } |
7a333af6b net: phy: realtek... |
475 |
static int rtl822x_get_features(struct phy_device *phydev) |
087f5b875 net: phy: realtek... |
476 |
{ |
5181b473d net: phy: realtek... |
477 478 479 480 481 482 483 484 485 486 487 488 |
int val; val = phy_read_paged(phydev, 0xa61, 0x13); if (val < 0) return val; linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported, val & RTL_SUPPORTS_2500FULL); linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, phydev->supported, val & RTL_SUPPORTS_5000FULL); linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, phydev->supported, val & RTL_SUPPORTS_10000FULL); |
087f5b875 net: phy: realtek... |
489 490 491 |
return genphy_read_abilities(phydev); } |
7a333af6b net: phy: realtek... |
492 |
static int rtl822x_config_aneg(struct phy_device *phydev) |
087f5b875 net: phy: realtek... |
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
{ int ret = 0; if (phydev->autoneg == AUTONEG_ENABLE) { u16 adv2500 = 0; if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising)) adv2500 = RTL_ADV_2500FULL; ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, RTL_ADV_2500FULL, adv2500); if (ret < 0) return ret; } return __genphy_config_aneg(phydev, ret); } |
7a333af6b net: phy: realtek... |
511 |
static int rtl822x_read_status(struct phy_device *phydev) |
087f5b875 net: phy: realtek... |
512 |
{ |
d445dff2d net: phy: realtek... |
513 |
int ret; |
087f5b875 net: phy: realtek... |
514 515 516 517 518 519 520 521 522 523 524 525 526 |
if (phydev->autoneg == AUTONEG_ENABLE) { int lpadv = phy_read_paged(phydev, 0xa5d, 0x13); if (lpadv < 0) return lpadv; linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL); linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL); linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL); } |
d445dff2d net: phy: realtek... |
527 528 529 530 531 |
ret = genphy_read_status(phydev); if (ret < 0) return ret; return rtlgen_get_speed(phydev); |
087f5b875 net: phy: realtek... |
532 |
} |
5181b473d net: phy: realtek... |
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 |
static bool rtlgen_supports_2_5gbps(struct phy_device *phydev) { int val; phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61); val = phy_read(phydev, 0x13); phy_write(phydev, RTL821x_PAGE_SELECT, 0); return val >= 0 && val & RTL_SUPPORTS_2500FULL; } static int rtlgen_match_phy_device(struct phy_device *phydev) { return phydev->phy_id == RTL_GENERIC_PHYID && !rtlgen_supports_2_5gbps(phydev); } |
7a333af6b net: phy: realtek... |
549 |
static int rtl8226_match_phy_device(struct phy_device *phydev) |
5181b473d net: phy: realtek... |
550 551 552 553 |
{ return phydev->phy_id == RTL_GENERIC_PHYID && rtlgen_supports_2_5gbps(phydev); } |
fee698d62 net: phy: realtek... |
554 555 556 557 558 559 560 561 562 |
static int rtlgen_resume(struct phy_device *phydev) { int ret = genphy_resume(phydev); /* Internal PHY's from RTL8168h up may not be instantly ready */ msleep(20); return ret; } |
71b9c4a83 net: phy: realtek... |
563 564 |
static struct phy_driver realtek_drvs[] = { { |
ca4949363 net: phy: realtek... |
565 |
PHY_ID_MATCH_EXACT(0x00008201), |
71b9c4a83 net: phy: realtek... |
566 |
.name = "RTL8201CP Ethernet", |
f3037c5a3 net: phy: realtek... |
567 568 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
71b9c4a83 net: phy: realtek... |
569 |
}, { |
ca4949363 net: phy: realtek... |
570 |
PHY_ID_MATCH_EXACT(0x001cc816), |
0432e8331 net: phy: realtek... |
571 |
.name = "RTL8201F Fast Ethernet", |
513588dd4 net: phy: realtek... |
572 573 574 575 |
.ack_interrupt = &rtl8201_ack_interrupt, .config_intr = &rtl8201_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, |
d98c8ccde phy: realtek: use... |
576 577 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
513588dd4 net: phy: realtek... |
578 |
}, { |
f3284e014 net: phy: realtek... |
579 580 581 582 583 584 585 586 587 |
PHY_ID_MATCH_MODEL(0x001cc880), .name = "RTL8208 Fast Ethernet", .read_mmd = genphy_read_mmd_unsupported, .write_mmd = genphy_write_mmd_unsupported, .suspend = genphy_suspend, .resume = genphy_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, }, { |
ca4949363 net: phy: realtek... |
588 |
PHY_ID_MATCH_EXACT(0x001cc910), |
d241d4aac net: phy: realtek... |
589 |
.name = "RTL8211 Gigabit Ethernet", |
d241d4aac net: phy: realtek... |
590 591 592 |
.config_aneg = rtl8211_config_aneg, .read_mmd = &genphy_read_mmd_unsupported, .write_mmd = &genphy_write_mmd_unsupported, |
daf3ddbe1 net: phy: realtek... |
593 594 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
d241d4aac net: phy: realtek... |
595 |
}, { |
ca4949363 net: phy: realtek... |
596 |
PHY_ID_MATCH_EXACT(0x001cc912), |
71b9c4a83 net: phy: realtek... |
597 |
.name = "RTL8211B Gigabit Ethernet", |
71b9c4a83 net: phy: realtek... |
598 599 |
.ack_interrupt = &rtl821x_ack_interrupt, .config_intr = &rtl8211b_config_intr, |
0231b1a07 net: phy: realtek... |
600 601 |
.read_mmd = &genphy_read_mmd_unsupported, .write_mmd = &genphy_write_mmd_unsupported, |
049ff57a2 net: phy: realtek... |
602 603 |
.suspend = rtl8211b_suspend, .resume = rtl8211b_resume, |
daf3ddbe1 net: phy: realtek... |
604 605 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
71b9c4a83 net: phy: realtek... |
606 |
}, { |
ca4949363 net: phy: realtek... |
607 |
PHY_ID_MATCH_EXACT(0x001cc913), |
cf87915cb net: phy: realtek... |
608 |
.name = "RTL8211C Gigabit Ethernet", |
cf87915cb net: phy: realtek... |
609 610 611 |
.config_init = rtl8211c_config_init, .read_mmd = &genphy_read_mmd_unsupported, .write_mmd = &genphy_write_mmd_unsupported, |
daf3ddbe1 net: phy: realtek... |
612 613 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
cf87915cb net: phy: realtek... |
614 |
}, { |
ca4949363 net: phy: realtek... |
615 |
PHY_ID_MATCH_EXACT(0x001cc914), |
0024f8920 net: phy: add Rea... |
616 |
.name = "RTL8211DN Gigabit Ethernet", |
0024f8920 net: phy: add Rea... |
617 618 619 620 |
.ack_interrupt = rtl821x_ack_interrupt, .config_intr = rtl8211e_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, |
daf3ddbe1 net: phy: realtek... |
621 622 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
0024f8920 net: phy: add Rea... |
623 |
}, { |
ca4949363 net: phy: realtek... |
624 |
PHY_ID_MATCH_EXACT(0x001cc915), |
71b9c4a83 net: phy: realtek... |
625 |
.name = "RTL8211E Gigabit Ethernet", |
f81dadbcf net: phy: realtek... |
626 |
.config_init = &rtl8211e_config_init, |
71b9c4a83 net: phy: realtek... |
627 628 629 630 |
.ack_interrupt = &rtl821x_ack_interrupt, .config_intr = &rtl8211e_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, |
daf3ddbe1 net: phy: realtek... |
631 632 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
3447cf2e9 net/phy: Add supp... |
633 |
}, { |
ca4949363 net: phy: realtek... |
634 |
PHY_ID_MATCH_EXACT(0x001cc916), |
3447cf2e9 net/phy: Add supp... |
635 |
.name = "RTL8211F Gigabit Ethernet", |
83430a4ff MLK-24295 net: ph... |
636 |
.probe = rtl821x_probe, |
3447cf2e9 net/phy: Add supp... |
637 |
.config_init = &rtl8211f_config_init, |
3447cf2e9 net/phy: Add supp... |
638 639 640 641 |
.ack_interrupt = &rtl8211f_ack_interrupt, .config_intr = &rtl8211f_config_intr, .suspend = genphy_suspend, .resume = genphy_resume, |
d98c8ccde phy: realtek: use... |
642 643 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
d85458256 net: phy: realtek... |
644 |
}, { |
5181b473d net: phy: realtek... |
645 646 |
.name = "Generic FE-GE Realtek PHY", .match_phy_device = rtlgen_match_phy_device, |
d445dff2d net: phy: realtek... |
647 |
.read_status = rtlgen_read_status, |
f66ebd14a net: phy: realtek... |
648 |
.suspend = genphy_suspend, |
fee698d62 net: phy: realtek... |
649 |
.resume = rtlgen_resume, |
f66ebd14a net: phy: realtek... |
650 651 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
5b3f13950 net: phy: realtek... |
652 653 |
.read_mmd = rtlgen_read_mmd, .write_mmd = rtlgen_write_mmd, |
f66ebd14a net: phy: realtek... |
654 |
}, { |
7a333af6b net: phy: realtek... |
655 656 657 658 659 |
.name = "RTL8226 2.5Gbps PHY", .match_phy_device = rtl8226_match_phy_device, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .read_status = rtl822x_read_status, |
087f5b875 net: phy: realtek... |
660 |
.suspend = genphy_suspend, |
fee698d62 net: phy: realtek... |
661 |
.resume = rtlgen_resume, |
087f5b875 net: phy: realtek... |
662 663 |
.read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
7a333af6b net: phy: realtek... |
664 665 |
.read_mmd = rtl822x_read_mmd, .write_mmd = rtl822x_write_mmd, |
087f5b875 net: phy: realtek... |
666 |
}, { |
b3ba9ae8d net: phy: realtek... |
667 |
PHY_ID_MATCH_EXACT(0x001cc840), |
7a333af6b net: phy: realtek... |
668 669 670 671 |
.name = "RTL8226B_RTL8221B 2.5Gbps PHY", .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .read_status = rtl822x_read_status, |
b3ba9ae8d net: phy: realtek... |
672 673 674 675 |
.suspend = genphy_suspend, .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, |
7a333af6b net: phy: realtek... |
676 677 |
.read_mmd = rtl822x_read_mmd, .write_mmd = rtl822x_write_mmd, |
b3ba9ae8d net: phy: realtek... |
678 |
}, { |
ca4949363 net: phy: realtek... |
679 |
PHY_ID_MATCH_EXACT(0x001cc961), |
d85458256 net: phy: realtek... |
680 |
.name = "RTL8366RB Gigabit Ethernet", |
d85458256 net: phy: realtek... |
681 |
.config_init = &rtl8366rb_config_init, |
4c8e0459b net: phy: realtek... |
682 683 684 685 686 687 688 |
/* These interrupts are handled by the irq controller * embedded inside the RTL8366RB, they get unmasked when the * irq is requested and ACKed by reading the status register, * which is done by the irqchip code. */ .ack_interrupt = genphy_no_ack_interrupt, .config_intr = genphy_no_config_intr, |
d85458256 net: phy: realtek... |
689 690 |
.suspend = genphy_suspend, .resume = genphy_resume, |
71b9c4a83 net: phy: realtek... |
691 |
}, |
097c2aa89 phylib: Add Realt... |
692 |
}; |
50fd71507 net: phy: replace... |
693 |
module_phy_driver(realtek_drvs); |
4e4f10f64 phylib: Add modul... |
694 |
|
3b73e842c net: phy: realtek... |
695 |
static const struct mdio_device_id __maybe_unused realtek_tbl[] = { |
ca4949363 net: phy: realtek... |
696 |
{ PHY_ID_MATCH_VENDOR(0x001cc800) }, |
4e4f10f64 phylib: Add modul... |
697 698 699 700 |
{ } }; MODULE_DEVICE_TABLE(mdio, realtek_tbl); |