1 /*-----------------------------------------------------------------------------+
3 | This source code has been made available to you by IBM on an AS-IS
4 | basis. Anyone receiving this source is licensed under IBM
5 | copyrights to use it in any way he or she deems fit, including
6 | copying it, modifying it, compiling it, and redistributing it either
7 | with or without modifications. No license under IBM patents or
8 | patent applications is to be implied by the copyright license.
10 | Any user of this software should understand that IBM cannot provide
11 | technical support for this software and will not be responsible for
12 | any consequences resulting from the use of this software.
14 | Any person who transfers this source code or any derivative work
15 | must include the IBM copyright notice, this paragraph, and the
16 | preceding two paragraphs in the transferred software.
18 | COPYRIGHT I B M CORPORATION 1995
19 | LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
20 +-----------------------------------------------------------------------------*/
21 /*-----------------------------------------------------------------------------+
25 | Function: This module has utilities for accessing the MII PHY through
30 +-----------------------------------------------------------------------------*/
33 #include <asm/processor.h>
35 #include <ppc_asm.tmpl>
37 #include <ppc4xx_enet.h>
42 /***********************************************************/
43 /* Dump out to the screen PHY regs */
44 /***********************************************************/
46 void miiphy_dump (char *devname, unsigned char addr)
51 for (i = 0; i < 0x1A; i++) {
52 if (miiphy_read (devname, addr, i, &data)) {
53 printf ("read error for reg %lx\n", i);
56 printf ("Phy reg %lx ==> %4x\n", i, data);
58 /* jump to the next set of regs */
65 /***********************************************************/
66 /* (Re)start autonegotiation */
67 /***********************************************************/
68 int phy_setup_aneg (char *devname, unsigned char addr)
72 #if defined(CONFIG_PHY_DYNAMIC_ANEG)
74 * Set up advertisement based on capablilities reported by the PHY.
75 * This should work for both copper and fiber.
78 #if defined(CONFIG_PHY_GIGE)
82 miiphy_read (devname, addr, PHY_BMSR, &bmsr);
84 #if defined(CONFIG_PHY_GIGE)
85 if (bmsr & PHY_BMSR_EXT_STAT)
86 miiphy_read (devname, addr, PHY_EXSR, &exsr);
88 if (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH)) {
92 if (exsr & PHY_EXSR_1000XF)
93 anar |= PHY_X_ANLPAR_FD;
95 if (exsr & PHY_EXSR_1000XH)
96 anar |= PHY_X_ANLPAR_HD;
98 miiphy_write (devname, addr, PHY_ANAR, anar);
104 miiphy_read (devname, addr, PHY_ANAR, &anar);
105 anar &= ~(0x5000 | PHY_ANLPAR_T4 | PHY_ANLPAR_TXFD |
106 PHY_ANLPAR_TX | PHY_ANLPAR_10FD | PHY_ANLPAR_10);
108 miiphy_read (devname, addr, PHY_1000BTCR, &btcr);
109 btcr &= ~(0x00FF | PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD);
111 if (bmsr & PHY_BMSR_100T4)
112 anar |= PHY_ANLPAR_T4;
114 if (bmsr & PHY_BMSR_100TXF)
115 anar |= PHY_ANLPAR_TXFD;
117 if (bmsr & PHY_BMSR_100TXH)
118 anar |= PHY_ANLPAR_TX;
120 if (bmsr & PHY_BMSR_10TF)
121 anar |= PHY_ANLPAR_10FD;
123 if (bmsr & PHY_BMSR_10TH)
124 anar |= PHY_ANLPAR_10;
126 miiphy_write (devname, addr, PHY_ANAR, anar);
128 #if defined(CONFIG_PHY_GIGE)
129 if (exsr & PHY_EXSR_1000TF)
130 btcr |= PHY_1000BTCR_1000FD;
132 if (exsr & PHY_EXSR_1000TH)
133 btcr |= PHY_1000BTCR_1000HD;
135 miiphy_write (devname, addr, PHY_1000BTCR, btcr);
139 #else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
141 * Set up standard advertisement
145 miiphy_read (devname, addr, PHY_ANAR, &adv);
146 adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 |
147 PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD |
149 miiphy_write (devname, addr, PHY_ANAR, adv);
151 miiphy_read (devname, addr, PHY_1000BTCR, &adv);
153 miiphy_write (devname, addr, PHY_1000BTCR, adv);
155 #endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
157 /* Start/Restart aneg */
158 miiphy_read (devname, addr, PHY_BMCR, &bmcr);
159 bmcr |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
160 miiphy_write (devname, addr, PHY_BMCR, bmcr);
165 /***********************************************************/
166 /* read a phy reg and return the value with a rc */
167 /***********************************************************/
168 unsigned int miiphy_getemac_offset (void)
170 #if (defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)) && defined(CONFIG_NET_MULTI)
172 unsigned long eoffset;
174 /* Need to find out which mdi port we're using */
175 zmii = in_be32((void *)ZMII_FER);
177 if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0)))
181 else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1)))
185 else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2)))
189 else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3)))
194 /* None of the mdi ports are enabled! */
196 zmii |= ZMII_FER_MDI << ZMII_FER_V (0);
197 out_be32((void *)ZMII_FER, zmii);
199 /* need to soft reset port 0 */
200 zmii = in_be32((void *)EMAC_M0);
201 zmii |= EMAC_M0_SRST;
202 out_be32((void *)EMAC_M0, zmii);
208 #if defined(CONFIG_NET_MULTI) && defined(CONFIG_405EX)
212 rgmii = in_be32((void *)RGMII_FER);
213 if (rgmii & (1 << (19 - devnum)))
221 int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg,
222 unsigned short *value)
224 unsigned long sta_reg; /* STA scratch area */
226 unsigned long emac_reg;
228 emac_reg = miiphy_getemac_offset ();
229 /* see if it is ready for 1000 nsec */
232 /* see if it is ready for sec */
233 while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) ==
234 EMAC_STACR_OC_MASK) {
238 sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
239 printf ("read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
240 printf ("read err 1\n");
246 sta_reg = reg; /* reg address */
247 /* set clock (50Mhz) and read flags */
248 #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
249 defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
250 defined(CONFIG_405EX)
251 #if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */
252 sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ;
254 sta_reg |= EMAC_STACR_READ;
257 sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ;
260 #if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \
261 !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
262 !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \
263 !defined(CONFIG_405EX)
264 sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;
266 sta_reg = sta_reg | (addr << 5); /* Phy address */
267 sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
268 out_be32((void *)EMAC_STACR + emac_reg, sta_reg);
270 printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
273 sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
275 printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
278 while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
284 sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
286 printf ("a22: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
289 if ((sta_reg & EMAC_STACR_PHYE) != 0)
292 *value = *(short *)(&sta_reg);
297 /***********************************************************/
298 /* write a phy reg and return the value with a rc */
299 /***********************************************************/
301 int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg,
302 unsigned short value)
304 unsigned long sta_reg; /* STA scratch area */
306 unsigned long emac_reg;
308 emac_reg = miiphy_getemac_offset ();
309 /* see if it is ready for 1000 nsec */
312 while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) ==
313 EMAC_STACR_OC_MASK) {
321 sta_reg = reg; /* reg address */
322 /* set clock (50Mhz) and read flags */
323 #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
324 defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
325 defined(CONFIG_405EX)
326 #if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */
327 sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE;
329 sta_reg |= EMAC_STACR_WRITE;
332 sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ;
335 #if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \
336 !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
337 !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \
338 !defined(CONFIG_405EX)
339 sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; /* Set clock frequency (PLB freq. dependend) */
341 sta_reg = sta_reg | ((unsigned long)addr << 5); /* Phy address */
342 sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
343 memcpy (&sta_reg, &value, 2); /* put in data */
345 out_be32((void *)EMAC_STACR + emac_reg, sta_reg);
347 /* wait for completion */
349 sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
351 printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
353 while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
359 sta_reg = in_be32((void *)EMAC_STACR + emac_reg);
361 printf ("a32: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
365 if ((sta_reg & EMAC_STACR_PHYE) != 0)