xref: /netbsd-src/sys/dev/mii/mii_bitbang.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: mii_bitbang.c,v 1.10 2005/12/11 12:22:42 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Common module for bit-bang'ing the MII.
42  */
43 
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: mii_bitbang.c,v 1.10 2005/12/11 12:22:42 christos Exp $");
46 
47 #include <sys/param.h>
48 #include <sys/device.h>
49 
50 #include <dev/mii/mii.h>
51 #include <dev/mii/mii_bitbang.h>
52 
53 #define	WRITE(x)							\
54 do {									\
55 	ops->mbo_write(sc, (x));					\
56 	delay(1);							\
57 } while (/* CONSTCOND */ 0)
58 
59 #define	READ		ops->mbo_read(sc)
60 
61 #define	MDO		ops->mbo_bits[MII_BIT_MDO]
62 #define	MDI		ops->mbo_bits[MII_BIT_MDI]
63 #define	MDC		ops->mbo_bits[MII_BIT_MDC]
64 #define	MDIRPHY		ops->mbo_bits[MII_BIT_DIR_HOST_PHY]
65 #define	MDIRHOST	ops->mbo_bits[MII_BIT_DIR_PHY_HOST]
66 
67 /*
68  * mii_bitbang_sync:
69  *
70  *	Synchronize the MII.
71  */
72 static void
73 mii_bitbang_sync(struct device *sc, mii_bitbang_ops_t ops)
74 {
75 	int i;
76 	u_int32_t v;
77 
78 	v = MDIRPHY | MDO;
79 
80 	WRITE(v);
81 	for (i = 0; i < 32; i++) {
82 		WRITE(v | MDC);
83 		WRITE(v);
84 	}
85 }
86 
87 /*
88  * mii_bitbang_sendbits:
89  *
90  *	Send a series of bits to the MII.
91  */
92 static void
93 mii_bitbang_sendbits(struct device *sc, mii_bitbang_ops_t ops, uint32_t data,
94     int nbits)
95 {
96 	int i;
97 	u_int32_t v;
98 
99 	v = MDIRPHY;
100 	WRITE(v);
101 
102 	for (i = 1 << (nbits - 1); i != 0; i >>= 1) {
103 		if (data & i)
104 			v |= MDO;
105 		else
106 			v &= ~MDO;
107 		WRITE(v);
108 		WRITE(v | MDC);
109 		WRITE(v);
110 	}
111 }
112 
113 /*
114  * mii_bitbang_readreg:
115  *
116  *	Read a PHY register by bit-bang'ing the MII.
117  */
118 int
119 mii_bitbang_readreg(struct device *sc, mii_bitbang_ops_t ops, int phy, int reg)
120 {
121 	int val = 0, err = 0, i;
122 
123 	mii_bitbang_sync(sc, ops);
124 
125 	mii_bitbang_sendbits(sc, ops, MII_COMMAND_START, 2);
126 	mii_bitbang_sendbits(sc, ops, MII_COMMAND_READ, 2);
127 	mii_bitbang_sendbits(sc, ops, phy, 5);
128 	mii_bitbang_sendbits(sc, ops, reg, 5);
129 
130 	/* Switch direction to PHY->host, without a clock transition. */
131 	WRITE(MDIRHOST);
132 
133 	/* Turnaround clock. */
134 	WRITE(MDIRHOST | MDC);
135 	WRITE(MDIRHOST);
136 
137 	/* Check for error. */
138 	err = READ & MDI;
139 
140 	/* Idle clock. */
141 	WRITE(MDIRHOST | MDC);
142 	WRITE(MDIRHOST);
143 
144 	for (i = 0; i < 16; i++) {
145 		val <<= 1;
146 		/* Read data prior to clock low-high transition. */
147 		if (err == 0 && (READ & MDI) != 0)
148 			val |= 1;
149 
150 		WRITE(MDIRHOST | MDC);
151 		WRITE(MDIRHOST);
152 	}
153 
154 	/* Set direction to host->PHY, without a clock transition. */
155 	WRITE(MDIRPHY);
156 
157 	return (err ? 0 : val);
158 }
159 
160 /*
161  * mii_bitbang_writereg:
162  *
163  *	Write a PHY register by bit-bang'ing the MII.
164  */
165 void
166 mii_bitbang_writereg(struct device *sc, mii_bitbang_ops_t ops, int phy,
167 int reg, int val)
168 {
169 
170 	mii_bitbang_sync(sc, ops);
171 
172 	mii_bitbang_sendbits(sc, ops, MII_COMMAND_START, 2);
173 	mii_bitbang_sendbits(sc, ops, MII_COMMAND_WRITE, 2);
174 	mii_bitbang_sendbits(sc, ops, phy, 5);
175 	mii_bitbang_sendbits(sc, ops, reg, 5);
176 	mii_bitbang_sendbits(sc, ops, MII_COMMAND_ACK, 2);
177 	mii_bitbang_sendbits(sc, ops, val, 16);
178 
179 	WRITE(MDIRPHY);
180 }
181