1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#if 0
17#define DEBUG
18#endif
19
20#include <common.h>
21#include <asm/processor.h>
22#include <asm/io.h>
23#include <ppc_asm.tmpl>
24#include <commproc.h>
25#include <asm/ppc4xx-emac.h>
26#include <asm/ppc4xx-mal.h>
27#include <miiphy.h>
28
29#if !defined(CONFIG_PHY_CLK_FREQ)
30#define CONFIG_PHY_CLK_FREQ 0
31#endif
32
33
34
35
36
37void miiphy_dump (char *devname, unsigned char addr)
38{
39 unsigned long i;
40 unsigned short data;
41
42 for (i = 0; i < 0x1A; i++) {
43 if (miiphy_read (devname, addr, i, &data)) {
44 printf ("read error for reg %lx\n", i);
45 return;
46 }
47 printf ("Phy reg %lx ==> %4x\n", i, data);
48
49
50 if (i == 0x07)
51 i = 0x0f;
52
53 }
54}
55
56
57
58
59int phy_setup_aneg (char *devname, unsigned char addr)
60{
61 u16 bmcr;
62
63#if defined(CONFIG_PHY_DYNAMIC_ANEG)
64
65
66
67
68 u16 bmsr;
69#if defined(CONFIG_PHY_GIGE)
70 u16 exsr = 0x0000;
71#endif
72
73 miiphy_read (devname, addr, MII_BMSR, &bmsr);
74
75#if defined(CONFIG_PHY_GIGE)
76 if (bmsr & BMSR_ESTATEN)
77 miiphy_read (devname, addr, MII_ESTATUS, &exsr);
78
79 if (exsr & (ESTATUS_1000XF | ESTATUS_1000XH)) {
80
81 u16 anar = 0x0000;
82
83 if (exsr & ESTATUS_1000XF)
84 anar |= ADVERTISE_1000XFULL;
85
86 if (exsr & ESTATUS_1000XH)
87 anar |= ADVERTISE_1000XHALF;
88
89 miiphy_write (devname, addr, MII_ADVERTISE, anar);
90 } else
91#endif
92 {
93 u16 anar, btcr;
94
95 miiphy_read (devname, addr, MII_ADVERTISE, &anar);
96 anar &= ~(0x5000 | LPA_100BASE4 | LPA_100FULL |
97 LPA_100HALF | LPA_10FULL | LPA_10HALF);
98
99 miiphy_read (devname, addr, MII_CTRL1000, &btcr);
100 btcr &= ~(0x00FF | PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD);
101
102 if (bmsr & BMSR_100BASE4)
103 anar |= LPA_100BASE4;
104
105 if (bmsr & BMSR_100FULL)
106 anar |= LPA_100FULL;
107
108 if (bmsr & BMSR_100HALF)
109 anar |= LPA_100HALF;
110
111 if (bmsr & BMSR_10FULL)
112 anar |= LPA_10FULL;
113
114 if (bmsr & BMSR_10HALF)
115 anar |= LPA_10HALF;
116
117 miiphy_write (devname, addr, MII_ADVERTISE, anar);
118
119#if defined(CONFIG_PHY_GIGE)
120 if (exsr & ESTATUS_1000_TFULL)
121 btcr |= PHY_1000BTCR_1000FD;
122
123 if (exsr & ESTATUS_1000_THALF)
124 btcr |= PHY_1000BTCR_1000HD;
125
126 miiphy_write (devname, addr, MII_CTRL1000, btcr);
127#endif
128 }
129
130#else
131
132
133
134 u16 adv;
135
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);
140
141 miiphy_read (devname, addr, MII_CTRL1000, &adv);
142 adv |= (0x0300);
143 miiphy_write (devname, addr, MII_CTRL1000, adv);
144
145#endif
146
147
148 miiphy_read (devname, addr, MII_BMCR, &bmcr);
149 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
150 miiphy_write (devname, addr, MII_BMCR, bmcr);
151
152 return 0;
153}
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169unsigned int miiphy_getemac_offset(u8 addr)
170{
171#if defined(CONFIG_440) && \
172 !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
173 !defined(CONFIG_460EX) && !defined(CONFIG_460GT)
174 unsigned long zmii;
175 unsigned long eoffset;
176
177
178 zmii = in_be32((void *)ZMII0_FER);
179
180 if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0)))
181
182 eoffset = 0;
183
184 else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1)))
185
186 eoffset = 0x100;
187
188 else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2)))
189
190 eoffset = 0x400;
191
192 else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3)))
193
194 eoffset = 0x600;
195
196 else {
197
198
199 zmii |= ZMII_FER_MDI << ZMII_FER_V (0);
200 out_be32((void *)ZMII0_FER, zmii);
201 eoffset = 0;
202
203 zmii = in_be32((void *)EMAC0_MR0);
204 zmii |= EMAC_MR0_SRST;
205 out_be32((void *)EMAC0_MR0, zmii);
206 }
207
208 return (eoffset);
209#else
210
211#if defined(CONFIG_405EX)
212 unsigned long rgmii;
213 int devnum = 1;
214
215 rgmii = in_be32((void *)RGMII_FER);
216 if (rgmii & (1 << (19 - devnum)))
217 return 0x100;
218#endif
219
220#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
221 u32 eoffset = 0;
222
223 switch (addr) {
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)))
227 eoffset = 0x100;
228 break;
229#endif
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)))
233 eoffset = 0x300;
234 break;
235#endif
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)))
239 eoffset = 0x400;
240 break;
241#endif
242 default:
243 eoffset = 0;
244 break;
245 }
246 return eoffset;
247#endif
248
249 return 0;
250#endif
251}
252
253static int emac_miiphy_wait(u32 emac_reg)
254{
255 u32 sta_reg;
256 int i;
257
258
259 i = 0;
260 do {
261 sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
262 if (i++ > 5) {
263 debug("%s [%d]: Timeout! EMAC0_STACR=0x%0x\n", __func__,
264 __LINE__, sta_reg);
265 return -1;
266 }
267 udelay(10);
268 } while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK);
269
270 return 0;
271}
272
273static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value)
274{
275 u32 emac_reg;
276 u32 sta_reg;
277
278 emac_reg = miiphy_getemac_offset(addr);
279
280
281 if (emac_miiphy_wait(emac_reg) != 0)
282 return -1;
283
284 sta_reg = reg;
285
286
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)
292 sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | cmd;
293#else
294 sta_reg |= cmd;
295#endif
296#else
297 sta_reg = (sta_reg | cmd) & ~EMAC_STACR_CLK_100MHZ;
298#endif
299
300
301 sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;
302 sta_reg = sta_reg | ((u32)addr << 5);
303 sta_reg = sta_reg | EMAC_STACR_OC_MASK;
304 if (cmd == EMAC_STACR_WRITE)
305 memcpy(&sta_reg, &value, 2);
306
307 out_be32((void *)EMAC0_STACR + emac_reg, sta_reg);
308 debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg);
309
310
311 if (emac_miiphy_wait(emac_reg) != 0)
312 return -1;
313
314 debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg);
315 if ((sta_reg & EMAC_STACR_PHYE) != 0)
316 return -1;
317
318 return 0;
319}
320
321int emac4xx_miiphy_read (const char *devname, unsigned char addr, unsigned char reg,
322 unsigned short *value)
323{
324 unsigned long sta_reg;
325 unsigned long emac_reg;
326
327 emac_reg = miiphy_getemac_offset(addr);
328
329 if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0)
330 return -1;
331
332 sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
333 *value = sta_reg >> 16;
334
335 return 0;
336}
337
338
339
340
341
342int emac4xx_miiphy_write (const char *devname, unsigned char addr, unsigned char reg,
343 unsigned short value)
344{
345 return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value);
346}
347