1226995Smarius/* $NetBSD: mii_bitbang.c,v 1.12 2008/05/04 17:06:09 xtraeme Exp $ */ 2226995Smarius 3226995Smarius/*- 4226995Smarius * Copyright (c) 1999 The NetBSD Foundation, Inc. 5226995Smarius * All rights reserved. 6226995Smarius * 7226995Smarius * This code is derived from software contributed to The NetBSD Foundation 8226995Smarius * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9226995Smarius * NASA Ames Research Center. 10226995Smarius * 11226995Smarius * Redistribution and use in source and binary forms, with or without 12226995Smarius * modification, are permitted provided that the following conditions 13226995Smarius * are met: 14226995Smarius * 1. Redistributions of source code must retain the above copyright 15226995Smarius * notice, this list of conditions and the following didevlaimer. 16226995Smarius * 2. Redistributions in binary form must reproduce the above copyright 17226995Smarius * notice, this list of conditions and the following didevlaimer in the 18226995Smarius * documentation and/or other materials provided with the distribution. 19226995Smarius * 20226995Smarius * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21226995Smarius * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22226995Smarius * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23226995Smarius * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24226995Smarius * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25226995Smarius * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26226995Smarius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27226995Smarius * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28226995Smarius * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29226995Smarius * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30226995Smarius * POSSIBILITY OF SUCH DAMAGE. 31226995Smarius */ 32226995Smarius 33226995Smarius/* 34226995Smarius * Common module for bit-bang'ing the MII. 35226995Smarius */ 36226995Smarius 37226995Smarius#include <sys/cdefs.h> 38226995Smarius__FBSDID("$FreeBSD$"); 39226995Smarius 40226995Smarius#include <sys/param.h> 41226995Smarius#include <sys/systm.h> 42226995Smarius#include <sys/module.h> 43226995Smarius 44226995Smarius#include <dev/mii/mii.h> 45226995Smarius#include <dev/mii/mii_bitbang.h> 46226995Smarius 47226995SmariusMODULE_VERSION(mii_bitbang, 1); 48226995Smarius 49226995Smariusstatic void mii_bitbang_sendbits(device_t dev, mii_bitbang_ops_t ops, 50226995Smarius uint32_t data, int nbits); 51226995Smarius 52226995Smarius#define MWRITE(x) \ 53226995Smariusdo { \ 54226995Smarius ops->mbo_write(dev, (x)); \ 55226995Smarius DELAY(1); \ 56226995Smarius} while (/* CONSTCOND */ 0) 57226995Smarius 58226995Smarius#define MREAD ops->mbo_read(dev) 59226995Smarius 60226995Smarius#define MDO ops->mbo_bits[MII_BIT_MDO] 61226995Smarius#define MDI ops->mbo_bits[MII_BIT_MDI] 62226995Smarius#define MDC ops->mbo_bits[MII_BIT_MDC] 63226995Smarius#define MDIRPHY ops->mbo_bits[MII_BIT_DIR_HOST_PHY] 64226995Smarius#define MDIRHOST ops->mbo_bits[MII_BIT_DIR_PHY_HOST] 65226995Smarius 66226995Smarius/* 67226995Smarius * mii_bitbang_sync: 68226995Smarius * 69226995Smarius * Synchronize the MII. 70226995Smarius */ 71226995Smariusvoid 72226995Smariusmii_bitbang_sync(device_t dev, mii_bitbang_ops_t ops) 73226995Smarius{ 74226995Smarius int i; 75226995Smarius uint32_t v; 76226995Smarius 77226995Smarius v = MDIRPHY | MDO; 78226995Smarius 79226995Smarius MWRITE(v); 80226995Smarius for (i = 0; i < 32; i++) { 81226995Smarius MWRITE(v | MDC); 82226995Smarius MWRITE(v); 83226995Smarius } 84226995Smarius} 85226995Smarius 86226995Smarius/* 87226995Smarius * mii_bitbang_sendbits: 88226995Smarius * 89226995Smarius * Send a series of bits to the MII. 90226995Smarius */ 91226995Smariusstatic void 92226995Smariusmii_bitbang_sendbits(device_t dev, mii_bitbang_ops_t ops, uint32_t data, 93226995Smarius int nbits) 94226995Smarius{ 95226995Smarius int i; 96226995Smarius uint32_t v; 97226995Smarius 98226995Smarius v = MDIRPHY; 99226995Smarius MWRITE(v); 100226995Smarius 101226995Smarius for (i = 1 << (nbits - 1); i != 0; i >>= 1) { 102226995Smarius if (data & i) 103226995Smarius v |= MDO; 104226995Smarius else 105226995Smarius v &= ~MDO; 106226995Smarius MWRITE(v); 107226995Smarius MWRITE(v | MDC); 108226995Smarius MWRITE(v); 109226995Smarius } 110226995Smarius} 111226995Smarius 112226995Smarius/* 113226995Smarius * mii_bitbang_readreg: 114226995Smarius * 115226995Smarius * Read a PHY register by bit-bang'ing the MII. 116226995Smarius */ 117226995Smariusint 118226995Smariusmii_bitbang_readreg(device_t dev, mii_bitbang_ops_t ops, int phy, int reg) 119226995Smarius{ 120226995Smarius int i, error, val; 121226995Smarius 122226995Smarius mii_bitbang_sync(dev, ops); 123226995Smarius 124226995Smarius mii_bitbang_sendbits(dev, ops, MII_COMMAND_START, 2); 125226995Smarius mii_bitbang_sendbits(dev, ops, MII_COMMAND_READ, 2); 126226995Smarius mii_bitbang_sendbits(dev, ops, phy, 5); 127226995Smarius mii_bitbang_sendbits(dev, ops, reg, 5); 128226995Smarius 129226995Smarius /* Switch direction to PHY->host, without a clock transition. */ 130226995Smarius MWRITE(MDIRHOST); 131226995Smarius 132226995Smarius /* Turnaround clock. */ 133226995Smarius MWRITE(MDIRHOST | MDC); 134226995Smarius MWRITE(MDIRHOST); 135226995Smarius 136226995Smarius /* Check for error. */ 137226995Smarius error = MREAD & MDI; 138226995Smarius 139226995Smarius /* Idle clock. */ 140226995Smarius MWRITE(MDIRHOST | MDC); 141226995Smarius MWRITE(MDIRHOST); 142226995Smarius 143226995Smarius val = 0; 144226995Smarius for (i = 0; i < 16; i++) { 145226995Smarius val <<= 1; 146226995Smarius /* Read data prior to clock low-high transition. */ 147226995Smarius if (error == 0 && (MREAD & MDI) != 0) 148226995Smarius val |= 1; 149226995Smarius 150226995Smarius MWRITE(MDIRHOST | MDC); 151226995Smarius MWRITE(MDIRHOST); 152226995Smarius } 153226995Smarius 154226995Smarius /* Set direction to host->PHY, without a clock transition. */ 155226995Smarius MWRITE(MDIRPHY); 156226995Smarius 157226995Smarius return (error != 0 ? 0 : val); 158226995Smarius} 159226995Smarius 160226995Smarius/* 161226995Smarius * mii_bitbang_writereg: 162226995Smarius * 163226995Smarius * Write a PHY register by bit-bang'ing the MII. 164226995Smarius */ 165226995Smariusvoid 166226995Smariusmii_bitbang_writereg(device_t dev, mii_bitbang_ops_t ops, int phy, int reg, 167226995Smarius int val) 168226995Smarius{ 169226995Smarius 170226995Smarius mii_bitbang_sync(dev, ops); 171226995Smarius 172226995Smarius mii_bitbang_sendbits(dev, ops, MII_COMMAND_START, 2); 173226995Smarius mii_bitbang_sendbits(dev, ops, MII_COMMAND_WRITE, 2); 174226995Smarius mii_bitbang_sendbits(dev, ops, phy, 5); 175226995Smarius mii_bitbang_sendbits(dev, ops, reg, 5); 176226995Smarius mii_bitbang_sendbits(dev, ops, MII_COMMAND_ACK, 2); 177226995Smarius mii_bitbang_sendbits(dev, ops, val, 16); 178226995Smarius 179226995Smarius MWRITE(MDIRPHY); 180226995Smarius} 181