broadcom.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  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. #include <linux/module.h>
  17. #include <linux/phy.h>
  18. #include <linux/brcmphy.h>
  19. #define BRCM_PHY_MODEL(phydev) \
  20. ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
  21. #define BRCM_PHY_REV(phydev) \
  22. ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
  23. MODULE_DESCRIPTION("Broadcom PHY driver");
  24. MODULE_AUTHOR("Maciej W. Rozycki");
  25. MODULE_LICENSE("GPL");
  26. /* Indirect register access functions for the Expansion Registers */
  27. static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
  28. {
  29. int val;
  30. val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
  31. if (val < 0)
  32. return val;
  33. val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
  34. /* Restore default value. It's O.K. if this write fails. */
  35. phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
  36. return val;
  37. }
  38. static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
  39. {
  40. int ret;
  41. ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
  42. if (ret < 0)
  43. return ret;
  44. ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
  45. /* Restore default value. It's O.K. if this write fails. */
  46. phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
  47. return ret;
  48. }
  49. static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
  50. {
  51. return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
  52. }
  53. /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
  54. static int bcm50610_a0_workaround(struct phy_device *phydev)
  55. {
  56. int err;
  57. err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
  58. MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
  59. MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
  60. if (err < 0)
  61. return err;
  62. err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
  63. MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
  64. if (err < 0)
  65. return err;
  66. err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
  67. MII_BCM54XX_EXP_EXP75_VDACCTRL);
  68. if (err < 0)
  69. return err;
  70. err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
  71. MII_BCM54XX_EXP_EXP96_MYST);
  72. if (err < 0)
  73. return err;
  74. err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
  75. MII_BCM54XX_EXP_EXP97_MYST);
  76. return err;
  77. }
  78. static int bcm54xx_phydsp_config(struct phy_device *phydev)
  79. {
  80. int err, err2;
  81. /* Enable the SMDSP clock */
  82. err = bcm54xx_auxctl_write(phydev,
  83. MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
  84. MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
  85. MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
  86. if (err < 0)
  87. return err;
  88. if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
  89. BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
  90. /* Clear bit 9 to fix a phy interop issue. */
  91. err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
  92. MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
  93. if (err < 0)
  94. goto error;
  95. if (phydev->drv->phy_id == PHY_ID_BCM50610) {
  96. err = bcm50610_a0_workaround(phydev);
  97. if (err < 0)
  98. goto error;
  99. }
  100. }
  101. if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
  102. int val;
  103. val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
  104. if (val < 0)
  105. goto error;
  106. val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
  107. err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
  108. }
  109. error:
  110. /* Disable the SMDSP clock */
  111. err2 = bcm54xx_auxctl_write(phydev,
  112. MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
  113. MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
  114. /* Return the first error reported. */
  115. return err ? err : err2;
  116. }
  117. static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
  118. {
  119. u32 orig;
  120. int val;
  121. bool clk125en = true;
  122. /* Abort if we are using an untested phy. */
  123. if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
  124. BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
  125. BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
  126. return;
  127. val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
  128. if (val < 0)
  129. return;
  130. orig = val;
  131. if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
  132. BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
  133. BRCM_PHY_REV(phydev) >= 0x3) {
  134. /*
  135. * Here, bit 0 _disables_ CLK125 when set.
  136. * This bit is set by default.
  137. */
  138. clk125en = false;
  139. } else {
  140. if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
  141. /* Here, bit 0 _enables_ CLK125 when set */
  142. val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
  143. clk125en = false;
  144. }
  145. }
  146. if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
  147. val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
  148. else
  149. val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
  150. if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
  151. val |= BCM54XX_SHD_SCR3_TRDDAPD;
  152. if (orig != val)
  153. bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
  154. val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
  155. if (val < 0)
  156. return;
  157. orig = val;
  158. if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
  159. val |= BCM54XX_SHD_APD_EN;
  160. else
  161. val &= ~BCM54XX_SHD_APD_EN;
  162. if (orig != val)
  163. bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
  164. }
  165. static int bcm54xx_config_init(struct phy_device *phydev)
  166. {
  167. int reg, err;
  168. reg = phy_read(phydev, MII_BCM54XX_ECR);
  169. if (reg < 0)
  170. return reg;
  171. /* Mask interrupts globally. */
  172. reg |= MII_BCM54XX_ECR_IM;
  173. err = phy_write(phydev, MII_BCM54XX_ECR, reg);
  174. if (err < 0)
  175. return err;
  176. /* Unmask events we are interested in. */
  177. reg = ~(MII_BCM54XX_INT_DUPLEX |
  178. MII_BCM54XX_INT_SPEED |
  179. MII_BCM54XX_INT_LINK);
  180. err = phy_write(phydev, MII_BCM54XX_IMR, reg);
  181. if (err < 0)
  182. return err;
  183. if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
  184. BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
  185. (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
  186. bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
  187. if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
  188. (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
  189. (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
  190. bcm54xx_adjust_rxrefclk(phydev);
  191. bcm54xx_phydsp_config(phydev);
  192. return 0;
  193. }
  194. static int bcm5482_config_init(struct phy_device *phydev)
  195. {
  196. int err, reg;
  197. err = bcm54xx_config_init(phydev);
  198. if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
  199. /*
  200. * Enable secondary SerDes and its use as an LED source
  201. */
  202. reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
  203. bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
  204. reg |
  205. BCM5482_SHD_SSD_LEDM |
  206. BCM5482_SHD_SSD_EN);
  207. /*
  208. * Enable SGMII slave mode and auto-detection
  209. */
  210. reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
  211. err = bcm54xx_exp_read(phydev, reg);
  212. if (err < 0)
  213. return err;
  214. err = bcm54xx_exp_write(phydev, reg, err |
  215. BCM5482_SSD_SGMII_SLAVE_EN |
  216. BCM5482_SSD_SGMII_SLAVE_AD);
  217. if (err < 0)
  218. return err;
  219. /*
  220. * Disable secondary SerDes powerdown
  221. */
  222. reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
  223. err = bcm54xx_exp_read(phydev, reg);
  224. if (err < 0)
  225. return err;
  226. err = bcm54xx_exp_write(phydev, reg,
  227. err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
  228. if (err < 0)
  229. return err;
  230. /*
  231. * Select 1000BASE-X register set (primary SerDes)
  232. */
  233. reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
  234. bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
  235. reg | BCM5482_SHD_MODE_1000BX);
  236. /*
  237. * LED1=ACTIVITYLED, LED3=LINKSPD[2]
  238. * (Use LED1 as secondary SerDes ACTIVITY LED)
  239. */
  240. bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
  241. BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
  242. BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
  243. /*
  244. * Auto-negotiation doesn't seem to work quite right
  245. * in this mode, so we disable it and force it to the
  246. * right speed/duplex setting. Only 'link status'
  247. * is important.
  248. */
  249. phydev->autoneg = AUTONEG_DISABLE;
  250. phydev->speed = SPEED_1000;
  251. phydev->duplex = DUPLEX_FULL;
  252. }
  253. return err;
  254. }
  255. static int bcm5482_read_status(struct phy_device *phydev)
  256. {
  257. int err;
  258. err = genphy_read_status(phydev);
  259. if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
  260. /*
  261. * Only link status matters for 1000Base-X mode, so force
  262. * 1000 Mbit/s full-duplex status
  263. */
  264. if (phydev->link) {
  265. phydev->speed = SPEED_1000;
  266. phydev->duplex = DUPLEX_FULL;
  267. }
  268. }
  269. return err;
  270. }
  271. static int bcm54xx_ack_interrupt(struct phy_device *phydev)
  272. {
  273. int reg;
  274. /* Clear pending interrupts. */
  275. reg = phy_read(phydev, MII_BCM54XX_ISR);
  276. if (reg < 0)
  277. return reg;
  278. return 0;
  279. }
  280. static int bcm54xx_config_intr(struct phy_device *phydev)
  281. {
  282. int reg, err;
  283. reg = phy_read(phydev, MII_BCM54XX_ECR);
  284. if (reg < 0)
  285. return reg;
  286. if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
  287. reg &= ~MII_BCM54XX_ECR_IM;
  288. else
  289. reg |= MII_BCM54XX_ECR_IM;
  290. err = phy_write(phydev, MII_BCM54XX_ECR, reg);
  291. return err;
  292. }
  293. static int bcm5481_config_aneg(struct phy_device *phydev)
  294. {
  295. int ret;
  296. /* Aneg firsly. */
  297. ret = genphy_config_aneg(phydev);
  298. /* Then we can set up the delay. */
  299. if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
  300. u16 reg;
  301. /*
  302. * There is no BCM5481 specification available, so down
  303. * here is everything we know about "register 0x18". This
  304. * at least helps BCM5481 to successfully receive packets
  305. * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
  306. * says: "This sets delay between the RXD and RXC signals
  307. * instead of using trace lengths to achieve timing".
  308. */
  309. /* Set RDX clk delay. */
  310. reg = 0x7 | (0x7 << 12);
  311. phy_write(phydev, 0x18, reg);
  312. reg = phy_read(phydev, 0x18);
  313. /* Set RDX-RXC skew. */
  314. reg |= (1 << 8);
  315. /* Write bits 14:0. */
  316. reg |= (1 << 15);
  317. phy_write(phydev, 0x18, reg);
  318. }
  319. return ret;
  320. }
  321. static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
  322. {
  323. int val;
  324. val = phy_read(phydev, reg);
  325. if (val < 0)
  326. return val;
  327. return phy_write(phydev, reg, val | set);
  328. }
  329. static int brcm_fet_config_init(struct phy_device *phydev)
  330. {
  331. int reg, err, err2, brcmtest;
  332. /* Reset the PHY to bring it to a known state. */
  333. err = phy_write(phydev, MII_BMCR, BMCR_RESET);
  334. if (err < 0)
  335. return err;
  336. reg = phy_read(phydev, MII_BRCM_FET_INTREG);
  337. if (reg < 0)
  338. return reg;
  339. /* Unmask events we are interested in and mask interrupts globally. */
  340. reg = MII_BRCM_FET_IR_DUPLEX_EN |
  341. MII_BRCM_FET_IR_SPEED_EN |
  342. MII_BRCM_FET_IR_LINK_EN |
  343. MII_BRCM_FET_IR_ENABLE |
  344. MII_BRCM_FET_IR_MASK;
  345. err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
  346. if (err < 0)
  347. return err;
  348. /* Enable shadow register access */
  349. brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
  350. if (brcmtest < 0)
  351. return brcmtest;
  352. reg = brcmtest | MII_BRCM_FET_BT_SRE;
  353. err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
  354. if (err < 0)
  355. return err;
  356. /* Set the LED mode */
  357. reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
  358. if (reg < 0) {
  359. err = reg;
  360. goto done;
  361. }
  362. reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
  363. reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
  364. err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
  365. if (err < 0)
  366. goto done;
  367. /* Enable auto MDIX */
  368. err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
  369. MII_BRCM_FET_SHDW_MC_FAME);
  370. if (err < 0)
  371. goto done;
  372. if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
  373. /* Enable auto power down */
  374. err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
  375. MII_BRCM_FET_SHDW_AS2_APDE);
  376. }
  377. done:
  378. /* Disable shadow register access */
  379. err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
  380. if (!err)
  381. err = err2;
  382. return err;
  383. }
  384. static int brcm_fet_ack_interrupt(struct phy_device *phydev)
  385. {
  386. int reg;
  387. /* Clear pending interrupts. */
  388. reg = phy_read(phydev, MII_BRCM_FET_INTREG);
  389. if (reg < 0)
  390. return reg;
  391. return 0;
  392. }
  393. static int brcm_fet_config_intr(struct phy_device *phydev)
  394. {
  395. int reg, err;
  396. reg = phy_read(phydev, MII_BRCM_FET_INTREG);
  397. if (reg < 0)
  398. return reg;
  399. if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
  400. reg &= ~MII_BRCM_FET_IR_MASK;
  401. else
  402. reg |= MII_BRCM_FET_IR_MASK;
  403. err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
  404. return err;
  405. }
  406. static struct phy_driver broadcom_drivers[] = {
  407. {
  408. .phy_id = PHY_ID_BCM5411,
  409. .phy_id_mask = 0xfffffff0,
  410. .name = "Broadcom BCM5411",
  411. .features = PHY_GBIT_FEATURES |
  412. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  413. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  414. .config_init = bcm54xx_config_init,
  415. .config_aneg = genphy_config_aneg,
  416. .read_status = genphy_read_status,
  417. .ack_interrupt = bcm54xx_ack_interrupt,
  418. .config_intr = bcm54xx_config_intr,
  419. .driver = { .owner = THIS_MODULE },
  420. }, {
  421. .phy_id = PHY_ID_BCM5421,
  422. .phy_id_mask = 0xfffffff0,
  423. .name = "Broadcom BCM5421",
  424. .features = PHY_GBIT_FEATURES |
  425. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  426. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  427. .config_init = bcm54xx_config_init,
  428. .config_aneg = genphy_config_aneg,
  429. .read_status = genphy_read_status,
  430. .ack_interrupt = bcm54xx_ack_interrupt,
  431. .config_intr = bcm54xx_config_intr,
  432. .driver = { .owner = THIS_MODULE },
  433. }, {
  434. .phy_id = PHY_ID_BCM5461,
  435. .phy_id_mask = 0xfffffff0,
  436. .name = "Broadcom BCM5461",
  437. .features = PHY_GBIT_FEATURES |
  438. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  439. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  440. .config_init = bcm54xx_config_init,
  441. .config_aneg = genphy_config_aneg,
  442. .read_status = genphy_read_status,
  443. .ack_interrupt = bcm54xx_ack_interrupt,
  444. .config_intr = bcm54xx_config_intr,
  445. .driver = { .owner = THIS_MODULE },
  446. }, {
  447. .phy_id = PHY_ID_BCM54616S,
  448. .phy_id_mask = 0xfffffff0,
  449. .name = "Broadcom BCM54616S",
  450. .features = PHY_GBIT_FEATURES |
  451. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  452. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  453. .config_init = bcm54xx_config_init,
  454. .config_aneg = genphy_config_aneg,
  455. .read_status = genphy_read_status,
  456. .ack_interrupt = bcm54xx_ack_interrupt,
  457. .config_intr = bcm54xx_config_intr,
  458. .driver = { .owner = THIS_MODULE },
  459. }, {
  460. .phy_id = PHY_ID_BCM5464,
  461. .phy_id_mask = 0xfffffff0,
  462. .name = "Broadcom BCM5464",
  463. .features = PHY_GBIT_FEATURES |
  464. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  465. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  466. .config_init = bcm54xx_config_init,
  467. .config_aneg = genphy_config_aneg,
  468. .read_status = genphy_read_status,
  469. .ack_interrupt = bcm54xx_ack_interrupt,
  470. .config_intr = bcm54xx_config_intr,
  471. .driver = { .owner = THIS_MODULE },
  472. }, {
  473. .phy_id = PHY_ID_BCM5481,
  474. .phy_id_mask = 0xfffffff0,
  475. .name = "Broadcom BCM5481",
  476. .features = PHY_GBIT_FEATURES |
  477. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  478. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  479. .config_init = bcm54xx_config_init,
  480. .config_aneg = bcm5481_config_aneg,
  481. .read_status = genphy_read_status,
  482. .ack_interrupt = bcm54xx_ack_interrupt,
  483. .config_intr = bcm54xx_config_intr,
  484. .driver = { .owner = THIS_MODULE },
  485. }, {
  486. .phy_id = PHY_ID_BCM5482,
  487. .phy_id_mask = 0xfffffff0,
  488. .name = "Broadcom BCM5482",
  489. .features = PHY_GBIT_FEATURES |
  490. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  491. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  492. .config_init = bcm5482_config_init,
  493. .config_aneg = genphy_config_aneg,
  494. .read_status = bcm5482_read_status,
  495. .ack_interrupt = bcm54xx_ack_interrupt,
  496. .config_intr = bcm54xx_config_intr,
  497. .driver = { .owner = THIS_MODULE },
  498. }, {
  499. .phy_id = PHY_ID_BCM50610,
  500. .phy_id_mask = 0xfffffff0,
  501. .name = "Broadcom BCM50610",
  502. .features = PHY_GBIT_FEATURES |
  503. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  504. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  505. .config_init = bcm54xx_config_init,
  506. .config_aneg = genphy_config_aneg,
  507. .read_status = genphy_read_status,
  508. .ack_interrupt = bcm54xx_ack_interrupt,
  509. .config_intr = bcm54xx_config_intr,
  510. .driver = { .owner = THIS_MODULE },
  511. }, {
  512. .phy_id = PHY_ID_BCM50610M,
  513. .phy_id_mask = 0xfffffff0,
  514. .name = "Broadcom BCM50610M",
  515. .features = PHY_GBIT_FEATURES |
  516. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  517. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  518. .config_init = bcm54xx_config_init,
  519. .config_aneg = genphy_config_aneg,
  520. .read_status = genphy_read_status,
  521. .ack_interrupt = bcm54xx_ack_interrupt,
  522. .config_intr = bcm54xx_config_intr,
  523. .driver = { .owner = THIS_MODULE },
  524. }, {
  525. .phy_id = PHY_ID_BCM57780,
  526. .phy_id_mask = 0xfffffff0,
  527. .name = "Broadcom BCM57780",
  528. .features = PHY_GBIT_FEATURES |
  529. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  530. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  531. .config_init = bcm54xx_config_init,
  532. .config_aneg = genphy_config_aneg,
  533. .read_status = genphy_read_status,
  534. .ack_interrupt = bcm54xx_ack_interrupt,
  535. .config_intr = bcm54xx_config_intr,
  536. .driver = { .owner = THIS_MODULE },
  537. }, {
  538. .phy_id = PHY_ID_BCMAC131,
  539. .phy_id_mask = 0xfffffff0,
  540. .name = "Broadcom BCMAC131",
  541. .features = PHY_BASIC_FEATURES |
  542. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  543. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  544. .config_init = brcm_fet_config_init,
  545. .config_aneg = genphy_config_aneg,
  546. .read_status = genphy_read_status,
  547. .ack_interrupt = brcm_fet_ack_interrupt,
  548. .config_intr = brcm_fet_config_intr,
  549. .driver = { .owner = THIS_MODULE },
  550. }, {
  551. .phy_id = PHY_ID_BCM5241,
  552. .phy_id_mask = 0xfffffff0,
  553. .name = "Broadcom BCM5241",
  554. .features = PHY_BASIC_FEATURES |
  555. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  556. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  557. .config_init = brcm_fet_config_init,
  558. .config_aneg = genphy_config_aneg,
  559. .read_status = genphy_read_status,
  560. .ack_interrupt = brcm_fet_ack_interrupt,
  561. .config_intr = brcm_fet_config_intr,
  562. .driver = { .owner = THIS_MODULE },
  563. } };
  564. module_phy_driver(broadcom_drivers);
  565. static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
  566. { PHY_ID_BCM5411, 0xfffffff0 },
  567. { PHY_ID_BCM5421, 0xfffffff0 },
  568. { PHY_ID_BCM5461, 0xfffffff0 },
  569. { PHY_ID_BCM54616S, 0xfffffff0 },
  570. { PHY_ID_BCM5464, 0xfffffff0 },
  571. { PHY_ID_BCM5482, 0xfffffff0 },
  572. { PHY_ID_BCM5482, 0xfffffff0 },
  573. { PHY_ID_BCM50610, 0xfffffff0 },
  574. { PHY_ID_BCM50610M, 0xfffffff0 },
  575. { PHY_ID_BCM57780, 0xfffffff0 },
  576. { PHY_ID_BCMAC131, 0xfffffff0 },
  577. { PHY_ID_BCM5241, 0xfffffff0 },
  578. { }
  579. };
  580. MODULE_DEVICE_TABLE(mdio, broadcom_tbl);