]>
Commit | Line | Data |
---|---|---|
affae2bf WD |
1 | /*-----------------------------------------------------------------------------+ |
2 | | | |
d6c61aab SR |
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. | |
affae2bf | 9 | | |
d6c61aab SR |
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. | |
affae2bf | 13 | | |
d6c61aab SR |
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. | |
affae2bf | 17 | | |
d6c61aab SR |
18 | | COPYRIGHT I B M CORPORATION 1995 |
19 | | LICENSED MATERIAL - PROGRAM PROPERTY OF I B M | |
affae2bf WD |
20 | +-----------------------------------------------------------------------------*/ |
21 | /*-----------------------------------------------------------------------------+ | |
22 | | | |
d6c61aab | 23 | | File Name: miiphy.c |
affae2bf | 24 | | |
d6c61aab | 25 | | Function: This module has utilities for accessing the MII PHY through |
affae2bf WD |
26 | | the EMAC3 macro. |
27 | | | |
d6c61aab | 28 | | Author: Mark Wisner |
affae2bf WD |
29 | | |
30 | | Change Activity- | |
31 | | | |
d6c61aab SR |
32 | | Date Description of Change BY |
33 | | --------- --------------------- --- | |
34 | | 05-May-99 Created MKW | |
35 | | 01-Jul-99 Changed clock setting of sta_reg from 66Mhz to 50Mhz to | |
36 | | better match OPB speed. Also modified delay times. JWB | |
37 | | 29-Jul-99 Added Full duplex support MKW | |
38 | | 24-Aug-99 Removed printf from dp83843_duplex() JWB | |
39 | | 19-Jul-00 Ported to esd cpci405 sr | |
40 | | 23-Dec-03 Ported from miiphy.c to 440GX Travis Sawyer TBS | |
41 | | <[email protected]> | |
affae2bf WD |
42 | | |
43 | +-----------------------------------------------------------------------------*/ | |
44 | ||
45 | #include <common.h> | |
46 | #include <asm/processor.h> | |
47 | #include <ppc_asm.tmpl> | |
48 | #include <commproc.h> | |
d6c61aab | 49 | #include <ppc4xx_enet.h> |
affae2bf WD |
50 | #include <405_mal.h> |
51 | #include <miiphy.h> | |
52 | ||
affae2bf WD |
53 | |
54 | /***********************************************************/ | |
d6c61aab | 55 | /* Dump out to the screen PHY regs */ |
affae2bf WD |
56 | /***********************************************************/ |
57 | ||
63ff004c | 58 | void miiphy_dump (char *devname, unsigned char addr) |
affae2bf WD |
59 | { |
60 | unsigned long i; | |
61 | unsigned short data; | |
62 | ||
63 | ||
64 | for (i = 0; i < 0x1A; i++) { | |
63ff004c | 65 | if (miiphy_read (devname, addr, i, &data)) { |
affae2bf WD |
66 | printf ("read error for reg %lx\n", i); |
67 | return; | |
68 | } | |
69 | printf ("Phy reg %lx ==> %4x\n", i, data); | |
70 | ||
71 | /* jump to the next set of regs */ | |
72 | if (i == 0x07) | |
73 | i = 0x0f; | |
74 | ||
d6c61aab SR |
75 | } /* end for loop */ |
76 | } /* end dump */ | |
affae2bf WD |
77 | |
78 | ||
affae2bf | 79 | /***********************************************************/ |
d6c61aab | 80 | /* (Re)start autonegotiation */ |
affae2bf | 81 | /***********************************************************/ |
63ff004c | 82 | int phy_setup_aneg (char *devname, unsigned char addr) |
d6c61aab SR |
83 | { |
84 | unsigned short ctl, adv; | |
85 | ||
86 | /* Setup standard advertise */ | |
63ff004c | 87 | miiphy_read (devname, addr, PHY_ANAR, &adv); |
d6c61aab SR |
88 | adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 | |
89 | PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD | | |
90 | PHY_ANLPAR_10); | |
63ff004c | 91 | miiphy_write (devname, addr, PHY_ANAR, adv); |
affae2bf | 92 | |
d6c61aab | 93 | /* Start/Restart aneg */ |
63ff004c | 94 | miiphy_read (devname, addr, PHY_BMCR, &ctl); |
d6c61aab | 95 | ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG); |
63ff004c | 96 | miiphy_write (devname, addr, PHY_BMCR, ctl); |
d6c61aab SR |
97 | |
98 | return 0; | |
99 | } | |
100 | ||
101 | ||
102 | /***********************************************************/ | |
103 | /* read a phy reg and return the value with a rc */ | |
104 | /***********************************************************/ | |
105 | unsigned int miiphy_getemac_offset (void) | |
affae2bf | 106 | { |
d6c61aab SR |
107 | #if defined(CONFIG_440) && defined(CONFIG_NET_MULTI) |
108 | unsigned long zmii; | |
109 | unsigned long eoffset; | |
110 | ||
111 | /* Need to find out which mdi port we're using */ | |
112 | zmii = in32 (ZMII_FER); | |
113 | ||
114 | if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0))) { | |
115 | /* using port 0 */ | |
116 | eoffset = 0; | |
117 | } else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1))) { | |
118 | /* using port 1 */ | |
119 | eoffset = 0x100; | |
120 | } else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2))) { | |
121 | /* using port 2 */ | |
122 | eoffset = 0x400; | |
123 | } else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3))) { | |
124 | /* using port 3 */ | |
125 | eoffset = 0x600; | |
126 | } else { | |
127 | /* None of the mdi ports are enabled! */ | |
128 | /* enable port 0 */ | |
129 | zmii |= ZMII_FER_MDI << ZMII_FER_V (0); | |
130 | out32 (ZMII_FER, zmii); | |
131 | eoffset = 0; | |
132 | /* need to soft reset port 0 */ | |
133 | zmii = in32 (EMAC_M0); | |
134 | zmii |= EMAC_M0_SRST; | |
135 | out32 (EMAC_M0, zmii); | |
136 | } | |
137 | ||
138 | return (eoffset); | |
139 | #else | |
140 | return 0; | |
141 | #endif | |
142 | } | |
143 | ||
144 | ||
63ff004c MB |
145 | int emac4xx_miiphy_read (char *devname, unsigned char addr, |
146 | unsigned char reg, unsigned short *value) | |
d6c61aab SR |
147 | { |
148 | unsigned long sta_reg; /* STA scratch area */ | |
affae2bf | 149 | unsigned long i; |
d6c61aab SR |
150 | unsigned long emac_reg; |
151 | ||
affae2bf | 152 | |
d6c61aab | 153 | emac_reg = miiphy_getemac_offset (); |
affae2bf WD |
154 | /* see if it is ready for 1000 nsec */ |
155 | i = 0; | |
156 | ||
157 | /* see if it is ready for sec */ | |
d6c61aab | 158 | while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == 0) { |
affae2bf WD |
159 | udelay (7); |
160 | if (i > 5) { | |
d6c61aab | 161 | #if 0 |
affae2bf | 162 | printf ("read err 1\n"); |
38a95195 | 163 | #endif |
affae2bf WD |
164 | return -1; |
165 | } | |
166 | i++; | |
167 | } | |
d6c61aab | 168 | sta_reg = reg; /* reg address */ |
affae2bf | 169 | /* set clock (50Mhz) and read flags */ |
d6c61aab SR |
170 | #if defined(CONFIG_440GX) |
171 | sta_reg |= EMAC_STACR_READ; | |
172 | #else | |
affae2bf | 173 | sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ; |
d6c61aab SR |
174 | #endif |
175 | ||
176 | #if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) | |
12f34241 | 177 | sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; |
093ae273 | 178 | #endif |
affae2bf WD |
179 | sta_reg = sta_reg | (addr << 5); /* Phy address */ |
180 | ||
d6c61aab SR |
181 | out32 (EMAC_STACR + emac_reg, sta_reg); |
182 | #if 0 /* test-only */ | |
affae2bf WD |
183 | printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ |
184 | #endif | |
185 | ||
d6c61aab | 186 | sta_reg = in32 (EMAC_STACR + emac_reg); |
affae2bf WD |
187 | i = 0; |
188 | while ((sta_reg & EMAC_STACR_OC) == 0) { | |
189 | udelay (7); | |
190 | if (i > 5) { | |
affae2bf WD |
191 | return -1; |
192 | } | |
193 | i++; | |
d6c61aab | 194 | sta_reg = in32 (EMAC_STACR + emac_reg); |
affae2bf WD |
195 | } |
196 | if ((sta_reg & EMAC_STACR_PHYE) != 0) { | |
affae2bf WD |
197 | return -1; |
198 | } | |
199 | ||
200 | *value = *(short *) (&sta_reg); | |
201 | return 0; | |
202 | ||
203 | ||
d6c61aab | 204 | } /* phy_read */ |
affae2bf WD |
205 | |
206 | ||
207 | /***********************************************************/ | |
d6c61aab | 208 | /* write a phy reg and return the value with a rc */ |
affae2bf WD |
209 | /***********************************************************/ |
210 | ||
63ff004c MB |
211 | int emac4xx_miiphy_write (char *devname, unsigned char addr, |
212 | unsigned char reg, unsigned short value) | |
affae2bf | 213 | { |
d6c61aab | 214 | unsigned long sta_reg; /* STA scratch area */ |
affae2bf | 215 | unsigned long i; |
d6c61aab | 216 | unsigned long emac_reg; |
affae2bf | 217 | |
d6c61aab | 218 | emac_reg = miiphy_getemac_offset (); |
affae2bf WD |
219 | /* see if it is ready for 1000 nsec */ |
220 | i = 0; | |
221 | ||
d6c61aab | 222 | while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == 0) { |
affae2bf WD |
223 | if (i > 5) |
224 | return -1; | |
225 | udelay (7); | |
226 | i++; | |
227 | } | |
228 | sta_reg = 0; | |
d6c61aab | 229 | sta_reg = reg; /* reg address */ |
affae2bf | 230 | /* set clock (50Mhz) and read flags */ |
d6c61aab SR |
231 | #if defined(CONFIG_440GX) |
232 | sta_reg |= EMAC_STACR_WRITE; | |
233 | #else | |
affae2bf | 234 | sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ; |
d6c61aab SR |
235 | #endif |
236 | ||
237 | #if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) | |
238 | sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; /* Set clock frequency (PLB freq. dependend) */ | |
093ae273 | 239 | #endif |
affae2bf WD |
240 | sta_reg = sta_reg | ((unsigned long) addr << 5); /* Phy address */ |
241 | memcpy (&sta_reg, &value, 2); /* put in data */ | |
242 | ||
d6c61aab | 243 | out32 (EMAC_STACR + emac_reg, sta_reg); |
affae2bf WD |
244 | |
245 | /* wait for completion */ | |
246 | i = 0; | |
d6c61aab | 247 | sta_reg = in32 (EMAC_STACR + emac_reg); |
affae2bf WD |
248 | while ((sta_reg & EMAC_STACR_OC) == 0) { |
249 | udelay (7); | |
250 | if (i > 5) | |
251 | return -1; | |
252 | i++; | |
d6c61aab | 253 | sta_reg = in32 (EMAC_STACR + emac_reg); |
affae2bf WD |
254 | } |
255 | ||
256 | if ((sta_reg & EMAC_STACR_PHYE) != 0) | |
257 | return -1; | |
258 | return 0; | |
259 | ||
d6c61aab | 260 | } /* phy_write */ |