xref: /openbmc/u-boot/drivers/net/phy/miiphybb.c (revision 85829017)
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 }
243