1 /**************************************************************************
2 SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 Copyright (c) 2007-2009, Chelsio Inc.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
13 2. Neither the name of the Chelsio Corporation nor the names of its
14 contributors may be used to endorse or promote products derived from
15 this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
29 ***************************************************************************/
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <cxgb_include.h>
37 #define msleep t3_os_sleep
40 PMD_RSD = 10, /* PMA/PMD receive signal detect register */
41 PCS_STAT1_X = 24, /* 10GBASE-X PCS status 1 register */
42 PCS_STAT1_R = 32, /* 10GBASE-R PCS status 1 register */
43 XS_LN_STAT = 24 /* XS lane status register */
47 AEL100X_TX_DISABLE = 9,
48 AEL100X_TX_CONFIG1 = 0xc002,
50 AEL1002_PWR_DOWN_HI = 0xc011,
51 AEL1002_PWR_DOWN_LO = 0xc012,
52 AEL1002_XFI_EQL = 0xc015,
53 AEL1002_LB_EN = 0xc017,
55 AEL_OPT_SETTINGS = 0xc017,
56 AEL_I2C_CTRL = 0xc30a,
57 AEL_I2C_DATA = 0xc30b,
58 AEL_I2C_STAT = 0xc30c,
60 AEL2005_GPIO_CTRL = 0xc214,
61 AEL2005_GPIO_STAT = 0xc215,
63 AEL2020_GPIO_INTR = 0xc103,
64 AEL2020_GPIO_CTRL = 0xc108,
65 AEL2020_GPIO_STAT = 0xc10c,
66 AEL2020_GPIO_CFG = 0xc110,
69 AEL2020_GPIO_MODDET = 1,
72 AEL2020_GPIO_LSTAT = AEL2020_GPIO_1,
75 enum { edc_none, edc_sr, edc_twinax };
77 /* PHY module I2C device address */
79 MODULE_DEV_ADDR = 0xa0,
83 /* PHY transceiver type */
85 phy_transtype_unknown = 0,
86 phy_transtype_sfp = 3,
87 phy_transtype_xfp = 6,
90 #define AEL2005_MODDET_IRQ 4
93 unsigned short mmd_addr;
94 unsigned short reg_addr;
95 unsigned short clear_bits;
96 unsigned short set_bits;
99 static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms);
101 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
105 for (err = 0; rv->mmd_addr && !err; rv++) {
106 if (rv->clear_bits == 0xffff)
107 err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
110 err = t3_mdio_change_bits(phy, rv->mmd_addr,
111 rv->reg_addr, rv->clear_bits,
117 static void ael100x_txon(struct cphy *phy)
119 int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
122 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
127 * Read an 8-bit word from a device attached to the PHY's i2c bus.
129 static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
132 unsigned int stat, data;
134 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
135 (dev_addr << 8) | (1 << 8) | word_addr);
139 for (i = 0; i < 200; i++) {
141 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
144 if ((stat & 3) == 1) {
145 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
152 CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %x.%x timed out\n",
153 phy->addr, dev_addr, word_addr);
158 * Write an 8-bit word to a device attached to the PHY's i2c bus.
160 static int ael_i2c_wr(struct cphy *phy, int dev_addr, int word_addr, int data)
165 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, data);
169 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
170 (dev_addr << 8) | word_addr);
174 for (i = 0; i < 200; i++) {
176 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
182 CH_WARN(phy->adapter, "PHY %u i2c Write of dev.addr %x.%x = %#x timed out\n",
183 phy->addr, dev_addr, word_addr, data);
187 static int get_phytrans_type(struct cphy *phy)
191 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
193 return phy_transtype_unknown;
198 static int ael_laser_down(struct cphy *phy, int enable)
202 v = get_phytrans_type(phy);
206 if (v == phy_transtype_sfp) {
207 /* Check SFF Soft TX disable is supported */
208 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 93);
216 dev_addr = SFF_DEV_ADDR;
217 } else if (v == phy_transtype_xfp)
218 dev_addr = MODULE_DEV_ADDR;
222 v = ael_i2c_rd(phy, dev_addr, 110);
231 v = ael_i2c_wr(phy, dev_addr, 110, v);
236 static int ael1002_power_down(struct cphy *phy, int enable)
240 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
242 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
243 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
247 static int ael1002_get_module_type(struct cphy *phy, int delay_ms)
254 v = ael2xxx_get_module_type(phy, delay_ms);
256 return (v == -ETIMEDOUT ? phy_modtype_none : v);
259 static int ael1002_reset(struct cphy *phy, int wait)
263 if ((err = ael1002_power_down(phy, 0)) ||
264 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
265 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
266 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
267 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
268 (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
272 err = ael1002_get_module_type(phy, 300);
279 static int ael1002_intr_noop(struct cphy *phy)
285 * Get link status for a 10GBASE-R device.
287 static int get_link_status_r(struct cphy *phy, int *link_state, int *speed,
288 int *duplex, int *fc)
291 unsigned int stat0, stat1, stat2;
292 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
295 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
297 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
303 stat2 = (stat2 >> 12) & 1;
304 if (stat0 & stat1 & stat2)
305 *link_state = PHY_LINK_UP;
306 else if (stat0 == 1 && stat1 == 0 && stat2 == 1)
307 *link_state = PHY_LINK_PARTIAL;
309 *link_state = PHY_LINK_DOWN;
312 *speed = SPEED_10000;
314 *duplex = DUPLEX_FULL;
318 #ifdef C99_NOT_SUPPORTED
319 static struct cphy_ops ael1002_ops = {
334 static struct cphy_ops ael1002_ops = {
335 .reset = ael1002_reset,
336 .intr_enable = ael1002_intr_noop,
337 .intr_disable = ael1002_intr_noop,
338 .intr_clear = ael1002_intr_noop,
339 .intr_handler = ael1002_intr_noop,
340 .get_link_status = get_link_status_r,
341 .power_down = ael1002_power_down,
345 int t3_ael1002_phy_prep(pinfo_t *pinfo, int phy_addr,
346 const struct mdio_ops *mdio_ops)
349 struct cphy *phy = &pinfo->phy;
351 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1002_ops, mdio_ops,
352 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
355 ael_laser_down(phy, 0);
357 err = ael1002_get_module_type(phy, 0);
364 static int ael1006_reset(struct cphy *phy, int wait)
368 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
372 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
377 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
378 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL);
382 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
388 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1);
394 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0);
400 #ifdef C99_NOT_SUPPORTED
401 static struct cphy_ops ael1006_ops = {
403 t3_phy_lasi_intr_enable,
404 t3_phy_lasi_intr_disable,
405 t3_phy_lasi_intr_clear,
406 t3_phy_lasi_intr_handler,
416 static struct cphy_ops ael1006_ops = {
417 .reset = ael1006_reset,
418 .intr_enable = t3_phy_lasi_intr_enable,
419 .intr_disable = t3_phy_lasi_intr_disable,
420 .intr_clear = t3_phy_lasi_intr_clear,
421 .intr_handler = t3_phy_lasi_intr_handler,
422 .get_link_status = get_link_status_r,
423 .power_down = ael1002_power_down,
427 int t3_ael1006_phy_prep(pinfo_t *pinfo, int phy_addr,
428 const struct mdio_ops *mdio_ops)
430 struct cphy *phy = &pinfo->phy;
432 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1006_ops, mdio_ops,
433 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
435 phy->modtype = phy_modtype_sr;
441 * Decode our module type.
443 static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
450 v = get_phytrans_type(phy);
451 if (v == phy_transtype_sfp) {
452 /* SFP: see SFF-8472 for below */
454 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
461 return phy_modtype_sr;
463 return phy_modtype_lr;
465 return phy_modtype_lrm;
467 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 8);
471 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 60);
478 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
482 return phy_modtype_unknown;
484 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
490 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
493 return v > 10 ? phy_modtype_twinax_long :
496 } else if (v == phy_transtype_xfp) {
497 /* XFP: See INF-8077i for details. */
499 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127);
504 /* XXX: set page select to table 1 yourself */
505 return phy_modtype_unknown;
508 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131);
513 return phy_modtype_lrm;
515 return phy_modtype_lr;
517 return phy_modtype_sr;
520 return phy_modtype_unknown;
524 * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
526 static int ael2005_setup_sr_edc(struct cphy *phy)
528 static struct reg_val regs[] = {
529 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
530 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
531 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
534 static u16 sr_edc[] = {
809 err = set_phy_regs(phy, regs);
815 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
816 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
823 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
825 static struct reg_val regs[] = {
826 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
829 static struct reg_val preemphasis[] = {
830 { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
831 { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
834 static u16 twinax_edc[] = {
1204 err = set_phy_regs(phy, regs);
1205 if (!err && modtype == phy_modtype_twinax_long)
1206 err = set_phy_regs(phy, preemphasis);
1212 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1213 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1216 phy->priv = edc_twinax;
1220 static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1225 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1229 if (stat & (1 << 8)) /* module absent */
1230 return phy_modtype_none;
1232 return ael2xxx_get_module_type(phy, delay_ms);
1235 static int ael2005_intr_enable(struct cphy *phy)
1237 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1238 return err ? err : t3_phy_lasi_intr_enable(phy);
1241 static int ael2005_intr_disable(struct cphy *phy)
1243 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1244 return err ? err : t3_phy_lasi_intr_disable(phy);
1247 static int ael2005_intr_clear(struct cphy *phy)
1249 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1250 return err ? err : t3_phy_lasi_intr_clear(phy);
1253 static int ael2005_reset(struct cphy *phy, int wait)
1255 static struct reg_val regs0[] = {
1256 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1257 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1258 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1259 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1260 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1261 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1262 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1265 static struct reg_val regs1[] = {
1266 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1267 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1272 unsigned int lasi_ctrl;
1274 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1278 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1283 phy->priv = edc_none;
1284 err = set_phy_regs(phy, regs0);
1290 err = ael2005_get_module_type(phy, 0);
1293 phy->modtype = (u8)err;
1295 if (err == phy_modtype_none)
1297 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1298 err = ael2005_setup_twinax_edc(phy, err);
1300 err = ael2005_setup_sr_edc(phy);
1304 err = set_phy_regs(phy, regs1);
1308 /* reset wipes out interrupts, reenable them if they were on */
1310 err = ael2005_intr_enable(phy);
1314 static int ael2005_intr_handler(struct cphy *phy)
1317 int ret, edc_needed, cause = 0;
1319 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1323 if (stat & AEL2005_MODDET_IRQ) {
1324 ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1329 /* modules have max 300 ms init time after hot plug */
1330 ret = ael2005_get_module_type(phy, 300);
1334 phy->modtype = (u8)ret;
1335 if (ret == phy_modtype_none)
1336 edc_needed = phy->priv; /* on unplug retain EDC */
1337 else if (ret == phy_modtype_twinax ||
1338 ret == phy_modtype_twinax_long)
1339 edc_needed = edc_twinax;
1341 edc_needed = edc_sr;
1343 if (edc_needed != phy->priv) {
1344 ret = ael2005_reset(phy, 0);
1345 return ret ? ret : cphy_cause_module_change;
1347 cause = cphy_cause_module_change;
1350 ret = t3_phy_lasi_intr_handler(phy);
1356 ret |= cphy_cause_link_change;
1360 static struct cphy_ops ael2005_ops = {
1361 #ifdef C99_NOT_SUPPORTED
1363 ael2005_intr_enable,
1364 ael2005_intr_disable,
1366 ael2005_intr_handler,
1375 .reset = ael2005_reset,
1376 .intr_enable = ael2005_intr_enable,
1377 .intr_disable = ael2005_intr_disable,
1378 .intr_clear = ael2005_intr_clear,
1379 .intr_handler = ael2005_intr_handler,
1380 .get_link_status = get_link_status_r,
1381 .power_down = ael1002_power_down,
1385 int t3_ael2005_phy_prep(pinfo_t *pinfo, int phy_addr,
1386 const struct mdio_ops *mdio_ops)
1389 struct cphy *phy = &pinfo->phy;
1391 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2005_ops, mdio_ops,
1392 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1393 SUPPORTED_IRQ, "10GBASE-R");
1395 ael_laser_down(phy, 0);
1397 err = ael2005_get_module_type(phy, 0);
1401 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1406 * Setup EDC and other parameters for operation with an optical module.
1408 static int ael2020_setup_sr_edc(struct cphy *phy)
1410 static struct reg_val regs[] = {
1411 { MDIO_DEV_PMA_PMD, 0xcc01, 0xffff, 0x488a },
1413 { MDIO_DEV_PMA_PMD, 0xcb1b, 0xffff, 0x0200 },
1414 { MDIO_DEV_PMA_PMD, 0xcb1c, 0xffff, 0x00f0 },
1415 { MDIO_DEV_PMA_PMD, 0xcc06, 0xffff, 0x00e0 },
1422 err = set_phy_regs(phy, regs);
1432 * Setup EDC and other parameters for operation with an TWINAX module.
1434 static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
1436 static struct reg_val uCclock40MHz[] = {
1437 { MDIO_DEV_PMA_PMD, 0xff28, 0xffff, 0x4001 },
1438 { MDIO_DEV_PMA_PMD, 0xff2a, 0xffff, 0x0002 },
1442 static struct reg_val uCclockActivate[] = {
1443 { MDIO_DEV_PMA_PMD, 0xd000, 0xffff, 0x5200 },
1447 static struct reg_val uCactivate[] = {
1448 { MDIO_DEV_PMA_PMD, 0xd080, 0xffff, 0x0100 },
1449 { MDIO_DEV_PMA_PMD, 0xd092, 0xffff, 0x0000 },
1453 static u16 twinax_edc[] = {
1896 /* set uC clock and activate it */
1897 err = set_phy_regs(phy, uCclock40MHz);
1901 err = set_phy_regs(phy, uCclockActivate);
1906 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1907 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1910 err = set_phy_regs(phy, uCactivate);
1912 phy->priv = edc_twinax;
1917 * Return Module Type.
1919 static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
1924 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_STAT, &stat);
1928 if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
1930 return phy_modtype_none;
1933 return ael2xxx_get_module_type(phy, delay_ms);
1937 * Enable PHY interrupts. We enable "Module Detection" interrupts (on any
1938 * state transition) and then generic Link Alarm Status Interrupt (LASI).
1940 static int ael2020_intr_enable(struct cphy *phy)
1942 struct reg_val regs[] = {
1943 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
1945 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1946 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
1948 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1949 0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
1956 err = set_phy_regs(phy, regs);
1960 /* enable standard Link Alarm Status Interrupts */
1961 err = t3_phy_lasi_intr_enable(phy);
1969 * Disable PHY interrupts. The mirror of the above ...
1971 static int ael2020_intr_disable(struct cphy *phy)
1973 struct reg_val regs[] = {
1974 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1975 0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
1977 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1978 0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
1985 err = set_phy_regs(phy, regs);
1989 /* disable standard Link Alarm Status Interrupts */
1990 return t3_phy_lasi_intr_disable(phy);
1994 * Clear PHY interrupt state.
1996 static int ael2020_intr_clear(struct cphy *phy)
1999 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
2000 return err ? err : t3_phy_lasi_intr_clear(phy);
2004 * Common register settings for the AEL2020 when it comes out of reset.
2006 static struct reg_val ael2020_reset_regs[] = {
2007 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x3101 },
2009 { MDIO_DEV_PMA_PMD, 0xcd40, 0xffff, 0x0001 },
2011 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0x0100 },
2012 { MDIO_DEV_PMA_PMD, 0xca22, 0xffff, 0x0100 },
2013 { MDIO_DEV_PMA_PMD, 0xca42, 0xffff, 0x0100 },
2014 { MDIO_DEV_PMA_PMD, 0xff02, 0xffff, 0x0023 },
2015 { MDIO_DEV_PMA_PMD, 0xff03, 0xffff, 0x0000 },
2016 { MDIO_DEV_PMA_PMD, 0xff04, 0xffff, 0x0000 },
2018 { MDIO_DEV_PMA_PMD, 0xc20d, 0xffff, 0x0002 },
2024 * Reset the PHY and put it into a canonical operating state.
2026 static int ael2020_reset(struct cphy *phy, int wait)
2029 unsigned int lasi_ctrl;
2031 /* grab current interrupt state */
2032 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
2036 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 125);
2041 /* basic initialization for all module types */
2042 phy->priv = edc_none;
2043 err = set_phy_regs(phy, ael2020_reset_regs);
2048 /* determine module type and perform appropriate initialization */
2049 err = ael2020_get_module_type(phy, 0);
2052 phy->modtype = (u8)err;
2053 if (err == phy_modtype_none)
2055 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
2056 err = ael2020_setup_twinax_edc(phy, err);
2058 err = ael2020_setup_sr_edc(phy);
2062 /* reset wipes out interrupts, reenable them if they were on */
2064 err = ael2020_intr_enable(phy);
2069 * Handle a PHY interrupt.
2071 static int ael2020_intr_handler(struct cphy *phy)
2074 int ret, edc_needed, cause = 0;
2076 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
2080 if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
2081 /* modules have max 300 ms init time after hot plug */
2082 ret = ael2020_get_module_type(phy, 300);
2086 phy->modtype = (u8)ret;
2087 if (ret == phy_modtype_none)
2088 edc_needed = phy->priv; /* on unplug retain EDC */
2089 else if (ret == phy_modtype_twinax ||
2090 ret == phy_modtype_twinax_long)
2091 edc_needed = edc_twinax;
2093 edc_needed = edc_sr;
2095 if (edc_needed != phy->priv) {
2096 ret = ael2020_reset(phy, 0);
2097 return ret ? ret : cphy_cause_module_change;
2099 cause = cphy_cause_module_change;
2102 ret = t3_phy_lasi_intr_handler(phy);
2108 ret |= cphy_cause_link_change;
2112 static struct cphy_ops ael2020_ops = {
2113 #ifdef C99_NOT_SUPPORTED
2115 ael2020_intr_enable,
2116 ael2020_intr_disable,
2118 ael2020_intr_handler,
2127 .reset = ael2020_reset,
2128 .intr_enable = ael2020_intr_enable,
2129 .intr_disable = ael2020_intr_disable,
2130 .intr_clear = ael2020_intr_clear,
2131 .intr_handler = ael2020_intr_handler,
2132 .get_link_status = get_link_status_r,
2133 .power_down = ael1002_power_down,
2137 int t3_ael2020_phy_prep(pinfo_t *pinfo, int phy_addr,
2138 const struct mdio_ops *mdio_ops)
2141 struct cphy *phy = &pinfo->phy;
2143 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2020_ops, mdio_ops,
2144 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
2145 SUPPORTED_IRQ, "10GBASE-R");
2148 err = set_phy_regs(phy, ael2020_reset_regs);
2153 err = ael2020_get_module_type(phy, 0);
2157 ael_laser_down(phy, 0);
2162 * Get link status for a 10GBASE-X device.
2164 static int get_link_status_x(struct cphy *phy, int *link_state, int *speed,
2165 int *duplex, int *fc)
2168 unsigned int stat0, stat1, stat2;
2169 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
2172 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
2174 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
2177 if ((stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1)
2178 *link_state = PHY_LINK_UP;
2180 *link_state = PHY_LINK_DOWN;
2183 *speed = SPEED_10000;
2185 *duplex = DUPLEX_FULL;
2189 #ifdef C99_NOT_SUPPORTED
2190 static struct cphy_ops qt2045_ops = {
2192 t3_phy_lasi_intr_enable,
2193 t3_phy_lasi_intr_disable,
2194 t3_phy_lasi_intr_clear,
2195 t3_phy_lasi_intr_handler,
2205 static struct cphy_ops qt2045_ops = {
2206 .reset = ael1006_reset,
2207 .intr_enable = t3_phy_lasi_intr_enable,
2208 .intr_disable = t3_phy_lasi_intr_disable,
2209 .intr_clear = t3_phy_lasi_intr_clear,
2210 .intr_handler = t3_phy_lasi_intr_handler,
2211 .get_link_status = get_link_status_x,
2212 .power_down = ael1002_power_down,
2216 int t3_qt2045_phy_prep(pinfo_t *pinfo, int phy_addr,
2217 const struct mdio_ops *mdio_ops)
2220 struct cphy *phy = &pinfo->phy;
2222 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &qt2045_ops, mdio_ops,
2223 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
2227 * Some cards where the PHY is supposed to be at address 0 actually
2230 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
2236 static int xaui_direct_reset(struct cphy *phy, int wait)
2241 static int xaui_direct_get_link_status(struct cphy *phy, int *link_state,
2242 int *speed, int *duplex, int *fc)
2245 unsigned int status;
2246 adapter_t *adapter = phy->adapter;
2248 status = t3_read_reg(adapter,
2249 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
2250 t3_read_reg(adapter,
2251 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
2252 t3_read_reg(adapter,
2253 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
2254 t3_read_reg(adapter,
2255 XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
2256 *link_state = status & F_LOWSIG0 ? PHY_LINK_DOWN : PHY_LINK_UP;
2259 *speed = SPEED_10000;
2261 *duplex = DUPLEX_FULL;
2265 static int xaui_direct_power_down(struct cphy *phy, int enable)
2270 #ifdef C99_NOT_SUPPORTED
2271 static struct cphy_ops xaui_direct_ops = {
2282 xaui_direct_get_link_status,
2283 xaui_direct_power_down,
2286 static struct cphy_ops xaui_direct_ops = {
2287 .reset = xaui_direct_reset,
2288 .intr_enable = ael1002_intr_noop,
2289 .intr_disable = ael1002_intr_noop,
2290 .intr_clear = ael1002_intr_noop,
2291 .intr_handler = ael1002_intr_noop,
2292 .get_link_status = xaui_direct_get_link_status,
2293 .power_down = xaui_direct_power_down,
2297 int t3_xaui_direct_phy_prep(pinfo_t *pinfo, int phy_addr,
2298 const struct mdio_ops *mdio_ops)
2300 cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &xaui_direct_ops, mdio_ops,
2301 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,