2 * This file is part of the Chelsio T3 Ethernet driver.
4 * Copyright (C) 2005-2006 Chelsio Communications. All rights reserved.
6 * This program is distributed in the hope that it will be useful, but WITHOUT
7 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8 * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
9 * release for licensing terms and conditions.
16 AEL100X_TX_DISABLE = 9,
17 AEL100X_TX_CONFIG1 = 0xc002,
18 AEL1002_PWR_DOWN_HI = 0xc011,
19 AEL1002_PWR_DOWN_LO = 0xc012,
20 AEL1002_XFI_EQL = 0xc015,
21 AEL1002_LB_EN = 0xc017,
27 static void ael100x_txon(struct cphy *phy)
29 int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
32 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
36 static int ael1002_power_down(struct cphy *phy, int enable)
40 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
42 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
43 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
47 static int ael1002_reset(struct cphy *phy, int wait)
51 if ((err = ael1002_power_down(phy, 0)) ||
52 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
53 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
54 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
55 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
56 (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
62 static int ael1002_intr_noop(struct cphy *phy)
67 static int ael100x_get_link_status(struct cphy *phy, int *link_ok,
68 int *speed, int *duplex, int *fc)
72 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status);
75 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
76 * once more to get the current link state.
78 if (!err && !(status & BMSR_LSTATUS))
79 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR,
83 *link_ok = !!(status & BMSR_LSTATUS);
88 *duplex = DUPLEX_FULL;
92 static struct cphy_ops ael1002_ops = {
93 .reset = ael1002_reset,
94 .intr_enable = ael1002_intr_noop,
95 .intr_disable = ael1002_intr_noop,
96 .intr_clear = ael1002_intr_noop,
97 .intr_handler = ael1002_intr_noop,
98 .get_link_status = ael100x_get_link_status,
99 .power_down = ael1002_power_down,
102 void t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
103 int phy_addr, const struct mdio_ops *mdio_ops)
105 cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops);
109 static int ael1006_reset(struct cphy *phy, int wait)
111 return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
114 static int ael1006_intr_enable(struct cphy *phy)
116 return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
119 static int ael1006_intr_disable(struct cphy *phy)
121 return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
124 static int ael1006_intr_clear(struct cphy *phy)
128 return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
131 static int ael1006_intr_handler(struct cphy *phy)
134 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
138 return (status & 1) ? cphy_cause_link_change : 0;
141 static int ael1006_power_down(struct cphy *phy, int enable)
143 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
144 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
147 static struct cphy_ops ael1006_ops = {
148 .reset = ael1006_reset,
149 .intr_enable = ael1006_intr_enable,
150 .intr_disable = ael1006_intr_disable,
151 .intr_clear = ael1006_intr_clear,
152 .intr_handler = ael1006_intr_handler,
153 .get_link_status = ael100x_get_link_status,
154 .power_down = ael1006_power_down,
157 void t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
158 int phy_addr, const struct mdio_ops *mdio_ops)
160 cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops);
164 static struct cphy_ops qt2045_ops = {
165 .reset = ael1006_reset,
166 .intr_enable = ael1006_intr_enable,
167 .intr_disable = ael1006_intr_disable,
168 .intr_clear = ael1006_intr_clear,
169 .intr_handler = ael1006_intr_handler,
170 .get_link_status = ael100x_get_link_status,
171 .power_down = ael1006_power_down,
174 void t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
175 int phy_addr, const struct mdio_ops *mdio_ops)
179 cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops);
182 * Some cards where the PHY is supposed to be at address 0 actually
185 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
190 static int xaui_direct_reset(struct cphy *phy, int wait)
195 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
196 int *speed, int *duplex, int *fc)
201 status = t3_read_reg(phy->adapter,
202 XGM_REG(A_XGM_SERDES_STAT0, phy->addr));
203 *link_ok = !(status & F_LOWSIG0);
206 *speed = SPEED_10000;
208 *duplex = DUPLEX_FULL;
212 static int xaui_direct_power_down(struct cphy *phy, int enable)
217 static struct cphy_ops xaui_direct_ops = {
218 .reset = xaui_direct_reset,
219 .intr_enable = ael1002_intr_noop,
220 .intr_disable = ael1002_intr_noop,
221 .intr_clear = ael1002_intr_noop,
222 .intr_handler = ael1002_intr_noop,
223 .get_link_status = xaui_direct_get_link_status,
224 .power_down = xaui_direct_power_down,
227 void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
228 int phy_addr, const struct mdio_ops *mdio_ops)
230 cphy_init(phy, adapter, 1, &xaui_direct_ops, mdio_ops);