Merge branch 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel...
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / drivers / net / phy / broadcom.c
CommitLineData
c4b41c9f
MR
1/*
2 * drivers/net/phy/broadcom.c
3 *
4 * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
5 * transceivers.
6 *
7 * Copyright (c) 2006 Maciej W. Rozycki
8 *
9 * Inspired by code written by Amy Fong.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
a1cba561 17#include "bcm-phy-lib.h"
c4b41c9f
MR
18#include <linux/module.h>
19#include <linux/phy.h>
8649f13d 20#include <linux/brcmphy.h>
b14995ac 21#include <linux/of.h>
d9221e66
MC
22
23#define BRCM_PHY_MODEL(phydev) \
24 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
25
32e5a8d6
MC
26#define BRCM_PHY_REV(phydev) \
27 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
28
c4b41c9f
MR
29MODULE_DESCRIPTION("Broadcom PHY driver");
30MODULE_AUTHOR("Maciej W. Rozycki");
31MODULE_LICENSE("GPL");
32
b14995ac
JM
33static int bcm54810_config(struct phy_device *phydev)
34{
35 int rc, val;
36
37 val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
38 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
39 rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
40 val);
41 if (rc < 0)
42 return rc;
43
44 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
45 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
46 val |= MII_BCM54XX_AUXCTL_MISC_WREN;
47 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
48 val);
49 if (rc < 0)
50 return rc;
51
52 val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
53 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
54 rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
55 if (rc < 0)
56 return rc;
57
58 return 0;
59}
60
47b1b53b 61/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
772638b6
MC
62static int bcm50610_a0_workaround(struct phy_device *phydev)
63{
64 int err;
65
a1cba561 66 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,
772638b6
MC
67 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
68 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
69 if (err < 0)
47b1b53b 70 return err;
772638b6 71
a1cba561
AP
72 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,
73 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
772638b6 74 if (err < 0)
47b1b53b 75 return err;
772638b6 76
a1cba561 77 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,
772638b6
MC
78 MII_BCM54XX_EXP_EXP75_VDACCTRL);
79 if (err < 0)
47b1b53b 80 return err;
772638b6 81
a1cba561 82 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,
772638b6
MC
83 MII_BCM54XX_EXP_EXP96_MYST);
84 if (err < 0)
47b1b53b 85 return err;
772638b6 86
a1cba561 87 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,
772638b6
MC
88 MII_BCM54XX_EXP_EXP97_MYST);
89
47b1b53b
MC
90 return err;
91}
92
93static int bcm54xx_phydsp_config(struct phy_device *phydev)
94{
95 int err, err2;
96
97 /* Enable the SMDSP clock */
98 err = bcm54xx_auxctl_write(phydev,
99 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
100 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
101 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
102 if (err < 0)
103 return err;
104
219c6efe
MC
105 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
106 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
107 /* Clear bit 9 to fix a phy interop issue. */
a1cba561 108 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,
219c6efe
MC
109 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
110 if (err < 0)
111 goto error;
112
113 if (phydev->drv->phy_id == PHY_ID_BCM50610) {
114 err = bcm50610_a0_workaround(phydev);
115 if (err < 0)
116 goto error;
117 }
118 }
47b1b53b
MC
119
120 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
121 int val;
122
a1cba561 123 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);
47b1b53b
MC
124 if (val < 0)
125 goto error;
126
127 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
a1cba561 128 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);
47b1b53b
MC
129 }
130
772638b6 131error:
47b1b53b
MC
132 /* Disable the SMDSP clock */
133 err2 = bcm54xx_auxctl_write(phydev,
134 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
135 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
772638b6 136
47b1b53b
MC
137 /* Return the first error reported. */
138 return err ? err : err2;
772638b6
MC
139}
140
32e5a8d6
MC
141static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
142{
5ee6f6a1
RK
143 u32 orig;
144 int val;
c704dc23 145 bool clk125en = true;
32e5a8d6
MC
146
147 /* Abort if we are using an untested phy. */
7ec4e7d3 148 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
149 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
32e5a8d6
MC
150 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
151 return;
152
a1cba561 153 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
32e5a8d6
MC
154 if (val < 0)
155 return;
156
157 orig = val;
158
c704dc23
MC
159 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
160 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
161 BRCM_PHY_REV(phydev) >= 0x3) {
162 /*
163 * Here, bit 0 _disables_ CLK125 when set.
164 * This bit is set by default.
165 */
166 clk125en = false;
167 } else {
168 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
32e5a8d6
MC
169 /* Here, bit 0 _enables_ CLK125 when set */
170 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
c704dc23 171 clk125en = false;
32e5a8d6
MC
172 }
173 }
174
23677ce3 175 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
c704dc23
MC
176 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
177 else
178 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
179
52fae083
MC
180 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
181 val |= BCM54XX_SHD_SCR3_TRDDAPD;
182
32e5a8d6 183 if (orig != val)
a1cba561 184 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
c704dc23 185
a1cba561 186 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
c704dc23
MC
187 if (val < 0)
188 return;
189
190 orig = val;
191
23677ce3 192 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
c704dc23
MC
193 val |= BCM54XX_SHD_APD_EN;
194 else
195 val &= ~BCM54XX_SHD_APD_EN;
196
197 if (orig != val)
a1cba561 198 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
32e5a8d6
MC
199}
200
c4b41c9f
MR
201static int bcm54xx_config_init(struct phy_device *phydev)
202{
203 int reg, err;
204
205 reg = phy_read(phydev, MII_BCM54XX_ECR);
206 if (reg < 0)
207 return reg;
208
209 /* Mask interrupts globally. */
210 reg |= MII_BCM54XX_ECR_IM;
211 err = phy_write(phydev, MII_BCM54XX_ECR, reg);
212 if (err < 0)
213 return err;
214
215 /* Unmask events we are interested in. */
216 reg = ~(MII_BCM54XX_INT_DUPLEX |
217 MII_BCM54XX_INT_SPEED |
218 MII_BCM54XX_INT_LINK);
219 err = phy_write(phydev, MII_BCM54XX_IMR, reg);
220 if (err < 0)
221 return err;
772638b6 222
63a14ce4
MC
223 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
224 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
225 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
a1cba561 226 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);
63a14ce4 227
c704dc23 228 if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
52fae083 229 (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
c704dc23 230 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
32e5a8d6
MC
231 bcm54xx_adjust_rxrefclk(phydev);
232
b14995ac
JM
233 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
234 err = bcm54810_config(phydev);
235 if (err)
236 return err;
237 }
238
47b1b53b 239 bcm54xx_phydsp_config(phydev);
d9221e66 240
c4b41c9f
MR
241 return 0;
242}
243
cd9af3da
NC
244static int bcm5482_config_init(struct phy_device *phydev)
245{
246 int err, reg;
247
248 err = bcm54xx_config_init(phydev);
249
250 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
251 /*
252 * Enable secondary SerDes and its use as an LED source
253 */
a1cba561
AP
254 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD);
255 bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD,
cd9af3da
NC
256 reg |
257 BCM5482_SHD_SSD_LEDM |
258 BCM5482_SHD_SSD_EN);
259
260 /*
261 * Enable SGMII slave mode and auto-detection
262 */
042a75b9 263 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
a1cba561 264 err = bcm_phy_read_exp(phydev, reg);
042a75b9
MC
265 if (err < 0)
266 return err;
a1cba561 267 err = bcm_phy_write_exp(phydev, reg, err |
042a75b9
MC
268 BCM5482_SSD_SGMII_SLAVE_EN |
269 BCM5482_SSD_SGMII_SLAVE_AD);
270 if (err < 0)
271 return err;
cd9af3da
NC
272
273 /*
274 * Disable secondary SerDes powerdown
275 */
042a75b9 276 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
a1cba561 277 err = bcm_phy_read_exp(phydev, reg);
042a75b9
MC
278 if (err < 0)
279 return err;
a1cba561 280 err = bcm_phy_write_exp(phydev, reg,
042a75b9
MC
281 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
282 if (err < 0)
283 return err;
cd9af3da
NC
284
285 /*
286 * Select 1000BASE-X register set (primary SerDes)
287 */
a1cba561
AP
288 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
289 bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
cd9af3da
NC
290 reg | BCM5482_SHD_MODE_1000BX);
291
292 /*
293 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
294 * (Use LED1 as secondary SerDes ACTIVITY LED)
295 */
a1cba561 296 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1,
cd9af3da
NC
297 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
298 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
299
300 /*
301 * Auto-negotiation doesn't seem to work quite right
302 * in this mode, so we disable it and force it to the
303 * right speed/duplex setting. Only 'link status'
304 * is important.
305 */
306 phydev->autoneg = AUTONEG_DISABLE;
307 phydev->speed = SPEED_1000;
308 phydev->duplex = DUPLEX_FULL;
309 }
310
311 return err;
312}
313
314static int bcm5482_read_status(struct phy_device *phydev)
315{
316 int err;
317
318 err = genphy_read_status(phydev);
319
320 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
321 /*
322 * Only link status matters for 1000Base-X mode, so force
323 * 1000 Mbit/s full-duplex status
324 */
325 if (phydev->link) {
326 phydev->speed = SPEED_1000;
327 phydev->duplex = DUPLEX_FULL;
328 }
329 }
330
331 return err;
332}
333
57bb7e22
AV
334static int bcm5481_config_aneg(struct phy_device *phydev)
335{
b14995ac 336 struct device_node *np = phydev->mdio.dev.of_node;
57bb7e22
AV
337 int ret;
338
339 /* Aneg firsly. */
340 ret = genphy_config_aneg(phydev);
341
342 /* Then we can set up the delay. */
343 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
344 u16 reg;
345
346 /*
347 * There is no BCM5481 specification available, so down
348 * here is everything we know about "register 0x18". This
bfb9035c 349 * at least helps BCM5481 to successfully receive packets
57bb7e22
AV
350 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
351 * says: "This sets delay between the RXD and RXC signals
352 * instead of using trace lengths to achieve timing".
353 */
354
355 /* Set RDX clk delay. */
356 reg = 0x7 | (0x7 << 12);
357 phy_write(phydev, 0x18, reg);
358
359 reg = phy_read(phydev, 0x18);
360 /* Set RDX-RXC skew. */
361 reg |= (1 << 8);
362 /* Write bits 14:0. */
363 reg |= (1 << 15);
364 phy_write(phydev, 0x18, reg);
365 }
366
b14995ac
JM
367 if (of_property_read_bool(np, "enet-phy-lane-swap")) {
368 /* Lane Swap - Undocumented register...magic! */
369 ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
370 0x11B);
371 if (ret < 0)
372 return ret;
373 }
374
57bb7e22
AV
375 return ret;
376}
377
d92ead16
XW
378static int bcm54612e_config_aneg(struct phy_device *phydev)
379{
380 int ret;
381
382 /* First, auto-negotiate. */
383 ret = genphy_config_aneg(phydev);
384
385 /* Clear TX internal delay unless requested. */
386 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
387 (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
388 /* Disable TXD to GTXCLK clock delay (default set) */
389 /* Bit 9 is the only field in shadow register 00011 */
390 bcm_phy_write_shadow(phydev, 0x03, 0);
391 }
392
393 /* Clear RX internal delay unless requested. */
394 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
395 (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
396 u16 reg;
397
398 /* Errata: reads require filling in the write selector field */
399 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
400 MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC);
401 reg = phy_read(phydev, MII_BCM54XX_AUX_CTL);
402 /* Disable RXD to RXC delay (default set) */
403 reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
404 /* Clear shadow selector field */
405 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
406 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
407 MII_BCM54XX_AUXCTL_MISC_WREN | reg);
408 }
409
410 return ret;
411}
412
d7a2ed92
MC
413static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
414{
415 int val;
416
417 val = phy_read(phydev, reg);
418 if (val < 0)
419 return val;
420
421 return phy_write(phydev, reg, val | set);
422}
423
424static int brcm_fet_config_init(struct phy_device *phydev)
425{
426 int reg, err, err2, brcmtest;
427
428 /* Reset the PHY to bring it to a known state. */
429 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
430 if (err < 0)
431 return err;
432
433 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
434 if (reg < 0)
435 return reg;
436
437 /* Unmask events we are interested in and mask interrupts globally. */
438 reg = MII_BRCM_FET_IR_DUPLEX_EN |
439 MII_BRCM_FET_IR_SPEED_EN |
440 MII_BRCM_FET_IR_LINK_EN |
441 MII_BRCM_FET_IR_ENABLE |
442 MII_BRCM_FET_IR_MASK;
443
444 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
445 if (err < 0)
446 return err;
447
448 /* Enable shadow register access */
449 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
450 if (brcmtest < 0)
451 return brcmtest;
452
453 reg = brcmtest | MII_BRCM_FET_BT_SRE;
454
455 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
456 if (err < 0)
457 return err;
458
459 /* Set the LED mode */
460 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
461 if (reg < 0) {
462 err = reg;
463 goto done;
464 }
465
466 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
467 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
468
469 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
470 if (err < 0)
471 goto done;
472
473 /* Enable auto MDIX */
474 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
475 MII_BRCM_FET_SHDW_MC_FAME);
476 if (err < 0)
477 goto done;
478
cdd4e09d
MC
479 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
480 /* Enable auto power down */
481 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
482 MII_BRCM_FET_SHDW_AS2_APDE);
483 }
d7a2ed92
MC
484
485done:
486 /* Disable shadow register access */
487 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
488 if (!err)
489 err = err2;
490
491 return err;
492}
493
494static int brcm_fet_ack_interrupt(struct phy_device *phydev)
495{
496 int reg;
497
498 /* Clear pending interrupts. */
499 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
500 if (reg < 0)
501 return reg;
502
503 return 0;
504}
505
506static int brcm_fet_config_intr(struct phy_device *phydev)
507{
508 int reg, err;
509
510 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
511 if (reg < 0)
512 return reg;
513
514 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
515 reg &= ~MII_BRCM_FET_IR_MASK;
516 else
517 reg |= MII_BRCM_FET_IR_MASK;
518
519 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
520 return err;
521}
522
d5bf9071
CH
523static struct phy_driver broadcom_drivers[] = {
524{
fcb26ec5 525 .phy_id = PHY_ID_BCM5411,
c4b41c9f
MR
526 .phy_id_mask = 0xfffffff0,
527 .name = "Broadcom BCM5411",
529ed127 528 .features = PHY_GBIT_FEATURES,
c4b41c9f
MR
529 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
530 .config_init = bcm54xx_config_init,
531 .config_aneg = genphy_config_aneg,
532 .read_status = genphy_read_status,
a1cba561
AP
533 .ack_interrupt = bcm_phy_ack_intr,
534 .config_intr = bcm_phy_config_intr,
d5bf9071 535}, {
fcb26ec5 536 .phy_id = PHY_ID_BCM5421,
c4b41c9f
MR
537 .phy_id_mask = 0xfffffff0,
538 .name = "Broadcom BCM5421",
529ed127 539 .features = PHY_GBIT_FEATURES,
c4b41c9f
MR
540 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
541 .config_init = bcm54xx_config_init,
542 .config_aneg = genphy_config_aneg,
543 .read_status = genphy_read_status,
a1cba561
AP
544 .ack_interrupt = bcm_phy_ack_intr,
545 .config_intr = bcm_phy_config_intr,
d5bf9071 546}, {
fcb26ec5 547 .phy_id = PHY_ID_BCM5461,
c4b41c9f
MR
548 .phy_id_mask = 0xfffffff0,
549 .name = "Broadcom BCM5461",
529ed127 550 .features = PHY_GBIT_FEATURES,
c4b41c9f
MR
551 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
552 .config_init = bcm54xx_config_init,
553 .config_aneg = genphy_config_aneg,
554 .read_status = genphy_read_status,
a1cba561
AP
555 .ack_interrupt = bcm_phy_ack_intr,
556 .config_intr = bcm_phy_config_intr,
d92ead16
XW
557}, {
558 .phy_id = PHY_ID_BCM54612E,
559 .phy_id_mask = 0xfffffff0,
560 .name = "Broadcom BCM54612E",
529ed127 561 .features = PHY_GBIT_FEATURES,
d92ead16
XW
562 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
563 .config_init = bcm54xx_config_init,
564 .config_aneg = bcm54612e_config_aneg,
565 .read_status = genphy_read_status,
566 .ack_interrupt = bcm_phy_ack_intr,
567 .config_intr = bcm_phy_config_intr,
3bca4cf6
AIB
568}, {
569 .phy_id = PHY_ID_BCM54616S,
570 .phy_id_mask = 0xfffffff0,
571 .name = "Broadcom BCM54616S",
529ed127 572 .features = PHY_GBIT_FEATURES,
3bca4cf6
AIB
573 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
574 .config_init = bcm54xx_config_init,
575 .config_aneg = genphy_config_aneg,
576 .read_status = genphy_read_status,
a1cba561
AP
577 .ack_interrupt = bcm_phy_ack_intr,
578 .config_intr = bcm_phy_config_intr,
d5bf9071 579}, {
fcb26ec5 580 .phy_id = PHY_ID_BCM5464,
b1394f96
PG
581 .phy_id_mask = 0xfffffff0,
582 .name = "Broadcom BCM5464",
529ed127 583 .features = PHY_GBIT_FEATURES,
b1394f96
PG
584 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
585 .config_init = bcm54xx_config_init,
586 .config_aneg = genphy_config_aneg,
587 .read_status = genphy_read_status,
a1cba561
AP
588 .ack_interrupt = bcm_phy_ack_intr,
589 .config_intr = bcm_phy_config_intr,
d5bf9071 590}, {
fcb26ec5 591 .phy_id = PHY_ID_BCM5481,
57bb7e22
AV
592 .phy_id_mask = 0xfffffff0,
593 .name = "Broadcom BCM5481",
529ed127 594 .features = PHY_GBIT_FEATURES,
57bb7e22
AV
595 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
596 .config_init = bcm54xx_config_init,
597 .config_aneg = bcm5481_config_aneg,
598 .read_status = genphy_read_status,
a1cba561
AP
599 .ack_interrupt = bcm_phy_ack_intr,
600 .config_intr = bcm_phy_config_intr,
b14995ac
JM
601}, {
602 .phy_id = PHY_ID_BCM54810,
603 .phy_id_mask = 0xfffffff0,
604 .name = "Broadcom BCM54810",
529ed127 605 .features = PHY_GBIT_FEATURES,
b14995ac
JM
606 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
607 .config_init = bcm54xx_config_init,
608 .config_aneg = bcm5481_config_aneg,
609 .read_status = genphy_read_status,
610 .ack_interrupt = bcm_phy_ack_intr,
611 .config_intr = bcm_phy_config_intr,
d5bf9071 612}, {
fcb26ec5 613 .phy_id = PHY_ID_BCM5482,
03157ac3
NC
614 .phy_id_mask = 0xfffffff0,
615 .name = "Broadcom BCM5482",
529ed127 616 .features = PHY_GBIT_FEATURES,
03157ac3 617 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
cd9af3da 618 .config_init = bcm5482_config_init,
03157ac3 619 .config_aneg = genphy_config_aneg,
cd9af3da 620 .read_status = bcm5482_read_status,
a1cba561
AP
621 .ack_interrupt = bcm_phy_ack_intr,
622 .config_intr = bcm_phy_config_intr,
d5bf9071 623}, {
772638b6
MC
624 .phy_id = PHY_ID_BCM50610,
625 .phy_id_mask = 0xfffffff0,
626 .name = "Broadcom BCM50610",
529ed127 627 .features = PHY_GBIT_FEATURES,
772638b6
MC
628 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
629 .config_init = bcm54xx_config_init,
630 .config_aneg = genphy_config_aneg,
631 .read_status = genphy_read_status,
a1cba561
AP
632 .ack_interrupt = bcm_phy_ack_intr,
633 .config_intr = bcm_phy_config_intr,
d5bf9071 634}, {
4f4598fd
MC
635 .phy_id = PHY_ID_BCM50610M,
636 .phy_id_mask = 0xfffffff0,
637 .name = "Broadcom BCM50610M",
529ed127 638 .features = PHY_GBIT_FEATURES,
4f4598fd
MC
639 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
640 .config_init = bcm54xx_config_init,
641 .config_aneg = genphy_config_aneg,
642 .read_status = genphy_read_status,
a1cba561
AP
643 .ack_interrupt = bcm_phy_ack_intr,
644 .config_intr = bcm_phy_config_intr,
d5bf9071 645}, {
d9221e66 646 .phy_id = PHY_ID_BCM57780,
2fbb69aa
MC
647 .phy_id_mask = 0xfffffff0,
648 .name = "Broadcom BCM57780",
529ed127 649 .features = PHY_GBIT_FEATURES,
2fbb69aa
MC
650 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
651 .config_init = bcm54xx_config_init,
652 .config_aneg = genphy_config_aneg,
653 .read_status = genphy_read_status,
a1cba561
AP
654 .ack_interrupt = bcm_phy_ack_intr,
655 .config_intr = bcm_phy_config_intr,
d5bf9071 656}, {
6a443a0f 657 .phy_id = PHY_ID_BCMAC131,
d7a2ed92
MC
658 .phy_id_mask = 0xfffffff0,
659 .name = "Broadcom BCMAC131",
529ed127 660 .features = PHY_BASIC_FEATURES,
d7a2ed92
MC
661 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
662 .config_init = brcm_fet_config_init,
663 .config_aneg = genphy_config_aneg,
664 .read_status = genphy_read_status,
665 .ack_interrupt = brcm_fet_ack_interrupt,
666 .config_intr = brcm_fet_config_intr,
d5bf9071 667}, {
7a938f80
DES
668 .phy_id = PHY_ID_BCM5241,
669 .phy_id_mask = 0xfffffff0,
670 .name = "Broadcom BCM5241",
529ed127 671 .features = PHY_BASIC_FEATURES,
7a938f80
DES
672 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
673 .config_init = brcm_fet_config_init,
674 .config_aneg = genphy_config_aneg,
675 .read_status = genphy_read_status,
676 .ack_interrupt = brcm_fet_ack_interrupt,
677 .config_intr = brcm_fet_config_intr,
d5bf9071 678} };
7a938f80 679
50fd7150 680module_phy_driver(broadcom_drivers);
4e4f10f6 681
cf93c945 682static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
fcb26ec5
DES
683 { PHY_ID_BCM5411, 0xfffffff0 },
684 { PHY_ID_BCM5421, 0xfffffff0 },
685 { PHY_ID_BCM5461, 0xfffffff0 },
d92ead16 686 { PHY_ID_BCM54612E, 0xfffffff0 },
3bca4cf6 687 { PHY_ID_BCM54616S, 0xfffffff0 },
fcb26ec5 688 { PHY_ID_BCM5464, 0xfffffff0 },
3c25a860 689 { PHY_ID_BCM5481, 0xfffffff0 },
b14995ac 690 { PHY_ID_BCM54810, 0xfffffff0 },
fcb26ec5 691 { PHY_ID_BCM5482, 0xfffffff0 },
4e4f10f6
DW
692 { PHY_ID_BCM50610, 0xfffffff0 },
693 { PHY_ID_BCM50610M, 0xfffffff0 },
694 { PHY_ID_BCM57780, 0xfffffff0 },
695 { PHY_ID_BCMAC131, 0xfffffff0 },
7a938f80 696 { PHY_ID_BCM5241, 0xfffffff0 },
4e4f10f6
DW
697 { }
698};
699
700MODULE_DEVICE_TABLE(mdio, broadcom_tbl);