1 /**************************************************************************
3 Copyright (c) 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 /* MDIO_DEV_PMA_PMD registers */
40 AQ_LINK_STAT = 0xe800,
42 /* MDIO_DEV_XGXS registers */
43 AQ_XAUI_RX_CFG = 0xc400,
44 AQ_XAUI_KX_CFG = 0xc440,
45 AQ_XAUI_TX_CFG = 0xe400,
47 /* MDIO_DEV_ANEG registers */
48 AQ_100M_CTRL = 0x0010,
51 AQ_ANEG_STAT = 0xc800,
53 /* MDIO_DEV_VEND1 registers */
54 AQ_FW_VERSION = 0x0020,
55 AQ_THERMAL_THR = 0xc421,
58 AQ_IFLAG_GLOBAL = 0xfc00,
59 AQ_IMASK_GLOBAL = 0xff00,
62 #define AQBIT(x) (1 << (0x##x))
63 #define ADV_1G_FULL AQBIT(f)
64 #define ADV_1G_HALF AQBIT(e)
65 #define ADV_10G_FULL AQBIT(c)
67 #define AQ_WRITE_REGS(phy, regs) do { \
69 for (i = 0; i < ARRAY_SIZE(regs); i++) { \
70 (void) mdio_write(phy, regs[i].mmd, regs[i].reg, regs[i].val); \
73 #define AQ_READ_REGS(phy, regs) do { \
75 for (i = 0; i < ARRAY_SIZE(regs); i++) { \
76 (void) mdio_read(phy, regs[i].mmd, regs[i].reg, &v); \
81 * Return value is temperature in celcius, 0xffff for error or don't know.
84 aq100x_temperature(struct cphy *phy)
88 if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL2, &v) ||
89 v == 0xffff || (v & 1) != 1)
92 if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL1, &v))
95 return ((int)((signed char)(v >> 8)));
99 aq100x_set_defaults(struct cphy *phy)
101 return mdio_write(phy, MDIO_DEV_VEND1, AQ_THERMAL_THR, 0x6c00);
105 aq100x_reset(struct cphy *phy, int wait)
108 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
110 err = aq100x_set_defaults(phy);
115 aq100x_intr_enable(struct cphy *phy)
122 {MDIO_DEV_VEND1, 0xd400, AQBIT(e)},
123 {MDIO_DEV_VEND1, 0xff01, AQBIT(2)},
124 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, AQBIT(0)}
127 AQ_WRITE_REGS(phy, imasks);
133 aq100x_intr_disable(struct cphy *phy)
140 {MDIO_DEV_VEND1, 0xd400, 0},
141 {MDIO_DEV_VEND1, 0xff01, 0},
142 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, 0}
145 AQ_WRITE_REGS(phy, imasks);
151 aq100x_intr_clear(struct cphy *phy)
157 {MDIO_DEV_VEND1, 0xcc00},
158 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL} /* needed? */
161 AQ_READ_REGS(phy, iclr);
167 aq100x_vendor_intr(struct cphy *phy, int *rc)
170 unsigned int cause, v;
172 err = mdio_read(phy, MDIO_DEV_VEND1, 0xfc01, &cause);
176 if (cause & AQBIT(2)) {
177 err = mdio_read(phy, MDIO_DEV_VEND1, 0xcc00, &v);
182 CH_WARN(phy->adapter, "PHY%d: temperature is now %dC\n",
183 phy->addr, aq100x_temperature(phy));
185 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
186 phy->addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL, 0);
188 *rc |= cphy_cause_alarm;
195 CH_WARN(phy->adapter, "PHY%d: unhandled vendor interrupt"
196 " (0x%x)\n", phy->addr, cause);
203 aq100x_intr_handler(struct cphy *phy)
208 err = mdio_read(phy, MDIO_DEV_VEND1, AQ_IFLAG_GLOBAL, &cause);
212 if (cause & AQBIT(0)) {
213 err = aq100x_vendor_intr(phy, &rc);
220 CH_WARN(phy->adapter, "PHY%d: unhandled interrupt (0x%x)\n",
227 aq100x_power_down(struct cphy *phy, int off)
232 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, BMCR_PDOWN,
233 off ? BMCR_PDOWN : 0);
239 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
245 } while (v && --wait);
247 CH_WARN(phy->adapter, "PHY%d: power-up timed out (0x%x).\n",
256 aq100x_autoneg_enable(struct cphy *phy)
260 err = aq100x_power_down(phy, 0);
262 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
263 BMCR_RESET, BMCR_ANENABLE | BMCR_ANRESTART);
269 aq100x_autoneg_restart(struct cphy *phy)
271 return aq100x_autoneg_enable(phy);
275 aq100x_advertise(struct cphy *phy, unsigned int advertise_map)
280 /* 10G advertisement */
282 if (advertise_map & ADVERTISED_10000baseT_Full)
284 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_10G_CTRL,
289 /* 1G advertisement */
291 if (advertise_map & ADVERTISED_1000baseT_Full)
293 if (advertise_map & ADVERTISED_1000baseT_Half)
295 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_1G_CTRL,
296 ADV_1G_FULL | ADV_1G_HALF, adv);
300 /* 100M, pause advertisement */
302 if (advertise_map & ADVERTISED_100baseT_Half)
303 adv |= ADVERTISE_100HALF;
304 if (advertise_map & ADVERTISED_100baseT_Full)
305 adv |= ADVERTISE_100FULL;
306 if (advertise_map & ADVERTISED_Pause)
307 adv |= ADVERTISE_PAUSE_CAP;
308 if (advertise_map & ADVERTISED_Asym_Pause)
309 adv |= ADVERTISE_PAUSE_ASYM;
310 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_100M_CTRL, 0xfe0, adv);
316 aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable)
318 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
319 BMCR_LOOPBACK, enable ? BMCR_LOOPBACK : 0);
323 aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex)
327 if (speed == SPEED_100)
329 else if (speed == SPEED_1000)
330 set = BMCR_SPEED1000;
331 else if (speed == SPEED_10000)
332 set = BMCR_SPEED1000 | BMCR_SPEED100;
336 if (duplex != DUPLEX_FULL)
339 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
340 BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART, 0);
344 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
345 BMCR_SPEED1000 | BMCR_SPEED100, set);
353 aq100x_get_link_status(struct cphy *phy, int *link_ok, int *speed, int *duplex,
357 unsigned int v, link = 0;
359 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AQ_LINK_STAT, &v);
362 if (v == 0xffff || !(v & 1))
365 err = mdio_read(phy, MDIO_DEV_ANEG, MII_BMCR, &v);
370 if (v & BMCR_ANENABLE) {
372 err = mdio_read(phy, MDIO_DEV_ANEG, 1, &v);
378 err = mdio_read(phy, MDIO_DEV_ANEG, AQ_ANEG_STAT, &v);
384 case 0x6: *speed = SPEED_10000;
386 case 0x4: *speed = SPEED_1000;
388 case 0x2: *speed = SPEED_100;
390 case 0x0: *speed = SPEED_10;
396 *duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF;
399 unsigned int lpa, adv;
400 err = mdio_read(phy, MDIO_DEV_ANEG, 0x13, &lpa);
402 err = mdio_read(phy, MDIO_DEV_ANEG,
407 if (lpa & adv & ADVERTISE_PAUSE_CAP)
408 *fc = PAUSE_RX | PAUSE_TX;
409 else if (lpa & ADVERTISE_PAUSE_CAP &&
410 lpa & ADVERTISE_PAUSE_ASYM &&
411 adv & ADVERTISE_PAUSE_ASYM)
413 else if (lpa & ADVERTISE_PAUSE_ASYM &&
414 adv & ADVERTISE_PAUSE_CAP)
421 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
425 v &= BMCR_SPEED1000 | BMCR_SPEED100;
427 if (v == (BMCR_SPEED1000 | BMCR_SPEED100))
428 *speed = SPEED_10000;
429 else if (v == BMCR_SPEED1000)
431 else if (v == BMCR_SPEED100)
438 *duplex = DUPLEX_FULL;
448 static struct cphy_ops aq100x_ops = {
449 .reset = aq100x_reset,
450 .intr_enable = aq100x_intr_enable,
451 .intr_disable = aq100x_intr_disable,
452 .intr_clear = aq100x_intr_clear,
453 .intr_handler = aq100x_intr_handler,
454 .autoneg_enable = aq100x_autoneg_enable,
455 .autoneg_restart = aq100x_autoneg_restart,
456 .advertise = aq100x_advertise,
457 .set_loopback = aq100x_set_loopback,
458 .set_speed_duplex = aq100x_set_speed_duplex,
459 .get_link_status = aq100x_get_link_status,
460 .power_down = aq100x_power_down,
464 t3_aq100x_phy_prep(pinfo_t *pinfo, int phy_addr,
465 const struct mdio_ops *mdio_ops)
467 struct cphy *phy = &pinfo->phy;
468 unsigned int v, v2, gpio, wait;
470 adapter_t *adapter = pinfo->adapter;
472 cphy_init(&pinfo->phy, adapter, pinfo, phy_addr, &aq100x_ops, mdio_ops,
473 SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
474 SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI |
475 SUPPORTED_MISC_IRQ, "1000/10GBASE-T");
478 * Hard reset the PHY.
480 gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
481 t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
483 t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);
486 * Give it enough time to load the firmware and get ready for mdio.
489 wait = 500; /* in 10ms increments */
491 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
492 if (err || v == 0xffff) {
494 /* Allow prep_adapter to succeed when ffff is read */
496 CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
504 } while (v && --wait);
506 CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
509 goto done; /* let prep_adapter succeed */
512 /* Firmware version check. */
513 (void) mdio_read(phy, MDIO_DEV_VEND1, AQ_FW_VERSION, &v);
515 CH_WARN(adapter, "PHY%d: unknown firmware %d.%d\n", phy_addr,
518 /* The PHY should start in really-low-power mode. */
519 (void) mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
520 if ((v & BMCR_PDOWN) == 0)
521 CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
525 * Verify XAUI and 1000-X settings, but let prep succeed no matter what.
528 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_RX_CFG, &v);
529 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_TX_CFG, &v2);
530 if (v != 0x1b || v2 != 0x1b)
531 CH_WARN(adapter, "PHY%d: incorrect XAUI settings "
532 "(0x%x, 0x%x).\n", phy_addr, v, v2);
534 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_KX_CFG, &v);
535 if ((v & 0xf) != 0xf)
536 CH_WARN(adapter, "PHY%d: incorrect 1000-X settings "
537 "(0x%x).\n", phy_addr, v);
539 (void) aq100x_set_defaults(phy);