xref: /openbmc/u-boot/drivers/net/phy/miiphybb.c (revision ab0df36f)
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 *) CFG_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 *) CFG_IMMR, MDIO_PORT);
128 #endif
129 
130 	miiphy_pre (1, addr, reg);
131 
132 	/* tri-state our MDIO I/O pin so we can read */
133 	MDC (0);
134 	MDIO_TRISTATE;
135 	MIIDELAY;
136 	MDC (1);
137 	MIIDELAY;
138 
139 	/* check the turnaround bit: the PHY should be driving it to zero */
140 	if (MDIO_READ != 0) {
141 		/* puts ("PHY didn't drive TA low\n"); */
142 		for (j = 0; j < 32; j++) {
143 			MDC (0);
144 			MIIDELAY;
145 			MDC (1);
146 			MIIDELAY;
147 		}
148 		return (-1);
149 	}
150 
151 	MDC (0);
152 	MIIDELAY;
153 
154 	/* read 16 bits of register data, MSB first */
155 	rdreg = 0;
156 	for (j = 0; j < 16; j++) {
157 		MDC (1);
158 		MIIDELAY;
159 		rdreg <<= 1;
160 		rdreg |= MDIO_READ;
161 		MDC (0);
162 		MIIDELAY;
163 	}
164 
165 	MDC (1);
166 	MIIDELAY;
167 	MDC (0);
168 	MIIDELAY;
169 	MDC (1);
170 	MIIDELAY;
171 
172 	*value = rdreg;
173 
174 #ifdef DEBUG
175 	printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
176 #endif
177 
178 	return 0;
179 }
180 
181 
182 /*****************************************************************************
183  *
184  * Write a MII PHY register.
185  *
186  * Returns:
187  *   0 on success
188  */
189 int bb_miiphy_write (char *devname, unsigned char addr,
190 		unsigned char reg, unsigned short value)
191 {
192 	int j;			/* counter */
193 #if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM))
194 	volatile ioport_t *iop = ioport_addr ((immap_t *) CFG_IMMR, MDIO_PORT);
195 #endif
196 
197 	miiphy_pre (0, addr, reg);
198 
199 	/* send the turnaround (10) */
200 	MDC (0);
201 	MDIO (1);
202 	MIIDELAY;
203 	MDC (1);
204 	MIIDELAY;
205 	MDC (0);
206 	MDIO (0);
207 	MIIDELAY;
208 	MDC (1);
209 	MIIDELAY;
210 
211 	/* write 16 bits of register data, MSB first */
212 	for (j = 0; j < 16; j++) {
213 		MDC (0);
214 		if ((value & 0x00008000) == 0) {
215 			MDIO (0);
216 		} else {
217 			MDIO (1);
218 		}
219 		MIIDELAY;
220 		MDC (1);
221 		MIIDELAY;
222 		value <<= 1;
223 	}
224 
225 	/*
226 	 * Tri-state the MDIO line.
227 	 */
228 	MDIO_TRISTATE;
229 	MDC (0);
230 	MIIDELAY;
231 	MDC (1);
232 	MIIDELAY;
233 
234 	return 0;
235 }
236