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_write (addr, PHY_BMCR, 0x8000) != 0) { 97 #ifdef DEBUG 98 puts ("PHY reset failed\n"); 99 #endif 100 return (-1); 101 } 102 #ifdef CONFIG_PHY_RESET_DELAY 103 udelay (CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */ 104 #endif 105 /* 106 * Poll the control register for the reset bit to go to 0 (it is 107 * auto-clearing). This should happen within 0.5 seconds per the 108 * IEEE spec. 109 */ 110 loop_cnt = 0; 111 reg = 0x8000; 112 while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) { 113 if (miiphy_read (addr, PHY_BMCR, ®) != 0) { 114 # ifdef DEBUG 115 puts ("PHY status read failed\n"); 116 # endif 117 return (-1); 118 } 119 } 120 if ((reg & 0x8000) == 0) { 121 return (0); 122 } else { 123 puts ("PHY reset timed out\n"); 124 return (-1); 125 } 126 return (0); 127 } 128 129 130 /***************************************************************************** 131 * 132 * Determine the ethernet speed (10/100). 133 */ 134 int miiphy_speed (unsigned char addr) 135 { 136 unsigned short reg; 137 138 #if defined(CONFIG_PHY_GIGE) 139 if (miiphy_read (addr, PHY_1000BTSR, ®)) { 140 printf ("PHY 1000BT Status read failed\n"); 141 } else { 142 if (reg != 0xFFFF) { 143 if ((reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) !=0) { 144 return (_1000BASET); 145 } 146 } 147 } 148 #endif /* CONFIG_PHY_GIGE */ 149 150 /* Check Basic Management Control Register first. */ 151 if (miiphy_read (addr, PHY_BMCR, ®)) { 152 puts ("PHY speed read failed, assuming 10bT\n"); 153 return (_10BASET); 154 } 155 /* Check if auto-negotiation is on. */ 156 if ((reg & PHY_BMCR_AUTON) != 0) { 157 /* Get auto-negotiation results. */ 158 if (miiphy_read (addr, PHY_ANLPAR, ®)) { 159 puts ("PHY AN speed read failed, assuming 10bT\n"); 160 return (_10BASET); 161 } 162 if ((reg & PHY_ANLPAR_100) != 0) { 163 return (_100BASET); 164 } else { 165 return (_10BASET); 166 } 167 } 168 /* Get speed from basic control settings. */ 169 else if (reg & PHY_BMCR_100MB) { 170 return (_100BASET); 171 } else { 172 return (_10BASET); 173 } 174 175 } 176 177 178 /***************************************************************************** 179 * 180 * Determine full/half duplex. 181 */ 182 int miiphy_duplex (unsigned char addr) 183 { 184 unsigned short reg; 185 186 #if defined(CONFIG_PHY_GIGE) 187 if (miiphy_read (addr, PHY_1000BTSR, ®)) { 188 printf ("PHY 1000BT Status read failed\n"); 189 } else { 190 if ( (reg != 0xFFFF) && 191 (reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) ) { 192 if ((reg & PHY_1000BTSR_1000FD) !=0) { 193 return (FULL); 194 } else { 195 return (HALF); 196 } 197 } 198 } 199 #endif /* CONFIG_PHY_GIGE */ 200 201 /* Check Basic Management Control Register first. */ 202 if (miiphy_read (addr, PHY_BMCR, ®)) { 203 puts ("PHY duplex read failed, assuming half duplex\n"); 204 return (HALF); 205 } 206 /* Check if auto-negotiation is on. */ 207 if ((reg & PHY_BMCR_AUTON) != 0) { 208 /* Get auto-negotiation results. */ 209 if (miiphy_read (addr, PHY_ANLPAR, ®)) { 210 puts ("PHY AN duplex read failed, assuming half duplex\n"); 211 return (HALF); 212 } 213 214 if ((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) { 215 return (FULL); 216 } else { 217 return (HALF); 218 } 219 } 220 /* Get speed from basic control settings. */ 221 else if (reg & PHY_BMCR_DPLX) { 222 return (FULL); 223 } else { 224 return (HALF); 225 } 226 227 } 228 229 #ifdef CFG_FAULT_ECHO_LINK_DOWN 230 /***************************************************************************** 231 * 232 * Determine link status 233 */ 234 int miiphy_link (unsigned char addr) 235 { 236 unsigned short reg; 237 238 /* dummy read; needed to latch some phys */ 239 (void)miiphy_read(addr, PHY_BMSR, ®); 240 if (miiphy_read (addr, PHY_BMSR, ®)) { 241 puts ("PHY_BMSR read failed, assuming no link\n"); 242 return (0); 243 } 244 245 /* Determine if a link is active */ 246 if ((reg & PHY_BMSR_LS) != 0) { 247 return (1); 248 } else { 249 return (0); 250 } 251 } 252 #endif 253 254 #endif /* CONFIG_MII || (CONFIG_COMMANDS & CFG_CMD_MII) */ 255