vsc8244.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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. }
  89. t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
  90. }
  91. return 0;
  92. }
  93. static int vsc8244_intr_disable(struct cphy *cphy)
  94. {
  95. simple_mdio_write(cphy, VSC8244_INTR_ENABLE, 0);
  96. if (t1_is_asic(cphy->adapter)) {
  97. u32 elmer;
  98. t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer);
  99. elmer &= ~ELMER0_GP_BIT1;
  100. if (is_T2(cphy->adapter)) {
  101. elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4);
  102. }
  103. t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer);
  104. }
  105. return 0;
  106. }
  107. static int vsc8244_intr_clear(struct cphy *cphy)
  108. {
  109. u32 val;
  110. u32 elmer;
  111. /* Clear PHY interrupts by reading the register. */
  112. simple_mdio_read(cphy, VSC8244_INTR_ENABLE, &val);
  113. if (t1_is_asic(cphy->adapter)) {
  114. t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer);
  115. elmer |= ELMER0_GP_BIT1;
  116. if (is_T2(cphy->adapter)) {
  117. elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4;
  118. }
  119. t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer);
  120. }
  121. return 0;
  122. }
  123. /*
  124. * Force the PHY speed and duplex. This also disables auto-negotiation, except
  125. * for 1Gb/s, where auto-negotiation is mandatory.
  126. */
  127. static int vsc8244_set_speed_duplex(struct cphy *phy, int speed, int duplex)
  128. {
  129. int err;
  130. unsigned int ctl;
  131. err = simple_mdio_read(phy, MII_BMCR, &ctl);
  132. if (err)
  133. return err;
  134. if (speed >= 0) {
  135. ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
  136. if (speed == SPEED_100)
  137. ctl |= BMCR_SPEED100;
  138. else if (speed == SPEED_1000)
  139. ctl |= BMCR_SPEED1000;
  140. }
  141. if (duplex >= 0) {
  142. ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE);
  143. if (duplex == DUPLEX_FULL)
  144. ctl |= BMCR_FULLDPLX;
  145. }
  146. if (ctl & BMCR_SPEED1000) /* auto-negotiation required for 1Gb/s */
  147. ctl |= BMCR_ANENABLE;
  148. return simple_mdio_write(phy, MII_BMCR, ctl);
  149. }
  150. int t1_mdio_set_bits(struct cphy *phy, int mmd, int reg, unsigned int bits)
  151. {
  152. int ret;
  153. unsigned int val;
  154. ret = mdio_read(phy, mmd, reg, &val);
  155. if (!ret)
  156. ret = mdio_write(phy, mmd, reg, val | bits);
  157. return ret;
  158. }
  159. static int vsc8244_autoneg_enable(struct cphy *cphy)
  160. {
  161. return t1_mdio_set_bits(cphy, 0, MII_BMCR,
  162. BMCR_ANENABLE | BMCR_ANRESTART);
  163. }
  164. static int vsc8244_autoneg_restart(struct cphy *cphy)
  165. {
  166. return t1_mdio_set_bits(cphy, 0, MII_BMCR, BMCR_ANRESTART);
  167. }
  168. static int vsc8244_advertise(struct cphy *phy, unsigned int advertise_map)
  169. {
  170. int err;
  171. unsigned int val = 0;
  172. err = simple_mdio_read(phy, MII_CTRL1000, &val);
  173. if (err)
  174. return err;
  175. val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
  176. if (advertise_map & ADVERTISED_1000baseT_Half)
  177. val |= ADVERTISE_1000HALF;
  178. if (advertise_map & ADVERTISED_1000baseT_Full)
  179. val |= ADVERTISE_1000FULL;
  180. err = simple_mdio_write(phy, MII_CTRL1000, val);
  181. if (err)
  182. return err;
  183. val = 1;
  184. if (advertise_map & ADVERTISED_10baseT_Half)
  185. val |= ADVERTISE_10HALF;
  186. if (advertise_map & ADVERTISED_10baseT_Full)
  187. val |= ADVERTISE_10FULL;
  188. if (advertise_map & ADVERTISED_100baseT_Half)
  189. val |= ADVERTISE_100HALF;
  190. if (advertise_map & ADVERTISED_100baseT_Full)
  191. val |= ADVERTISE_100FULL;
  192. if (advertise_map & ADVERTISED_PAUSE)
  193. val |= ADVERTISE_PAUSE_CAP;
  194. if (advertise_map & ADVERTISED_ASYM_PAUSE)
  195. val |= ADVERTISE_PAUSE_ASYM;
  196. return simple_mdio_write(phy, MII_ADVERTISE, val);
  197. }
  198. static int vsc8244_get_link_status(struct cphy *cphy, int *link_ok,
  199. int *speed, int *duplex, int *fc)
  200. {
  201. unsigned int bmcr, status, lpa, adv;
  202. int err, sp = -1, dplx = -1, pause = 0;
  203. err = simple_mdio_read(cphy, MII_BMCR, &bmcr);
  204. if (!err)
  205. err = simple_mdio_read(cphy, MII_BMSR, &status);
  206. if (err)
  207. return err;
  208. if (link_ok) {
  209. /*
  210. * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
  211. * once more to get the current link state.
  212. */
  213. if (!(status & BMSR_LSTATUS))
  214. err = simple_mdio_read(cphy, MII_BMSR, &status);
  215. if (err)
  216. return err;
  217. *link_ok = (status & BMSR_LSTATUS) != 0;
  218. }
  219. if (!(bmcr & BMCR_ANENABLE)) {
  220. dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
  221. if (bmcr & BMCR_SPEED1000)
  222. sp = SPEED_1000;
  223. else if (bmcr & BMCR_SPEED100)
  224. sp = SPEED_100;
  225. else
  226. sp = SPEED_10;
  227. } else if (status & BMSR_ANEGCOMPLETE) {
  228. err = simple_mdio_read(cphy, VSC8244_AUX_CTRL_STAT, &status);
  229. if (err)
  230. return err;
  231. dplx = (status & F_ACSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
  232. sp = G_ACSR_SPEED(status);
  233. if (sp == 0)
  234. sp = SPEED_10;
  235. else if (sp == 1)
  236. sp = SPEED_100;
  237. else
  238. sp = SPEED_1000;
  239. if (fc && dplx == DUPLEX_FULL) {
  240. err = simple_mdio_read(cphy, MII_LPA, &lpa);
  241. if (!err)
  242. err = simple_mdio_read(cphy, MII_ADVERTISE,
  243. &adv);
  244. if (err)
  245. return err;
  246. if (lpa & adv & ADVERTISE_PAUSE_CAP)
  247. pause = PAUSE_RX | PAUSE_TX;
  248. else if ((lpa & ADVERTISE_PAUSE_CAP) &&
  249. (lpa & ADVERTISE_PAUSE_ASYM) &&
  250. (adv & ADVERTISE_PAUSE_ASYM))
  251. pause = PAUSE_TX;
  252. else if ((lpa & ADVERTISE_PAUSE_ASYM) &&
  253. (adv & ADVERTISE_PAUSE_CAP))
  254. pause = PAUSE_RX;
  255. }
  256. }
  257. if (speed)
  258. *speed = sp;
  259. if (duplex)
  260. *duplex = dplx;
  261. if (fc)
  262. *fc = pause;
  263. return 0;
  264. }
  265. static int vsc8244_intr_handler(struct cphy *cphy)
  266. {
  267. unsigned int cause;
  268. int err, cphy_cause = 0;
  269. err = simple_mdio_read(cphy, VSC8244_INTR_STATUS, &cause);
  270. if (err)
  271. return err;
  272. cause &= INTR_MASK;
  273. if (cause & CFG_CHG_INTR_MASK)
  274. cphy_cause |= cphy_cause_link_change;
  275. if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO))
  276. cphy_cause |= cphy_cause_fifo_error;
  277. return cphy_cause;
  278. }
  279. static void vsc8244_destroy(struct cphy *cphy)
  280. {
  281. kfree(cphy);
  282. }
  283. static struct cphy_ops vsc8244_ops = {
  284. .destroy = vsc8244_destroy,
  285. .reset = vsc8244_reset,
  286. .interrupt_enable = vsc8244_intr_enable,
  287. .interrupt_disable = vsc8244_intr_disable,
  288. .interrupt_clear = vsc8244_intr_clear,
  289. .interrupt_handler = vsc8244_intr_handler,
  290. .autoneg_enable = vsc8244_autoneg_enable,
  291. .autoneg_restart = vsc8244_autoneg_restart,
  292. .advertise = vsc8244_advertise,
  293. .set_speed_duplex = vsc8244_set_speed_duplex,
  294. .get_link_status = vsc8244_get_link_status
  295. };
  296. static struct cphy* vsc8244_phy_create(adapter_t *adapter, int phy_addr, struct mdio_ops *mdio_ops)
  297. {
  298. struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL);
  299. if (!cphy)
  300. return NULL;
  301. cphy_init(cphy, adapter, phy_addr, &vsc8244_ops, mdio_ops);
  302. return cphy;
  303. }
  304. static int vsc8244_phy_reset(adapter_t* adapter)
  305. {
  306. return 0;
  307. }
  308. struct gphy t1_vsc8244_ops = {
  309. vsc8244_phy_create,
  310. vsc8244_phy_reset
  311. };