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;
302 *speed = SPEED_10000;
304 *duplex = DUPLEX_FULL;
308 #ifdef C99_NOT_SUPPORTED
309 static struct cphy_ops ael1002_ops = {
324 static struct cphy_ops ael1002_ops = {
325 .reset = ael1002_reset,
326 .intr_enable = ael1002_intr_noop,
327 .intr_disable = ael1002_intr_noop,
328 .intr_clear = ael1002_intr_noop,
329 .intr_handler = ael1002_intr_noop,
330 .get_link_status = get_link_status_r,
331 .power_down = ael1002_power_down,
335 int t3_ael1002_phy_prep(pinfo_t *pinfo, int phy_addr,
336 const struct mdio_ops *mdio_ops)
339 struct cphy *phy = &pinfo->phy;
341 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1002_ops, mdio_ops,
342 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
345 ael_laser_down(phy, 0);
347 err = ael1002_get_module_type(phy, 0);
354 static int ael1006_reset(struct cphy *phy, int wait)
358 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
362 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
367 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
368 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL);
372 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
378 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1);
384 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0);
390 #ifdef C99_NOT_SUPPORTED
391 static struct cphy_ops ael1006_ops = {
393 t3_phy_lasi_intr_enable,
394 t3_phy_lasi_intr_disable,
395 t3_phy_lasi_intr_clear,
396 t3_phy_lasi_intr_handler,
406 static struct cphy_ops ael1006_ops = {
407 .reset = ael1006_reset,
408 .intr_enable = t3_phy_lasi_intr_enable,
409 .intr_disable = t3_phy_lasi_intr_disable,
410 .intr_clear = t3_phy_lasi_intr_clear,
411 .intr_handler = t3_phy_lasi_intr_handler,
412 .get_link_status = get_link_status_r,
413 .power_down = ael1002_power_down,
417 int t3_ael1006_phy_prep(pinfo_t *pinfo, int phy_addr,
418 const struct mdio_ops *mdio_ops)
420 struct cphy *phy = &pinfo->phy;
422 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1006_ops, mdio_ops,
423 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
425 phy->modtype = phy_modtype_sr;
431 * Decode our module type.
433 static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
440 v = get_phytrans_type(phy);
441 if (v == phy_transtype_sfp) {
442 /* SFP: see SFF-8472 for below */
444 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
451 return phy_modtype_sr;
453 return phy_modtype_lr;
455 return phy_modtype_lrm;
457 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 8);
461 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 60);
468 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
472 return phy_modtype_unknown;
474 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
480 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
483 return v > 10 ? phy_modtype_twinax_long :
486 } else if (v == phy_transtype_xfp) {
487 /* XFP: See INF-8077i for details. */
489 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127);
494 /* XXX: set page select to table 1 yourself */
495 return phy_modtype_unknown;
498 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131);
503 return phy_modtype_lrm;
505 return phy_modtype_lr;
507 return phy_modtype_sr;
510 return phy_modtype_unknown;
514 * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
516 static int ael2005_setup_sr_edc(struct cphy *phy)
518 static struct reg_val regs[] = {
519 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
520 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
521 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
524 static u16 sr_edc[] = {
799 err = set_phy_regs(phy, regs);
805 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
806 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
813 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
815 static struct reg_val regs[] = {
816 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
819 static struct reg_val preemphasis[] = {
820 { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
821 { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
824 static u16 twinax_edc[] = {
1194 err = set_phy_regs(phy, regs);
1195 if (!err && modtype == phy_modtype_twinax_long)
1196 err = set_phy_regs(phy, preemphasis);
1202 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1203 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1206 phy->priv = edc_twinax;
1210 static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1215 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1219 if (stat & (1 << 8)) /* module absent */
1220 return phy_modtype_none;
1222 return ael2xxx_get_module_type(phy, delay_ms);
1225 static int ael2005_intr_enable(struct cphy *phy)
1227 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1228 return err ? err : t3_phy_lasi_intr_enable(phy);
1231 static int ael2005_intr_disable(struct cphy *phy)
1233 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1234 return err ? err : t3_phy_lasi_intr_disable(phy);
1237 static int ael2005_intr_clear(struct cphy *phy)
1239 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1240 return err ? err : t3_phy_lasi_intr_clear(phy);
1243 static int ael2005_reset(struct cphy *phy, int wait)
1245 static struct reg_val regs0[] = {
1246 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1247 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1248 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1249 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1250 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1251 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1252 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1255 static struct reg_val regs1[] = {
1256 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1257 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1262 unsigned int lasi_ctrl;
1264 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1268 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1273 phy->priv = edc_none;
1274 err = set_phy_regs(phy, regs0);
1280 err = ael2005_get_module_type(phy, 0);
1283 phy->modtype = (u8)err;
1285 if (err == phy_modtype_none)
1287 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1288 err = ael2005_setup_twinax_edc(phy, err);
1290 err = ael2005_setup_sr_edc(phy);
1294 err = set_phy_regs(phy, regs1);
1298 /* reset wipes out interrupts, reenable them if they were on */
1300 err = ael2005_intr_enable(phy);
1304 static int ael2005_intr_handler(struct cphy *phy)
1307 int ret, edc_needed, cause = 0;
1309 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1313 if (stat & AEL2005_MODDET_IRQ) {
1314 ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1319 /* modules have max 300 ms init time after hot plug */
1320 ret = ael2005_get_module_type(phy, 300);
1324 phy->modtype = (u8)ret;
1325 if (ret == phy_modtype_none)
1326 edc_needed = phy->priv; /* on unplug retain EDC */
1327 else if (ret == phy_modtype_twinax ||
1328 ret == phy_modtype_twinax_long)
1329 edc_needed = edc_twinax;
1331 edc_needed = edc_sr;
1333 if (edc_needed != phy->priv) {
1334 ret = ael2005_reset(phy, 0);
1335 return ret ? ret : cphy_cause_module_change;
1337 cause = cphy_cause_module_change;
1340 ret = t3_phy_lasi_intr_handler(phy);
1346 ret |= cphy_cause_link_change;
1350 static struct cphy_ops ael2005_ops = {
1351 #ifdef C99_NOT_SUPPORTED
1353 ael2005_intr_enable,
1354 ael2005_intr_disable,
1356 ael2005_intr_handler,
1365 .reset = ael2005_reset,
1366 .intr_enable = ael2005_intr_enable,
1367 .intr_disable = ael2005_intr_disable,
1368 .intr_clear = ael2005_intr_clear,
1369 .intr_handler = ael2005_intr_handler,
1370 .get_link_status = get_link_status_r,
1371 .power_down = ael1002_power_down,
1375 int t3_ael2005_phy_prep(pinfo_t *pinfo, int phy_addr,
1376 const struct mdio_ops *mdio_ops)
1379 struct cphy *phy = &pinfo->phy;
1381 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2005_ops, mdio_ops,
1382 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1383 SUPPORTED_IRQ, "10GBASE-R");
1385 ael_laser_down(phy, 0);
1387 err = ael2005_get_module_type(phy, 0);
1391 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1396 * Setup EDC and other parameters for operation with an optical module.
1398 static int ael2020_setup_sr_edc(struct cphy *phy)
1400 static struct reg_val regs[] = {
1401 { MDIO_DEV_PMA_PMD, 0xcc01, 0xffff, 0x488a },
1403 { MDIO_DEV_PMA_PMD, 0xcb1b, 0xffff, 0x0200 },
1404 { MDIO_DEV_PMA_PMD, 0xcb1c, 0xffff, 0x00f0 },
1405 { MDIO_DEV_PMA_PMD, 0xcc06, 0xffff, 0x00e0 },
1412 err = set_phy_regs(phy, regs);
1422 * Setup EDC and other parameters for operation with an TWINAX module.
1424 static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
1426 static struct reg_val uCclock40MHz[] = {
1427 { MDIO_DEV_PMA_PMD, 0xff28, 0xffff, 0x4001 },
1428 { MDIO_DEV_PMA_PMD, 0xff2a, 0xffff, 0x0002 },
1432 static struct reg_val uCclockActivate[] = {
1433 { MDIO_DEV_PMA_PMD, 0xd000, 0xffff, 0x5200 },
1437 static struct reg_val uCactivate[] = {
1438 { MDIO_DEV_PMA_PMD, 0xd080, 0xffff, 0x0100 },
1439 { MDIO_DEV_PMA_PMD, 0xd092, 0xffff, 0x0000 },
1443 static u16 twinax_edc[] = {
1886 /* set uC clock and activate it */
1887 err = set_phy_regs(phy, uCclock40MHz);
1891 err = set_phy_regs(phy, uCclockActivate);
1896 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1897 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1900 err = set_phy_regs(phy, uCactivate);
1902 phy->priv = edc_twinax;
1907 * Return Module Type.
1909 static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
1914 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_STAT, &stat);
1918 if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
1920 return phy_modtype_none;
1923 return ael2xxx_get_module_type(phy, delay_ms);
1927 * Enable PHY interrupts. We enable "Module Detection" interrupts (on any
1928 * state transition) and then generic Link Alarm Status Interrupt (LASI).
1930 static int ael2020_intr_enable(struct cphy *phy)
1932 struct reg_val regs[] = {
1933 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
1935 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1936 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
1938 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1939 0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
1946 err = set_phy_regs(phy, regs);
1950 phy->caps |= POLL_LINK_1ST_TIME;
1952 /* enable standard Link Alarm Status Interrupts */
1953 err = t3_phy_lasi_intr_enable(phy);
1961 * Disable PHY interrupts. The mirror of the above ...
1963 static int ael2020_intr_disable(struct cphy *phy)
1965 struct reg_val regs[] = {
1966 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1967 0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
1969 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1970 0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
1977 err = set_phy_regs(phy, regs);
1981 /* disable standard Link Alarm Status Interrupts */
1982 return t3_phy_lasi_intr_disable(phy);
1986 * Clear PHY interrupt state.
1988 static int ael2020_intr_clear(struct cphy *phy)
1991 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
1992 return err ? err : t3_phy_lasi_intr_clear(phy);
1996 * Common register settings for the AEL2020 when it comes out of reset.
1998 static struct reg_val ael2020_reset_regs[] = {
1999 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x3101 },
2001 { MDIO_DEV_PMA_PMD, 0xcd40, 0xffff, 0x0001 },
2003 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0x0100 },
2004 { MDIO_DEV_PMA_PMD, 0xca22, 0xffff, 0x0100 },
2005 { MDIO_DEV_PMA_PMD, 0xca42, 0xffff, 0x0100 },
2006 { MDIO_DEV_PMA_PMD, 0xff02, 0xffff, 0x0023 },
2007 { MDIO_DEV_PMA_PMD, 0xff03, 0xffff, 0x0000 },
2008 { MDIO_DEV_PMA_PMD, 0xff04, 0xffff, 0x0000 },
2010 { MDIO_DEV_PMA_PMD, 0xc20d, 0xffff, 0x0002 },
2016 * Reset the PHY and put it into a canonical operating state.
2018 static int ael2020_reset(struct cphy *phy, int wait)
2021 unsigned int lasi_ctrl;
2023 /* grab current interrupt state */
2024 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
2028 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 125);
2033 /* basic initialization for all module types */
2034 phy->priv = edc_none;
2035 err = set_phy_regs(phy, ael2020_reset_regs);
2040 /* determine module type and perform appropriate initialization */
2041 err = ael2020_get_module_type(phy, 0);
2044 phy->modtype = (u8)err;
2045 if (err == phy_modtype_none)
2047 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
2048 err = ael2020_setup_twinax_edc(phy, err);
2050 err = ael2020_setup_sr_edc(phy);
2054 /* reset wipes out interrupts, reenable them if they were on */
2056 err = ael2020_intr_enable(phy);
2061 * Handle a PHY interrupt.
2063 static int ael2020_intr_handler(struct cphy *phy)
2066 int ret, edc_needed, cause = 0;
2068 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
2072 if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
2073 /* modules have max 300 ms init time after hot plug */
2074 ret = ael2020_get_module_type(phy, 300);
2078 phy->modtype = (u8)ret;
2079 if (ret == phy_modtype_none)
2080 edc_needed = phy->priv; /* on unplug retain EDC */
2081 else if (ret == phy_modtype_twinax ||
2082 ret == phy_modtype_twinax_long)
2083 edc_needed = edc_twinax;
2085 edc_needed = edc_sr;
2087 if (edc_needed != phy->priv) {
2088 ret = ael2020_reset(phy, 0);
2089 return ret ? ret : cphy_cause_module_change;
2091 cause = cphy_cause_module_change;
2094 ret = t3_phy_lasi_intr_handler(phy);
2100 ret |= cphy_cause_link_change;
2104 static struct cphy_ops ael2020_ops = {
2105 #ifdef C99_NOT_SUPPORTED
2107 ael2020_intr_enable,
2108 ael2020_intr_disable,
2110 ael2020_intr_handler,
2119 .reset = ael2020_reset,
2120 .intr_enable = ael2020_intr_enable,
2121 .intr_disable = ael2020_intr_disable,
2122 .intr_clear = ael2020_intr_clear,
2123 .intr_handler = ael2020_intr_handler,
2124 .get_link_status = get_link_status_r,
2125 .power_down = ael1002_power_down,
2129 int t3_ael2020_phy_prep(pinfo_t *pinfo, int phy_addr,
2130 const struct mdio_ops *mdio_ops)
2133 struct cphy *phy = &pinfo->phy;
2135 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2020_ops, mdio_ops,
2136 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
2137 SUPPORTED_IRQ, "10GBASE-R");
2140 err = set_phy_regs(phy, ael2020_reset_regs);
2145 err = ael2020_get_module_type(phy, 0);
2149 ael_laser_down(phy, 0);
2154 * Get link status for a 10GBASE-X device.
2156 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
2157 int *duplex, int *fc)
2160 unsigned int stat0, stat1, stat2;
2161 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
2164 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
2166 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
2169 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
2172 *speed = SPEED_10000;
2174 *duplex = DUPLEX_FULL;
2178 #ifdef C99_NOT_SUPPORTED
2179 static struct cphy_ops qt2045_ops = {
2181 t3_phy_lasi_intr_enable,
2182 t3_phy_lasi_intr_disable,
2183 t3_phy_lasi_intr_clear,
2184 t3_phy_lasi_intr_handler,
2194 static struct cphy_ops qt2045_ops = {
2195 .reset = ael1006_reset,
2196 .intr_enable = t3_phy_lasi_intr_enable,
2197 .intr_disable = t3_phy_lasi_intr_disable,
2198 .intr_clear = t3_phy_lasi_intr_clear,
2199 .intr_handler = t3_phy_lasi_intr_handler,
2200 .get_link_status = get_link_status_x,
2201 .power_down = ael1002_power_down,
2205 int t3_qt2045_phy_prep(pinfo_t *pinfo, int phy_addr,
2206 const struct mdio_ops *mdio_ops)
2209 struct cphy *phy = &pinfo->phy;
2211 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &qt2045_ops, mdio_ops,
2212 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
2216 * Some cards where the PHY is supposed to be at address 0 actually
2219 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
2225 static int xaui_direct_reset(struct cphy *phy, int wait)
2230 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
2231 int *speed, int *duplex, int *fc)
2234 unsigned int status;
2235 adapter_t *adapter = phy->adapter;
2237 status = t3_read_reg(adapter,
2238 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
2239 t3_read_reg(adapter,
2240 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
2241 t3_read_reg(adapter,
2242 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
2243 t3_read_reg(adapter,
2244 XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
2245 *link_ok = !(status & F_LOWSIG0);
2248 *speed = SPEED_10000;
2250 *duplex = DUPLEX_FULL;
2254 static int xaui_direct_power_down(struct cphy *phy, int enable)
2259 #ifdef C99_NOT_SUPPORTED
2260 static struct cphy_ops xaui_direct_ops = {
2271 xaui_direct_get_link_status,
2272 xaui_direct_power_down,
2275 static struct cphy_ops xaui_direct_ops = {
2276 .reset = xaui_direct_reset,
2277 .intr_enable = ael1002_intr_noop,
2278 .intr_disable = ael1002_intr_noop,
2279 .intr_clear = ael1002_intr_noop,
2280 .intr_handler = ael1002_intr_noop,
2281 .get_link_status = xaui_direct_get_link_status,
2282 .power_down = xaui_direct_power_down,
2286 int t3_xaui_direct_phy_prep(pinfo_t *pinfo, int phy_addr,
2287 const struct mdio_ops *mdio_ops)
2289 cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &xaui_direct_ops, mdio_ops,
2290 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,