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_ok, 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);
299 *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
305 *speed = SPEED_10000;
307 *duplex = DUPLEX_FULL;
311 #ifdef C99_NOT_SUPPORTED
312 static struct cphy_ops ael1002_ops = {
327 static struct cphy_ops ael1002_ops = {
328 .reset = ael1002_reset,
329 .intr_enable = ael1002_intr_noop,
330 .intr_disable = ael1002_intr_noop,
331 .intr_clear = ael1002_intr_noop,
332 .intr_handler = ael1002_intr_noop,
333 .get_link_status = get_link_status_r,
334 .power_down = ael1002_power_down,
338 int t3_ael1002_phy_prep(pinfo_t *pinfo, int phy_addr,
339 const struct mdio_ops *mdio_ops)
342 struct cphy *phy = &pinfo->phy;
344 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1002_ops, mdio_ops,
345 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
348 ael_laser_down(phy, 0);
350 err = ael1002_get_module_type(phy, 0);
357 static int ael1006_reset(struct cphy *phy, int wait)
361 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
365 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
370 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
371 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL);
375 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
381 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1);
387 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0);
393 #ifdef C99_NOT_SUPPORTED
394 static struct cphy_ops ael1006_ops = {
396 t3_phy_lasi_intr_enable,
397 t3_phy_lasi_intr_disable,
398 t3_phy_lasi_intr_clear,
399 t3_phy_lasi_intr_handler,
409 static struct cphy_ops ael1006_ops = {
410 .reset = ael1006_reset,
411 .intr_enable = t3_phy_lasi_intr_enable,
412 .intr_disable = t3_phy_lasi_intr_disable,
413 .intr_clear = t3_phy_lasi_intr_clear,
414 .intr_handler = t3_phy_lasi_intr_handler,
415 .get_link_status = get_link_status_r,
416 .power_down = ael1002_power_down,
420 int t3_ael1006_phy_prep(pinfo_t *pinfo, int phy_addr,
421 const struct mdio_ops *mdio_ops)
423 struct cphy *phy = &pinfo->phy;
425 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1006_ops, mdio_ops,
426 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
428 phy->modtype = phy_modtype_sr;
434 * Decode our module type.
436 static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
443 v = get_phytrans_type(phy);
444 if (v == phy_transtype_sfp) {
445 /* SFP: see SFF-8472 for below */
447 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
454 return phy_modtype_sr;
456 return phy_modtype_lr;
458 return phy_modtype_lrm;
460 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 8);
464 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 60);
471 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
475 return phy_modtype_unknown;
477 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
483 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
486 return v > 10 ? phy_modtype_twinax_long :
489 } else if (v == phy_transtype_xfp) {
490 /* XFP: See INF-8077i for details. */
492 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127);
497 /* XXX: set page select to table 1 yourself */
498 return phy_modtype_unknown;
501 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131);
506 return phy_modtype_lrm;
508 return phy_modtype_lr;
510 return phy_modtype_sr;
513 return phy_modtype_unknown;
517 * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
519 static int ael2005_setup_sr_edc(struct cphy *phy)
521 static struct reg_val regs[] = {
522 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
523 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
524 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
527 static u16 sr_edc[] = {
802 err = set_phy_regs(phy, regs);
808 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
809 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
816 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
818 static struct reg_val regs[] = {
819 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
822 static struct reg_val preemphasis[] = {
823 { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
824 { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
827 static u16 twinax_edc[] = {
1197 err = set_phy_regs(phy, regs);
1198 if (!err && modtype == phy_modtype_twinax_long)
1199 err = set_phy_regs(phy, preemphasis);
1205 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1206 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1209 phy->priv = edc_twinax;
1213 static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1218 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1222 if (stat & (1 << 8)) /* module absent */
1223 return phy_modtype_none;
1225 return ael2xxx_get_module_type(phy, delay_ms);
1228 static int ael2005_intr_enable(struct cphy *phy)
1230 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1231 return err ? err : t3_phy_lasi_intr_enable(phy);
1234 static int ael2005_intr_disable(struct cphy *phy)
1236 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1237 return err ? err : t3_phy_lasi_intr_disable(phy);
1240 static int ael2005_intr_clear(struct cphy *phy)
1242 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1243 return err ? err : t3_phy_lasi_intr_clear(phy);
1246 static int ael2005_reset(struct cphy *phy, int wait)
1248 static struct reg_val regs0[] = {
1249 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1250 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1251 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1252 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1253 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1254 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1255 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1258 static struct reg_val regs1[] = {
1259 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1260 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1265 unsigned int lasi_ctrl;
1267 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1271 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1276 phy->priv = edc_none;
1277 err = set_phy_regs(phy, regs0);
1283 err = ael2005_get_module_type(phy, 0);
1286 phy->modtype = (u8)err;
1288 if (err == phy_modtype_none)
1290 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1291 err = ael2005_setup_twinax_edc(phy, err);
1293 err = ael2005_setup_sr_edc(phy);
1297 err = set_phy_regs(phy, regs1);
1301 /* reset wipes out interrupts, reenable them if they were on */
1303 err = ael2005_intr_enable(phy);
1307 static int ael2005_intr_handler(struct cphy *phy)
1310 int ret, edc_needed, cause = 0;
1312 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1316 if (stat & AEL2005_MODDET_IRQ) {
1317 ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1322 /* modules have max 300 ms init time after hot plug */
1323 ret = ael2005_get_module_type(phy, 300);
1327 phy->modtype = (u8)ret;
1328 if (ret == phy_modtype_none)
1329 edc_needed = phy->priv; /* on unplug retain EDC */
1330 else if (ret == phy_modtype_twinax ||
1331 ret == phy_modtype_twinax_long)
1332 edc_needed = edc_twinax;
1334 edc_needed = edc_sr;
1336 if (edc_needed != phy->priv) {
1337 ret = ael2005_reset(phy, 0);
1338 return ret ? ret : cphy_cause_module_change;
1340 cause = cphy_cause_module_change;
1343 ret = t3_phy_lasi_intr_handler(phy);
1349 ret |= cphy_cause_link_change;
1353 static struct cphy_ops ael2005_ops = {
1354 #ifdef C99_NOT_SUPPORTED
1356 ael2005_intr_enable,
1357 ael2005_intr_disable,
1359 ael2005_intr_handler,
1368 .reset = ael2005_reset,
1369 .intr_enable = ael2005_intr_enable,
1370 .intr_disable = ael2005_intr_disable,
1371 .intr_clear = ael2005_intr_clear,
1372 .intr_handler = ael2005_intr_handler,
1373 .get_link_status = get_link_status_r,
1374 .power_down = ael1002_power_down,
1378 int t3_ael2005_phy_prep(pinfo_t *pinfo, int phy_addr,
1379 const struct mdio_ops *mdio_ops)
1382 struct cphy *phy = &pinfo->phy;
1384 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2005_ops, mdio_ops,
1385 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1386 SUPPORTED_IRQ, "10GBASE-R");
1388 ael_laser_down(phy, 0);
1390 err = ael2005_get_module_type(phy, 0);
1394 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1399 * Setup EDC and other parameters for operation with an optical module.
1401 static int ael2020_setup_sr_edc(struct cphy *phy)
1403 static struct reg_val regs[] = {
1404 { MDIO_DEV_PMA_PMD, 0xcc01, 0xffff, 0x488a },
1406 { MDIO_DEV_PMA_PMD, 0xcb1b, 0xffff, 0x0200 },
1407 { MDIO_DEV_PMA_PMD, 0xcb1c, 0xffff, 0x00f0 },
1408 { MDIO_DEV_PMA_PMD, 0xcc06, 0xffff, 0x00e0 },
1415 err = set_phy_regs(phy, regs);
1425 * Setup EDC and other parameters for operation with an TWINAX module.
1427 static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
1429 static struct reg_val uCclock40MHz[] = {
1430 { MDIO_DEV_PMA_PMD, 0xff28, 0xffff, 0x4001 },
1431 { MDIO_DEV_PMA_PMD, 0xff2a, 0xffff, 0x0002 },
1435 static struct reg_val uCclockActivate[] = {
1436 { MDIO_DEV_PMA_PMD, 0xd000, 0xffff, 0x5200 },
1440 static struct reg_val uCactivate[] = {
1441 { MDIO_DEV_PMA_PMD, 0xd080, 0xffff, 0x0100 },
1442 { MDIO_DEV_PMA_PMD, 0xd092, 0xffff, 0x0000 },
1446 static u16 twinax_edc[] = {
1889 /* set uC clock and activate it */
1890 err = set_phy_regs(phy, uCclock40MHz);
1894 err = set_phy_regs(phy, uCclockActivate);
1899 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1900 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1903 err = set_phy_regs(phy, uCactivate);
1905 phy->priv = edc_twinax;
1910 * Return Module Type.
1912 static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
1917 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_STAT, &stat);
1921 if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
1923 return phy_modtype_none;
1926 return ael2xxx_get_module_type(phy, delay_ms);
1930 * Enable PHY interrupts. We enable "Module Detection" interrupts (on any
1931 * state transition) and then generic Link Alarm Status Interrupt (LASI).
1933 static int ael2020_intr_enable(struct cphy *phy)
1935 struct reg_val regs[] = {
1936 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
1938 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1939 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
1941 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1942 0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
1949 err = set_phy_regs(phy, regs);
1953 /* enable standard Link Alarm Status Interrupts */
1954 err = t3_phy_lasi_intr_enable(phy);
1962 * Disable PHY interrupts. The mirror of the above ...
1964 static int ael2020_intr_disable(struct cphy *phy)
1966 struct reg_val regs[] = {
1967 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1968 0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
1970 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1971 0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
1978 err = set_phy_regs(phy, regs);
1982 /* disable standard Link Alarm Status Interrupts */
1983 return t3_phy_lasi_intr_disable(phy);
1987 * Clear PHY interrupt state.
1989 static int ael2020_intr_clear(struct cphy *phy)
1992 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
1993 return err ? err : t3_phy_lasi_intr_clear(phy);
1997 * Common register settings for the AEL2020 when it comes out of reset.
1999 static struct reg_val ael2020_reset_regs[] = {
2000 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x3101 },
2002 { MDIO_DEV_PMA_PMD, 0xcd40, 0xffff, 0x0001 },
2004 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0x0100 },
2005 { MDIO_DEV_PMA_PMD, 0xca22, 0xffff, 0x0100 },
2006 { MDIO_DEV_PMA_PMD, 0xca42, 0xffff, 0x0100 },
2007 { MDIO_DEV_PMA_PMD, 0xff02, 0xffff, 0x0023 },
2008 { MDIO_DEV_PMA_PMD, 0xff03, 0xffff, 0x0000 },
2009 { MDIO_DEV_PMA_PMD, 0xff04, 0xffff, 0x0000 },
2011 { MDIO_DEV_PMA_PMD, 0xc20d, 0xffff, 0x0002 },
2017 * Reset the PHY and put it into a canonical operating state.
2019 static int ael2020_reset(struct cphy *phy, int wait)
2022 unsigned int lasi_ctrl;
2024 /* grab current interrupt state */
2025 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
2029 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 125);
2034 /* basic initialization for all module types */
2035 phy->priv = edc_none;
2036 err = set_phy_regs(phy, ael2020_reset_regs);
2041 /* determine module type and perform appropriate initialization */
2042 err = ael2020_get_module_type(phy, 0);
2045 phy->modtype = (u8)err;
2046 if (err == phy_modtype_none)
2048 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
2049 err = ael2020_setup_twinax_edc(phy, err);
2051 err = ael2020_setup_sr_edc(phy);
2055 /* reset wipes out interrupts, reenable them if they were on */
2057 err = ael2020_intr_enable(phy);
2062 * Handle a PHY interrupt.
2064 static int ael2020_intr_handler(struct cphy *phy)
2067 int ret, edc_needed, cause = 0;
2069 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
2073 if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
2074 /* modules have max 300 ms init time after hot plug */
2075 ret = ael2020_get_module_type(phy, 300);
2079 phy->modtype = (u8)ret;
2080 if (ret == phy_modtype_none)
2081 edc_needed = phy->priv; /* on unplug retain EDC */
2082 else if (ret == phy_modtype_twinax ||
2083 ret == phy_modtype_twinax_long)
2084 edc_needed = edc_twinax;
2086 edc_needed = edc_sr;
2088 if (edc_needed != phy->priv) {
2089 ret = ael2020_reset(phy, 0);
2090 return ret ? ret : cphy_cause_module_change;
2092 cause = cphy_cause_module_change;
2095 ret = t3_phy_lasi_intr_handler(phy);
2101 ret |= cphy_cause_link_change;
2105 static struct cphy_ops ael2020_ops = {
2106 #ifdef C99_NOT_SUPPORTED
2108 ael2020_intr_enable,
2109 ael2020_intr_disable,
2111 ael2020_intr_handler,
2120 .reset = ael2020_reset,
2121 .intr_enable = ael2020_intr_enable,
2122 .intr_disable = ael2020_intr_disable,
2123 .intr_clear = ael2020_intr_clear,
2124 .intr_handler = ael2020_intr_handler,
2125 .get_link_status = get_link_status_r,
2126 .power_down = ael1002_power_down,
2130 int t3_ael2020_phy_prep(pinfo_t *pinfo, int phy_addr,
2131 const struct mdio_ops *mdio_ops)
2134 struct cphy *phy = &pinfo->phy;
2136 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2020_ops, mdio_ops,
2137 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
2138 SUPPORTED_IRQ, "10GBASE-R");
2141 err = set_phy_regs(phy, ael2020_reset_regs);
2146 err = ael2020_get_module_type(phy, 0);
2150 ael_laser_down(phy, 0);
2155 * Get link status for a 10GBASE-X device.
2157 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
2158 int *duplex, int *fc)
2161 unsigned int stat0, stat1, stat2;
2162 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
2165 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
2167 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
2170 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
2173 *speed = SPEED_10000;
2175 *duplex = DUPLEX_FULL;
2179 #ifdef C99_NOT_SUPPORTED
2180 static struct cphy_ops qt2045_ops = {
2182 t3_phy_lasi_intr_enable,
2183 t3_phy_lasi_intr_disable,
2184 t3_phy_lasi_intr_clear,
2185 t3_phy_lasi_intr_handler,
2195 static struct cphy_ops qt2045_ops = {
2196 .reset = ael1006_reset,
2197 .intr_enable = t3_phy_lasi_intr_enable,
2198 .intr_disable = t3_phy_lasi_intr_disable,
2199 .intr_clear = t3_phy_lasi_intr_clear,
2200 .intr_handler = t3_phy_lasi_intr_handler,
2201 .get_link_status = get_link_status_x,
2202 .power_down = ael1002_power_down,
2206 int t3_qt2045_phy_prep(pinfo_t *pinfo, int phy_addr,
2207 const struct mdio_ops *mdio_ops)
2210 struct cphy *phy = &pinfo->phy;
2212 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &qt2045_ops, mdio_ops,
2213 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
2217 * Some cards where the PHY is supposed to be at address 0 actually
2220 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
2226 static int xaui_direct_reset(struct cphy *phy, int wait)
2231 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
2232 int *speed, int *duplex, int *fc)
2235 unsigned int status;
2236 adapter_t *adapter = phy->adapter;
2238 status = t3_read_reg(adapter,
2239 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
2240 t3_read_reg(adapter,
2241 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
2242 t3_read_reg(adapter,
2243 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
2244 t3_read_reg(adapter,
2245 XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
2246 *link_ok = !(status & F_LOWSIG0);
2249 *speed = SPEED_10000;
2251 *duplex = DUPLEX_FULL;
2255 static int xaui_direct_power_down(struct cphy *phy, int enable)
2260 #ifdef C99_NOT_SUPPORTED
2261 static struct cphy_ops xaui_direct_ops = {
2272 xaui_direct_get_link_status,
2273 xaui_direct_power_down,
2276 static struct cphy_ops xaui_direct_ops = {
2277 .reset = xaui_direct_reset,
2278 .intr_enable = ael1002_intr_noop,
2279 .intr_disable = ael1002_intr_noop,
2280 .intr_clear = ael1002_intr_noop,
2281 .intr_handler = ael1002_intr_noop,
2282 .get_link_status = xaui_direct_get_link_status,
2283 .power_down = xaui_direct_power_down,
2287 int t3_xaui_direct_phy_prep(pinfo_t *pinfo, int phy_addr,
2288 const struct mdio_ops *mdio_ops)
2290 cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &xaui_direct_ops, mdio_ops,
2291 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,