vitesse.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. #include <miiphy.h>
  23. /* Cicada Auxiliary Control/Status Register */
  24. #define MIIM_CIS82xx_AUX_CONSTAT 0x1c
  25. #define MIIM_CIS82xx_AUXCONSTAT_INIT 0x0004
  26. #define MIIM_CIS82xx_AUXCONSTAT_DUPLEX 0x0020
  27. #define MIIM_CIS82xx_AUXCONSTAT_SPEED 0x0018
  28. #define MIIM_CIS82xx_AUXCONSTAT_GBIT 0x0010
  29. #define MIIM_CIS82xx_AUXCONSTAT_100 0x0008
  30. /* Cicada Extended Control Register 1 */
  31. #define MIIM_CIS82xx_EXT_CON1 0x17
  32. #define MIIM_CIS8201_EXTCON1_INIT 0x0000
  33. /* Cicada 8204 Extended PHY Control Register 1 */
  34. #define MIIM_CIS8204_EPHY_CON 0x17
  35. #define MIIM_CIS8204_EPHYCON_INIT 0x0006
  36. #define MIIM_CIS8204_EPHYCON_RGMII 0x1100
  37. /* Cicada 8204 Serial LED Control Register */
  38. #define MIIM_CIS8204_SLED_CON 0x1b
  39. #define MIIM_CIS8204_SLEDCON_INIT 0x1115
  40. /* Vitesse VSC8601 Extended PHY Control Register 1 */
  41. #define MIIM_VSC8601_EPHY_CON 0x17
  42. #define MIIM_VSC8601_EPHY_CON_INIT_SKEW 0x1120
  43. #define MIIM_VSC8601_SKEW_CTRL 0x1c
  44. #define PHY_EXT_PAGE_ACCESS 0x1f
  45. #define PHY_EXT_PAGE_ACCESS_GENERAL 0x10
  46. #define PHY_EXT_PAGE_ACCESS_EXTENDED3 0x3
  47. /* Vitesse VSC8574 control register */
  48. #define MIIM_VSC8574_MAC_SERDES_CON 0x10
  49. #define MIIM_VSC8574_MAC_SERDES_ANEG 0x80
  50. #define MIIM_VSC8574_GENERAL18 0x12
  51. #define MIIM_VSC8574_GENERAL19 0x13
  52. /* Vitesse VSC8574 gerenal purpose register 18 */
  53. #define MIIM_VSC8574_18G_SGMII 0x80f0
  54. #define MIIM_VSC8574_18G_QSGMII 0x80e0
  55. #define MIIM_VSC8574_18G_CMDSTAT 0x8000
  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. genphy_update_link(phydev);
  94. vitesse_parse_status(phydev);
  95. return 0;
  96. }
  97. static int cis8204_config(struct phy_device *phydev)
  98. {
  99. /* Override PHY config settings */
  100. phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
  101. MIIM_CIS82xx_AUXCONSTAT_INIT);
  102. genphy_config_aneg(phydev);
  103. if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
  104. (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 regiser 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 struct phy_driver VSC8211_driver = {
  173. .name = "Vitesse VSC8211",
  174. .uid = 0xfc4b0,
  175. .mask = 0xffff0,
  176. .features = PHY_GBIT_FEATURES,
  177. .config = &vitesse_config,
  178. .startup = &vitesse_startup,
  179. .shutdown = &genphy_shutdown,
  180. };
  181. static struct phy_driver VSC8221_driver = {
  182. .name = "Vitesse VSC8221",
  183. .uid = 0xfc550,
  184. .mask = 0xffff0,
  185. .features = PHY_GBIT_FEATURES,
  186. .config = &genphy_config_aneg,
  187. .startup = &vitesse_startup,
  188. .shutdown = &genphy_shutdown,
  189. };
  190. static struct phy_driver VSC8244_driver = {
  191. .name = "Vitesse VSC8244",
  192. .uid = 0xfc6c0,
  193. .mask = 0xffff0,
  194. .features = PHY_GBIT_FEATURES,
  195. .config = &genphy_config_aneg,
  196. .startup = &vitesse_startup,
  197. .shutdown = &genphy_shutdown,
  198. };
  199. static struct phy_driver VSC8234_driver = {
  200. .name = "Vitesse VSC8234",
  201. .uid = 0xfc620,
  202. .mask = 0xffff0,
  203. .features = PHY_GBIT_FEATURES,
  204. .config = &genphy_config_aneg,
  205. .startup = &vitesse_startup,
  206. .shutdown = &genphy_shutdown,
  207. };
  208. static struct phy_driver VSC8574_driver = {
  209. .name = "Vitesse VSC8574",
  210. .uid = 0x704a0,
  211. .mask = 0xffff0,
  212. .features = PHY_GBIT_FEATURES,
  213. .config = &vsc8574_config,
  214. .startup = &vitesse_startup,
  215. .shutdown = &genphy_shutdown,
  216. };
  217. static struct phy_driver VSC8601_driver = {
  218. .name = "Vitesse VSC8601",
  219. .uid = 0x70420,
  220. .mask = 0xffff0,
  221. .features = PHY_GBIT_FEATURES,
  222. .config = &vsc8601_config,
  223. .startup = &vitesse_startup,
  224. .shutdown = &genphy_shutdown,
  225. };
  226. static struct phy_driver VSC8641_driver = {
  227. .name = "Vitesse VSC8641",
  228. .uid = 0x70430,
  229. .mask = 0xffff0,
  230. .features = PHY_GBIT_FEATURES,
  231. .config = &genphy_config_aneg,
  232. .startup = &vitesse_startup,
  233. .shutdown = &genphy_shutdown,
  234. };
  235. static struct phy_driver VSC8662_driver = {
  236. .name = "Vitesse VSC8662",
  237. .uid = 0x70660,
  238. .mask = 0xffff0,
  239. .features = PHY_GBIT_FEATURES,
  240. .config = &genphy_config_aneg,
  241. .startup = &vitesse_startup,
  242. .shutdown = &genphy_shutdown,
  243. };
  244. /* Vitesse bought Cicada, so we'll put these here */
  245. static struct phy_driver cis8201_driver = {
  246. .name = "CIS8201",
  247. .uid = 0xfc410,
  248. .mask = 0xffff0,
  249. .features = PHY_GBIT_FEATURES,
  250. .config = &vitesse_config,
  251. .startup = &vitesse_startup,
  252. .shutdown = &genphy_shutdown,
  253. };
  254. static struct phy_driver cis8204_driver = {
  255. .name = "Cicada Cis8204",
  256. .uid = 0xfc440,
  257. .mask = 0xffff0,
  258. .features = PHY_GBIT_FEATURES,
  259. .config = &cis8204_config,
  260. .startup = &vitesse_startup,
  261. .shutdown = &genphy_shutdown,
  262. };
  263. int phy_vitesse_init(void)
  264. {
  265. phy_register(&VSC8641_driver);
  266. phy_register(&VSC8601_driver);
  267. phy_register(&VSC8234_driver);
  268. phy_register(&VSC8244_driver);
  269. phy_register(&VSC8211_driver);
  270. phy_register(&VSC8221_driver);
  271. phy_register(&VSC8574_driver);
  272. phy_register(&VSC8662_driver);
  273. phy_register(&cis8201_driver);
  274. phy_register(&cis8204_driver);
  275. return 0;
  276. }