]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/miiphybb.c
* Switch LWMON board default config from FRAM to EEPROM;
[karo-tx-uboot.git] / common / 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 #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