vitesse.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * Vitesse PHY drivers
  3. *
  4. * Copyright 2010-2014 Freescale Semiconductor, Inc.
  5. * Original Author: Andy Fleming
  6. * Add vsc8662 phy support - Priyanka Jain
  7. * SPDX-License-Identifier: GPL-2.0+
  8. */
  9. #include <miiphy.h>
  10. /* Cicada Auxiliary Control/Status Register */
  11. #define MIIM_CIS82xx_AUX_CONSTAT 0x1c
  12. #define MIIM_CIS82xx_AUXCONSTAT_INIT 0x0004
  13. #define MIIM_CIS82xx_AUXCONSTAT_DUPLEX 0x0020
  14. #define MIIM_CIS82xx_AUXCONSTAT_SPEED 0x0018
  15. #define MIIM_CIS82xx_AUXCONSTAT_GBIT 0x0010
  16. #define MIIM_CIS82xx_AUXCONSTAT_100 0x0008
  17. /* Cicada Extended Control Register 1 */
  18. #define MIIM_CIS82xx_EXT_CON1 0x17
  19. #define MIIM_CIS8201_EXTCON1_INIT 0x0000
  20. /* Cicada 8204 Extended PHY Control Register 1 */
  21. #define MIIM_CIS8204_EPHY_CON 0x17
  22. #define MIIM_CIS8204_EPHYCON_INIT 0x0006
  23. #define MIIM_CIS8204_EPHYCON_RGMII 0x1100
  24. /* Cicada 8204 Serial LED Control Register */
  25. #define MIIM_CIS8204_SLED_CON 0x1b
  26. #define MIIM_CIS8204_SLEDCON_INIT 0x1115
  27. /* Vitesse VSC8601 Extended PHY Control Register 1 */
  28. #define MII_VSC8601_EPHY_CTL 0x17
  29. #define MII_VSC8601_EPHY_CTL_RGMII_SKEW (1 << 8)
  30. #define PHY_EXT_PAGE_ACCESS 0x1f
  31. #define PHY_EXT_PAGE_ACCESS_GENERAL 0x10
  32. #define PHY_EXT_PAGE_ACCESS_EXTENDED3 0x3
  33. /* Vitesse VSC8574 control register */
  34. #define MIIM_VSC8574_MAC_SERDES_CON 0x10
  35. #define MIIM_VSC8574_MAC_SERDES_ANEG 0x80
  36. #define MIIM_VSC8574_GENERAL18 0x12
  37. #define MIIM_VSC8574_GENERAL19 0x13
  38. /* Vitesse VSC8574 gerenal purpose register 18 */
  39. #define MIIM_VSC8574_18G_SGMII 0x80f0
  40. #define MIIM_VSC8574_18G_QSGMII 0x80e0
  41. #define MIIM_VSC8574_18G_CMDSTAT 0x8000
  42. /* Vitesse VSC8514 control register */
  43. #define MIIM_VSC8514_MAC_SERDES_CON 0x10
  44. #define MIIM_VSC8514_GENERAL18 0x12
  45. #define MIIM_VSC8514_GENERAL19 0x13
  46. #define MIIM_VSC8514_GENERAL23 0x17
  47. /* Vitesse VSC8514 gerenal purpose register 18 */
  48. #define MIIM_VSC8514_18G_QSGMII 0x80e0
  49. #define MIIM_VSC8514_18G_CMDSTAT 0x8000
  50. /* Vitesse VSC8664 Control/Status Register */
  51. #define MIIM_VSC8664_SERDES_AND_SIGDET 0x13
  52. #define MIIM_VSC8664_ADDITIONAL_DEV 0x16
  53. #define MIIM_VSC8664_EPHY_CON 0x17
  54. #define MIIM_VSC8664_LED_CON 0x1E
  55. #define PHY_EXT_PAGE_ACCESS_EXTENDED 0x0001
  56. /* CIS8201 */
  57. static int vitesse_config(struct phy_device *phydev)
  58. {
  59. /* Override PHY config settings */
  60. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
  61. MIIM_CIS82xx_AUXCONSTAT_INIT);
  62. /* Set up the interface mode */
  63. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1,
  64. MIIM_CIS8201_EXTCON1_INIT);
  65. genphy_config_aneg(phydev);
  66. return 0;
  67. }
  68. static int vitesse_parse_status(struct phy_device *phydev)
  69. {
  70. int speed;
  71. int mii_reg;
  72. mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT);
  73. if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX)
  74. phydev->duplex = DUPLEX_FULL;
  75. else
  76. phydev->duplex = DUPLEX_HALF;
  77. speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED;
  78. switch (speed) {
  79. case MIIM_CIS82xx_AUXCONSTAT_GBIT:
  80. phydev->speed = SPEED_1000;
  81. break;
  82. case MIIM_CIS82xx_AUXCONSTAT_100:
  83. phydev->speed = SPEED_100;
  84. break;
  85. default:
  86. phydev->speed = SPEED_10;
  87. break;
  88. }
  89. return 0;
  90. }
  91. static int vitesse_startup(struct phy_device *phydev)
  92. {
  93. int ret;
  94. ret = genphy_update_link(phydev);
  95. if (ret)
  96. return ret;
  97. return vitesse_parse_status(phydev);
  98. }
  99. static int cis8204_config(struct phy_device *phydev)
  100. {
  101. /* Override PHY config settings */
  102. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
  103. MIIM_CIS82xx_AUXCONSTAT_INIT);
  104. genphy_config_aneg(phydev);
  105. if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
  106. (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
  107. (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
  108. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
  109. MIIM_CIS8204_EPHYCON_INIT |
  110. MIIM_CIS8204_EPHYCON_RGMII);
  111. else
  112. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
  113. MIIM_CIS8204_EPHYCON_INIT);
  114. return 0;
  115. }
  116. /* Vitesse VSC8601 */
  117. /* This adds a skew for both TX and RX clocks, so the skew should only be
  118. * applied to "rgmii-id" interfaces. It may not work as expected
  119. * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */
  120. static int vsc8601_add_skew(struct phy_device *phydev)
  121. {
  122. int ret;
  123. ret = phy_read(phydev, MDIO_DEVAD_NONE, MII_VSC8601_EPHY_CTL);
  124. if (ret < 0)
  125. return ret;
  126. ret |= MII_VSC8601_EPHY_CTL_RGMII_SKEW;
  127. return phy_write(phydev, MDIO_DEVAD_NONE, MII_VSC8601_EPHY_CTL, ret);
  128. }
  129. static int vsc8601_config(struct phy_device *phydev)
  130. {
  131. int ret = 0;
  132. if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
  133. ret = vsc8601_add_skew(phydev);
  134. if (ret < 0)
  135. return ret;
  136. return genphy_config_aneg(phydev);
  137. }
  138. static int vsc8574_config(struct phy_device *phydev)
  139. {
  140. u32 val;
  141. /* configure register 19G for MAC */
  142. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
  143. PHY_EXT_PAGE_ACCESS_GENERAL);
  144. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19);
  145. if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
  146. /* set bit 15:14 to '01' for QSGMII mode */
  147. val = (val & 0x3fff) | (1 << 14);
  148. phy_write(phydev, MDIO_DEVAD_NONE,
  149. MIIM_VSC8574_GENERAL19, val);
  150. /* Enable 4 ports MAC QSGMII */
  151. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18,
  152. MIIM_VSC8574_18G_QSGMII);
  153. } else {
  154. /* set bit 15:14 to '00' for SGMII mode */
  155. val = val & 0x3fff;
  156. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL19, val);
  157. /* Enable 4 ports MAC SGMII */
  158. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18,
  159. MIIM_VSC8574_18G_SGMII);
  160. }
  161. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18);
  162. /* When bit 15 is cleared the command has completed */
  163. while (val & MIIM_VSC8574_18G_CMDSTAT)
  164. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_GENERAL18);
  165. /* Enable Serdes Auto-negotiation */
  166. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
  167. PHY_EXT_PAGE_ACCESS_EXTENDED3);
  168. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON);
  169. val = val | MIIM_VSC8574_MAC_SERDES_ANEG;
  170. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8574_MAC_SERDES_CON, val);
  171. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
  172. genphy_config_aneg(phydev);
  173. return 0;
  174. }
  175. static int vsc8514_config(struct phy_device *phydev)
  176. {
  177. u32 val;
  178. int timeout = 1000000;
  179. /* configure register to access 19G */
  180. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
  181. PHY_EXT_PAGE_ACCESS_GENERAL);
  182. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL19);
  183. if (phydev->interface == PHY_INTERFACE_MODE_QSGMII) {
  184. /* set bit 15:14 to '01' for QSGMII mode */
  185. val = (val & 0x3fff) | (1 << 14);
  186. phy_write(phydev, MDIO_DEVAD_NONE,
  187. MIIM_VSC8514_GENERAL19, val);
  188. /* Enable 4 ports MAC QSGMII */
  189. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18,
  190. MIIM_VSC8514_18G_QSGMII);
  191. } else {
  192. /*TODO Add SGMII functionality once spec sheet
  193. * for VSC8514 defines complete functionality
  194. */
  195. }
  196. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18);
  197. /* When bit 15 is cleared the command has completed */
  198. while ((val & MIIM_VSC8514_18G_CMDSTAT) && timeout--)
  199. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL18);
  200. if (0 == timeout) {
  201. printf("PHY 8514 config failed\n");
  202. return -1;
  203. }
  204. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
  205. /* configure register to access 23 */
  206. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23);
  207. /* set bits 10:8 to '000' */
  208. val = (val & 0xf8ff);
  209. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_GENERAL23, val);
  210. /* Enable Serdes Auto-negotiation */
  211. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
  212. PHY_EXT_PAGE_ACCESS_EXTENDED3);
  213. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON);
  214. val = val | MIIM_VSC8574_MAC_SERDES_ANEG;
  215. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON, val);
  216. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
  217. genphy_config_aneg(phydev);
  218. return 0;
  219. }
  220. static int vsc8664_config(struct phy_device *phydev)
  221. {
  222. u32 val;
  223. /* Enable MAC interface auto-negotiation */
  224. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
  225. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_EPHY_CON);
  226. val |= (1 << 13);
  227. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_EPHY_CON, val);
  228. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS,
  229. PHY_EXT_PAGE_ACCESS_EXTENDED);
  230. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_SERDES_AND_SIGDET);
  231. val |= (1 << 11);
  232. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_SERDES_AND_SIGDET, val);
  233. phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
  234. /* Enable LED blink */
  235. val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_LED_CON);
  236. val &= ~(1 << 2);
  237. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8664_LED_CON, val);
  238. genphy_config_aneg(phydev);
  239. return 0;
  240. }
  241. static struct phy_driver VSC8211_driver = {
  242. .name = "Vitesse VSC8211",
  243. .uid = 0xfc4b0,
  244. .mask = 0xffff0,
  245. .features = PHY_GBIT_FEATURES,
  246. .config = &vitesse_config,
  247. .startup = &vitesse_startup,
  248. .shutdown = &genphy_shutdown,
  249. };
  250. static struct phy_driver VSC8221_driver = {
  251. .name = "Vitesse VSC8221",
  252. .uid = 0xfc550,
  253. .mask = 0xffff0,
  254. .features = PHY_GBIT_FEATURES,
  255. .config = &genphy_config_aneg,
  256. .startup = &vitesse_startup,
  257. .shutdown = &genphy_shutdown,
  258. };
  259. static struct phy_driver VSC8244_driver = {
  260. .name = "Vitesse VSC8244",
  261. .uid = 0xfc6c0,
  262. .mask = 0xffff0,
  263. .features = PHY_GBIT_FEATURES,
  264. .config = &genphy_config_aneg,
  265. .startup = &vitesse_startup,
  266. .shutdown = &genphy_shutdown,
  267. };
  268. static struct phy_driver VSC8234_driver = {
  269. .name = "Vitesse VSC8234",
  270. .uid = 0xfc620,
  271. .mask = 0xffff0,
  272. .features = PHY_GBIT_FEATURES,
  273. .config = &genphy_config_aneg,
  274. .startup = &vitesse_startup,
  275. .shutdown = &genphy_shutdown,
  276. };
  277. static struct phy_driver VSC8574_driver = {
  278. .name = "Vitesse VSC8574",
  279. .uid = 0x704a0,
  280. .mask = 0xffff0,
  281. .features = PHY_GBIT_FEATURES,
  282. .config = &vsc8574_config,
  283. .startup = &vitesse_startup,
  284. .shutdown = &genphy_shutdown,
  285. };
  286. static struct phy_driver VSC8514_driver = {
  287. .name = "Vitesse VSC8514",
  288. .uid = 0x70670,
  289. .mask = 0xffff0,
  290. .features = PHY_GBIT_FEATURES,
  291. .config = &vsc8514_config,
  292. .startup = &vitesse_startup,
  293. .shutdown = &genphy_shutdown,
  294. };
  295. static struct phy_driver VSC8584_driver = {
  296. .name = "Vitesse VSC8584",
  297. .uid = 0x707c0,
  298. .mask = 0xffff0,
  299. .features = PHY_GBIT_FEATURES,
  300. .config = &vsc8574_config,
  301. .startup = &vitesse_startup,
  302. .shutdown = &genphy_shutdown,
  303. };
  304. static struct phy_driver VSC8601_driver = {
  305. .name = "Vitesse VSC8601",
  306. .uid = 0x70420,
  307. .mask = 0xffff0,
  308. .features = PHY_GBIT_FEATURES,
  309. .config = &vsc8601_config,
  310. .startup = &vitesse_startup,
  311. .shutdown = &genphy_shutdown,
  312. };
  313. static struct phy_driver VSC8641_driver = {
  314. .name = "Vitesse VSC8641",
  315. .uid = 0x70430,
  316. .mask = 0xffff0,
  317. .features = PHY_GBIT_FEATURES,
  318. .config = &genphy_config_aneg,
  319. .startup = &vitesse_startup,
  320. .shutdown = &genphy_shutdown,
  321. };
  322. static struct phy_driver VSC8662_driver = {
  323. .name = "Vitesse VSC8662",
  324. .uid = 0x70660,
  325. .mask = 0xffff0,
  326. .features = PHY_GBIT_FEATURES,
  327. .config = &genphy_config_aneg,
  328. .startup = &vitesse_startup,
  329. .shutdown = &genphy_shutdown,
  330. };
  331. static struct phy_driver VSC8664_driver = {
  332. .name = "Vitesse VSC8664",
  333. .uid = 0x70660,
  334. .mask = 0xffff0,
  335. .features = PHY_GBIT_FEATURES,
  336. .config = &vsc8664_config,
  337. .startup = &vitesse_startup,
  338. .shutdown = &genphy_shutdown,
  339. };
  340. /* Vitesse bought Cicada, so we'll put these here */
  341. static struct phy_driver cis8201_driver = {
  342. .name = "CIS8201",
  343. .uid = 0xfc410,
  344. .mask = 0xffff0,
  345. .features = PHY_GBIT_FEATURES,
  346. .config = &vitesse_config,
  347. .startup = &vitesse_startup,
  348. .shutdown = &genphy_shutdown,
  349. };
  350. static struct phy_driver cis8204_driver = {
  351. .name = "Cicada Cis8204",
  352. .uid = 0xfc440,
  353. .mask = 0xffff0,
  354. .features = PHY_GBIT_FEATURES,
  355. .config = &cis8204_config,
  356. .startup = &vitesse_startup,
  357. .shutdown = &genphy_shutdown,
  358. };
  359. int phy_vitesse_init(void)
  360. {
  361. phy_register(&VSC8641_driver);
  362. phy_register(&VSC8601_driver);
  363. phy_register(&VSC8234_driver);
  364. phy_register(&VSC8244_driver);
  365. phy_register(&VSC8211_driver);
  366. phy_register(&VSC8221_driver);
  367. phy_register(&VSC8574_driver);
  368. phy_register(&VSC8584_driver);
  369. phy_register(&VSC8514_driver);
  370. phy_register(&VSC8662_driver);
  371. phy_register(&VSC8664_driver);
  372. phy_register(&cis8201_driver);
  373. phy_register(&cis8204_driver);
  374. return 0;
  375. }