micrel.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /*
  2. * drivers/net/phy/micrel.c
  3. *
  4. * Driver for Micrel PHYs
  5. *
  6. * Author: David J. Choi
  7. *
  8. * Copyright (c) 2010-2013 Micrel, Inc.
  9. *
  10. * This program is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by the
  12. * Free Software Foundation; either version 2 of the License, or (at your
  13. * option) any later version.
  14. *
  15. * Support : Micrel Phys:
  16. * Giga phys: ksz9021, ksz9031
  17. * 100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041
  18. * ksz8021, ksz8031, ksz8051,
  19. * ksz8081, ksz8091,
  20. * ksz8061,
  21. * Switch : ksz8873, ksz886x
  22. */
  23. #include <linux/kernel.h>
  24. #include <linux/module.h>
  25. #include <linux/phy.h>
  26. #include <linux/micrel_phy.h>
  27. #include <linux/of.h>
  28. #include <linux/clk.h>
  29. /* Operation Mode Strap Override */
  30. #define MII_KSZPHY_OMSO 0x16
  31. #define KSZPHY_OMSO_B_CAST_OFF (1 << 9)
  32. #define KSZPHY_OMSO_RMII_OVERRIDE (1 << 1)
  33. #define KSZPHY_OMSO_MII_OVERRIDE (1 << 0)
  34. /* general Interrupt control/status reg in vendor specific block. */
  35. #define MII_KSZPHY_INTCS 0x1B
  36. #define KSZPHY_INTCS_JABBER (1 << 15)
  37. #define KSZPHY_INTCS_RECEIVE_ERR (1 << 14)
  38. #define KSZPHY_INTCS_PAGE_RECEIVE (1 << 13)
  39. #define KSZPHY_INTCS_PARELLEL (1 << 12)
  40. #define KSZPHY_INTCS_LINK_PARTNER_ACK (1 << 11)
  41. #define KSZPHY_INTCS_LINK_DOWN (1 << 10)
  42. #define KSZPHY_INTCS_REMOTE_FAULT (1 << 9)
  43. #define KSZPHY_INTCS_LINK_UP (1 << 8)
  44. #define KSZPHY_INTCS_ALL (KSZPHY_INTCS_LINK_UP |\
  45. KSZPHY_INTCS_LINK_DOWN)
  46. /* general PHY control reg in vendor specific block. */
  47. #define MII_KSZPHY_CTRL 0x1F
  48. /* bitmap of PHY register to set interrupt mode */
  49. #define KSZPHY_CTRL_INT_ACTIVE_HIGH (1 << 9)
  50. #define KSZ9021_CTRL_INT_ACTIVE_HIGH (1 << 14)
  51. #define KS8737_CTRL_INT_ACTIVE_HIGH (1 << 14)
  52. #define KSZ8051_RMII_50MHZ_CLK (1 << 7)
  53. /* Write/read to/from extended registers */
  54. #define MII_KSZPHY_EXTREG 0x0b
  55. #define KSZPHY_EXTREG_WRITE 0x8000
  56. #define MII_KSZPHY_EXTREG_WRITE 0x0c
  57. #define MII_KSZPHY_EXTREG_READ 0x0d
  58. /* Extended registers */
  59. #define MII_KSZPHY_CLK_CONTROL_PAD_SKEW 0x104
  60. #define MII_KSZPHY_RX_DATA_PAD_SKEW 0x105
  61. #define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106
  62. #define PS_TO_REG 200
  63. static int ksz_config_flags(struct phy_device *phydev)
  64. {
  65. int regval;
  66. if (phydev->dev_flags & (MICREL_PHY_50MHZ_CLK | MICREL_PHY_25MHZ_CLK)) {
  67. regval = phy_read(phydev, MII_KSZPHY_CTRL);
  68. if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK)
  69. regval |= KSZ8051_RMII_50MHZ_CLK;
  70. else
  71. regval &= ~KSZ8051_RMII_50MHZ_CLK;
  72. return phy_write(phydev, MII_KSZPHY_CTRL, regval);
  73. }
  74. return 0;
  75. }
  76. static int kszphy_extended_write(struct phy_device *phydev,
  77. u32 regnum, u16 val)
  78. {
  79. phy_write(phydev, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | regnum);
  80. return phy_write(phydev, MII_KSZPHY_EXTREG_WRITE, val);
  81. }
  82. static int kszphy_extended_read(struct phy_device *phydev,
  83. u32 regnum)
  84. {
  85. phy_write(phydev, MII_KSZPHY_EXTREG, regnum);
  86. return phy_read(phydev, MII_KSZPHY_EXTREG_READ);
  87. }
  88. static int kszphy_ack_interrupt(struct phy_device *phydev)
  89. {
  90. /* bit[7..0] int status, which is a read and clear register. */
  91. int rc;
  92. rc = phy_read(phydev, MII_KSZPHY_INTCS);
  93. return (rc < 0) ? rc : 0;
  94. }
  95. static int kszphy_set_interrupt(struct phy_device *phydev)
  96. {
  97. int temp;
  98. temp = (PHY_INTERRUPT_ENABLED == phydev->interrupts) ?
  99. KSZPHY_INTCS_ALL : 0;
  100. return phy_write(phydev, MII_KSZPHY_INTCS, temp);
  101. }
  102. static int kszphy_config_intr(struct phy_device *phydev)
  103. {
  104. int temp, rc;
  105. /* set the interrupt pin active low */
  106. temp = phy_read(phydev, MII_KSZPHY_CTRL);
  107. temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH;
  108. phy_write(phydev, MII_KSZPHY_CTRL, temp);
  109. rc = kszphy_set_interrupt(phydev);
  110. return rc < 0 ? rc : 0;
  111. }
  112. static int ksz9021_config_intr(struct phy_device *phydev)
  113. {
  114. int temp, rc;
  115. /* set the interrupt pin active low */
  116. temp = phy_read(phydev, MII_KSZPHY_CTRL);
  117. temp &= ~KSZ9021_CTRL_INT_ACTIVE_HIGH;
  118. phy_write(phydev, MII_KSZPHY_CTRL, temp);
  119. rc = kszphy_set_interrupt(phydev);
  120. return rc < 0 ? rc : 0;
  121. }
  122. static int ks8737_config_intr(struct phy_device *phydev)
  123. {
  124. int temp, rc;
  125. /* set the interrupt pin active low */
  126. temp = phy_read(phydev, MII_KSZPHY_CTRL);
  127. temp &= ~KS8737_CTRL_INT_ACTIVE_HIGH;
  128. phy_write(phydev, MII_KSZPHY_CTRL, temp);
  129. rc = kszphy_set_interrupt(phydev);
  130. return rc < 0 ? rc : 0;
  131. }
  132. static int kszphy_setup_led(struct phy_device *phydev,
  133. unsigned int reg, unsigned int shift)
  134. {
  135. struct device *dev = &phydev->dev;
  136. struct device_node *of_node = dev->of_node;
  137. int rc, temp;
  138. u32 val;
  139. if (!of_node && dev->parent->of_node)
  140. of_node = dev->parent->of_node;
  141. if (of_property_read_u32(of_node, "micrel,led-mode", &val))
  142. return 0;
  143. temp = phy_read(phydev, reg);
  144. if (temp < 0)
  145. return temp;
  146. temp &= ~(3 << shift);
  147. temp |= val << shift;
  148. rc = phy_write(phydev, reg, temp);
  149. return rc < 0 ? rc : 0;
  150. }
  151. static int kszphy_config_init(struct phy_device *phydev)
  152. {
  153. return 0;
  154. }
  155. static int kszphy_config_init_led8041(struct phy_device *phydev)
  156. {
  157. /* single led control, register 0x1e bits 15..14 */
  158. return kszphy_setup_led(phydev, 0x1e, 14);
  159. }
  160. static int ksz8021_config_init(struct phy_device *phydev)
  161. {
  162. const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE;
  163. int rc;
  164. rc = kszphy_setup_led(phydev, 0x1f, 4);
  165. if (rc)
  166. dev_err(&phydev->dev, "failed to set led mode\n");
  167. rc = ksz_config_flags(phydev);
  168. if (rc < 0)
  169. return rc;
  170. rc = phy_write(phydev, MII_KSZPHY_OMSO, val);
  171. return rc < 0 ? rc : 0;
  172. }
  173. static int ks8051_config_init(struct phy_device *phydev)
  174. {
  175. int rc;
  176. rc = kszphy_setup_led(phydev, 0x1f, 4);
  177. if (rc)
  178. dev_err(&phydev->dev, "failed to set led mode\n");
  179. rc = ksz_config_flags(phydev);
  180. return rc < 0 ? rc : 0;
  181. }
  182. static int ksz9021_load_values_from_of(struct phy_device *phydev,
  183. struct device_node *of_node, u16 reg,
  184. char *field1, char *field2,
  185. char *field3, char *field4)
  186. {
  187. int val1 = -1;
  188. int val2 = -2;
  189. int val3 = -3;
  190. int val4 = -4;
  191. int newval;
  192. int matches = 0;
  193. if (!of_property_read_u32(of_node, field1, &val1))
  194. matches++;
  195. if (!of_property_read_u32(of_node, field2, &val2))
  196. matches++;
  197. if (!of_property_read_u32(of_node, field3, &val3))
  198. matches++;
  199. if (!of_property_read_u32(of_node, field4, &val4))
  200. matches++;
  201. if (!matches)
  202. return 0;
  203. if (matches < 4)
  204. newval = kszphy_extended_read(phydev, reg);
  205. else
  206. newval = 0;
  207. if (val1 != -1)
  208. newval = ((newval & 0xfff0) | ((val1 / PS_TO_REG) & 0xf) << 0);
  209. if (val2 != -2)
  210. newval = ((newval & 0xff0f) | ((val2 / PS_TO_REG) & 0xf) << 4);
  211. if (val3 != -3)
  212. newval = ((newval & 0xf0ff) | ((val3 / PS_TO_REG) & 0xf) << 8);
  213. if (val4 != -4)
  214. newval = ((newval & 0x0fff) | ((val4 / PS_TO_REG) & 0xf) << 12);
  215. return kszphy_extended_write(phydev, reg, newval);
  216. }
  217. static int ksz9021_config_init(struct phy_device *phydev)
  218. {
  219. struct device *dev = &phydev->dev;
  220. struct device_node *of_node = dev->of_node;
  221. if (!of_node && dev->parent->of_node)
  222. of_node = dev->parent->of_node;
  223. if (of_node) {
  224. ksz9021_load_values_from_of(phydev, of_node,
  225. MII_KSZPHY_CLK_CONTROL_PAD_SKEW,
  226. "txen-skew-ps", "txc-skew-ps",
  227. "rxdv-skew-ps", "rxc-skew-ps");
  228. ksz9021_load_values_from_of(phydev, of_node,
  229. MII_KSZPHY_RX_DATA_PAD_SKEW,
  230. "rxd0-skew-ps", "rxd1-skew-ps",
  231. "rxd2-skew-ps", "rxd3-skew-ps");
  232. ksz9021_load_values_from_of(phydev, of_node,
  233. MII_KSZPHY_TX_DATA_PAD_SKEW,
  234. "txd0-skew-ps", "txd1-skew-ps",
  235. "txd2-skew-ps", "txd3-skew-ps");
  236. }
  237. return 0;
  238. }
  239. #define MII_KSZ9031RN_MMD_CTRL_REG 0x0d
  240. #define MII_KSZ9031RN_MMD_REGDATA_REG 0x0e
  241. #define OP_DATA 1
  242. #define KSZ9031_PS_TO_REG 60
  243. /* Extended registers */
  244. #define MII_KSZ9031RN_CONTROL_PAD_SKEW 4
  245. #define MII_KSZ9031RN_RX_DATA_PAD_SKEW 5
  246. #define MII_KSZ9031RN_TX_DATA_PAD_SKEW 6
  247. #define MII_KSZ9031RN_CLK_PAD_SKEW 8
  248. static int ksz9031_extended_write(struct phy_device *phydev,
  249. u8 mode, u32 dev_addr, u32 regnum, u16 val)
  250. {
  251. phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr);
  252. phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum);
  253. phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr);
  254. return phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, val);
  255. }
  256. static int ksz9031_extended_read(struct phy_device *phydev,
  257. u8 mode, u32 dev_addr, u32 regnum)
  258. {
  259. phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr);
  260. phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum);
  261. phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr);
  262. return phy_read(phydev, MII_KSZ9031RN_MMD_REGDATA_REG);
  263. }
  264. static int ksz9031_of_load_skew_values(struct phy_device *phydev,
  265. struct device_node *of_node,
  266. u16 reg, size_t field_sz,
  267. char *field[], u8 numfields)
  268. {
  269. int val[4] = {-1, -2, -3, -4};
  270. int matches = 0;
  271. u16 mask;
  272. u16 maxval;
  273. u16 newval;
  274. int i;
  275. for (i = 0; i < numfields; i++)
  276. if (!of_property_read_u32(of_node, field[i], val + i))
  277. matches++;
  278. if (!matches)
  279. return 0;
  280. if (matches < numfields)
  281. newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg);
  282. else
  283. newval = 0;
  284. maxval = (field_sz == 4) ? 0xf : 0x1f;
  285. for (i = 0; i < numfields; i++)
  286. if (val[i] != -(i + 1)) {
  287. mask = 0xffff;
  288. mask ^= maxval << (field_sz * i);
  289. newval = (newval & mask) |
  290. (((val[i] / KSZ9031_PS_TO_REG) & maxval)
  291. << (field_sz * i));
  292. }
  293. return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval);
  294. }
  295. static int ksz9031_config_init(struct phy_device *phydev)
  296. {
  297. struct device *dev = &phydev->dev;
  298. struct device_node *of_node = dev->of_node;
  299. char *clk_skews[2] = {"rxc-skew-ps", "txc-skew-ps"};
  300. char *rx_data_skews[4] = {
  301. "rxd0-skew-ps", "rxd1-skew-ps",
  302. "rxd2-skew-ps", "rxd3-skew-ps"
  303. };
  304. char *tx_data_skews[4] = {
  305. "txd0-skew-ps", "txd1-skew-ps",
  306. "txd2-skew-ps", "txd3-skew-ps"
  307. };
  308. char *control_skews[2] = {"txen-skew-ps", "rxdv-skew-ps"};
  309. if (!of_node && dev->parent->of_node)
  310. of_node = dev->parent->of_node;
  311. if (of_node) {
  312. ksz9031_of_load_skew_values(phydev, of_node,
  313. MII_KSZ9031RN_CLK_PAD_SKEW, 5,
  314. clk_skews, 2);
  315. ksz9031_of_load_skew_values(phydev, of_node,
  316. MII_KSZ9031RN_CONTROL_PAD_SKEW, 4,
  317. control_skews, 2);
  318. ksz9031_of_load_skew_values(phydev, of_node,
  319. MII_KSZ9031RN_RX_DATA_PAD_SKEW, 4,
  320. rx_data_skews, 4);
  321. ksz9031_of_load_skew_values(phydev, of_node,
  322. MII_KSZ9031RN_TX_DATA_PAD_SKEW, 4,
  323. tx_data_skews, 4);
  324. }
  325. return 0;
  326. }
  327. #define KSZ8873MLL_GLOBAL_CONTROL_4 0x06
  328. #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX (1 << 6)
  329. #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED (1 << 4)
  330. static int ksz8873mll_read_status(struct phy_device *phydev)
  331. {
  332. int regval;
  333. /* dummy read */
  334. regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
  335. regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
  336. if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
  337. phydev->duplex = DUPLEX_HALF;
  338. else
  339. phydev->duplex = DUPLEX_FULL;
  340. if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
  341. phydev->speed = SPEED_10;
  342. else
  343. phydev->speed = SPEED_100;
  344. phydev->link = 1;
  345. phydev->pause = phydev->asym_pause = 0;
  346. return 0;
  347. }
  348. static int ksz8873mll_config_aneg(struct phy_device *phydev)
  349. {
  350. return 0;
  351. }
  352. /* This routine returns -1 as an indication to the caller that the
  353. * Micrel ksz9021 10/100/1000 PHY does not support standard IEEE
  354. * MMD extended PHY registers.
  355. */
  356. static int
  357. ksz9021_rd_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
  358. int regnum)
  359. {
  360. return -1;
  361. }
  362. /* This routine does nothing since the Micrel ksz9021 does not support
  363. * standard IEEE MMD extended PHY registers.
  364. */
  365. static void
  366. ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
  367. int regnum, u32 val)
  368. {
  369. }
  370. static int ksz8021_probe(struct phy_device *phydev)
  371. {
  372. struct clk *clk;
  373. clk = devm_clk_get(&phydev->dev, "rmii-ref");
  374. if (!IS_ERR(clk)) {
  375. unsigned long rate = clk_get_rate(clk);
  376. if (rate > 24500000 && rate < 25500000) {
  377. phydev->dev_flags |= MICREL_PHY_25MHZ_CLK;
  378. } else if (rate > 49500000 && rate < 50500000) {
  379. phydev->dev_flags |= MICREL_PHY_50MHZ_CLK;
  380. } else {
  381. dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate);
  382. return -EINVAL;
  383. }
  384. }
  385. return 0;
  386. }
  387. static struct phy_driver ksphy_driver[] = {
  388. {
  389. .phy_id = PHY_ID_KS8737,
  390. .phy_id_mask = 0x00fffff0,
  391. .name = "Micrel KS8737",
  392. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
  393. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  394. .config_init = kszphy_config_init,
  395. .config_aneg = genphy_config_aneg,
  396. .read_status = genphy_read_status,
  397. .ack_interrupt = kszphy_ack_interrupt,
  398. .config_intr = ks8737_config_intr,
  399. .suspend = genphy_suspend,
  400. .resume = genphy_resume,
  401. .driver = { .owner = THIS_MODULE,},
  402. }, {
  403. .phy_id = PHY_ID_KSZ8021,
  404. .phy_id_mask = 0x00ffffff,
  405. .name = "Micrel KSZ8021 or KSZ8031",
  406. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
  407. SUPPORTED_Asym_Pause),
  408. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  409. .probe = ksz8021_probe,
  410. .config_init = ksz8021_config_init,
  411. .config_aneg = genphy_config_aneg,
  412. .read_status = genphy_read_status,
  413. .ack_interrupt = kszphy_ack_interrupt,
  414. .config_intr = kszphy_config_intr,
  415. .suspend = genphy_suspend,
  416. .resume = genphy_resume,
  417. .driver = { .owner = THIS_MODULE,},
  418. }, {
  419. .phy_id = PHY_ID_KSZ8031,
  420. .phy_id_mask = 0x00ffffff,
  421. .name = "Micrel KSZ8031",
  422. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
  423. SUPPORTED_Asym_Pause),
  424. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  425. .probe = ksz8021_probe,
  426. .config_init = ksz8021_config_init,
  427. .config_aneg = genphy_config_aneg,
  428. .read_status = genphy_read_status,
  429. .ack_interrupt = kszphy_ack_interrupt,
  430. .config_intr = kszphy_config_intr,
  431. .suspend = genphy_suspend,
  432. .resume = genphy_resume,
  433. .driver = { .owner = THIS_MODULE,},
  434. }, {
  435. .phy_id = PHY_ID_KSZ8041,
  436. .phy_id_mask = 0x00fffff0,
  437. .name = "Micrel KSZ8041",
  438. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
  439. | SUPPORTED_Asym_Pause),
  440. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  441. .config_init = kszphy_config_init_led8041,
  442. .config_aneg = genphy_config_aneg,
  443. .read_status = genphy_read_status,
  444. .ack_interrupt = kszphy_ack_interrupt,
  445. .config_intr = kszphy_config_intr,
  446. .suspend = genphy_suspend,
  447. .resume = genphy_resume,
  448. .driver = { .owner = THIS_MODULE,},
  449. }, {
  450. .phy_id = PHY_ID_KSZ8041RNLI,
  451. .phy_id_mask = 0x00fffff0,
  452. .name = "Micrel KSZ8041RNLI",
  453. .features = PHY_BASIC_FEATURES |
  454. SUPPORTED_Pause | SUPPORTED_Asym_Pause,
  455. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  456. .config_init = kszphy_config_init_led8041,
  457. .config_aneg = genphy_config_aneg,
  458. .read_status = genphy_read_status,
  459. .ack_interrupt = kszphy_ack_interrupt,
  460. .config_intr = kszphy_config_intr,
  461. .suspend = genphy_suspend,
  462. .resume = genphy_resume,
  463. .driver = { .owner = THIS_MODULE,},
  464. }, {
  465. .phy_id = PHY_ID_KSZ8051,
  466. .phy_id_mask = 0x00fffff0,
  467. .name = "Micrel KSZ8051",
  468. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
  469. | SUPPORTED_Asym_Pause),
  470. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  471. .config_init = ks8051_config_init,
  472. .config_aneg = genphy_config_aneg,
  473. .read_status = genphy_read_status,
  474. .ack_interrupt = kszphy_ack_interrupt,
  475. .config_intr = kszphy_config_intr,
  476. .suspend = genphy_suspend,
  477. .resume = genphy_resume,
  478. .driver = { .owner = THIS_MODULE,},
  479. }, {
  480. .phy_id = PHY_ID_KSZ8001,
  481. .name = "Micrel KSZ8001 or KS8721",
  482. .phy_id_mask = 0x00ffffff,
  483. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
  484. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  485. .config_init = kszphy_config_init_led8041,
  486. .config_aneg = genphy_config_aneg,
  487. .read_status = genphy_read_status,
  488. .ack_interrupt = kszphy_ack_interrupt,
  489. .config_intr = kszphy_config_intr,
  490. .suspend = genphy_suspend,
  491. .resume = genphy_resume,
  492. .driver = { .owner = THIS_MODULE,},
  493. }, {
  494. .phy_id = PHY_ID_KSZ8081,
  495. .name = "Micrel KSZ8081 or KSZ8091",
  496. .phy_id_mask = 0x00fffff0,
  497. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
  498. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  499. .config_init = kszphy_config_init,
  500. .config_aneg = genphy_config_aneg,
  501. .read_status = genphy_read_status,
  502. .ack_interrupt = kszphy_ack_interrupt,
  503. .config_intr = kszphy_config_intr,
  504. .suspend = genphy_suspend,
  505. .resume = genphy_resume,
  506. .driver = { .owner = THIS_MODULE,},
  507. }, {
  508. .phy_id = PHY_ID_KSZ8061,
  509. .name = "Micrel KSZ8061",
  510. .phy_id_mask = 0x00fffff0,
  511. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
  512. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  513. .config_init = kszphy_config_init,
  514. .config_aneg = genphy_config_aneg,
  515. .read_status = genphy_read_status,
  516. .ack_interrupt = kszphy_ack_interrupt,
  517. .config_intr = kszphy_config_intr,
  518. .suspend = genphy_suspend,
  519. .resume = genphy_resume,
  520. .driver = { .owner = THIS_MODULE,},
  521. }, {
  522. .phy_id = PHY_ID_KSZ9021,
  523. .phy_id_mask = 0x000ffffe,
  524. .name = "Micrel KSZ9021 Gigabit PHY",
  525. .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
  526. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  527. .config_init = ksz9021_config_init,
  528. .config_aneg = genphy_config_aneg,
  529. .read_status = genphy_read_status,
  530. .ack_interrupt = kszphy_ack_interrupt,
  531. .config_intr = ksz9021_config_intr,
  532. .suspend = genphy_suspend,
  533. .resume = genphy_resume,
  534. .read_mmd_indirect = ksz9021_rd_mmd_phyreg,
  535. .write_mmd_indirect = ksz9021_wr_mmd_phyreg,
  536. .driver = { .owner = THIS_MODULE, },
  537. }, {
  538. .phy_id = PHY_ID_KSZ9031,
  539. .phy_id_mask = 0x00fffff0,
  540. .name = "Micrel KSZ9031 Gigabit PHY",
  541. .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause),
  542. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  543. .config_init = ksz9031_config_init,
  544. .config_aneg = genphy_config_aneg,
  545. .read_status = genphy_read_status,
  546. .ack_interrupt = kszphy_ack_interrupt,
  547. .config_intr = ksz9021_config_intr,
  548. .suspend = genphy_suspend,
  549. .resume = genphy_resume,
  550. .driver = { .owner = THIS_MODULE, },
  551. }, {
  552. .phy_id = PHY_ID_KSZ8873MLL,
  553. .phy_id_mask = 0x00fffff0,
  554. .name = "Micrel KSZ8873MLL Switch",
  555. .features = (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
  556. .flags = PHY_HAS_MAGICANEG,
  557. .config_init = kszphy_config_init,
  558. .config_aneg = ksz8873mll_config_aneg,
  559. .read_status = ksz8873mll_read_status,
  560. .suspend = genphy_suspend,
  561. .resume = genphy_resume,
  562. .driver = { .owner = THIS_MODULE, },
  563. }, {
  564. .phy_id = PHY_ID_KSZ886X,
  565. .phy_id_mask = 0x00fffff0,
  566. .name = "Micrel KSZ886X Switch",
  567. .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
  568. .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
  569. .config_init = kszphy_config_init,
  570. .config_aneg = genphy_config_aneg,
  571. .read_status = genphy_read_status,
  572. .suspend = genphy_suspend,
  573. .resume = genphy_resume,
  574. .driver = { .owner = THIS_MODULE, },
  575. } };
  576. static int __init ksphy_init(void)
  577. {
  578. return phy_drivers_register(ksphy_driver,
  579. ARRAY_SIZE(ksphy_driver));
  580. }
  581. static void __exit ksphy_exit(void)
  582. {
  583. phy_drivers_unregister(ksphy_driver,
  584. ARRAY_SIZE(ksphy_driver));
  585. }
  586. module_init(ksphy_init);
  587. module_exit(ksphy_exit);
  588. MODULE_DESCRIPTION("Micrel PHY driver");
  589. MODULE_AUTHOR("David J. Choi");
  590. MODULE_LICENSE("GPL");
  591. static struct mdio_device_id __maybe_unused micrel_tbl[] = {
  592. { PHY_ID_KSZ9021, 0x000ffffe },
  593. { PHY_ID_KSZ9031, 0x00fffff0 },
  594. { PHY_ID_KSZ8001, 0x00ffffff },
  595. { PHY_ID_KS8737, 0x00fffff0 },
  596. { PHY_ID_KSZ8021, 0x00ffffff },
  597. { PHY_ID_KSZ8031, 0x00ffffff },
  598. { PHY_ID_KSZ8041, 0x00fffff0 },
  599. { PHY_ID_KSZ8051, 0x00fffff0 },
  600. { PHY_ID_KSZ8061, 0x00fffff0 },
  601. { PHY_ID_KSZ8081, 0x00fffff0 },
  602. { PHY_ID_KSZ8873MLL, 0x00fffff0 },
  603. { PHY_ID_KSZ886X, 0x00fffff0 },
  604. { }
  605. };
  606. MODULE_DEVICE_TABLE(mdio, micrel_tbl);