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
;
106 t1_tpi_write(cphy
->adapter
, A_ELMER0_INT_ENABLE
, elmer
);
112 static int vsc8244_intr_disable(struct cphy
*cphy
)
114 simple_mdio_write(cphy
, VSC8244_INTR_ENABLE
, 0);
116 if (t1_is_asic(cphy
->adapter
)) {
119 t1_tpi_read(cphy
->adapter
, A_ELMER0_INT_ENABLE
, &elmer
);
120 elmer
&= ~ELMER0_GP_BIT1
;
121 if (is_T2(cphy
->adapter
)) {
122 elmer
&= ~(ELMER0_GP_BIT2
|ELMER0_GP_BIT3
|ELMER0_GP_BIT4
);
124 t1_tpi_write(cphy
->adapter
, A_ELMER0_INT_ENABLE
, elmer
);
130 static int vsc8244_intr_clear(struct cphy
*cphy
)
135 /* Clear PHY interrupts by reading the register. */
136 simple_mdio_read(cphy
, VSC8244_INTR_ENABLE
, &val
);
138 if (t1_is_asic(cphy
->adapter
)) {
139 t1_tpi_read(cphy
->adapter
, A_ELMER0_INT_CAUSE
, &elmer
);
140 elmer
|= ELMER0_GP_BIT1
;
141 if (is_T2(cphy
->adapter
)) {
142 elmer
|= ELMER0_GP_BIT2
|ELMER0_GP_BIT3
|ELMER0_GP_BIT4
;
144 t1_tpi_write(cphy
->adapter
, A_ELMER0_INT_CAUSE
, elmer
);
151 * Force the PHY speed and duplex. This also disables auto-negotiation, except
152 * for 1Gb/s, where auto-negotiation is mandatory.
154 static int vsc8244_set_speed_duplex(struct cphy
*phy
, int speed
, int duplex
)
159 err
= simple_mdio_read(phy
, MII_BMCR
, &ctl
);
164 ctl
&= ~(BMCR_SPEED100
| BMCR_SPEED1000
| BMCR_ANENABLE
);
165 if (speed
== SPEED_100
)
166 ctl
|= BMCR_SPEED100
;
167 else if (speed
== SPEED_1000
)
168 ctl
|= BMCR_SPEED1000
;
171 ctl
&= ~(BMCR_FULLDPLX
| BMCR_ANENABLE
);
172 if (duplex
== DUPLEX_FULL
)
173 ctl
|= BMCR_FULLDPLX
;
175 if (ctl
& BMCR_SPEED1000
) /* auto-negotiation required for 1Gb/s */
176 ctl
|= BMCR_ANENABLE
;
177 return simple_mdio_write(phy
, MII_BMCR
, ctl
);
180 int t1_mdio_set_bits(struct cphy
*phy
, int mmd
, int reg
, unsigned int bits
)
185 ret
= mdio_read(phy
, mmd
, reg
, &val
);
187 ret
= mdio_write(phy
, mmd
, reg
, val
| bits
);
191 static int vsc8244_autoneg_enable(struct cphy
*cphy
)
193 return t1_mdio_set_bits(cphy
, 0, MII_BMCR
,
194 BMCR_ANENABLE
| BMCR_ANRESTART
);
197 static int vsc8244_autoneg_restart(struct cphy
*cphy
)
199 return t1_mdio_set_bits(cphy
, 0, MII_BMCR
, BMCR_ANRESTART
);
202 static int vsc8244_advertise(struct cphy
*phy
, unsigned int advertise_map
)
205 unsigned int val
= 0;
207 err
= simple_mdio_read(phy
, MII_CTRL1000
, &val
);
211 val
&= ~(ADVERTISE_1000HALF
| ADVERTISE_1000FULL
);
212 if (advertise_map
& ADVERTISED_1000baseT_Half
)
213 val
|= ADVERTISE_1000HALF
;
214 if (advertise_map
& ADVERTISED_1000baseT_Full
)
215 val
|= ADVERTISE_1000FULL
;
217 err
= simple_mdio_write(phy
, MII_CTRL1000
, val
);
222 if (advertise_map
& ADVERTISED_10baseT_Half
)
223 val
|= ADVERTISE_10HALF
;
224 if (advertise_map
& ADVERTISED_10baseT_Full
)
225 val
|= ADVERTISE_10FULL
;
226 if (advertise_map
& ADVERTISED_100baseT_Half
)
227 val
|= ADVERTISE_100HALF
;
228 if (advertise_map
& ADVERTISED_100baseT_Full
)
229 val
|= ADVERTISE_100FULL
;
230 if (advertise_map
& ADVERTISED_PAUSE
)
231 val
|= ADVERTISE_PAUSE_CAP
;
232 if (advertise_map
& ADVERTISED_ASYM_PAUSE
)
233 val
|= ADVERTISE_PAUSE_ASYM
;
234 return simple_mdio_write(phy
, MII_ADVERTISE
, val
);
237 static int vsc8244_get_link_status(struct cphy
*cphy
, int *link_ok
,
238 int *speed
, int *duplex
, int *fc
)
240 unsigned int bmcr
, status
, lpa
, adv
;
241 int err
, sp
= -1, dplx
= -1, pause
= 0;
243 err
= simple_mdio_read(cphy
, MII_BMCR
, &bmcr
);
245 err
= simple_mdio_read(cphy
, MII_BMSR
, &status
);
251 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
252 * once more to get the current link state.
254 if (!(status
& BMSR_LSTATUS
))
255 err
= simple_mdio_read(cphy
, MII_BMSR
, &status
);
258 *link_ok
= (status
& BMSR_LSTATUS
) != 0;
260 if (!(bmcr
& BMCR_ANENABLE
)) {
261 dplx
= (bmcr
& BMCR_FULLDPLX
) ? DUPLEX_FULL
: DUPLEX_HALF
;
262 if (bmcr
& BMCR_SPEED1000
)
264 else if (bmcr
& BMCR_SPEED100
)
268 } else if (status
& BMSR_ANEGCOMPLETE
) {
269 err
= simple_mdio_read(cphy
, VSC8244_AUX_CTRL_STAT
, &status
);
273 dplx
= (status
& F_ACSR_DUPLEX
) ? DUPLEX_FULL
: DUPLEX_HALF
;
274 sp
= G_ACSR_SPEED(status
);
282 if (fc
&& dplx
== DUPLEX_FULL
) {
283 err
= simple_mdio_read(cphy
, MII_LPA
, &lpa
);
285 err
= simple_mdio_read(cphy
, MII_ADVERTISE
,
290 if (lpa
& adv
& ADVERTISE_PAUSE_CAP
)
291 pause
= PAUSE_RX
| PAUSE_TX
;
292 else if ((lpa
& ADVERTISE_PAUSE_CAP
) &&
293 (lpa
& ADVERTISE_PAUSE_ASYM
) &&
294 (adv
& ADVERTISE_PAUSE_ASYM
))
296 else if ((lpa
& ADVERTISE_PAUSE_ASYM
) &&
297 (adv
& ADVERTISE_PAUSE_CAP
))
310 static int vsc8244_intr_handler(struct cphy
*cphy
)
313 int err
, cphy_cause
= 0;
315 err
= simple_mdio_read(cphy
, VSC8244_INTR_STATUS
, &cause
);
320 if (cause
& CFG_CHG_INTR_MASK
)
321 cphy_cause
|= cphy_cause_link_change
;
322 if (cause
& (VSC_INTR_RX_FIFO
| VSC_INTR_TX_FIFO
))
323 cphy_cause
|= cphy_cause_fifo_error
;
327 static void vsc8244_destroy(struct cphy
*cphy
)
332 static struct cphy_ops vsc8244_ops
= {
333 .destroy
= vsc8244_destroy
,
334 .reset
= vsc8244_reset
,
335 .interrupt_enable
= vsc8244_intr_enable
,
336 .interrupt_disable
= vsc8244_intr_disable
,
337 .interrupt_clear
= vsc8244_intr_clear
,
338 .interrupt_handler
= vsc8244_intr_handler
,
339 .autoneg_enable
= vsc8244_autoneg_enable
,
340 .autoneg_restart
= vsc8244_autoneg_restart
,
341 .advertise
= vsc8244_advertise
,
342 .set_speed_duplex
= vsc8244_set_speed_duplex
,
343 .get_link_status
= vsc8244_get_link_status
346 static struct cphy
* vsc8244_phy_create(adapter_t
*adapter
, int phy_addr
, struct mdio_ops
*mdio_ops
)
348 struct cphy
*cphy
= kzalloc(sizeof(*cphy
), GFP_KERNEL
);
350 if (!cphy
) return NULL
;
352 cphy_init(cphy
, adapter
, phy_addr
, &vsc8244_ops
, mdio_ops
);
358 static int vsc8244_phy_reset(adapter_t
* adapter
)
363 struct gphy t1_vsc8244_ops
= {