]>
Commit | Line | Data |
---|---|---|
affae2bf WD |
1 | /* |
2 | * (C) Copyright 2001 | |
3 | * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | /* | |
25 | * This provides a bit-banged interface to the ethernet MII management | |
26 | * channel. | |
27 | */ | |
28 | ||
29 | #include <common.h> | |
30 | #include <ioports.h> | |
31 | #include <ppc_asm.tmpl> | |
32 | ||
33 | #ifdef CONFIG_BITBANGMII | |
34 | ||
35 | ||
36 | /***************************************************************************** | |
37 | * | |
38 | * Utility to send the preamble, address, and register (common to read | |
39 | * and write). | |
40 | */ | |
41 | static void miiphy_pre(char read, | |
42 | unsigned char addr, | |
43 | unsigned char reg) | |
44 | { | |
45 | int j; /* counter */ | |
46 | volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT); | |
47 | ||
48 | /* | |
49 | * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure. | |
50 | * The IEEE spec says this is a PHY optional requirement. The AMD | |
51 | * 79C874 requires one after power up and one after a MII communications | |
52 | * error. This means that we are doing more preambles than we need, | |
53 | * but it is safer and will be much more robust. | |
54 | */ | |
55 | ||
56 | MDIO_ACTIVE; | |
57 | MDIO(1); | |
58 | for(j = 0; j < 32; j++) | |
59 | { | |
60 | MDC(0); | |
61 | MIIDELAY; | |
62 | MDC(1); | |
63 | MIIDELAY; | |
64 | } | |
65 | ||
66 | /* send the start bit (01) and the read opcode (10) or write (10) */ | |
67 | MDC(0); MDIO(0); MIIDELAY; MDC(1); MIIDELAY; | |
68 | MDC(0); MDIO(1); MIIDELAY; MDC(1); MIIDELAY; | |
69 | MDC(0); MDIO(read); MIIDELAY; MDC(1); MIIDELAY; | |
70 | MDC(0); MDIO(!read); MIIDELAY; MDC(1); MIIDELAY; | |
71 | ||
72 | /* send the PHY address */ | |
73 | for(j = 0; j < 5; j++) | |
74 | { | |
75 | MDC(0); | |
76 | if((addr & 0x10) == 0) | |
77 | { | |
78 | MDIO(0); | |
79 | } | |
80 | else | |
81 | { | |
82 | MDIO(1); | |
83 | } | |
84 | MIIDELAY; | |
85 | MDC(1); | |
86 | MIIDELAY; | |
87 | addr <<= 1; | |
88 | } | |
89 | ||
90 | /* send the register address */ | |
91 | for(j = 0; j < 5; j++) | |
92 | { | |
93 | MDC(0); | |
94 | if((reg & 0x10) == 0) | |
95 | { | |
96 | MDIO(0); | |
97 | } | |
98 | else | |
99 | { | |
100 | MDIO(1); | |
101 | } | |
102 | MIIDELAY; | |
103 | MDC(1); | |
104 | MIIDELAY; | |
105 | reg <<= 1; | |
106 | } | |
107 | } | |
108 | ||
109 | ||
110 | /***************************************************************************** | |
111 | * | |
112 | * Read a MII PHY register. | |
113 | * | |
114 | * Returns: | |
115 | * 0 on success | |
116 | */ | |
117 | int miiphy_read(unsigned char addr, | |
118 | unsigned char reg, | |
119 | unsigned short *value) | |
120 | { | |
121 | short rdreg; /* register working value */ | |
122 | int j; /* counter */ | |
123 | volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT); | |
124 | ||
125 | miiphy_pre(1, addr, reg); | |
126 | ||
127 | /* tri-state our MDIO I/O pin so we can read */ | |
128 | MDC(0); | |
129 | MDIO_TRISTATE; | |
130 | MIIDELAY; | |
131 | MDC(1); | |
132 | MIIDELAY; | |
133 | ||
134 | /* check the turnaround bit: the PHY should be driving it to zero */ | |
135 | if(MDIO_READ != 0) | |
136 | { | |
137 | /* printf("PHY didn't drive TA low\n"); */ | |
138 | for(j = 0; j < 32; j++) | |
139 | { | |
140 | MDC(0); | |
141 | MIIDELAY; | |
142 | MDC(1); | |
143 | MIIDELAY; | |
144 | } | |
145 | return(-1); | |
146 | } | |
147 | ||
148 | MDC(0); | |
149 | MIIDELAY; | |
150 | ||
151 | /* read 16 bits of register data, MSB first */ | |
152 | rdreg = 0; | |
153 | for(j = 0; j < 16; j++) | |
154 | { | |
155 | MDC(1); | |
156 | MIIDELAY; | |
157 | rdreg <<= 1; | |
158 | rdreg |= MDIO_READ; | |
159 | MDC(0); | |
160 | MIIDELAY; | |
161 | } | |
162 | ||
163 | MDC(1); | |
164 | MIIDELAY; | |
165 | MDC(0); | |
166 | MIIDELAY; | |
167 | MDC(1); | |
168 | MIIDELAY; | |
169 | ||
170 | *value = rdreg; | |
171 | ||
172 | #ifdef DEBUG | |
173 | printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value); | |
174 | #endif | |
175 | ||
176 | return 0; | |
177 | } | |
178 | ||
179 | ||
180 | /***************************************************************************** | |
181 | * | |
182 | * Write a MII PHY register. | |
183 | * | |
184 | * Returns: | |
185 | * 0 on success | |
186 | */ | |
187 | int miiphy_write(unsigned char addr, | |
188 | unsigned char reg, | |
189 | unsigned short value) | |
190 | { | |
191 | int j; /* counter */ | |
192 | volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, MDIO_PORT); | |
193 | ||
194 | miiphy_pre(0, addr, reg); | |
195 | ||
196 | /* send the turnaround (10) */ | |
197 | MDC(0); MDIO(1); MIIDELAY; MDC(1); MIIDELAY; | |
198 | MDC(0); MDIO(0); MIIDELAY; MDC(1); MIIDELAY; | |
199 | ||
200 | /* write 16 bits of register data, MSB first */ | |
201 | for(j = 0; j < 16; j++) | |
202 | { | |
203 | MDC(0); | |
204 | if((value & 0x00008000) == 0) | |
205 | { | |
206 | MDIO(0); | |
207 | } | |
208 | else | |
209 | { | |
210 | MDIO(1); | |
211 | } | |
212 | MIIDELAY; | |
213 | MDC(1); | |
214 | MIIDELAY; | |
215 | value <<= 1; | |
216 | } | |
217 | ||
218 | /* | |
219 | * Tri-state the MDIO line. | |
220 | */ | |
221 | MDIO_TRISTATE; | |
222 | MDC(0); | |
223 | MIIDELAY; | |
224 | MDC(1); | |
225 | MIIDELAY; | |
226 | ||
227 | return 0; | |
228 | } | |
229 | ||
230 | #endif /* CONFIG_BITBANGMII */ | |
231 |