ael1002.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
  3. *
  4. * This software is available to you under a choice of one of two
  5. * licenses. You may choose to be licensed under the terms of the GNU
  6. * General Public License (GPL) Version 2, available from the file
  7. * COPYING in the main directory of this source tree, or the
  8. * OpenIB.org BSD license below:
  9. *
  10. * Redistribution and use in source and binary forms, with or
  11. * without modification, are permitted provided that the following
  12. * conditions are met:
  13. *
  14. * - Redistributions of source code must retain the above
  15. * copyright notice, this list of conditions and the following
  16. * disclaimer.
  17. *
  18. * - Redistributions in binary form must reproduce the above
  19. * copyright notice, this list of conditions and the following
  20. * disclaimer in the documentation and/or other materials
  21. * provided with the distribution.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30. * SOFTWARE.
  31. */
  32. #include "common.h"
  33. #include "regs.h"
  34. enum {
  35. AEL100X_TX_DISABLE = 9,
  36. AEL100X_TX_CONFIG1 = 0xc002,
  37. AEL1002_PWR_DOWN_HI = 0xc011,
  38. AEL1002_PWR_DOWN_LO = 0xc012,
  39. AEL1002_XFI_EQL = 0xc015,
  40. AEL1002_LB_EN = 0xc017,
  41. LASI_CTRL = 0x9002,
  42. LASI_STAT = 0x9005
  43. };
  44. static void ael100x_txon(struct cphy *phy)
  45. {
  46. int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
  47. msleep(100);
  48. t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
  49. msleep(30);
  50. }
  51. static int ael1002_power_down(struct cphy *phy, int enable)
  52. {
  53. int err;
  54. err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
  55. if (!err)
  56. err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
  57. BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
  58. return err;
  59. }
  60. static int ael1002_reset(struct cphy *phy, int wait)
  61. {
  62. int err;
  63. if ((err = ael1002_power_down(phy, 0)) ||
  64. (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
  65. (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
  66. (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
  67. (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
  68. (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
  69. 0, 1 << 5)))
  70. return err;
  71. return 0;
  72. }
  73. static int ael1002_intr_noop(struct cphy *phy)
  74. {
  75. return 0;
  76. }
  77. static int ael100x_get_link_status(struct cphy *phy, int *link_ok,
  78. int *speed, int *duplex, int *fc)
  79. {
  80. if (link_ok) {
  81. unsigned int status;
  82. int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status);
  83. /*
  84. * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
  85. * once more to get the current link state.
  86. */
  87. if (!err && !(status & BMSR_LSTATUS))
  88. err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR,
  89. &status);
  90. if (err)
  91. return err;
  92. *link_ok = !!(status & BMSR_LSTATUS);
  93. }
  94. if (speed)
  95. *speed = SPEED_10000;
  96. if (duplex)
  97. *duplex = DUPLEX_FULL;
  98. return 0;
  99. }
  100. static struct cphy_ops ael1002_ops = {
  101. .reset = ael1002_reset,
  102. .intr_enable = ael1002_intr_noop,
  103. .intr_disable = ael1002_intr_noop,
  104. .intr_clear = ael1002_intr_noop,
  105. .intr_handler = ael1002_intr_noop,
  106. .get_link_status = ael100x_get_link_status,
  107. .power_down = ael1002_power_down,
  108. };
  109. void t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
  110. int phy_addr, const struct mdio_ops *mdio_ops)
  111. {
  112. cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops);
  113. ael100x_txon(phy);
  114. }
  115. static int ael1006_reset(struct cphy *phy, int wait)
  116. {
  117. return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
  118. }
  119. static int ael1006_intr_enable(struct cphy *phy)
  120. {
  121. return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
  122. }
  123. static int ael1006_intr_disable(struct cphy *phy)
  124. {
  125. return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
  126. }
  127. static int ael1006_intr_clear(struct cphy *phy)
  128. {
  129. u32 val;
  130. return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
  131. }
  132. static int ael1006_intr_handler(struct cphy *phy)
  133. {
  134. unsigned int status;
  135. int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
  136. if (err)
  137. return err;
  138. return (status & 1) ? cphy_cause_link_change : 0;
  139. }
  140. static int ael1006_power_down(struct cphy *phy, int enable)
  141. {
  142. return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
  143. BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
  144. }
  145. static struct cphy_ops ael1006_ops = {
  146. .reset = ael1006_reset,
  147. .intr_enable = ael1006_intr_enable,
  148. .intr_disable = ael1006_intr_disable,
  149. .intr_clear = ael1006_intr_clear,
  150. .intr_handler = ael1006_intr_handler,
  151. .get_link_status = ael100x_get_link_status,
  152. .power_down = ael1006_power_down,
  153. };
  154. void t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
  155. int phy_addr, const struct mdio_ops *mdio_ops)
  156. {
  157. cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops);
  158. ael100x_txon(phy);
  159. }
  160. static struct cphy_ops qt2045_ops = {
  161. .reset = ael1006_reset,
  162. .intr_enable = ael1006_intr_enable,
  163. .intr_disable = ael1006_intr_disable,
  164. .intr_clear = ael1006_intr_clear,
  165. .intr_handler = ael1006_intr_handler,
  166. .get_link_status = ael100x_get_link_status,
  167. .power_down = ael1006_power_down,
  168. };
  169. void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
  170. int phy_addr, const struct mdio_ops *mdio_ops)
  171. {
  172. unsigned int stat;
  173. cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops);
  174. /*
  175. * Some cards where the PHY is supposed to be at address 0 actually
  176. * have it at 1.
  177. */
  178. if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
  179. stat == 0xffff)
  180. phy->addr = 1;
  181. }
  182. static int xaui_direct_reset(struct cphy *phy, int wait)
  183. {
  184. return 0;
  185. }
  186. static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
  187. int *speed, int *duplex, int *fc)
  188. {
  189. if (link_ok) {
  190. unsigned int status;
  191. status = t3_read_reg(phy->adapter,
  192. XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
  193. t3_read_reg(phy->adapter,
  194. XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
  195. t3_read_reg(phy->adapter,
  196. XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
  197. t3_read_reg(phy->adapter,
  198. XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
  199. *link_ok = !(status & F_LOWSIG0);
  200. }
  201. if (speed)
  202. *speed = SPEED_10000;
  203. if (duplex)
  204. *duplex = DUPLEX_FULL;
  205. return 0;
  206. }
  207. static int xaui_direct_power_down(struct cphy *phy, int enable)
  208. {
  209. return 0;
  210. }
  211. static struct cphy_ops xaui_direct_ops = {
  212. .reset = xaui_direct_reset,
  213. .intr_enable = ael1002_intr_noop,
  214. .intr_disable = ael1002_intr_noop,
  215. .intr_clear = ael1002_intr_noop,
  216. .intr_handler = ael1002_intr_noop,
  217. .get_link_status = xaui_direct_get_link_status,
  218. .power_down = xaui_direct_power_down,
  219. };
  220. void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
  221. int phy_addr, const struct mdio_ops *mdio_ops)
  222. {
  223. cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops);
  224. }