1 /* 2 * (C) Copyright 2001 3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 /* 25 * This provides a bit-banged interface to the ethernet MII management 26 * channel. 27 */ 28 29 #include <common.h> 30 #include <miiphy.h> 31 32 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) 33 34 /***************************************************************************** 35 * 36 * Read the OUI, manufacture's model number, and revision number. 37 * 38 * OUI: 22 bits (unsigned int) 39 * Model: 6 bits (unsigned char) 40 * Revision: 4 bits (unsigned char) 41 * 42 * Returns: 43 * 0 on success 44 */ 45 int miiphy_info (unsigned char addr, 46 unsigned int *oui, 47 unsigned char *model, unsigned char *rev) 48 { 49 unsigned int reg = 0; 50 unsigned short tmp; 51 52 if (miiphy_read (addr, PHY_PHYIDR2, &tmp) != 0) { 53 #ifdef DEBUG 54 puts ("PHY ID register 2 read failed\n"); 55 #endif 56 return (-1); 57 } 58 reg = tmp; 59 60 #ifdef DEBUG 61 printf ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg); 62 #endif 63 if (reg == 0xFFFF) { 64 /* No physical device present at this address */ 65 return (-1); 66 } 67 68 if (miiphy_read (addr, PHY_PHYIDR1, &tmp) != 0) { 69 #ifdef DEBUG 70 puts ("PHY ID register 1 read failed\n"); 71 #endif 72 return (-1); 73 } 74 reg |= tmp << 16; 75 #ifdef DEBUG 76 printf ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg); 77 #endif 78 *oui = ( reg >> 10); 79 *model = (unsigned char) ((reg >> 4) & 0x0000003F); 80 *rev = (unsigned char) ( reg & 0x0000000F); 81 return (0); 82 } 83 84 85 /***************************************************************************** 86 * 87 * Reset the PHY. 88 * Returns: 89 * 0 on success 90 */ 91 int miiphy_reset (unsigned char addr) 92 { 93 unsigned short reg; 94 int loop_cnt; 95 96 if (miiphy_read (addr, PHY_BMCR, ®) != 0) { 97 #ifdef DEBUG 98 printf ("PHY status read failed\n"); 99 #endif 100 return (-1); 101 } 102 if (miiphy_write (addr, PHY_BMCR, reg | 0x8000) != 0) { 103 #ifdef DEBUG 104 puts ("PHY reset failed\n"); 105 #endif 106 return (-1); 107 } 108 #ifdef CONFIG_PHY_RESET_DELAY 109 udelay (CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */ 110 #endif 111 /* 112 * Poll the control register for the reset bit to go to 0 (it is 113 * auto-clearing). This should happen within 0.5 seconds per the 114 * IEEE spec. 115 */ 116 loop_cnt = 0; 117 reg = 0x8000; 118 while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) { 119 if (miiphy_read (addr, PHY_BMCR, ®) != 0) { 120 # ifdef DEBUG 121 puts ("PHY status read failed\n"); 122 # endif 123 return (-1); 124 } 125 } 126 if ((reg & 0x8000) == 0) { 127 return (0); 128 } else { 129 puts ("PHY reset timed out\n"); 130 return (-1); 131 } 132 return (0); 133 } 134 135 136 /***************************************************************************** 137 * 138 * Determine the ethernet speed (10/100). 139 */ 140 int miiphy_speed (unsigned char addr) 141 { 142 unsigned short reg; 143 144 #if defined(CONFIG_PHY_GIGE) 145 if (miiphy_read (addr, PHY_1000BTSR, ®)) { 146 printf ("PHY 1000BT Status read failed\n"); 147 } else { 148 if (reg != 0xFFFF) { 149 if ((reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) !=0) { 150 return (_1000BASET); 151 } 152 } 153 } 154 #endif /* CONFIG_PHY_GIGE */ 155 156 /* Check Basic Management Control Register first. */ 157 if (miiphy_read (addr, PHY_BMCR, ®)) { 158 puts ("PHY speed read failed, assuming 10bT\n"); 159 return (_10BASET); 160 } 161 /* Check if auto-negotiation is on. */ 162 if ((reg & PHY_BMCR_AUTON) != 0) { 163 /* Get auto-negotiation results. */ 164 if (miiphy_read (addr, PHY_ANLPAR, ®)) { 165 puts ("PHY AN speed read failed, assuming 10bT\n"); 166 return (_10BASET); 167 } 168 if ((reg & PHY_ANLPAR_100) != 0) { 169 return (_100BASET); 170 } else { 171 return (_10BASET); 172 } 173 } 174 /* Get speed from basic control settings. */ 175 else if (reg & PHY_BMCR_100MB) { 176 return (_100BASET); 177 } else { 178 return (_10BASET); 179 } 180 181 } 182 183 184 /***************************************************************************** 185 * 186 * Determine full/half duplex. 187 */ 188 int miiphy_duplex (unsigned char addr) 189 { 190 unsigned short reg; 191 192 #if defined(CONFIG_PHY_GIGE) 193 if (miiphy_read (addr, PHY_1000BTSR, ®)) { 194 printf ("PHY 1000BT Status read failed\n"); 195 } else { 196 if ( (reg != 0xFFFF) && 197 (reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) ) { 198 if ((reg & PHY_1000BTSR_1000FD) !=0) { 199 return (FULL); 200 } else { 201 return (HALF); 202 } 203 } 204 } 205 #endif /* CONFIG_PHY_GIGE */ 206 207 /* Check Basic Management Control Register first. */ 208 if (miiphy_read (addr, PHY_BMCR, ®)) { 209 puts ("PHY duplex read failed, assuming half duplex\n"); 210 return (HALF); 211 } 212 /* Check if auto-negotiation is on. */ 213 if ((reg & PHY_BMCR_AUTON) != 0) { 214 /* Get auto-negotiation results. */ 215 if (miiphy_read (addr, PHY_ANLPAR, ®)) { 216 puts ("PHY AN duplex read failed, assuming half duplex\n"); 217 return (HALF); 218 } 219 220 if ((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) { 221 return (FULL); 222 } else { 223 return (HALF); 224 } 225 } 226 /* Get speed from basic control settings. */ 227 else if (reg & PHY_BMCR_DPLX) { 228 return (FULL); 229 } else { 230 return (HALF); 231 } 232 233 } 234 235 #ifdef CFG_FAULT_ECHO_LINK_DOWN 236 /***************************************************************************** 237 * 238 * Determine link status 239 */ 240 int miiphy_link (unsigned char addr) 241 { 242 unsigned short reg; 243 244 /* dummy read; needed to latch some phys */ 245 (void)miiphy_read(addr, PHY_BMSR, ®); 246 if (miiphy_read (addr, PHY_BMSR, ®)) { 247 puts ("PHY_BMSR read failed, assuming no link\n"); 248 return (0); 249 } 250 251 /* Determine if a link is active */ 252 if ((reg & PHY_BMSR_LS) != 0) { 253 return (1); 254 } else { 255 return (0); 256 } 257 } 258 #endif 259 260 #endif /* CONFIG_MII || (CONFIG_COMMANDS & CFG_CMD_MII) */ 261