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