vitesse.c 12 KB

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