2 * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
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:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
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.
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
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 AEL_OPT_SETTINGS = 0xc017,
42 AEL_I2C_CTRL = 0xc30a,
43 AEL_I2C_DATA = 0xc30b,
44 AEL_I2C_STAT = 0xc30c,
45 AEL2005_GPIO_CTRL = 0xc214,
46 AEL2005_GPIO_STAT = 0xc215,
49 enum { edc_none, edc_sr, edc_twinax };
51 /* PHY module I2C device address */
52 #define MODULE_DEV_ADDR 0xa0
54 #define AEL2005_MODDET_IRQ 4
57 unsigned short mmd_addr;
58 unsigned short reg_addr;
59 unsigned short clear_bits;
60 unsigned short set_bits;
63 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
67 for (err = 0; rv->mmd_addr && !err; rv++) {
68 if (rv->clear_bits == 0xffff)
69 err = t3_mdio_write(phy, rv->mmd_addr, rv->reg_addr,
72 err = t3_mdio_change_bits(phy, rv->mmd_addr,
73 rv->reg_addr, rv->clear_bits,
79 static void ael100x_txon(struct cphy *phy)
82 phy->mdio.prtad == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
85 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
89 static int ael1002_power_down(struct cphy *phy, int enable)
93 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, !!enable);
95 err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
96 MDIO_MMD_PMAPMD, MDIO_CTRL1,
97 MDIO_CTRL1_LPOWER, enable);
101 static int ael1002_reset(struct cphy *phy, int wait)
105 if ((err = ael1002_power_down(phy, 0)) ||
106 (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL100X_TX_CONFIG1, 1)) ||
107 (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_HI, 0)) ||
108 (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_LO, 0)) ||
109 (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_XFI_EQL, 0x18)) ||
110 (err = t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL1002_LB_EN,
116 static int ael1002_intr_noop(struct cphy *phy)
122 * Get link status for a 10GBASE-R device.
124 static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
125 int *duplex, int *fc)
128 unsigned int stat0, stat1, stat2;
129 int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
130 MDIO_PMA_RXDET, &stat0);
133 err = t3_mdio_read(phy, MDIO_MMD_PCS,
134 MDIO_PCS_10GBRT_STAT1, &stat1);
136 err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
137 MDIO_PHYXS_LNSTAT, &stat2);
140 *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
143 *speed = SPEED_10000;
145 *duplex = DUPLEX_FULL;
149 static struct cphy_ops ael1002_ops = {
150 .reset = ael1002_reset,
151 .intr_enable = ael1002_intr_noop,
152 .intr_disable = ael1002_intr_noop,
153 .intr_clear = ael1002_intr_noop,
154 .intr_handler = ael1002_intr_noop,
155 .get_link_status = get_link_status_r,
156 .power_down = ael1002_power_down,
157 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
160 int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
161 int phy_addr, const struct mdio_ops *mdio_ops)
163 cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
164 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
170 static int ael1006_reset(struct cphy *phy, int wait)
172 return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait);
175 static int ael1006_power_down(struct cphy *phy, int enable)
177 return mdio_set_flag(&phy->mdio, phy->mdio.prtad, MDIO_MMD_PMAPMD,
178 MDIO_CTRL1, MDIO_CTRL1_LPOWER, enable);
181 static struct cphy_ops ael1006_ops = {
182 .reset = ael1006_reset,
183 .intr_enable = t3_phy_lasi_intr_enable,
184 .intr_disable = t3_phy_lasi_intr_disable,
185 .intr_clear = t3_phy_lasi_intr_clear,
186 .intr_handler = t3_phy_lasi_intr_handler,
187 .get_link_status = get_link_status_r,
188 .power_down = ael1006_power_down,
189 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
192 int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
193 int phy_addr, const struct mdio_ops *mdio_ops)
195 cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
196 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
202 static int ael2005_setup_sr_edc(struct cphy *phy)
204 static struct reg_val regs[] = {
205 { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 },
206 { MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a },
207 { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
210 static u16 sr_edc[] = {
485 err = set_phy_regs(phy, regs);
491 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
492 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, sr_edc[i],
499 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
501 static struct reg_val regs[] = {
502 { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 },
505 static struct reg_val preemphasis[] = {
506 { MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 },
507 { MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
510 static u16 twinax_edc[] = {
880 err = set_phy_regs(phy, regs);
881 if (!err && modtype == phy_modtype_twinax_long)
882 err = set_phy_regs(phy, preemphasis);
888 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
889 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i],
892 phy->priv = edc_twinax;
896 static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
899 unsigned int stat, data;
901 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL,
902 (dev_addr << 8) | (1 << 8) | word_addr);
906 for (i = 0; i < 5; i++) {
908 err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat);
911 if ((stat & 3) == 1) {
912 err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA,
919 CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n",
920 phy->mdio.prtad, word_addr);
924 static int get_module_type(struct cphy *phy, int delay_ms)
929 v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat);
933 if (stat & (1 << 8)) /* module absent */
934 return phy_modtype_none;
939 /* see SFF-8472 for below */
940 v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3);
945 return phy_modtype_sr;
947 return phy_modtype_lr;
949 return phy_modtype_lrm;
951 v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6);
957 v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10);
962 v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
965 return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
968 return phy_modtype_unknown;
971 static int ael2005_intr_enable(struct cphy *phy)
973 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200);
974 return err ? err : t3_phy_lasi_intr_enable(phy);
977 static int ael2005_intr_disable(struct cphy *phy)
979 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100);
980 return err ? err : t3_phy_lasi_intr_disable(phy);
983 static int ael2005_intr_clear(struct cphy *phy)
985 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00);
986 return err ? err : t3_phy_lasi_intr_clear(phy);
989 static int ael2005_reset(struct cphy *phy, int wait)
991 static struct reg_val regs0[] = {
992 { MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 },
993 { MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 },
994 { MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 },
995 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
996 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 },
997 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
998 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 },
1001 static struct reg_val regs1[] = {
1002 { MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 },
1003 { MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 },
1008 unsigned int lasi_ctrl;
1010 err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
1015 err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0);
1020 phy->priv = edc_none;
1021 err = set_phy_regs(phy, regs0);
1027 err = get_module_type(phy, 0);
1032 if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1033 err = ael2005_setup_twinax_edc(phy, err);
1035 err = ael2005_setup_sr_edc(phy);
1039 err = set_phy_regs(phy, regs1);
1043 /* reset wipes out interrupts, reenable them if they were on */
1045 err = ael2005_intr_enable(phy);
1049 static int ael2005_intr_handler(struct cphy *phy)
1052 int ret, edc_needed, cause = 0;
1054 ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat);
1058 if (stat & AEL2005_MODDET_IRQ) {
1059 ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL,
1064 /* modules have max 300 ms init time after hot plug */
1065 ret = get_module_type(phy, 300);
1070 if (ret == phy_modtype_none)
1071 edc_needed = phy->priv; /* on unplug retain EDC */
1072 else if (ret == phy_modtype_twinax ||
1073 ret == phy_modtype_twinax_long)
1074 edc_needed = edc_twinax;
1076 edc_needed = edc_sr;
1078 if (edc_needed != phy->priv) {
1079 ret = ael2005_reset(phy, 0);
1080 return ret ? ret : cphy_cause_module_change;
1082 cause = cphy_cause_module_change;
1085 ret = t3_phy_lasi_intr_handler(phy);
1090 return ret ? ret : cphy_cause_link_change;
1093 static struct cphy_ops ael2005_ops = {
1094 .reset = ael2005_reset,
1095 .intr_enable = ael2005_intr_enable,
1096 .intr_disable = ael2005_intr_disable,
1097 .intr_clear = ael2005_intr_clear,
1098 .intr_handler = ael2005_intr_handler,
1099 .get_link_status = get_link_status_r,
1100 .power_down = ael1002_power_down,
1101 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
1104 int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
1105 int phy_addr, const struct mdio_ops *mdio_ops)
1107 cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
1108 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1109 SUPPORTED_IRQ, "10GBASE-R");
1111 return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0,
1116 * Get link status for a 10GBASE-X device.
1118 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
1119 int *duplex, int *fc)
1122 unsigned int stat0, stat1, stat2;
1123 int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
1124 MDIO_PMA_RXDET, &stat0);
1127 err = t3_mdio_read(phy, MDIO_MMD_PCS,
1128 MDIO_PCS_10GBX_STAT1, &stat1);
1130 err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
1131 MDIO_PHYXS_LNSTAT, &stat2);
1134 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
1137 *speed = SPEED_10000;
1139 *duplex = DUPLEX_FULL;
1143 static struct cphy_ops qt2045_ops = {
1144 .reset = ael1006_reset,
1145 .intr_enable = t3_phy_lasi_intr_enable,
1146 .intr_disable = t3_phy_lasi_intr_disable,
1147 .intr_clear = t3_phy_lasi_intr_clear,
1148 .intr_handler = t3_phy_lasi_intr_handler,
1149 .get_link_status = get_link_status_x,
1150 .power_down = ael1006_power_down,
1151 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
1154 int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
1155 int phy_addr, const struct mdio_ops *mdio_ops)
1159 cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
1160 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1164 * Some cards where the PHY is supposed to be at address 0 actually
1168 !t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) &&
1170 phy->mdio.prtad = 1;
1174 static int xaui_direct_reset(struct cphy *phy, int wait)
1179 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
1180 int *speed, int *duplex, int *fc)
1183 unsigned int status;
1184 int prtad = phy->mdio.prtad;
1186 status = t3_read_reg(phy->adapter,
1187 XGM_REG(A_XGM_SERDES_STAT0, prtad)) |
1188 t3_read_reg(phy->adapter,
1189 XGM_REG(A_XGM_SERDES_STAT1, prtad)) |
1190 t3_read_reg(phy->adapter,
1191 XGM_REG(A_XGM_SERDES_STAT2, prtad)) |
1192 t3_read_reg(phy->adapter,
1193 XGM_REG(A_XGM_SERDES_STAT3, prtad));
1194 *link_ok = !(status & F_LOWSIG0);
1197 *speed = SPEED_10000;
1199 *duplex = DUPLEX_FULL;
1203 static int xaui_direct_power_down(struct cphy *phy, int enable)
1208 static struct cphy_ops xaui_direct_ops = {
1209 .reset = xaui_direct_reset,
1210 .intr_enable = ael1002_intr_noop,
1211 .intr_disable = ael1002_intr_noop,
1212 .intr_clear = ael1002_intr_noop,
1213 .intr_handler = ael1002_intr_noop,
1214 .get_link_status = xaui_direct_get_link_status,
1215 .power_down = xaui_direct_power_down,
1218 int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
1219 int phy_addr, const struct mdio_ops *mdio_ops)
1221 cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops,
1222 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,