2 * This file is part of the Chelsio T2 Ethernet driver.
4 * Copyright (C) 2005 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 #ifndef ADVERTISE_PAUSE_CAP
17 # define ADVERTISE_PAUSE_CAP 0x400
19 #ifndef ADVERTISE_PAUSE_ASYM
20 # define ADVERTISE_PAUSE_ASYM 0x800
23 /* Gigabit MII registers */
25 # define MII_CTRL1000 9
28 #ifndef ADVERTISE_1000FULL
29 # define ADVERTISE_1000FULL 0x200
30 # define ADVERTISE_1000HALF 0x100
33 /* VSC8244 PHY specific registers. */
35 VSC8244_INTR_ENABLE
= 25,
36 VSC8244_INTR_STATUS
= 26,
37 VSC8244_AUX_CTRL_STAT
= 28,
41 VSC_INTR_RX_ERR
= 1 << 0,
42 VSC_INTR_MS_ERR
= 1 << 1, /* master/slave resolution error */
43 VSC_INTR_CABLE
= 1 << 2, /* cable impairment */
44 VSC_INTR_FALSE_CARR
= 1 << 3, /* false carrier */
45 VSC_INTR_MEDIA_CHG
= 1 << 4, /* AMS media change */
46 VSC_INTR_RX_FIFO
= 1 << 5, /* Rx FIFO over/underflow */
47 VSC_INTR_TX_FIFO
= 1 << 6, /* Tx FIFO over/underflow */
48 VSC_INTR_DESCRAMBL
= 1 << 7, /* descrambler lock-lost */
49 VSC_INTR_SYMBOL_ERR
= 1 << 8, /* symbol error */
50 VSC_INTR_NEG_DONE
= 1 << 10, /* autoneg done */
51 VSC_INTR_NEG_ERR
= 1 << 11, /* autoneg error */
52 VSC_INTR_LINK_CHG
= 1 << 13, /* link change */
53 VSC_INTR_ENABLE
= 1 << 15, /* interrupt enable */
56 #define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \
58 #define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \
61 /* PHY specific auxiliary control & status register fields */
62 #define S_ACSR_ACTIPHY_TMR 0
63 #define M_ACSR_ACTIPHY_TMR 0x3
64 #define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR)
66 #define S_ACSR_SPEED 3
67 #define M_ACSR_SPEED 0x3
68 #define G_ACSR_SPEED(x) (((x) >> S_ACSR_SPEED) & M_ACSR_SPEED)
70 #define S_ACSR_DUPLEX 5
71 #define F_ACSR_DUPLEX (1 << S_ACSR_DUPLEX)
73 #define S_ACSR_ACTIPHY 6
74 #define F_ACSR_ACTIPHY (1 << S_ACSR_ACTIPHY)
77 * Reset the PHY. This PHY completes reset immediately so we never wait.
79 static int vsc8244_reset(struct cphy
*cphy
, int wait
)
84 err
= simple_mdio_read(cphy
, MII_BMCR
, &ctl
);
90 return simple_mdio_write(cphy
, MII_BMCR
, ctl
);
93 static int vsc8244_intr_enable(struct cphy
*cphy
)
95 simple_mdio_write(cphy
, VSC8244_INTR_ENABLE
, INTR_MASK
);
97 /* Enable interrupts through Elmer */
98 if (t1_is_asic(cphy
->adapter
)) {
101 t1_tpi_read(cphy
->adapter
, A_ELMER0_INT_ENABLE
, &elmer
);
102 elmer
|= ELMER0_GP_BIT1
;
103 if (is_T2(cphy
->adapter
))
104 elmer
|= ELMER0_GP_BIT2
|ELMER0_GP_BIT3
|ELMER0_GP_BIT4
;
105 t1_tpi_write(cphy
->adapter
, A_ELMER0_INT_ENABLE
, elmer
);
111 static int vsc8244_intr_disable(struct cphy
*cphy
)
113 simple_mdio_write(cphy
, VSC8244_INTR_ENABLE
, 0);
115 if (t1_is_asic(cphy
->adapter
)) {
118 t1_tpi_read(cphy
->adapter
, A_ELMER0_INT_ENABLE
, &elmer
);
119 elmer
&= ~ELMER0_GP_BIT1
;
120 if (is_T2(cphy
->adapter
))
121 elmer
&= ~(ELMER0_GP_BIT2
|ELMER0_GP_BIT3
|ELMER0_GP_BIT4
);
122 t1_tpi_write(cphy
->adapter
, A_ELMER0_INT_ENABLE
, elmer
);
128 static int vsc8244_intr_clear(struct cphy
*cphy
)
133 /* Clear PHY interrupts by reading the register. */
134 simple_mdio_read(cphy
, VSC8244_INTR_ENABLE
, &val
);
136 if (t1_is_asic(cphy
->adapter
)) {
137 t1_tpi_read(cphy
->adapter
, A_ELMER0_INT_CAUSE
, &elmer
);
138 elmer
|= ELMER0_GP_BIT1
;
139 if (is_T2(cphy
->adapter
))
140 elmer
|= ELMER0_GP_BIT2
|ELMER0_GP_BIT3
|ELMER0_GP_BIT4
;
141 t1_tpi_write(cphy
->adapter
, A_ELMER0_INT_CAUSE
, elmer
);
148 * Force the PHY speed and duplex. This also disables auto-negotiation, except
149 * for 1Gb/s, where auto-negotiation is mandatory.
151 static int vsc8244_set_speed_duplex(struct cphy
*phy
, int speed
, int duplex
)
156 err
= simple_mdio_read(phy
, MII_BMCR
, &ctl
);
161 ctl
&= ~(BMCR_SPEED100
| BMCR_SPEED1000
| BMCR_ANENABLE
);
162 if (speed
== SPEED_100
)
163 ctl
|= BMCR_SPEED100
;
164 else if (speed
== SPEED_1000
)
165 ctl
|= BMCR_SPEED1000
;
168 ctl
&= ~(BMCR_FULLDPLX
| BMCR_ANENABLE
);
169 if (duplex
== DUPLEX_FULL
)
170 ctl
|= BMCR_FULLDPLX
;
172 if (ctl
& BMCR_SPEED1000
) /* auto-negotiation required for 1Gb/s */
173 ctl
|= BMCR_ANENABLE
;
174 return simple_mdio_write(phy
, MII_BMCR
, ctl
);
177 int t1_mdio_set_bits(struct cphy
*phy
, int mmd
, int reg
, unsigned int bits
)
182 ret
= mdio_read(phy
, mmd
, reg
, &val
);
184 ret
= mdio_write(phy
, mmd
, reg
, val
| bits
);
188 static int vsc8244_autoneg_enable(struct cphy
*cphy
)
190 return t1_mdio_set_bits(cphy
, 0, MII_BMCR
,
191 BMCR_ANENABLE
| BMCR_ANRESTART
);
194 static int vsc8244_autoneg_restart(struct cphy
*cphy
)
196 return t1_mdio_set_bits(cphy
, 0, MII_BMCR
, BMCR_ANRESTART
);
199 static int vsc8244_advertise(struct cphy
*phy
, unsigned int advertise_map
)
202 unsigned int val
= 0;
204 err
= simple_mdio_read(phy
, MII_CTRL1000
, &val
);
208 val
&= ~(ADVERTISE_1000HALF
| ADVERTISE_1000FULL
);
209 if (advertise_map
& ADVERTISED_1000baseT_Half
)
210 val
|= ADVERTISE_1000HALF
;
211 if (advertise_map
& ADVERTISED_1000baseT_Full
)
212 val
|= ADVERTISE_1000FULL
;
214 err
= simple_mdio_write(phy
, MII_CTRL1000
, val
);
219 if (advertise_map
& ADVERTISED_10baseT_Half
)
220 val
|= ADVERTISE_10HALF
;
221 if (advertise_map
& ADVERTISED_10baseT_Full
)
222 val
|= ADVERTISE_10FULL
;
223 if (advertise_map
& ADVERTISED_100baseT_Half
)
224 val
|= ADVERTISE_100HALF
;
225 if (advertise_map
& ADVERTISED_100baseT_Full
)
226 val
|= ADVERTISE_100FULL
;
227 if (advertise_map
& ADVERTISED_PAUSE
)
228 val
|= ADVERTISE_PAUSE_CAP
;
229 if (advertise_map
& ADVERTISED_ASYM_PAUSE
)
230 val
|= ADVERTISE_PAUSE_ASYM
;
231 return simple_mdio_write(phy
, MII_ADVERTISE
, val
);
234 static int vsc8244_get_link_status(struct cphy
*cphy
, int *link_ok
,
235 int *speed
, int *duplex
, int *fc
)
237 unsigned int bmcr
, status
, lpa
, adv
;
238 int err
, sp
= -1, dplx
= -1, pause
= 0;
240 err
= simple_mdio_read(cphy
, MII_BMCR
, &bmcr
);
242 err
= simple_mdio_read(cphy
, MII_BMSR
, &status
);
248 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
249 * once more to get the current link state.
251 if (!(status
& BMSR_LSTATUS
))
252 err
= simple_mdio_read(cphy
, MII_BMSR
, &status
);
255 *link_ok
= (status
& BMSR_LSTATUS
) != 0;
257 if (!(bmcr
& BMCR_ANENABLE
)) {
258 dplx
= (bmcr
& BMCR_FULLDPLX
) ? DUPLEX_FULL
: DUPLEX_HALF
;
259 if (bmcr
& BMCR_SPEED1000
)
261 else if (bmcr
& BMCR_SPEED100
)
265 } else if (status
& BMSR_ANEGCOMPLETE
) {
266 err
= simple_mdio_read(cphy
, VSC8244_AUX_CTRL_STAT
, &status
);
270 dplx
= (status
& F_ACSR_DUPLEX
) ? DUPLEX_FULL
: DUPLEX_HALF
;
271 sp
= G_ACSR_SPEED(status
);
279 if (fc
&& dplx
== DUPLEX_FULL
) {
280 err
= simple_mdio_read(cphy
, MII_LPA
, &lpa
);
282 err
= simple_mdio_read(cphy
, MII_ADVERTISE
,
287 if (lpa
& adv
& ADVERTISE_PAUSE_CAP
)
288 pause
= PAUSE_RX
| PAUSE_TX
;
289 else if ((lpa
& ADVERTISE_PAUSE_CAP
) &&
290 (lpa
& ADVERTISE_PAUSE_ASYM
) &&
291 (adv
& ADVERTISE_PAUSE_ASYM
))
293 else if ((lpa
& ADVERTISE_PAUSE_ASYM
) &&
294 (adv
& ADVERTISE_PAUSE_CAP
))
307 static int vsc8244_intr_handler(struct cphy
*cphy
)
310 int err
, cphy_cause
= 0;
312 err
= simple_mdio_read(cphy
, VSC8244_INTR_STATUS
, &cause
);
317 if (cause
& CFG_CHG_INTR_MASK
)
318 cphy_cause
|= cphy_cause_link_change
;
319 if (cause
& (VSC_INTR_RX_FIFO
| VSC_INTR_TX_FIFO
))
320 cphy_cause
|= cphy_cause_fifo_error
;
324 static void vsc8244_destroy(struct cphy
*cphy
)
329 static struct cphy_ops vsc8244_ops
= {
330 .destroy
= vsc8244_destroy
,
331 .reset
= vsc8244_reset
,
332 .interrupt_enable
= vsc8244_intr_enable
,
333 .interrupt_disable
= vsc8244_intr_disable
,
334 .interrupt_clear
= vsc8244_intr_clear
,
335 .interrupt_handler
= vsc8244_intr_handler
,
336 .autoneg_enable
= vsc8244_autoneg_enable
,
337 .autoneg_restart
= vsc8244_autoneg_restart
,
338 .advertise
= vsc8244_advertise
,
339 .set_speed_duplex
= vsc8244_set_speed_duplex
,
340 .get_link_status
= vsc8244_get_link_status
343 static struct cphy
* vsc8244_phy_create(adapter_t
*adapter
, int phy_addr
,
344 struct mdio_ops
*mdio_ops
)
346 struct cphy
*cphy
= kzalloc(sizeof(*cphy
), GFP_KERNEL
);
351 cphy_init(cphy
, adapter
, phy_addr
, &vsc8244_ops
, mdio_ops
);
357 static int vsc8244_phy_reset(adapter_t
* adapter
)
362 struct gphy t1_vsc8244_ops
= {