]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/mii/mii_bitbang.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / mii / mii_bitbang.c
1 /*      $NetBSD: mii_bitbang.c,v 1.12 2008/05/04 17:06:09 xtraeme 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 didevlaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following didevlaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  * Common module for bit-bang'ing the MII.
35  */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/module.h>
43
44 #include <dev/mii/mii.h>
45 #include <dev/mii/mii_bitbang.h>
46
47 MODULE_VERSION(mii_bitbang, 1);
48
49 static void mii_bitbang_sendbits(device_t dev, mii_bitbang_ops_t ops,
50     uint32_t data, int nbits);
51
52 #define MWRITE(x)                                                       \
53 do {                                                                    \
54         ops->mbo_write(dev, (x));                                       \
55         DELAY(1);                                                       \
56 } while (/* CONSTCOND */ 0)
57
58 #define MREAD           ops->mbo_read(dev)
59
60 #define MDO             ops->mbo_bits[MII_BIT_MDO]
61 #define MDI             ops->mbo_bits[MII_BIT_MDI]
62 #define MDC             ops->mbo_bits[MII_BIT_MDC]
63 #define MDIRPHY         ops->mbo_bits[MII_BIT_DIR_HOST_PHY]
64 #define MDIRHOST        ops->mbo_bits[MII_BIT_DIR_PHY_HOST]
65
66 /*
67  * mii_bitbang_sync:
68  *
69  *      Synchronize the MII.
70  */
71 void
72 mii_bitbang_sync(device_t dev, mii_bitbang_ops_t ops)
73 {
74         int i;
75         uint32_t v;
76
77         v = MDIRPHY | MDO;
78
79         MWRITE(v);
80         for (i = 0; i < 32; i++) {
81                 MWRITE(v | MDC);
82                 MWRITE(v);
83         }
84 }
85
86 /*
87  * mii_bitbang_sendbits:
88  *
89  *      Send a series of bits to the MII.
90  */
91 static void
92 mii_bitbang_sendbits(device_t dev, mii_bitbang_ops_t ops, uint32_t data,
93     int nbits)
94 {
95         int i;
96         uint32_t v;
97
98         v = MDIRPHY;
99         MWRITE(v);
100
101         for (i = 1 << (nbits - 1); i != 0; i >>= 1) {
102                 if (data & i)
103                         v |= MDO;
104                 else
105                         v &= ~MDO;
106                 MWRITE(v);
107                 MWRITE(v | MDC);
108                 MWRITE(v);
109         }
110 }
111
112 /*
113  * mii_bitbang_readreg:
114  *
115  *      Read a PHY register by bit-bang'ing the MII.
116  */
117 int
118 mii_bitbang_readreg(device_t dev, mii_bitbang_ops_t ops, int phy, int reg)
119 {
120         int i, error, val;
121
122         mii_bitbang_sync(dev, ops);
123
124         mii_bitbang_sendbits(dev, ops, MII_COMMAND_START, 2);
125         mii_bitbang_sendbits(dev, ops, MII_COMMAND_READ, 2);
126         mii_bitbang_sendbits(dev, ops, phy, 5);
127         mii_bitbang_sendbits(dev, ops, reg, 5);
128
129         /* Switch direction to PHY->host, without a clock transition. */
130         MWRITE(MDIRHOST);
131
132         /* Turnaround clock. */
133         MWRITE(MDIRHOST | MDC);
134         MWRITE(MDIRHOST);
135
136         /* Check for error. */
137         error = MREAD & MDI;
138
139         /* Idle clock. */
140         MWRITE(MDIRHOST | MDC);
141         MWRITE(MDIRHOST);
142
143         val = 0;
144         for (i = 0; i < 16; i++) {
145                 val <<= 1;
146                 /* Read data prior to clock low-high transition. */
147                 if (error == 0 && (MREAD & MDI) != 0)
148                         val |= 1;
149
150                 MWRITE(MDIRHOST | MDC);
151                 MWRITE(MDIRHOST);
152         }
153
154         /* Set direction to host->PHY, without a clock transition. */
155         MWRITE(MDIRPHY);
156
157         return (error != 0 ? 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(device_t dev, mii_bitbang_ops_t ops, int phy, int reg,
167     int val)
168 {
169
170         mii_bitbang_sync(dev, ops);
171
172         mii_bitbang_sendbits(dev, ops, MII_COMMAND_START, 2);
173         mii_bitbang_sendbits(dev, ops, MII_COMMAND_WRITE, 2);
174         mii_bitbang_sendbits(dev, ops, phy, 5);
175         mii_bitbang_sendbits(dev, ops, reg, 5);
176         mii_bitbang_sendbits(dev, ops, MII_COMMAND_ACK, 2);
177         mii_bitbang_sendbits(dev, ops, val, 16);
178
179         MWRITE(MDIRPHY);
180 }