1 /* 2 * Copyright (C) 2004-2008 Freescale Semiconductor, Inc. 3 * TsiChung Liew (Tsi-Chung.Liew@freescale.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 #include <common.h> 25 #include <config.h> 26 #include <net.h> 27 #include <netdev.h> 28 29 #ifdef CONFIG_MCF547x_8x 30 #include <asm/fsl_mcdmafec.h> 31 #else 32 #include <asm/fec.h> 33 #endif 34 #include <asm/immap.h> 35 36 DECLARE_GLOBAL_DATA_PTR; 37 38 #if defined(CONFIG_CMD_NET) 39 #undef MII_DEBUG 40 #undef ET_DEBUG 41 42 /*extern int fecpin_setclear(struct eth_device *dev, int setclear);*/ 43 44 #if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_CMD_MII) 45 #include <miiphy.h> 46 47 /* Make MII read/write commands for the FEC. */ 48 #define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \ 49 (REG & 0x1f) << 18)) 50 #define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \ 51 (REG & 0x1f) << 18) | (VAL & 0xffff)) 52 53 #ifndef CONFIG_SYS_UNSPEC_PHYID 54 # define CONFIG_SYS_UNSPEC_PHYID 0 55 #endif 56 #ifndef CONFIG_SYS_UNSPEC_STRID 57 # define CONFIG_SYS_UNSPEC_STRID 0 58 #endif 59 60 #ifdef CONFIG_MCF547x_8x 61 typedef struct fec_info_dma FEC_INFO_T; 62 #define FEC_T fecdma_t 63 #else 64 typedef struct fec_info_s FEC_INFO_T; 65 #define FEC_T fec_t 66 #endif 67 68 typedef struct phy_info_struct { 69 u32 phyid; 70 char *strid; 71 } phy_info_t; 72 73 phy_info_t phyinfo[] = { 74 {0x0022561B, "AMD79C784VC"}, /* AMD 79C784VC */ 75 {0x00406322, "BCM5222"}, /* Broadcom 5222 */ 76 {0x02a80150, "Intel82555"}, /* Intel 82555 */ 77 {0x0016f870, "LSI80225"}, /* LSI 80225 */ 78 {0x0016f880, "LSI80225/B"}, /* LSI 80225/B */ 79 {0x78100000, "LXT970"}, /* LXT970 */ 80 {0x001378e0, "LXT971"}, /* LXT971 and 972 */ 81 {0x00221619, "KS8721BL"}, /* Micrel KS8721BL/SL */ 82 {0x00221512, "KSZ8041NL"}, /* Micrel KSZ8041NL */ 83 {0x20005CE1, "N83640"}, /* National 83640 */ 84 {0x20005C90, "N83848"}, /* National 83848 */ 85 {0x20005CA2, "N83849"}, /* National 83849 */ 86 {0x01814400, "QS6612"}, /* QS6612 */ 87 #if defined(CONFIG_SYS_UNSPEC_PHYID) && defined(CONFIG_SYS_UNSPEC_STRID) 88 {CONFIG_SYS_UNSPEC_PHYID, CONFIG_SYS_UNSPEC_STRID}, 89 #endif 90 {0, 0} 91 }; 92 93 /* 94 * mii_init -- Initialize the MII for MII command without ethernet 95 * This function is a subset of eth_init 96 */ 97 void mii_reset(FEC_INFO_T *info) 98 { 99 volatile FEC_T *fecp = (FEC_T *) (info->miibase); 100 int i; 101 102 fecp->ecr = FEC_ECR_RESET; 103 104 for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) { 105 udelay(1); 106 } 107 if (i == FEC_RESET_DELAY) 108 printf("FEC_RESET_DELAY timeout\n"); 109 } 110 111 /* send command to phy using mii, wait for result */ 112 uint mii_send(uint mii_cmd) 113 { 114 FEC_INFO_T *info; 115 volatile FEC_T *ep; 116 struct eth_device *dev; 117 uint mii_reply; 118 int j = 0; 119 120 /* retrieve from register structure */ 121 dev = eth_get_dev(); 122 info = dev->priv; 123 124 ep = (FEC_T *) info->miibase; 125 126 ep->mmfr = mii_cmd; /* command to phy */ 127 128 /* wait for mii complete */ 129 while (!(ep->eir & FEC_EIR_MII) && (j < MCFFEC_TOUT_LOOP)) { 130 udelay(1); 131 j++; 132 } 133 if (j >= MCFFEC_TOUT_LOOP) { 134 printf("MII not complete\n"); 135 return -1; 136 } 137 138 mii_reply = ep->mmfr; /* result from phy */ 139 ep->eir = FEC_EIR_MII; /* clear MII complete */ 140 #ifdef ET_DEBUG 141 printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n", 142 __FILE__, __LINE__, __FUNCTION__, mii_cmd, mii_reply); 143 #endif 144 145 return (mii_reply & 0xffff); /* data read from phy */ 146 } 147 #endif /* CONFIG_SYS_DISCOVER_PHY || (CONFIG_MII) */ 148 149 #if defined(CONFIG_SYS_DISCOVER_PHY) 150 int mii_discover_phy(struct eth_device *dev) 151 { 152 #define MAX_PHY_PASSES 11 153 FEC_INFO_T *info = dev->priv; 154 int phyaddr, pass; 155 uint phyno, phytype; 156 int i, found = 0; 157 158 if (info->phyname_init) 159 return info->phy_addr; 160 161 phyaddr = -1; /* didn't find a PHY yet */ 162 for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) { 163 if (pass > 1) { 164 /* PHY may need more time to recover from reset. 165 * The LXT970 needs 50ms typical, no maximum is 166 * specified, so wait 10ms before try again. 167 * With 11 passes this gives it 100ms to wake up. 168 */ 169 udelay(10000); /* wait 10ms */ 170 } 171 172 for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) { 173 174 phytype = mii_send(mk_mii_read(phyno, MII_PHYSID1)); 175 #ifdef ET_DEBUG 176 printf("PHY type 0x%x pass %d type\n", phytype, pass); 177 #endif 178 if (phytype == 0xffff) 179 continue; 180 phyaddr = phyno; 181 phytype <<= 16; 182 phytype |= 183 mii_send(mk_mii_read(phyno, MII_PHYSID2)); 184 185 #ifdef ET_DEBUG 186 printf("PHY @ 0x%x pass %d\n", phyno, pass); 187 #endif 188 189 for (i = 0; (i < (sizeof(phyinfo) / sizeof(phy_info_t))) 190 && (phyinfo[i].phyid != 0); i++) { 191 if (phyinfo[i].phyid == phytype) { 192 #ifdef ET_DEBUG 193 printf("phyid %x - %s\n", 194 phyinfo[i].phyid, 195 phyinfo[i].strid); 196 #endif 197 strcpy(info->phy_name, phyinfo[i].strid); 198 info->phyname_init = 1; 199 found = 1; 200 break; 201 } 202 } 203 204 if (!found) { 205 #ifdef ET_DEBUG 206 printf("0x%08x\n", phytype); 207 #endif 208 strcpy(info->phy_name, "unknown"); 209 info->phyname_init = 1; 210 break; 211 } 212 } 213 } 214 215 if (phyaddr < 0) 216 printf("No PHY device found.\n"); 217 218 return phyaddr; 219 } 220 #endif /* CONFIG_SYS_DISCOVER_PHY */ 221 222 void mii_init(void) __attribute__((weak,alias("__mii_init"))); 223 224 void __mii_init(void) 225 { 226 FEC_INFO_T *info; 227 volatile FEC_T *fecp; 228 struct eth_device *dev; 229 int miispd = 0, i = 0; 230 u16 status = 0; 231 u16 linkgood = 0; 232 233 /* retrieve from register structure */ 234 dev = eth_get_dev(); 235 info = dev->priv; 236 237 fecp = (FEC_T *) info->miibase; 238 239 fecpin_setclear(dev, 1); 240 241 mii_reset(info); 242 243 /* We use strictly polling mode only */ 244 fecp->eimr = 0; 245 246 /* Clear any pending interrupt */ 247 fecp->eir = 0xffffffff; 248 249 /* Set MII speed */ 250 miispd = (gd->bus_clk / 1000000) / 5; 251 fecp->mscr = miispd << 1; 252 253 info->phy_addr = mii_discover_phy(dev); 254 255 while (i < MCFFEC_TOUT_LOOP) { 256 status = 0; 257 i++; 258 /* Read PHY control register */ 259 miiphy_read(dev->name, info->phy_addr, MII_BMCR, &status); 260 261 /* If phy set to autonegotiate, wait for autonegotiation done, 262 * if phy is not autonegotiating, just wait for link up. 263 */ 264 if ((status & BMCR_ANENABLE) == BMCR_ANENABLE) { 265 linkgood = (BMSR_ANEGCOMPLETE | BMSR_LSTATUS); 266 } else { 267 linkgood = BMSR_LSTATUS; 268 } 269 /* Read PHY status register */ 270 miiphy_read(dev->name, info->phy_addr, MII_BMSR, &status); 271 if ((status & linkgood) == linkgood) 272 break; 273 274 udelay(1); 275 } 276 if (i >= MCFFEC_TOUT_LOOP) { 277 printf("Link UP timeout\n"); 278 } 279 280 /* adapt to the duplex and speed settings of the phy */ 281 info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16; 282 info->dup_spd |= miiphy_speed(dev->name, info->phy_addr); 283 } 284 285 /* 286 * Read and write a MII PHY register, routines used by MII Utilities 287 * 288 * FIXME: These routines are expected to return 0 on success, but mii_send 289 * does _not_ return an error code. Maybe 0xFFFF means error, i.e. 290 * no PHY connected... 291 * For now always return 0. 292 * FIXME: These routines only work after calling eth_init() at least once! 293 * Otherwise they hang in mii_send() !!! Sorry! 294 */ 295 296 int mcffec_miiphy_read(const char *devname, unsigned char addr, unsigned char reg, 297 unsigned short *value) 298 { 299 short rdreg; /* register working value */ 300 301 #ifdef MII_DEBUG 302 printf("miiphy_read(0x%x) @ 0x%x = ", reg, addr); 303 #endif 304 rdreg = mii_send(mk_mii_read(addr, reg)); 305 306 *value = rdreg; 307 308 #ifdef MII_DEBUG 309 printf("0x%04x\n", *value); 310 #endif 311 312 return 0; 313 } 314 315 int mcffec_miiphy_write(const char *devname, unsigned char addr, unsigned char reg, 316 unsigned short value) 317 { 318 short rdreg; /* register working value */ 319 320 #ifdef MII_DEBUG 321 printf("miiphy_write(0x%x) @ 0x%x = ", reg, addr); 322 #endif 323 324 rdreg = mii_send(mk_mii_write(addr, reg, value)); 325 326 #ifdef MII_DEBUG 327 printf("0x%04x\n", value); 328 #endif 329 330 return 0; 331 } 332 333 #endif /* CONFIG_CMD_NET */ 334