vitesse.c 10.0 KB

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