Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / cxgb_ael1002.c
blob7d68ab78bd1b5523495f9a5cb507bc9332d800b3
1 /**************************************************************************
3 Copyright (c) 2007, Chelsio Inc.
4 All rights reserved.
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 #ifdef __NetBSD__
32 __KERNEL_RCSID(0, "$NetBSD: cxgb_ael1002.c,v 1.2 2007/12/11 11:25:46 lukem Exp $");
33 #endif
34 #ifdef __FreeBSD__
35 __FBSDID("$FreeBSD: src/sys/dev/cxgb/common/cxgb_ael1002.c,v 1.3 2007/06/13 05:36:00 kmacy Exp $");
36 #endif
38 #ifdef CONFIG_DEFINED
39 #include <cxgb_include.h>
40 #else
41 #ifdef __FreeBSD__
42 #include <dev/cxgb/cxgb_include.h>
43 #endif
44 #ifdef __NetBSD__
45 #include <dev/pci/cxgb_include.h>
46 #endif
47 #endif
49 enum {
50 AEL100X_TX_DISABLE = 9,
51 AEL100X_TX_CONFIG1 = 0xc002,
52 AEL1002_PWR_DOWN_HI = 0xc011,
53 AEL1002_PWR_DOWN_LO = 0xc012,
54 AEL1002_XFI_EQL = 0xc015,
55 AEL1002_LB_EN = 0xc017,
57 LASI_CTRL = 0x9002,
58 LASI_STAT = 0x9005
61 static void ael100x_txon(struct cphy *phy)
63 int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
65 t3_os_sleep(100);
66 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
67 t3_os_sleep(30);
70 static int ael1002_power_down(struct cphy *phy, int enable)
72 int err;
74 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
75 if (!err)
76 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
77 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
78 return err;
81 static int ael1002_reset(struct cphy *phy, int wait)
83 int err;
85 if ((err = ael1002_power_down(phy, 0)) ||
86 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
87 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
88 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
89 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
90 (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
91 0, 1 << 5)))
92 return err;
93 return 0;
96 static int ael1002_intr_noop(struct cphy *phy)
98 return 0;
101 static int ael100x_get_link_status(struct cphy *phy, int *link_ok,
102 int *speed, int *duplex, int *fc)
104 if (link_ok) {
105 unsigned int status;
106 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status);
109 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
110 * once more to get the current link state.
112 if (!err && !(status & BMSR_LSTATUS))
113 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR,
114 &status);
115 if (err)
116 return err;
117 *link_ok = !!(status & BMSR_LSTATUS);
119 if (speed)
120 *speed = SPEED_10000;
121 if (duplex)
122 *duplex = DUPLEX_FULL;
123 return 0;
126 #ifdef C99_NOT_SUPPORTED
127 static struct cphy_ops ael1002_ops = {
128 NULL,
129 ael1002_reset,
130 ael1002_intr_noop,
131 ael1002_intr_noop,
132 ael1002_intr_noop,
133 ael1002_intr_noop,
134 NULL,
135 NULL,
136 NULL,
137 NULL,
138 NULL,
139 ael100x_get_link_status,
140 ael1002_power_down,
142 #else
143 static struct cphy_ops ael1002_ops = {
144 .reset = ael1002_reset,
145 .intr_enable = ael1002_intr_noop,
146 .intr_disable = ael1002_intr_noop,
147 .intr_clear = ael1002_intr_noop,
148 .intr_handler = ael1002_intr_noop,
149 .get_link_status = ael100x_get_link_status,
150 .power_down = ael1002_power_down,
152 #endif
154 void t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
155 const struct mdio_ops *mdio_ops)
157 cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops);
158 ael100x_txon(phy);
161 static int ael1006_reset(struct cphy *phy, int wait)
163 return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
166 static int ael1006_intr_enable(struct cphy *phy)
168 return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1);
171 static int ael1006_intr_disable(struct cphy *phy)
173 return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0);
176 static int ael1006_intr_clear(struct cphy *phy)
178 u32 val;
180 return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val);
183 static int ael1006_intr_handler(struct cphy *phy)
185 unsigned int status;
186 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status);
188 if (err)
189 return err;
190 return (status & 1) ? cphy_cause_link_change : 0;
193 static int ael1006_power_down(struct cphy *phy, int enable)
195 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
196 BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
199 #ifdef C99_NOT_SUPPORTED
200 static struct cphy_ops ael1006_ops = {
201 NULL,
202 ael1006_reset,
203 ael1006_intr_enable,
204 ael1006_intr_disable,
205 ael1006_intr_clear,
206 ael1006_intr_handler,
207 NULL,
208 NULL,
209 NULL,
210 NULL,
211 NULL,
212 ael100x_get_link_status,
213 ael1006_power_down,
215 #else
216 static struct cphy_ops ael1006_ops = {
217 .reset = ael1006_reset,
218 .intr_enable = ael1006_intr_enable,
219 .intr_disable = ael1006_intr_disable,
220 .intr_clear = ael1006_intr_clear,
221 .intr_handler = ael1006_intr_handler,
222 .get_link_status = ael100x_get_link_status,
223 .power_down = ael1006_power_down,
225 #endif
227 void t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
228 const struct mdio_ops *mdio_ops)
230 cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops);
231 ael100x_txon(phy);
234 #ifdef C99_NOT_SUPPORTED
235 static struct cphy_ops qt2045_ops = {
236 NULL,
237 ael1006_reset,
238 ael1006_intr_enable,
239 ael1006_intr_disable,
240 ael1006_intr_clear,
241 ael1006_intr_handler,
242 NULL,
243 NULL,
244 NULL,
245 NULL,
246 NULL,
247 ael100x_get_link_status,
248 ael1006_power_down,
250 #else
251 static struct cphy_ops qt2045_ops = {
252 .reset = ael1006_reset,
253 .intr_enable = ael1006_intr_enable,
254 .intr_disable = ael1006_intr_disable,
255 .intr_clear = ael1006_intr_clear,
256 .intr_handler = ael1006_intr_handler,
257 .get_link_status = ael100x_get_link_status,
258 .power_down = ael1006_power_down,
260 #endif
262 void t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
263 const struct mdio_ops *mdio_ops)
265 unsigned int stat;
267 cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops);
270 * Some cards where the PHY is supposed to be at address 0 actually
271 * have it at 1.
273 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
274 stat == 0xffff)
275 phy->addr = 1;
278 static int xaui_direct_reset(struct cphy *phy, int wait)
280 return 0;
283 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
284 int *speed, int *duplex, int *fc)
286 if (link_ok) {
287 unsigned int status;
289 status = t3_read_reg(phy->adapter,
290 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
291 t3_read_reg(phy->adapter,
292 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
293 t3_read_reg(phy->adapter,
294 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
295 t3_read_reg(phy->adapter,
296 XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
297 *link_ok = !(status & F_LOWSIG0);
299 if (speed)
300 *speed = SPEED_10000;
301 if (duplex)
302 *duplex = DUPLEX_FULL;
303 return 0;
306 static int xaui_direct_power_down(struct cphy *phy, int enable)
308 return 0;
311 #ifdef C99_NOT_SUPPORTED
312 static struct cphy_ops xaui_direct_ops = {
313 NULL,
314 xaui_direct_reset,
315 ael1002_intr_noop,
316 ael1002_intr_noop,
317 ael1002_intr_noop,
318 ael1002_intr_noop,
319 NULL,
320 NULL,
321 NULL,
322 NULL,
323 NULL,
324 xaui_direct_get_link_status,
325 xaui_direct_power_down,
327 #else
328 static struct cphy_ops xaui_direct_ops = {
329 .reset = xaui_direct_reset,
330 .intr_enable = ael1002_intr_noop,
331 .intr_disable = ael1002_intr_noop,
332 .intr_clear = ael1002_intr_noop,
333 .intr_handler = ael1002_intr_noop,
334 .get_link_status = xaui_direct_get_link_status,
335 .power_down = xaui_direct_power_down,
337 #endif
339 void t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
340 const struct mdio_ops *mdio_ops)
342 cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops);