micrel_ksz90x1.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Micrel PHY drivers
  4. *
  5. * Copyright 2010-2011 Freescale Semiconductor, Inc.
  6. * author Andy Fleming
  7. * (C) 2012 NetModule AG, David Andrey, added KSZ9031
  8. * (C) Copyright 2017 Adaptrum, Inc.
  9. * Written by Alexandru Gagniuc <alex.g@adaptrum.com> for Adaptrum, Inc.
  10. */
  11. #include <config.h>
  12. #include <common.h>
  13. #include <dm.h>
  14. #include <errno.h>
  15. #include <micrel.h>
  16. #include <phy.h>
  17. /*
  18. * KSZ9021 - KSZ9031 common
  19. */
  20. #define MII_KSZ90xx_PHY_CTL 0x1f
  21. #define MIIM_KSZ90xx_PHYCTL_1000 (1 << 6)
  22. #define MIIM_KSZ90xx_PHYCTL_100 (1 << 5)
  23. #define MIIM_KSZ90xx_PHYCTL_10 (1 << 4)
  24. #define MIIM_KSZ90xx_PHYCTL_DUPLEX (1 << 3)
  25. /* KSZ9021 PHY Registers */
  26. #define MII_KSZ9021_EXTENDED_CTRL 0x0b
  27. #define MII_KSZ9021_EXTENDED_DATAW 0x0c
  28. #define MII_KSZ9021_EXTENDED_DATAR 0x0d
  29. #define CTRL1000_PREFER_MASTER (1 << 10)
  30. #define CTRL1000_CONFIG_MASTER (1 << 11)
  31. #define CTRL1000_MANUAL_CONFIG (1 << 12)
  32. /* KSZ9031 PHY Registers */
  33. #define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
  34. #define MII_KSZ9031_MMD_REG_DATA 0x0e
  35. static int ksz90xx_startup(struct phy_device *phydev)
  36. {
  37. unsigned phy_ctl;
  38. int ret;
  39. ret = genphy_update_link(phydev);
  40. if (ret)
  41. return ret;
  42. phy_ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ90xx_PHY_CTL);
  43. if (phy_ctl & MIIM_KSZ90xx_PHYCTL_DUPLEX)
  44. phydev->duplex = DUPLEX_FULL;
  45. else
  46. phydev->duplex = DUPLEX_HALF;
  47. if (phy_ctl & MIIM_KSZ90xx_PHYCTL_1000)
  48. phydev->speed = SPEED_1000;
  49. else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_100)
  50. phydev->speed = SPEED_100;
  51. else if (phy_ctl & MIIM_KSZ90xx_PHYCTL_10)
  52. phydev->speed = SPEED_10;
  53. return 0;
  54. }
  55. /* Common OF config bits for KSZ9021 and KSZ9031 */
  56. #ifdef CONFIG_DM_ETH
  57. struct ksz90x1_reg_field {
  58. const char *name;
  59. const u8 size; /* Size of the bitfield, in bits */
  60. const u8 off; /* Offset from bit 0 */
  61. const u8 dflt; /* Default value */
  62. };
  63. struct ksz90x1_ofcfg {
  64. const u16 reg;
  65. const u16 devad;
  66. const struct ksz90x1_reg_field *grp;
  67. const u16 grpsz;
  68. };
  69. static const struct ksz90x1_reg_field ksz90x1_rxd_grp[] = {
  70. { "rxd0-skew-ps", 4, 0, 0x7 }, { "rxd1-skew-ps", 4, 4, 0x7 },
  71. { "rxd2-skew-ps", 4, 8, 0x7 }, { "rxd3-skew-ps", 4, 12, 0x7 }
  72. };
  73. static const struct ksz90x1_reg_field ksz90x1_txd_grp[] = {
  74. { "txd0-skew-ps", 4, 0, 0x7 }, { "txd1-skew-ps", 4, 4, 0x7 },
  75. { "txd2-skew-ps", 4, 8, 0x7 }, { "txd3-skew-ps", 4, 12, 0x7 },
  76. };
  77. static const struct ksz90x1_reg_field ksz9021_clk_grp[] = {
  78. { "txen-skew-ps", 4, 0, 0x7 }, { "txc-skew-ps", 4, 4, 0x7 },
  79. { "rxdv-skew-ps", 4, 8, 0x7 }, { "rxc-skew-ps", 4, 12, 0x7 },
  80. };
  81. static const struct ksz90x1_reg_field ksz9031_ctl_grp[] = {
  82. { "txen-skew-ps", 4, 0, 0x7 }, { "rxdv-skew-ps", 4, 4, 0x7 }
  83. };
  84. static const struct ksz90x1_reg_field ksz9031_clk_grp[] = {
  85. { "rxc-skew-ps", 5, 0, 0xf }, { "txc-skew-ps", 5, 5, 0xf }
  86. };
  87. static int ksz90x1_of_config_group(struct phy_device *phydev,
  88. struct ksz90x1_ofcfg *ofcfg)
  89. {
  90. struct udevice *dev = phydev->dev;
  91. struct phy_driver *drv = phydev->drv;
  92. const int ps_to_regval = 60;
  93. int val[4];
  94. int i, changed = 0, offset, max;
  95. u16 regval = 0;
  96. if (!drv || !drv->writeext)
  97. return -EOPNOTSUPP;
  98. for (i = 0; i < ofcfg->grpsz; i++) {
  99. val[i] = dev_read_u32_default(dev, ofcfg->grp[i].name, ~0);
  100. offset = ofcfg->grp[i].off;
  101. if (val[i] == -1) {
  102. /* Default register value for KSZ9021 */
  103. regval |= ofcfg->grp[i].dflt << offset;
  104. } else {
  105. changed = 1; /* Value was changed in OF */
  106. /* Calculate the register value and fix corner cases */
  107. if (val[i] > ps_to_regval * 0xf) {
  108. max = (1 << ofcfg->grp[i].size) - 1;
  109. regval |= max << offset;
  110. } else {
  111. regval |= (val[i] / ps_to_regval) << offset;
  112. }
  113. }
  114. }
  115. if (!changed)
  116. return 0;
  117. return drv->writeext(phydev, 0, ofcfg->devad, ofcfg->reg, regval);
  118. }
  119. static int ksz9021_of_config(struct phy_device *phydev)
  120. {
  121. struct ksz90x1_ofcfg ofcfg[] = {
  122. { MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW, 0, ksz90x1_rxd_grp, 4 },
  123. { MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW, 0, ksz90x1_txd_grp, 4 },
  124. { MII_KSZ9021_EXT_RGMII_CLOCK_SKEW, 0, ksz9021_clk_grp, 4 },
  125. };
  126. int i, ret = 0;
  127. for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
  128. ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
  129. if (ret)
  130. return ret;
  131. }
  132. return 0;
  133. }
  134. static int ksz9031_of_config(struct phy_device *phydev)
  135. {
  136. struct ksz90x1_ofcfg ofcfg[] = {
  137. { MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW, 2, ksz9031_ctl_grp, 2 },
  138. { MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW, 2, ksz90x1_rxd_grp, 4 },
  139. { MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW, 2, ksz90x1_txd_grp, 4 },
  140. { MII_KSZ9031_EXT_RGMII_CLOCK_SKEW, 2, ksz9031_clk_grp, 2 },
  141. };
  142. int i, ret = 0;
  143. for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
  144. ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
  145. if (ret)
  146. return ret;
  147. }
  148. return 0;
  149. }
  150. static int ksz9031_center_flp_timing(struct phy_device *phydev)
  151. {
  152. struct phy_driver *drv = phydev->drv;
  153. int ret = 0;
  154. if (!drv || !drv->writeext)
  155. return -EOPNOTSUPP;
  156. ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_LO, 0x1A80);
  157. if (ret)
  158. return ret;
  159. ret = drv->writeext(phydev, 0, 0, MII_KSZ9031_FLP_BURST_TX_HI, 0x6);
  160. return ret;
  161. }
  162. #else /* !CONFIG_DM_ETH */
  163. static int ksz9021_of_config(struct phy_device *phydev)
  164. {
  165. return 0;
  166. }
  167. static int ksz9031_of_config(struct phy_device *phydev)
  168. {
  169. return 0;
  170. }
  171. static int ksz9031_center_flp_timing(struct phy_device *phydev)
  172. {
  173. return 0;
  174. }
  175. #endif
  176. /*
  177. * KSZ9021
  178. */
  179. int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val)
  180. {
  181. /* extended registers */
  182. phy_write(phydev, MDIO_DEVAD_NONE,
  183. MII_KSZ9021_EXTENDED_CTRL, regnum | 0x8000);
  184. return phy_write(phydev, MDIO_DEVAD_NONE,
  185. MII_KSZ9021_EXTENDED_DATAW, val);
  186. }
  187. int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum)
  188. {
  189. /* extended registers */
  190. phy_write(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_CTRL, regnum);
  191. return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9021_EXTENDED_DATAR);
  192. }
  193. static int ksz9021_phy_extread(struct phy_device *phydev, int addr, int devaddr,
  194. int regnum)
  195. {
  196. return ksz9021_phy_extended_read(phydev, regnum);
  197. }
  198. static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
  199. int devaddr, int regnum, u16 val)
  200. {
  201. return ksz9021_phy_extended_write(phydev, regnum, val);
  202. }
  203. static int ksz9021_config(struct phy_device *phydev)
  204. {
  205. unsigned ctrl1000 = 0;
  206. const unsigned master = CTRL1000_PREFER_MASTER |
  207. CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
  208. unsigned features = phydev->drv->features;
  209. int ret;
  210. ret = ksz9021_of_config(phydev);
  211. if (ret)
  212. return ret;
  213. if (env_get("disable_giga"))
  214. features &= ~(SUPPORTED_1000baseT_Half |
  215. SUPPORTED_1000baseT_Full);
  216. /* force master mode for 1000BaseT due to chip errata */
  217. if (features & SUPPORTED_1000baseT_Half)
  218. ctrl1000 |= ADVERTISE_1000HALF | master;
  219. if (features & SUPPORTED_1000baseT_Full)
  220. ctrl1000 |= ADVERTISE_1000FULL | master;
  221. phydev->advertising = features;
  222. phydev->supported = features;
  223. phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, ctrl1000);
  224. genphy_config_aneg(phydev);
  225. genphy_restart_aneg(phydev);
  226. return 0;
  227. }
  228. static struct phy_driver ksz9021_driver = {
  229. .name = "Micrel ksz9021",
  230. .uid = 0x221610,
  231. .mask = 0xfffff0,
  232. .features = PHY_GBIT_FEATURES,
  233. .config = &ksz9021_config,
  234. .startup = &ksz90xx_startup,
  235. .shutdown = &genphy_shutdown,
  236. .writeext = &ksz9021_phy_extwrite,
  237. .readext = &ksz9021_phy_extread,
  238. };
  239. /*
  240. * KSZ9031
  241. */
  242. int ksz9031_phy_extended_write(struct phy_device *phydev,
  243. int devaddr, int regnum, u16 mode, u16 val)
  244. {
  245. /*select register addr for mmd*/
  246. phy_write(phydev, MDIO_DEVAD_NONE,
  247. MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
  248. /*select register for mmd*/
  249. phy_write(phydev, MDIO_DEVAD_NONE,
  250. MII_KSZ9031_MMD_REG_DATA, regnum);
  251. /*setup mode*/
  252. phy_write(phydev, MDIO_DEVAD_NONE,
  253. MII_KSZ9031_MMD_ACCES_CTRL, (mode | devaddr));
  254. /*write the value*/
  255. return phy_write(phydev, MDIO_DEVAD_NONE,
  256. MII_KSZ9031_MMD_REG_DATA, val);
  257. }
  258. int ksz9031_phy_extended_read(struct phy_device *phydev, int devaddr,
  259. int regnum, u16 mode)
  260. {
  261. phy_write(phydev, MDIO_DEVAD_NONE,
  262. MII_KSZ9031_MMD_ACCES_CTRL, devaddr);
  263. phy_write(phydev, MDIO_DEVAD_NONE,
  264. MII_KSZ9031_MMD_REG_DATA, regnum);
  265. phy_write(phydev, MDIO_DEVAD_NONE,
  266. MII_KSZ9031_MMD_ACCES_CTRL, (devaddr | mode));
  267. return phy_read(phydev, MDIO_DEVAD_NONE, MII_KSZ9031_MMD_REG_DATA);
  268. }
  269. static int ksz9031_phy_extread(struct phy_device *phydev, int addr, int devaddr,
  270. int regnum)
  271. {
  272. return ksz9031_phy_extended_read(phydev, devaddr, regnum,
  273. MII_KSZ9031_MOD_DATA_NO_POST_INC);
  274. }
  275. static int ksz9031_phy_extwrite(struct phy_device *phydev, int addr,
  276. int devaddr, int regnum, u16 val)
  277. {
  278. return ksz9031_phy_extended_write(phydev, devaddr, regnum,
  279. MII_KSZ9031_MOD_DATA_POST_INC_RW, val);
  280. }
  281. static int ksz9031_config(struct phy_device *phydev)
  282. {
  283. int ret;
  284. ret = ksz9031_of_config(phydev);
  285. if (ret)
  286. return ret;
  287. ret = ksz9031_center_flp_timing(phydev);
  288. if (ret)
  289. return ret;
  290. /* add an option to disable the gigabit feature of this PHY */
  291. if (env_get("disable_giga")) {
  292. unsigned features;
  293. unsigned bmcr;
  294. /* disable speed 1000 in features supported by the PHY */
  295. features = phydev->drv->features;
  296. features &= ~(SUPPORTED_1000baseT_Half |
  297. SUPPORTED_1000baseT_Full);
  298. phydev->advertising = phydev->supported = features;
  299. /* disable speed 1000 in Basic Control Register */
  300. bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
  301. bmcr &= ~(1 << 6);
  302. phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr);
  303. /* disable speed 1000 in 1000Base-T Control Register */
  304. phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, 0);
  305. /* start autoneg */
  306. genphy_config_aneg(phydev);
  307. genphy_restart_aneg(phydev);
  308. return 0;
  309. }
  310. return genphy_config(phydev);
  311. }
  312. static struct phy_driver ksz9031_driver = {
  313. .name = "Micrel ksz9031",
  314. .uid = 0x221620,
  315. .mask = 0xfffff0,
  316. .features = PHY_GBIT_FEATURES,
  317. .config = &ksz9031_config,
  318. .startup = &ksz90xx_startup,
  319. .shutdown = &genphy_shutdown,
  320. .writeext = &ksz9031_phy_extwrite,
  321. .readext = &ksz9031_phy_extread,
  322. };
  323. int phy_micrel_ksz90x1_init(void)
  324. {
  325. phy_register(&ksz9021_driver);
  326. phy_register(&ksz9031_driver);
  327. return 0;
  328. }