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,
49 AEL1002_PWR_DOWN_HI = 0xc011,
50 AEL1002_PWR_DOWN_LO = 0xc012,
51 AEL1002_XFI_EQL = 0xc015,
52 AEL1002_LB_EN = 0xc017,
54 AEL_OPT_SETTINGS = 0xc017,
55 AEL_I2C_CTRL = 0xc30a,
56 AEL_I2C_DATA = 0xc30b,
57 AEL_I2C_STAT = 0xc30c,
59 AEL2005_GPIO_CTRL = 0xc214,
60 AEL2005_GPIO_STAT = 0xc215,
62 AEL2020_GPIO_INTR = 0xc103,
63 AEL2020_GPIO_CTRL = 0xc108,
64 AEL2020_GPIO_STAT = 0xc10c,
65 AEL2020_GPIO_CFG = 0xc110,
68 AEL2020_GPIO_MODDET = 1,
71 AEL2020_GPIO_LSTAT = AEL2020_GPIO_1,
74 enum { edc_none, edc_sr, edc_twinax };
76 /* PHY module I2C device address */
78 MODULE_DEV_ADDR = 0xa0,
82 /* PHY transceiver type */
84 phy_transtype_unknown = 0,
85 phy_transtype_sfp = 3,
86 phy_transtype_xfp = 6,
89 #define AEL2005_MODDET_IRQ 4
92 unsigned short mmd_addr;
93 unsigned short reg_addr;
94 unsigned short clear_bits;
95 unsigned short set_bits;
98 static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms);
100 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
104 for (err = 0; rv->mmd_addr && !err; rv++) {
105 if (rv->clear_bits == 0xffff)
106 err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
109 err = t3_mdio_change_bits(phy, rv->mmd_addr,
110 rv->reg_addr, rv->clear_bits,
116 static void ael100x_txon(struct cphy *phy)
118 int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
121 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
126 * Read an 8-bit word from a device attached to the PHY's i2c bus.
128 static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
131 unsigned int stat, data;
133 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
134 (dev_addr << 8) | (1 << 8) | word_addr);
138 for (i = 0; i < 200; i++) {
140 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
143 if ((stat & 3) == 1) {
144 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
151 CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %x.%x timed out\n",
152 phy->addr, dev_addr, word_addr);
157 * Write an 8-bit word to a device attached to the PHY's i2c bus.
159 static int ael_i2c_wr(struct cphy *phy, int dev_addr, int word_addr, int data)
164 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, data);
168 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
169 (dev_addr << 8) | word_addr);
173 for (i = 0; i < 200; i++) {
175 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
181 CH_WARN(phy->adapter, "PHY %u i2c Write of dev.addr %x.%x = %#x timed out\n",
182 phy->addr, dev_addr, word_addr, data);
186 static int get_phytrans_type(struct cphy *phy)
190 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
192 return phy_transtype_unknown;
197 static int ael_laser_down(struct cphy *phy, int enable)
201 v = get_phytrans_type(phy);
205 if (v == phy_transtype_sfp) {
206 /* Check SFF Soft TX disable is supported */
207 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 93);
215 dev_addr = SFF_DEV_ADDR;
216 } else if (v == phy_transtype_xfp)
217 dev_addr = MODULE_DEV_ADDR;
221 v = ael_i2c_rd(phy, dev_addr, 110);
230 v = ael_i2c_wr(phy, dev_addr, 110, v);
235 static int ael1002_power_down(struct cphy *phy, int enable)
239 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
241 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
242 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
246 static int ael1002_get_module_type(struct cphy *phy, int delay_ms)
253 v = ael2xxx_get_module_type(phy, delay_ms);
255 return (v == -ETIMEDOUT ? phy_modtype_none : v);
258 static int ael1002_reset(struct cphy *phy, int wait)
262 if ((err = ael1002_power_down(phy, 0)) ||
263 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
264 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
265 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
266 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
267 (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
271 err = ael1002_get_module_type(phy, 300);
278 static int ael1002_intr_noop(struct cphy *phy)
284 * Get link status for a 10GBASE-R device.
286 static int get_link_status_r(struct cphy *phy, int *link_state, int *speed,
287 int *duplex, int *fc)
290 unsigned int stat0, stat1, stat2;
291 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
294 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
296 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
302 stat2 = (stat2 >> 12) & 1;
303 if (stat0 & stat1 & stat2)
304 *link_state = PHY_LINK_UP;
305 else if (stat0 == 1 && stat1 == 0 && stat2 == 1)
306 *link_state = PHY_LINK_PARTIAL;
308 *link_state = PHY_LINK_DOWN;
311 *speed = SPEED_10000;
313 *duplex = DUPLEX_FULL;
317 #ifdef C99_NOT_SUPPORTED
318 static struct cphy_ops ael1002_ops = {
333 static struct cphy_ops ael1002_ops = {
334 .reset = ael1002_reset,
335 .intr_enable = ael1002_intr_noop,
336 .intr_disable = ael1002_intr_noop,
337 .intr_clear = ael1002_intr_noop,
338 .intr_handler = ael1002_intr_noop,
339 .get_link_status = get_link_status_r,
340 .power_down = ael1002_power_down,
344 int t3_ael1002_phy_prep(pinfo_t *pinfo, int phy_addr,
345 const struct mdio_ops *mdio_ops)
348 struct cphy *phy = &pinfo->phy;
350 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1002_ops, mdio_ops,
351 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
354 ael_laser_down(phy, 0);
356 err = ael1002_get_module_type(phy, 0);
363 static int ael1006_reset(struct cphy *phy, int wait)
367 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
371 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
376 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
377 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL);
381 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
387 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1);
393 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0);
399 #ifdef C99_NOT_SUPPORTED
400 static struct cphy_ops ael1006_ops = {
402 t3_phy_lasi_intr_enable,
403 t3_phy_lasi_intr_disable,
404 t3_phy_lasi_intr_clear,
405 t3_phy_lasi_intr_handler,
415 static struct cphy_ops ael1006_ops = {
416 .reset = ael1006_reset,
417 .intr_enable = t3_phy_lasi_intr_enable,
418 .intr_disable = t3_phy_lasi_intr_disable,
419 .intr_clear = t3_phy_lasi_intr_clear,
420 .intr_handler = t3_phy_lasi_intr_handler,
421 .get_link_status = get_link_status_r,
422 .power_down = ael1002_power_down,
426 int t3_ael1006_phy_prep(pinfo_t *pinfo, int phy_addr,
427 const struct mdio_ops *mdio_ops)
429 struct cphy *phy = &pinfo->phy;
431 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1006_ops, mdio_ops,
432 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
434 phy->modtype = phy_modtype_sr;
440 * Decode our module type.
442 static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
449 v = get_phytrans_type(phy);
450 if (v == phy_transtype_sfp) {
451 /* SFP: see SFF-8472 for below */
453 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
460 return phy_modtype_sr;
462 return phy_modtype_lr;
464 return phy_modtype_lrm;
466 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 8);
470 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 60);
477 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
481 return phy_modtype_unknown;
483 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
489 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
492 return v > 10 ? phy_modtype_twinax_long :
495 } else if (v == phy_transtype_xfp) {
496 /* XFP: See INF-8077i for details. */
498 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127);
503 /* XXX: set page select to table 1 yourself */
504 return phy_modtype_unknown;
507 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131);
512 return phy_modtype_lrm;
514 return phy_modtype_lr;
516 return phy_modtype_sr;
519 return phy_modtype_unknown;
523 * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
525 static int ael2005_setup_sr_edc(struct cphy *phy)
527 static struct reg_val regs[] = {
528 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
529 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
530 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
533 static u16 sr_edc[] = {
808 err = set_phy_regs(phy, regs);
814 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
815 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
822 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
824 static struct reg_val regs[] = {
825 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
828 static struct reg_val preemphasis[] = {
829 { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
830 { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
833 static u16 twinax_edc[] = {
1203 err = set_phy_regs(phy, regs);
1204 if (!err && modtype == phy_modtype_twinax_long)
1205 err = set_phy_regs(phy, preemphasis);
1211 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1212 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1215 phy->priv = edc_twinax;
1219 static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1224 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1228 if (stat & (1 << 8)) /* module absent */
1229 return phy_modtype_none;
1231 return ael2xxx_get_module_type(phy, delay_ms);
1234 static int ael2005_intr_enable(struct cphy *phy)
1236 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1237 return err ? err : t3_phy_lasi_intr_enable(phy);
1240 static int ael2005_intr_disable(struct cphy *phy)
1242 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1243 return err ? err : t3_phy_lasi_intr_disable(phy);
1246 static int ael2005_intr_clear(struct cphy *phy)
1248 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1249 return err ? err : t3_phy_lasi_intr_clear(phy);
1252 static int ael2005_reset(struct cphy *phy, int wait)
1254 static struct reg_val regs0[] = {
1255 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1256 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1257 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1258 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1259 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1260 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1261 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1264 static struct reg_val regs1[] = {
1265 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1266 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1271 unsigned int lasi_ctrl;
1273 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1277 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1282 phy->priv = edc_none;
1283 err = set_phy_regs(phy, regs0);
1289 err = ael2005_get_module_type(phy, 0);
1292 phy->modtype = (u8)err;
1294 if (err == phy_modtype_none)
1296 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1297 err = ael2005_setup_twinax_edc(phy, err);
1299 err = ael2005_setup_sr_edc(phy);
1303 err = set_phy_regs(phy, regs1);
1307 /* reset wipes out interrupts, reenable them if they were on */
1309 err = ael2005_intr_enable(phy);
1313 static int ael2005_intr_handler(struct cphy *phy)
1316 int ret, edc_needed, cause = 0;
1318 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1322 if (stat & AEL2005_MODDET_IRQ) {
1323 ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1328 /* modules have max 300 ms init time after hot plug */
1329 ret = ael2005_get_module_type(phy, 300);
1333 phy->modtype = (u8)ret;
1334 if (ret == phy_modtype_none)
1335 edc_needed = phy->priv; /* on unplug retain EDC */
1336 else if (ret == phy_modtype_twinax ||
1337 ret == phy_modtype_twinax_long)
1338 edc_needed = edc_twinax;
1340 edc_needed = edc_sr;
1342 if (edc_needed != phy->priv) {
1343 ret = ael2005_reset(phy, 0);
1344 return ret ? ret : cphy_cause_module_change;
1346 cause = cphy_cause_module_change;
1349 ret = t3_phy_lasi_intr_handler(phy);
1355 ret |= cphy_cause_link_change;
1359 static struct cphy_ops ael2005_ops = {
1360 #ifdef C99_NOT_SUPPORTED
1362 ael2005_intr_enable,
1363 ael2005_intr_disable,
1365 ael2005_intr_handler,
1374 .reset = ael2005_reset,
1375 .intr_enable = ael2005_intr_enable,
1376 .intr_disable = ael2005_intr_disable,
1377 .intr_clear = ael2005_intr_clear,
1378 .intr_handler = ael2005_intr_handler,
1379 .get_link_status = get_link_status_r,
1380 .power_down = ael1002_power_down,
1384 int t3_ael2005_phy_prep(pinfo_t *pinfo, int phy_addr,
1385 const struct mdio_ops *mdio_ops)
1388 struct cphy *phy = &pinfo->phy;
1390 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2005_ops, mdio_ops,
1391 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1392 SUPPORTED_IRQ, "10GBASE-R");
1394 ael_laser_down(phy, 0);
1396 err = ael2005_get_module_type(phy, 0);
1400 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1405 * Setup EDC and other parameters for operation with an optical module.
1407 static int ael2020_setup_sr_edc(struct cphy *phy)
1409 static struct reg_val regs[] = {
1410 { MDIO_DEV_PMA_PMD, 0xcc01, 0xffff, 0x488a },
1412 { MDIO_DEV_PMA_PMD, 0xcb1b, 0xffff, 0x0200 },
1413 { MDIO_DEV_PMA_PMD, 0xcb1c, 0xffff, 0x00f0 },
1414 { MDIO_DEV_PMA_PMD, 0xcc06, 0xffff, 0x00e0 },
1421 err = set_phy_regs(phy, regs);
1431 * Setup EDC and other parameters for operation with an TWINAX module.
1433 static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
1435 static struct reg_val uCclock40MHz[] = {
1436 { MDIO_DEV_PMA_PMD, 0xff28, 0xffff, 0x4001 },
1437 { MDIO_DEV_PMA_PMD, 0xff2a, 0xffff, 0x0002 },
1441 static struct reg_val uCclockActivate[] = {
1442 { MDIO_DEV_PMA_PMD, 0xd000, 0xffff, 0x5200 },
1446 static struct reg_val uCactivate[] = {
1447 { MDIO_DEV_PMA_PMD, 0xd080, 0xffff, 0x0100 },
1448 { MDIO_DEV_PMA_PMD, 0xd092, 0xffff, 0x0000 },
1452 static u16 twinax_edc[] = {
1895 /* set uC clock and activate it */
1896 err = set_phy_regs(phy, uCclock40MHz);
1900 err = set_phy_regs(phy, uCclockActivate);
1905 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1906 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1909 err = set_phy_regs(phy, uCactivate);
1911 phy->priv = edc_twinax;
1916 * Return Module Type.
1918 static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
1923 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_STAT, &stat);
1927 if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
1929 return phy_modtype_none;
1932 return ael2xxx_get_module_type(phy, delay_ms);
1936 * Enable PHY interrupts. We enable "Module Detection" interrupts (on any
1937 * state transition) and then generic Link Alarm Status Interrupt (LASI).
1939 static int ael2020_intr_enable(struct cphy *phy)
1941 struct reg_val regs[] = {
1942 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
1944 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1945 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
1947 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1948 0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
1955 err = set_phy_regs(phy, regs);
1959 /* enable standard Link Alarm Status Interrupts */
1960 err = t3_phy_lasi_intr_enable(phy);
1968 * Disable PHY interrupts. The mirror of the above ...
1970 static int ael2020_intr_disable(struct cphy *phy)
1972 struct reg_val regs[] = {
1973 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1974 0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
1976 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1977 0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
1984 err = set_phy_regs(phy, regs);
1988 /* disable standard Link Alarm Status Interrupts */
1989 return t3_phy_lasi_intr_disable(phy);
1993 * Clear PHY interrupt state.
1995 static int ael2020_intr_clear(struct cphy *phy)
1998 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
1999 return err ? err : t3_phy_lasi_intr_clear(phy);
2003 * Common register settings for the AEL2020 when it comes out of reset.
2005 static struct reg_val ael2020_reset_regs[] = {
2006 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x3101 },
2008 { MDIO_DEV_PMA_PMD, 0xcd40, 0xffff, 0x0001 },
2010 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0x0100 },
2011 { MDIO_DEV_PMA_PMD, 0xca22, 0xffff, 0x0100 },
2012 { MDIO_DEV_PMA_PMD, 0xca42, 0xffff, 0x0100 },
2013 { MDIO_DEV_PMA_PMD, 0xff02, 0xffff, 0x0023 },
2014 { MDIO_DEV_PMA_PMD, 0xff03, 0xffff, 0x0000 },
2015 { MDIO_DEV_PMA_PMD, 0xff04, 0xffff, 0x0000 },
2017 { MDIO_DEV_PMA_PMD, 0xc20d, 0xffff, 0x0002 },
2023 * Reset the PHY and put it into a canonical operating state.
2025 static int ael2020_reset(struct cphy *phy, int wait)
2028 unsigned int lasi_ctrl;
2030 /* grab current interrupt state */
2031 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
2035 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 125);
2040 /* basic initialization for all module types */
2041 phy->priv = edc_none;
2042 err = set_phy_regs(phy, ael2020_reset_regs);
2047 /* determine module type and perform appropriate initialization */
2048 err = ael2020_get_module_type(phy, 0);
2051 phy->modtype = (u8)err;
2052 if (err == phy_modtype_none)
2054 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
2055 err = ael2020_setup_twinax_edc(phy, err);
2057 err = ael2020_setup_sr_edc(phy);
2061 /* reset wipes out interrupts, reenable them if they were on */
2063 err = ael2020_intr_enable(phy);
2068 * Handle a PHY interrupt.
2070 static int ael2020_intr_handler(struct cphy *phy)
2073 int ret, edc_needed, cause = 0;
2075 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
2079 if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
2080 /* modules have max 300 ms init time after hot plug */
2081 ret = ael2020_get_module_type(phy, 300);
2085 phy->modtype = (u8)ret;
2086 if (ret == phy_modtype_none)
2087 edc_needed = phy->priv; /* on unplug retain EDC */
2088 else if (ret == phy_modtype_twinax ||
2089 ret == phy_modtype_twinax_long)
2090 edc_needed = edc_twinax;
2092 edc_needed = edc_sr;
2094 if (edc_needed != phy->priv) {
2095 ret = ael2020_reset(phy, 0);
2096 return ret ? ret : cphy_cause_module_change;
2098 cause = cphy_cause_module_change;
2101 ret = t3_phy_lasi_intr_handler(phy);
2107 ret |= cphy_cause_link_change;
2111 static struct cphy_ops ael2020_ops = {
2112 #ifdef C99_NOT_SUPPORTED
2114 ael2020_intr_enable,
2115 ael2020_intr_disable,
2117 ael2020_intr_handler,
2126 .reset = ael2020_reset,
2127 .intr_enable = ael2020_intr_enable,
2128 .intr_disable = ael2020_intr_disable,
2129 .intr_clear = ael2020_intr_clear,
2130 .intr_handler = ael2020_intr_handler,
2131 .get_link_status = get_link_status_r,
2132 .power_down = ael1002_power_down,
2136 int t3_ael2020_phy_prep(pinfo_t *pinfo, int phy_addr,
2137 const struct mdio_ops *mdio_ops)
2140 struct cphy *phy = &pinfo->phy;
2142 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2020_ops, mdio_ops,
2143 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
2144 SUPPORTED_IRQ, "10GBASE-R");
2147 err = set_phy_regs(phy, ael2020_reset_regs);
2152 err = ael2020_get_module_type(phy, 0);
2156 ael_laser_down(phy, 0);
2161 * Get link status for a 10GBASE-X device.
2163 static int get_link_status_x(struct cphy *phy, int *link_state, int *speed,
2164 int *duplex, int *fc)
2167 unsigned int stat0, stat1, stat2;
2168 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
2171 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
2173 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
2176 if ((stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1)
2177 *link_state = PHY_LINK_UP;
2179 *link_state = PHY_LINK_DOWN;
2182 *speed = SPEED_10000;
2184 *duplex = DUPLEX_FULL;
2188 #ifdef C99_NOT_SUPPORTED
2189 static struct cphy_ops qt2045_ops = {
2191 t3_phy_lasi_intr_enable,
2192 t3_phy_lasi_intr_disable,
2193 t3_phy_lasi_intr_clear,
2194 t3_phy_lasi_intr_handler,
2204 static struct cphy_ops qt2045_ops = {
2205 .reset = ael1006_reset,
2206 .intr_enable = t3_phy_lasi_intr_enable,
2207 .intr_disable = t3_phy_lasi_intr_disable,
2208 .intr_clear = t3_phy_lasi_intr_clear,
2209 .intr_handler = t3_phy_lasi_intr_handler,
2210 .get_link_status = get_link_status_x,
2211 .power_down = ael1002_power_down,
2215 int t3_qt2045_phy_prep(pinfo_t *pinfo, int phy_addr,
2216 const struct mdio_ops *mdio_ops)
2219 struct cphy *phy = &pinfo->phy;
2221 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &qt2045_ops, mdio_ops,
2222 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
2226 * Some cards where the PHY is supposed to be at address 0 actually
2229 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
2235 static int xaui_direct_reset(struct cphy *phy, int wait)
2240 static int xaui_direct_get_link_status(struct cphy *phy, int *link_state,
2241 int *speed, int *duplex, int *fc)
2244 unsigned int status;
2245 adapter_t *adapter = phy->adapter;
2247 status = t3_read_reg(adapter,
2248 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
2249 t3_read_reg(adapter,
2250 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
2251 t3_read_reg(adapter,
2252 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
2253 t3_read_reg(adapter,
2254 XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
2255 *link_state = status & F_LOWSIG0 ? PHY_LINK_DOWN : PHY_LINK_UP;
2258 *speed = SPEED_10000;
2260 *duplex = DUPLEX_FULL;
2264 static int xaui_direct_power_down(struct cphy *phy, int enable)
2269 #ifdef C99_NOT_SUPPORTED
2270 static struct cphy_ops xaui_direct_ops = {
2281 xaui_direct_get_link_status,
2282 xaui_direct_power_down,
2285 static struct cphy_ops xaui_direct_ops = {
2286 .reset = xaui_direct_reset,
2287 .intr_enable = ael1002_intr_noop,
2288 .intr_disable = ael1002_intr_noop,
2289 .intr_clear = ael1002_intr_noop,
2290 .intr_handler = ael1002_intr_noop,
2291 .get_link_status = xaui_direct_get_link_status,
2292 .power_down = xaui_direct_power_down,
2296 int t3_xaui_direct_phy_prep(pinfo_t *pinfo, int phy_addr,
2297 const struct mdio_ops *mdio_ops)
2299 cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &xaui_direct_ops, mdio_ops,
2300 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,