vsc8244.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /*
  2. * This file is part of the Chelsio T2 Ethernet driver.
  3. *
  4. * Copyright (C) 2005 Chelsio Communications. All rights reserved.
  5. *
  6. * This program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  8. * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
  9. * release for licensing terms and conditions.
  10. */
  11. #include "common.h"
  12. #include "cphy.h"
  13. #include "elmer0.h"
  14. #ifndef ADVERTISE_PAUSE_CAP
  15. # define ADVERTISE_PAUSE_CAP 0x400
  16. #endif
  17. #ifndef ADVERTISE_PAUSE_ASYM
  18. # define ADVERTISE_PAUSE_ASYM 0x800
  19. #endif
  20. /* Gigabit MII registers */
  21. #ifndef MII_CTRL1000
  22. # define MII_CTRL1000 9
  23. #endif
  24. #ifndef ADVERTISE_1000FULL
  25. # define ADVERTISE_1000FULL 0x200
  26. # define ADVERTISE_1000HALF 0x100
  27. #endif
  28. /* VSC8244 PHY specific registers. */
  29. enum {
  30. VSC8244_INTR_ENABLE = 25,
  31. VSC8244_INTR_STATUS = 26,
  32. VSC8244_AUX_CTRL_STAT = 28,
  33. };
  34. enum {
  35. VSC_INTR_RX_ERR = 1 << 0,
  36. VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */
  37. VSC_INTR_CABLE = 1 << 2, /* cable impairment */
  38. VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */
  39. VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */
  40. VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */
  41. VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */
  42. VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */
  43. VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */
  44. VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */
  45. VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */
  46. VSC_INTR_LINK_CHG = 1 << 13, /* link change */
  47. VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */
  48. };
  49. #define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \
  50. VSC_INTR_NEG_DONE)
  51. #define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \
  52. VSC_INTR_ENABLE)
  53. /* PHY specific auxiliary control & status register fields */
  54. #define S_ACSR_ACTIPHY_TMR 0
  55. #define M_ACSR_ACTIPHY_TMR 0x3
  56. #define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR)
  57. #define S_ACSR_SPEED 3
  58. #define M_ACSR_SPEED 0x3
  59. #define G_ACSR_SPEED(x) (((x) >> S_ACSR_SPEED) & M_ACSR_SPEED)
  60. #define S_ACSR_DUPLEX 5
  61. #define F_ACSR_DUPLEX (1 << S_ACSR_DUPLEX)
  62. #define S_ACSR_ACTIPHY 6
  63. #define F_ACSR_ACTIPHY (1 << S_ACSR_ACTIPHY)
  64. /*
  65. * Reset the PHY. This PHY completes reset immediately so we never wait.
  66. */
  67. static int vsc8244_reset(struct cphy *cphy, int wait)
  68. {
  69. int err;
  70. unsigned int ctl;
  71. err = simple_mdio_read(cphy, MII_BMCR, &ctl);
  72. if (err)
  73. return err;
  74. ctl &= ~BMCR_PDOWN;
  75. ctl |= BMCR_RESET;
  76. return simple_mdio_write(cphy, MII_BMCR, ctl);
  77. }
  78. static int vsc8244_intr_enable(struct cphy *cphy)
  79. {
  80. simple_mdio_write(cphy, VSC8244_INTR_ENABLE, INTR_MASK);
  81. /* Enable interrupts through Elmer */
  82. if (t1_is_asic(cphy->adapter)) {
  83. u32 elmer;
  84. t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
  85. elmer |= ELMER0_GP_BIT1;
  86. if (is_T2(cphy->adapter))
  87. elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4;
  88. t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
  89. }
  90. return 0;
  91. }
  92. static int vsc8244_intr_disable(struct cphy *cphy)
  93. {
  94. simple_mdio_write(cphy, VSC8244_INTR_ENABLE, 0);
  95. if (t1_is_asic(cphy->adapter)) {
  96. u32 elmer;
  97. t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
  98. elmer &= ~ELMER0_GP_BIT1;
  99. if (is_T2(cphy->adapter))
  100. elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4);
  101. t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
  102. }
  103. return 0;
  104. }
  105. static int vsc8244_intr_clear(struct cphy *cphy)
  106. {
  107. u32 val;
  108. u32 elmer;
  109. /* Clear PHY interrupts by reading the register. */
  110. simple_mdio_read(cphy, VSC8244_INTR_ENABLE, &val);
  111. if (t1_is_asic(cphy->adapter)) {
  112. t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
  113. elmer |= ELMER0_GP_BIT1;
  114. if (is_T2(cphy->adapter))
  115. elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4;
  116. t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
  117. }
  118. return 0;
  119. }
  120. /*
  121. * Force the PHY speed and duplex. This also disables auto-negotiation, except
  122. * for 1Gb/s, where auto-negotiation is mandatory.
  123. */
  124. static int vsc8244_set_speed_duplex(struct cphy *phy, int speed, int duplex)
  125. {
  126. int err;
  127. unsigned int ctl;
  128. err = simple_mdio_read(phy, MII_BMCR, &ctl);
  129. if (err)
  130. return err;
  131. if (speed >= 0) {
  132. ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
  133. if (speed == SPEED_100)
  134. ctl |= BMCR_SPEED100;
  135. else if (speed == SPEED_1000)
  136. ctl |= BMCR_SPEED1000;
  137. }
  138. if (duplex >= 0) {
  139. ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE);
  140. if (duplex == DUPLEX_FULL)
  141. ctl |= BMCR_FULLDPLX;
  142. }
  143. if (ctl & BMCR_SPEED1000) /* auto-negotiation required for 1Gb/s */
  144. ctl |= BMCR_ANENABLE;
  145. return simple_mdio_write(phy, MII_BMCR, ctl);
  146. }
  147. int t1_mdio_set_bits(struct cphy *phy, int mmd, int reg, unsigned int bits)
  148. {
  149. int ret;
  150. unsigned int val;
  151. ret = mdio_read(phy, mmd, reg, &val);
  152. if (!ret)
  153. ret = mdio_write(phy, mmd, reg, val | bits);
  154. return ret;
  155. }
  156. static int vsc8244_autoneg_enable(struct cphy *cphy)
  157. {
  158. return t1_mdio_set_bits(cphy, 0, MII_BMCR,
  159. BMCR_ANENABLE | BMCR_ANRESTART);
  160. }
  161. static int vsc8244_autoneg_restart(struct cphy *cphy)
  162. {
  163. return t1_mdio_set_bits(cphy, 0, MII_BMCR, BMCR_ANRESTART);
  164. }
  165. static int vsc8244_advertise(struct cphy *phy, unsigned int advertise_map)
  166. {
  167. int err;
  168. unsigned int val = 0;
  169. err = simple_mdio_read(phy, MII_CTRL1000, &val);
  170. if (err)
  171. return err;
  172. val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
  173. if (advertise_map & ADVERTISED_1000baseT_Half)
  174. val |= ADVERTISE_1000HALF;
  175. if (advertise_map & ADVERTISED_1000baseT_Full)
  176. val |= ADVERTISE_1000FULL;
  177. err = simple_mdio_write(phy, MII_CTRL1000, val);
  178. if (err)
  179. return err;
  180. val = 1;
  181. if (advertise_map & ADVERTISED_10baseT_Half)
  182. val |= ADVERTISE_10HALF;
  183. if (advertise_map & ADVERTISED_10baseT_Full)
  184. val |= ADVERTISE_10FULL;
  185. if (advertise_map & ADVERTISED_100baseT_Half)
  186. val |= ADVERTISE_100HALF;
  187. if (advertise_map & ADVERTISED_100baseT_Full)
  188. val |= ADVERTISE_100FULL;
  189. if (advertise_map & ADVERTISED_PAUSE)
  190. val |= ADVERTISE_PAUSE_CAP;
  191. if (advertise_map & ADVERTISED_ASYM_PAUSE)
  192. val |= ADVERTISE_PAUSE_ASYM;
  193. return simple_mdio_write(phy, MII_ADVERTISE, val);
  194. }
  195. static int vsc8244_get_link_status(struct cphy *cphy, int *link_ok,
  196. int *speed, int *duplex, int *fc)
  197. {
  198. unsigned int bmcr, status, lpa, adv;
  199. int err, sp = -1, dplx = -1, pause = 0;
  200. err = simple_mdio_read(cphy, MII_BMCR, &bmcr);
  201. if (!err)
  202. err = simple_mdio_read(cphy, MII_BMSR, &status);
  203. if (err)
  204. return err;
  205. if (link_ok) {
  206. /*
  207. * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
  208. * once more to get the current link state.
  209. */
  210. if (!(status & BMSR_LSTATUS))
  211. err = simple_mdio_read(cphy, MII_BMSR, &status);
  212. if (err)
  213. return err;
  214. *link_ok = (status & BMSR_LSTATUS) != 0;
  215. }
  216. if (!(bmcr & BMCR_ANENABLE)) {
  217. dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
  218. if (bmcr & BMCR_SPEED1000)
  219. sp = SPEED_1000;
  220. else if (bmcr & BMCR_SPEED100)
  221. sp = SPEED_100;
  222. else
  223. sp = SPEED_10;
  224. } else if (status & BMSR_ANEGCOMPLETE) {
  225. err = simple_mdio_read(cphy, VSC8244_AUX_CTRL_STAT, &status);
  226. if (err)
  227. return err;
  228. dplx = (status & F_ACSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
  229. sp = G_ACSR_SPEED(status);
  230. if (sp == 0)
  231. sp = SPEED_10;
  232. else if (sp == 1)
  233. sp = SPEED_100;
  234. else
  235. sp = SPEED_1000;
  236. if (fc && dplx == DUPLEX_FULL) {
  237. err = simple_mdio_read(cphy, MII_LPA, &lpa);
  238. if (!err)
  239. err = simple_mdio_read(cphy, MII_ADVERTISE,
  240. &adv);
  241. if (err)
  242. return err;
  243. if (lpa & adv & ADVERTISE_PAUSE_CAP)
  244. pause = PAUSE_RX | PAUSE_TX;
  245. else if ((lpa & ADVERTISE_PAUSE_CAP) &&
  246. (lpa & ADVERTISE_PAUSE_ASYM) &&
  247. (adv & ADVERTISE_PAUSE_ASYM))
  248. pause = PAUSE_TX;
  249. else if ((lpa & ADVERTISE_PAUSE_ASYM) &&
  250. (adv & ADVERTISE_PAUSE_CAP))
  251. pause = PAUSE_RX;
  252. }
  253. }
  254. if (speed)
  255. *speed = sp;
  256. if (duplex)
  257. *duplex = dplx;
  258. if (fc)
  259. *fc = pause;
  260. return 0;
  261. }
  262. static int vsc8244_intr_handler(struct cphy *cphy)
  263. {
  264. unsigned int cause;
  265. int err, cphy_cause = 0;
  266. err = simple_mdio_read(cphy, VSC8244_INTR_STATUS, &cause);
  267. if (err)
  268. return err;
  269. cause &= INTR_MASK;
  270. if (cause & CFG_CHG_INTR_MASK)
  271. cphy_cause |= cphy_cause_link_change;
  272. if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO))
  273. cphy_cause |= cphy_cause_fifo_error;
  274. return cphy_cause;
  275. }
  276. static void vsc8244_destroy(struct cphy *cphy)
  277. {
  278. kfree(cphy);
  279. }
  280. static struct cphy_ops vsc8244_ops = {
  281. .destroy = vsc8244_destroy,
  282. .reset = vsc8244_reset,
  283. .interrupt_enable = vsc8244_intr_enable,
  284. .interrupt_disable = vsc8244_intr_disable,
  285. .interrupt_clear = vsc8244_intr_clear,
  286. .interrupt_handler = vsc8244_intr_handler,
  287. .autoneg_enable = vsc8244_autoneg_enable,
  288. .autoneg_restart = vsc8244_autoneg_restart,
  289. .advertise = vsc8244_advertise,
  290. .set_speed_duplex = vsc8244_set_speed_duplex,
  291. .get_link_status = vsc8244_get_link_status
  292. };
  293. static struct cphy* vsc8244_phy_create(adapter_t *adapter, int phy_addr,
  294. struct mdio_ops *mdio_ops)
  295. {
  296. struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
  297. if (!cphy)
  298. return NULL;
  299. cphy_init(cphy, adapter, phy_addr, &vsc8244_ops, mdio_ops);
  300. return cphy;
  301. }
  302. static int vsc8244_phy_reset(adapter_t* adapter)
  303. {
  304. return 0;
  305. }
  306. struct gphy t1_vsc8244_ops = {
  307. vsc8244_phy_create,
  308. vsc8244_phy_reset
  309. };