]>
git.ipfire.org Git - people/ms/u-boot.git/blob - arch/powerpc/cpu/ppc4xx/miiphy.c
2 * SPDX-License-Identifier: GPL-2.0 IBM-pibs
4 /*-----------------------------------------------------------------------------+
8 | Function: This module has utilities for accessing the MII PHY through
13 +-----------------------------------------------------------------------------*/
15 /* define DEBUG for debugging output (obviously ;-)) */
21 #include <asm/processor.h>
23 #include <ppc_asm.tmpl>
24 #include <asm/ppc4xx.h>
25 #include <asm/ppc4xx-emac.h>
26 #include <asm/ppc4xx-mal.h>
29 #if !defined(CONFIG_PHY_CLK_FREQ)
30 #define CONFIG_PHY_CLK_FREQ 0
33 /***********************************************************/
34 /* Dump out to the screen PHY regs */
35 /***********************************************************/
37 void miiphy_dump (char *devname
, unsigned char addr
)
42 for (i
= 0; i
< 0x1A; i
++) {
43 if (miiphy_read (devname
, addr
, i
, &data
)) {
44 printf ("read error for reg %lx\n", i
);
47 printf ("Phy reg %lx ==> %4x\n", i
, data
);
49 /* jump to the next set of regs */
56 /***********************************************************/
57 /* (Re)start autonegotiation */
58 /***********************************************************/
59 int phy_setup_aneg (char *devname
, unsigned char addr
)
63 #if defined(CONFIG_PHY_DYNAMIC_ANEG)
65 * Set up advertisement based on capablilities reported by the PHY.
66 * This should work for both copper and fiber.
69 #if defined(CONFIG_PHY_GIGE)
73 miiphy_read (devname
, addr
, MII_BMSR
, &bmsr
);
75 #if defined(CONFIG_PHY_GIGE)
76 if (bmsr
& BMSR_ESTATEN
)
77 miiphy_read (devname
, addr
, MII_ESTATUS
, &exsr
);
79 if (exsr
& (ESTATUS_1000XF
| ESTATUS_1000XH
)) {
83 if (exsr
& ESTATUS_1000XF
)
84 anar
|= ADVERTISE_1000XFULL
;
86 if (exsr
& ESTATUS_1000XH
)
87 anar
|= ADVERTISE_1000XHALF
;
89 miiphy_write (devname
, addr
, MII_ADVERTISE
, anar
);
95 miiphy_read (devname
, addr
, MII_ADVERTISE
, &anar
);
96 anar
&= ~(0x5000 | LPA_100BASE4
| LPA_100FULL
|
97 LPA_100HALF
| LPA_10FULL
| LPA_10HALF
);
99 miiphy_read (devname
, addr
, MII_CTRL1000
, &btcr
);
100 btcr
&= ~(0x00FF | PHY_1000BTCR_1000FD
| PHY_1000BTCR_1000HD
);
102 if (bmsr
& BMSR_100BASE4
)
103 anar
|= LPA_100BASE4
;
105 if (bmsr
& BMSR_100FULL
)
108 if (bmsr
& BMSR_100HALF
)
111 if (bmsr
& BMSR_10FULL
)
114 if (bmsr
& BMSR_10HALF
)
117 miiphy_write (devname
, addr
, MII_ADVERTISE
, anar
);
119 #if defined(CONFIG_PHY_GIGE)
120 if (exsr
& ESTATUS_1000_TFULL
)
121 btcr
|= PHY_1000BTCR_1000FD
;
123 if (exsr
& ESTATUS_1000_THALF
)
124 btcr
|= PHY_1000BTCR_1000HD
;
126 miiphy_write (devname
, addr
, MII_CTRL1000
, btcr
);
130 #else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
132 * Set up standard advertisement
136 miiphy_read (devname
, addr
, MII_ADVERTISE
, &adv
);
137 adv
|= (LPA_LPACK
| LPA_100FULL
| LPA_100HALF
|
138 LPA_10FULL
| LPA_10HALF
);
139 miiphy_write (devname
, addr
, MII_ADVERTISE
, adv
);
141 miiphy_read (devname
, addr
, MII_CTRL1000
, &adv
);
143 miiphy_write (devname
, addr
, MII_CTRL1000
, adv
);
145 #endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
147 /* Start/Restart aneg */
148 miiphy_read (devname
, addr
, MII_BMCR
, &bmcr
);
149 bmcr
|= (BMCR_ANENABLE
| BMCR_ANRESTART
);
150 miiphy_write (devname
, addr
, MII_BMCR
, bmcr
);
155 /***********************************************************/
156 /* read a phy reg and return the value with a rc */
157 /***********************************************************/
159 * Find out of the choice for the emac for MDIO is from the bridges,
160 * i.e. ZMII or RGMII as approporiate. If the bridges are not used
161 * to determine the emac for MDIO, then is the SDR0_ETH_CFG[MDIO_SEL]
162 * used? If so, then this routine below does not apply to the 460EX/GT.
164 * sr: Currently on 460EX only EMAC0 works with MDIO, so we always
165 * return EMAC0 offset here
166 * vg: For 460EX/460GT if internal GPCS PHY address is specified
167 * return appropriate EMAC offset
169 unsigned int miiphy_getemac_offset(u8 addr
)
171 #if defined(CONFIG_440) && \
172 !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
173 !defined(CONFIG_460EX) && !defined(CONFIG_460GT)
175 unsigned long eoffset
;
177 /* Need to find out which mdi port we're using */
178 zmii
= in_be32((void *)ZMII0_FER
);
180 if (zmii
& (ZMII_FER_MDI
<< ZMII_FER_V (0)))
184 else if (zmii
& (ZMII_FER_MDI
<< ZMII_FER_V (1)))
188 else if (zmii
& (ZMII_FER_MDI
<< ZMII_FER_V (2)))
192 else if (zmii
& (ZMII_FER_MDI
<< ZMII_FER_V (3)))
197 /* None of the mdi ports are enabled! */
199 zmii
|= ZMII_FER_MDI
<< ZMII_FER_V (0);
200 out_be32((void *)ZMII0_FER
, zmii
);
202 /* need to soft reset port 0 */
203 zmii
= in_be32((void *)EMAC0_MR0
);
204 zmii
|= EMAC_MR0_SRST
;
205 out_be32((void *)EMAC0_MR0
, zmii
);
211 #if defined(CONFIG_405EX)
215 rgmii
= in_be32((void *)RGMII_FER
);
216 if (rgmii
& (1 << (19 - devnum
)))
220 #if defined(CONFIG_460EX) || defined(CONFIG_460GT)
224 #if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR)
225 case CONFIG_GPCS_PHY1_ADDR
:
226 if (addr
== EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1
+ 0x100)))
230 #if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR)
231 case CONFIG_GPCS_PHY2_ADDR
:
232 if (addr
== EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1
+ 0x300)))
236 #if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR)
237 case CONFIG_GPCS_PHY3_ADDR
:
238 if (addr
== EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1
+ 0x400)))
253 static int emac_miiphy_wait(u32 emac_reg
)
258 /* wait for completion */
261 sta_reg
= in_be32((void *)EMAC0_STACR
+ emac_reg
);
263 debug("%s [%d]: Timeout! EMAC0_STACR=0x%0x\n", __func__
,
268 } while ((sta_reg
& EMAC_STACR_OC
) == EMAC_STACR_OC_MASK
);
273 static int emac_miiphy_command(u8 addr
, u8 reg
, int cmd
, u16 value
)
278 emac_reg
= miiphy_getemac_offset(addr
);
280 /* wait for completion */
281 if (emac_miiphy_wait(emac_reg
) != 0)
284 sta_reg
= reg
; /* reg address */
286 /* set clock (50MHz) and read flags */
287 #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
288 defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
289 defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
290 defined(CONFIG_405EX)
291 #if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */
292 sta_reg
= (sta_reg
& ~EMAC_STACR_OP_MASK
) | cmd
;
297 sta_reg
= (sta_reg
| cmd
) & ~EMAC_STACR_CLK_100MHZ
;
300 /* Some boards (mainly 405EP based) define the PHY clock freqency fixed */
301 sta_reg
= sta_reg
| CONFIG_PHY_CLK_FREQ
;
302 sta_reg
= sta_reg
| ((u32
)addr
<< 5); /* Phy address */
303 sta_reg
= sta_reg
| EMAC_STACR_OC_MASK
; /* new IBM emac v4 */
304 if (cmd
== EMAC_STACR_WRITE
)
305 memcpy(&sta_reg
, &value
, 2); /* put in data */
307 out_be32((void *)EMAC0_STACR
+ emac_reg
, sta_reg
);
308 debug("%s [%d]: sta_reg=%08x\n", __func__
, __LINE__
, sta_reg
);
310 /* wait for completion */
311 if (emac_miiphy_wait(emac_reg
) != 0)
314 debug("%s [%d]: sta_reg=%08x\n", __func__
, __LINE__
, sta_reg
);
315 if ((sta_reg
& EMAC_STACR_PHYE
) != 0)
321 int emac4xx_miiphy_read(struct mii_dev
*bus
, int addr
, int devad
, int reg
)
323 unsigned long sta_reg
;
324 unsigned long emac_reg
;
326 emac_reg
= miiphy_getemac_offset(addr
);
328 if (emac_miiphy_command(addr
, reg
, EMAC_STACR_READ
, 0) != 0)
331 sta_reg
= in_be32((void *)EMAC0_STACR
+ emac_reg
);
332 return sta_reg
>> 16;
335 /***********************************************************/
336 /* write a phy reg and return the value with a rc */
337 /***********************************************************/
339 int emac4xx_miiphy_write(struct mii_dev
*bus
, int addr
, int devad
, int reg
,
342 return emac_miiphy_command(addr
, reg
, EMAC_STACR_WRITE
, value
);