1 /**************************************************************************
3 Copyright (c) 2007-2009, Chelsio Inc.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Neither the name of the Chelsio Corporation nor the names of its
13 contributors may be used to endorse or promote products derived from
14 this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
28 ***************************************************************************/
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <cxgb_include.h>
36 #define msleep t3_os_sleep
39 PMD_RSD = 10, /* PMA/PMD receive signal detect register */
40 PCS_STAT1_X = 24, /* 10GBASE-X PCS status 1 register */
41 PCS_STAT1_R = 32, /* 10GBASE-R PCS status 1 register */
42 XS_LN_STAT = 24 /* XS lane status register */
46 AEL100X_TX_DISABLE = 9,
47 AEL100X_TX_CONFIG1 = 0xc002,
48 AEL1002_PWR_DOWN_HI = 0xc011,
49 AEL1002_PWR_DOWN_LO = 0xc012,
50 AEL1002_XFI_EQL = 0xc015,
51 AEL1002_LB_EN = 0xc017,
52 AEL_OPT_SETTINGS = 0xc017,
53 AEL_I2C_CTRL = 0xc30a,
54 AEL_I2C_DATA = 0xc30b,
55 AEL_I2C_STAT = 0xc30c,
56 AEL2005_GPIO_CTRL = 0xc214,
57 AEL2005_GPIO_STAT = 0xc215,
60 enum { edc_none, edc_sr, edc_twinax };
62 /* PHY module I2C device address */
64 MODULE_DEV_ADDR = 0xa0,
68 /* PHY transceiver type */
70 phy_transtype_unknown = 0,
71 phy_transtype_sfp = 3,
72 phy_transtype_xfp = 6,
75 #define AEL2005_MODDET_IRQ 4
78 unsigned short mmd_addr;
79 unsigned short reg_addr;
80 unsigned short clear_bits;
81 unsigned short set_bits;
84 static int get_module_type(struct cphy *phy);
86 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
90 for (err = 0; rv->mmd_addr && !err; rv++) {
91 if (rv->clear_bits == 0xffff)
92 err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
95 err = t3_mdio_change_bits(phy, rv->mmd_addr,
96 rv->reg_addr, rv->clear_bits,
102 static void ael100x_txon(struct cphy *phy)
104 int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
107 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
111 static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
114 unsigned int stat, data;
116 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
117 (dev_addr << 8) | (1 << 8) | word_addr);
121 for (i = 0; i < 200; i++) {
123 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
126 if ((stat & 3) == 1) {
127 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
134 CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n",
135 phy->addr, word_addr);
139 static int ael_i2c_wr(struct cphy *phy, int dev_addr, int word_addr, int data)
144 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, data);
148 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
149 (dev_addr << 8) | word_addr);
153 for (i = 0; i < 200; i++) {
155 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
161 CH_WARN(phy->adapter, "PHY %u I2C Write of addr %u timed out\n",
162 phy->addr, word_addr);
166 static int get_phytrans_type(struct cphy *phy)
170 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
172 return phy_transtype_unknown;
177 static int ael_laser_down(struct cphy *phy, int enable)
181 v = get_phytrans_type(phy);
185 if (v == phy_transtype_sfp) {
186 /* Check SFF Soft TX disable is supported */
187 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 93);
195 dev_addr = SFF_DEV_ADDR;
196 } else if (v == phy_transtype_xfp)
197 dev_addr = MODULE_DEV_ADDR;
201 v = ael_i2c_rd(phy, dev_addr, 110);
210 v = ael_i2c_wr(phy, dev_addr, 110, v);
215 static int ael1002_power_down(struct cphy *phy, int enable)
219 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
221 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
222 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
226 static int ael1002_get_module_type(struct cphy *phy, int delay_ms)
233 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
235 return v == -ETIMEDOUT ? phy_modtype_none : get_module_type(phy);
238 static int ael1002_reset(struct cphy *phy, int wait)
242 if ((err = ael1002_power_down(phy, 0)) ||
243 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
244 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
245 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
246 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
247 (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
251 err = ael1002_get_module_type(phy, 300);
258 static int ael1002_intr_noop(struct cphy *phy)
264 * Get link status for a 10GBASE-R device.
266 static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
267 int *duplex, int *fc)
270 unsigned int stat0, stat1, stat2;
271 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
274 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
276 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
279 *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
282 *speed = SPEED_10000;
284 *duplex = DUPLEX_FULL;
288 #ifdef C99_NOT_SUPPORTED
289 static struct cphy_ops ael1002_ops = {
304 static struct cphy_ops ael1002_ops = {
305 .reset = ael1002_reset,
306 .intr_enable = ael1002_intr_noop,
307 .intr_disable = ael1002_intr_noop,
308 .intr_clear = ael1002_intr_noop,
309 .intr_handler = ael1002_intr_noop,
310 .get_link_status = get_link_status_r,
311 .power_down = ael1002_power_down,
315 int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
316 const struct mdio_ops *mdio_ops)
320 cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
321 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
324 ael_laser_down(phy, 0);
326 err = ael1002_get_module_type(phy, 0);
333 static int ael1006_reset(struct cphy *phy, int wait)
337 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
341 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
346 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
347 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL);
351 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
357 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1);
363 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0);
369 static int ael1006_power_down(struct cphy *phy, int enable)
371 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
372 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
375 #ifdef C99_NOT_SUPPORTED
376 static struct cphy_ops ael1006_ops = {
378 t3_phy_lasi_intr_enable,
379 t3_phy_lasi_intr_disable,
380 t3_phy_lasi_intr_clear,
381 t3_phy_lasi_intr_handler,
391 static struct cphy_ops ael1006_ops = {
392 .reset = ael1006_reset,
393 .intr_enable = t3_phy_lasi_intr_enable,
394 .intr_disable = t3_phy_lasi_intr_disable,
395 .intr_clear = t3_phy_lasi_intr_clear,
396 .intr_handler = t3_phy_lasi_intr_handler,
397 .get_link_status = get_link_status_r,
398 .power_down = ael1006_power_down,
402 int t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
403 const struct mdio_ops *mdio_ops)
405 cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
406 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
412 static int ael2005_setup_sr_edc(struct cphy *phy)
414 static struct reg_val regs[] = {
415 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
416 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
417 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
420 static u16 sr_edc[] = {
695 err = set_phy_regs(phy, regs);
701 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
702 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
709 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
711 static struct reg_val regs[] = {
712 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
715 static struct reg_val preemphasis[] = {
716 { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
717 { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
720 static u16 twinax_edc[] = {
1090 err = set_phy_regs(phy, regs);
1091 if (!err && modtype == phy_modtype_twinax_long)
1092 err = set_phy_regs(phy, preemphasis);
1098 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1099 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1102 phy->priv = edc_twinax;
1106 static int get_module_type(struct cphy *phy)
1110 v = get_phytrans_type(phy);
1111 if (v == phy_transtype_sfp) {
1112 /* SFP: see SFF-8472 for below */
1114 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
1119 return phy_modtype_twinax;
1121 return phy_modtype_sr;
1123 return phy_modtype_lr;
1125 return phy_modtype_lrm;
1127 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
1131 return phy_modtype_unknown;
1133 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
1138 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
1141 return v > 10 ? phy_modtype_twinax_long :
1144 } else if (v == phy_transtype_xfp) {
1145 /* XFP: See INF-8077i for details. */
1147 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127);
1152 /* XXX: set page select to table 1 yourself */
1153 return phy_modtype_unknown;
1156 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131);
1161 return phy_modtype_lrm;
1163 return phy_modtype_lr;
1165 return phy_modtype_sr;
1168 return phy_modtype_unknown;
1172 static int ael2005_intr_enable(struct cphy *phy)
1174 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1175 return err ? err : t3_phy_lasi_intr_enable(phy);
1178 static int ael2005_intr_disable(struct cphy *phy)
1180 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1181 return err ? err : t3_phy_lasi_intr_disable(phy);
1184 static int ael2005_intr_clear(struct cphy *phy)
1186 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1187 return err ? err : t3_phy_lasi_intr_clear(phy);
1190 static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1195 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1199 if (stat & (1 << 8)) /* module absent */
1200 return phy_modtype_none;
1205 return get_module_type(phy);
1208 static int ael2005_reset(struct cphy *phy, int wait)
1210 static struct reg_val regs0[] = {
1211 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1212 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1213 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1214 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1215 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1216 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1217 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1220 static struct reg_val regs1[] = {
1221 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1222 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1228 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1232 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1237 phy->priv = edc_none;
1238 err = set_phy_regs(phy, regs0);
1244 err = ael2005_get_module_type(phy, 0);
1247 phy->modtype = (u8)err;
1249 if (err == phy_modtype_none || err == phy_modtype_unknown)
1251 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1252 err = ael2005_setup_twinax_edc(phy, err);
1254 err = ael2005_setup_sr_edc(phy);
1258 err = set_phy_regs(phy, regs1);
1262 /* reset wipes out interrupts, reenable them if they were on */
1264 err = ael2005_intr_enable(phy);
1268 static int ael2005_intr_handler(struct cphy *phy)
1271 int ret, edc_needed, cause = 0;
1273 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1277 if (stat & AEL2005_MODDET_IRQ) {
1278 ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1283 /* modules have max 300 ms init time after hot plug */
1284 ret = ael2005_get_module_type(phy, 300);
1288 phy->modtype = (u8)ret;
1289 if (ret == phy_modtype_none)
1290 edc_needed = phy->priv; /* on unplug retain EDC */
1291 else if (ret == phy_modtype_twinax ||
1292 ret == phy_modtype_twinax_long)
1293 edc_needed = edc_twinax;
1295 edc_needed = edc_sr;
1297 if (edc_needed != phy->priv) {
1298 ret = ael2005_reset(phy, 0);
1299 return ret ? ret : cphy_cause_module_change;
1301 cause = cphy_cause_module_change;
1304 ret = t3_phy_lasi_intr_handler(phy);
1310 ret |= cphy_cause_link_change;
1314 #ifdef C99_NOT_SUPPORTED
1315 static struct cphy_ops ael2005_ops = {
1317 ael2005_intr_enable,
1318 ael2005_intr_disable,
1320 ael2005_intr_handler,
1330 static struct cphy_ops ael2005_ops = {
1331 .reset = ael2005_reset,
1332 .intr_enable = ael2005_intr_enable,
1333 .intr_disable = ael2005_intr_disable,
1334 .intr_clear = ael2005_intr_clear,
1335 .intr_handler = ael2005_intr_handler,
1336 .get_link_status = get_link_status_r,
1337 .power_down = ael1002_power_down,
1341 int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1342 const struct mdio_ops *mdio_ops)
1345 cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
1346 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1347 SUPPORTED_IRQ, "10GBASE-R");
1349 ael_laser_down(phy, 0);
1351 err = ael2005_get_module_type(phy, 0);
1355 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1360 * Get link status for a 10GBASE-X device.
1362 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
1363 int *duplex, int *fc)
1366 unsigned int stat0, stat1, stat2;
1367 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
1370 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
1372 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
1375 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
1378 *speed = SPEED_10000;
1380 *duplex = DUPLEX_FULL;
1384 #ifdef C99_NOT_SUPPORTED
1385 static struct cphy_ops qt2045_ops = {
1387 t3_phy_lasi_intr_enable,
1388 t3_phy_lasi_intr_disable,
1389 t3_phy_lasi_intr_clear,
1390 t3_phy_lasi_intr_handler,
1400 static struct cphy_ops qt2045_ops = {
1401 .reset = ael1006_reset,
1402 .intr_enable = t3_phy_lasi_intr_enable,
1403 .intr_disable = t3_phy_lasi_intr_disable,
1404 .intr_clear = t3_phy_lasi_intr_clear,
1405 .intr_handler = t3_phy_lasi_intr_handler,
1406 .get_link_status = get_link_status_x,
1407 .power_down = ael1006_power_down,
1411 int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1412 const struct mdio_ops *mdio_ops)
1416 cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
1417 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1421 * Some cards where the PHY is supposed to be at address 0 actually
1424 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
1430 static int xaui_direct_reset(struct cphy *phy, int wait)
1435 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
1436 int *speed, int *duplex, int *fc)
1439 unsigned int status;
1441 status = t3_read_reg(phy->adapter,
1442 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
1443 t3_read_reg(phy->adapter,
1444 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
1445 t3_read_reg(phy->adapter,
1446 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
1447 t3_read_reg(phy->adapter,
1448 XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
1449 *link_ok = !(status & F_LOWSIG0);
1452 *speed = SPEED_10000;
1454 *duplex = DUPLEX_FULL;
1458 static int xaui_direct_power_down(struct cphy *phy, int enable)
1463 #ifdef C99_NOT_SUPPORTED
1464 static struct cphy_ops xaui_direct_ops = {
1475 xaui_direct_get_link_status,
1476 xaui_direct_power_down,
1479 static struct cphy_ops xaui_direct_ops = {
1480 .reset = xaui_direct_reset,
1481 .intr_enable = ael1002_intr_noop,
1482 .intr_disable = ael1002_intr_noop,
1483 .intr_clear = ael1002_intr_noop,
1484 .intr_handler = ael1002_intr_noop,
1485 .get_link_status = xaui_direct_get_link_status,
1486 .power_down = xaui_direct_power_down,
1490 int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1491 const struct mdio_ops *mdio_ops)
1493 cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
1494 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,