iPXE
mii_bit.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2018 Sylvie Barlow <sylvie.c.barlow@gmail.com>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdint.h>
00027 #include <unistd.h>
00028 #include <ipxe/bitbash.h>
00029 #include <ipxe/mii_bit.h>
00030 
00031 /**
00032  * Transfer bits over MII bit-bashing interface
00033  *
00034  * @v basher            Bit basher
00035  * @v mask              Mask
00036  * @v write             Data to write
00037  * @ret read            Data read
00038  */
00039 static uint32_t mii_bit_xfer ( struct bit_basher *basher,
00040                                uint32_t mask, uint32_t write ) {
00041         uint32_t read = 0;
00042         int bit;
00043 
00044         for ( ; mask ; mask >>= 1 ) {
00045 
00046                 /* Delay */
00047                 udelay ( 1 );
00048 
00049                 /* Write bit to basher */
00050                 write_bit ( basher, MII_BIT_MDIO, ( write & mask ) );
00051 
00052                 /* Read bit from basher */
00053                 bit = read_bit ( basher, MII_BIT_MDIO );
00054                 read <<= 1;
00055                 read |= ( bit & 1 );
00056 
00057                 /* Set clock high */
00058                 write_bit ( basher, MII_BIT_MDC, 1 );
00059 
00060                 /* Delay */
00061                 udelay ( 1 );
00062 
00063                 /* Set clock low */
00064                 write_bit ( basher, MII_BIT_MDC, 0 );
00065         }
00066         return read;
00067 }
00068 
00069 /**
00070  * Read or write via MII bit-bashing interface
00071  *
00072  * @v basher            Bit basher
00073  * @v phy               PHY address
00074  * @v reg               Register address
00075  * @v data              Data to write
00076  * @v cmd               Command
00077  * @ret data            Data read
00078  */
00079 static unsigned int mii_bit_rw ( struct bit_basher *basher,
00080                                  unsigned int phy, unsigned int reg,
00081                                  unsigned int data, unsigned int cmd ) {
00082 
00083         /* Initiate drive for write */
00084         write_bit ( basher, MII_BIT_DRIVE, 1 );
00085 
00086         /* Write start */
00087         mii_bit_xfer ( basher, MII_BIT_START_MASK, MII_BIT_START );
00088 
00089         /* Write command */
00090         mii_bit_xfer ( basher, MII_BIT_CMD_MASK, cmd );
00091 
00092         /* Write PHY address */
00093         mii_bit_xfer ( basher, MII_BIT_PHY_MASK, phy );
00094 
00095         /* Write register address */
00096         mii_bit_xfer ( basher, MII_BIT_REG_MASK, reg );
00097 
00098         /* Switch drive to read if applicable */
00099         write_bit ( basher, MII_BIT_DRIVE, ( cmd & MII_BIT_CMD_RW ) );
00100 
00101         /* Allow space for turnaround */
00102         mii_bit_xfer ( basher, MII_BIT_SWITCH_MASK, MII_BIT_SWITCH );
00103 
00104         /* Read or write data */
00105         data = mii_bit_xfer (basher, MII_BIT_DATA_MASK, data );
00106 
00107         /* Initiate drive for read */
00108         write_bit ( basher, MII_BIT_DRIVE, 0 );
00109 
00110         return data;
00111 }
00112 
00113 /**
00114  * Read from MII register
00115  *
00116  * @v mdio              MII interface
00117  * @v phy               PHY address
00118  * @v reg               Register address
00119  * @ret data            Data read, or negative error
00120  */
00121 static int mii_bit_read ( struct mii_interface *mdio, unsigned int phy,
00122                           unsigned int reg ) {
00123         struct mii_bit_basher *miibit =
00124                 container_of ( mdio, struct mii_bit_basher, mdio );
00125         struct bit_basher *basher = &miibit->basher;
00126 
00127         return mii_bit_rw ( basher, phy, reg, 0, MII_BIT_CMD_READ );
00128 }
00129 
00130 /**
00131  * Write to MII register
00132  *
00133  * @v mdio              MII interface
00134  * @v phy               PHY address
00135  * @v reg               Register address
00136  * @v data              Data to write
00137  * @ret rc              Return status code
00138  */
00139 static int mii_bit_write ( struct mii_interface *mdio, unsigned int phy,
00140                            unsigned int reg, unsigned int data ) {
00141         struct mii_bit_basher *miibit =
00142                 container_of ( mdio, struct mii_bit_basher, mdio );
00143         struct bit_basher *basher = &miibit->basher;
00144 
00145         mii_bit_rw ( basher, phy, reg, data, MII_BIT_CMD_WRITE );
00146         return 0;
00147 }
00148 
00149 /** MII bit basher operations */
00150 static struct mii_operations mii_bit_op = {
00151         .read = mii_bit_read,
00152         .write = mii_bit_write,
00153 };
00154 
00155 /**
00156  * Initialise bit-bashing interface
00157  *
00158  * @v miibit            MII bit basher
00159  */
00160 void init_mii_bit_basher ( struct mii_bit_basher *miibit ) {
00161         mdio_init ( &miibit->mdio, &mii_bit_op );
00162 };