vitesse.c 12 KB

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