]> git.sur5r.net Git - u-boot/blob - drivers/net/phy/miiphybb.c
b77c917462ad654f53da93d9cf9eac3d0039ecb9
[u-boot] / drivers / net / phy / miiphybb.c
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 /*****************************************************************************
34  *
35  * Utility to send the preamble, address, and register (common to read
36  * and write).
37  */
38 static void miiphy_pre (char read, unsigned char addr, unsigned char reg)
39 {
40         int j;                  /* counter */
41 #if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM))
42         volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT);
43 #endif
44
45         /*
46          * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
47          * The IEEE spec says this is a PHY optional requirement.  The AMD
48          * 79C874 requires one after power up and one after a MII communications
49          * error.  This means that we are doing more preambles than we need,
50          * but it is safer and will be much more robust.
51          */
52
53         MDIO_ACTIVE;
54         MDIO (1);
55         for (j = 0; j < 32; j++) {
56                 MDC (0);
57                 MIIDELAY;
58                 MDC (1);
59                 MIIDELAY;
60         }
61
62         /* send the start bit (01) and the read opcode (10) or write (10) */
63         MDC (0);
64         MDIO (0);
65         MIIDELAY;
66         MDC (1);
67         MIIDELAY;
68         MDC (0);
69         MDIO (1);
70         MIIDELAY;
71         MDC (1);
72         MIIDELAY;
73         MDC (0);
74         MDIO (read);
75         MIIDELAY;
76         MDC (1);
77         MIIDELAY;
78         MDC (0);
79         MDIO (!read);
80         MIIDELAY;
81         MDC (1);
82         MIIDELAY;
83
84         /* send the PHY address */
85         for (j = 0; j < 5; j++) {
86                 MDC (0);
87                 if ((addr & 0x10) == 0) {
88                         MDIO (0);
89                 } else {
90                         MDIO (1);
91                 }
92                 MIIDELAY;
93                 MDC (1);
94                 MIIDELAY;
95                 addr <<= 1;
96         }
97
98         /* send the register address */
99         for (j = 0; j < 5; j++) {
100                 MDC (0);
101                 if ((reg & 0x10) == 0) {
102                         MDIO (0);
103                 } else {
104                         MDIO (1);
105                 }
106                 MIIDELAY;
107                 MDC (1);
108                 MIIDELAY;
109                 reg <<= 1;
110         }
111 }
112
113
114 /*****************************************************************************
115  *
116  * Read a MII PHY register.
117  *
118  * Returns:
119  *   0 on success
120  */
121 int bb_miiphy_read (char *devname, unsigned char addr,
122                 unsigned char reg, unsigned short *value)
123 {
124         short rdreg;            /* register working value */
125         int j;                  /* counter */
126 #if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM))
127         volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT);
128 #endif
129
130         if (value == NULL) {
131                 puts("NULL value pointer\n");
132                 return (-1);
133         }
134
135         miiphy_pre (1, addr, reg);
136
137         /* tri-state our MDIO I/O pin so we can read */
138         MDC (0);
139         MDIO_TRISTATE;
140         MIIDELAY;
141         MDC (1);
142         MIIDELAY;
143
144         /* check the turnaround bit: the PHY should be driving it to zero */
145         if (MDIO_READ != 0) {
146                 /* puts ("PHY didn't drive TA low\n"); */
147                 for (j = 0; j < 32; j++) {
148                         MDC (0);
149                         MIIDELAY;
150                         MDC (1);
151                         MIIDELAY;
152                 }
153                 /* There is no PHY, set value to 0xFFFF and return */
154                 *value = 0xFFFF;
155                 return (-1);
156         }
157
158         MDC (0);
159         MIIDELAY;
160
161         /* read 16 bits of register data, MSB first */
162         rdreg = 0;
163         for (j = 0; j < 16; j++) {
164                 MDC (1);
165                 MIIDELAY;
166                 rdreg <<= 1;
167                 rdreg |= MDIO_READ;
168                 MDC (0);
169                 MIIDELAY;
170         }
171
172         MDC (1);
173         MIIDELAY;
174         MDC (0);
175         MIIDELAY;
176         MDC (1);
177         MIIDELAY;
178
179         *value = rdreg;
180
181 #ifdef DEBUG
182         printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
183 #endif
184
185         return 0;
186 }
187
188
189 /*****************************************************************************
190  *
191  * Write a MII PHY register.
192  *
193  * Returns:
194  *   0 on success
195  */
196 int bb_miiphy_write (char *devname, unsigned char addr,
197                 unsigned char reg, unsigned short value)
198 {
199         int j;                  /* counter */
200 #if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM))
201         volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT);
202 #endif
203
204         miiphy_pre (0, addr, reg);
205
206         /* send the turnaround (10) */
207         MDC (0);
208         MDIO (1);
209         MIIDELAY;
210         MDC (1);
211         MIIDELAY;
212         MDC (0);
213         MDIO (0);
214         MIIDELAY;
215         MDC (1);
216         MIIDELAY;
217
218         /* write 16 bits of register data, MSB first */
219         for (j = 0; j < 16; j++) {
220                 MDC (0);
221                 if ((value & 0x00008000) == 0) {
222                         MDIO (0);
223                 } else {
224                         MDIO (1);
225                 }
226                 MIIDELAY;
227                 MDC (1);
228                 MIIDELAY;
229                 value <<= 1;
230         }
231
232         /*
233          * Tri-state the MDIO line.
234          */
235         MDIO_TRISTATE;
236         MDC (0);
237         MIIDELAY;
238         MDC (1);
239         MIIDELAY;
240
241         return 0;
242 }