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