Wolfgang Denk | 52744b4 | 2013-07-28 22:12:45 +0200 | [diff] [blame] | 1 | /* |
Wolfgang Denk | 815c967 | 2013-09-17 11:24:06 +0200 | [diff] [blame] | 2 | * SPDX-License-Identifier: GPL-2.0 IBM-pibs |
Wolfgang Denk | 52744b4 | 2013-07-28 22:12:45 +0200 | [diff] [blame] | 3 | */ |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 4 | /*-----------------------------------------------------------------------------+ |
| 5 | | |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 6 | | File Name: miiphy.c |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 7 | | |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 8 | | Function: This module has utilities for accessing the MII PHY through |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 9 | | the EMAC3 macro. |
| 10 | | |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 11 | | Author: Mark Wisner |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 12 | | |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 13 | +-----------------------------------------------------------------------------*/ |
| 14 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 15 | /* define DEBUG for debugging output (obviously ;-)) */ |
| 16 | #if 0 |
| 17 | #define DEBUG |
| 18 | #endif |
| 19 | |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 20 | #include <common.h> |
| 21 | #include <asm/processor.h> |
Stefan Roese | 69710095 | 2007-10-23 14:03:17 +0200 | [diff] [blame] | 22 | #include <asm/io.h> |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 23 | #include <ppc_asm.tmpl> |
| 24 | #include <commproc.h> |
Stefan Roese | 247e9d7 | 2010-09-09 19:18:00 +0200 | [diff] [blame] | 25 | #include <asm/ppc4xx-emac.h> |
| 26 | #include <asm/ppc4xx-mal.h> |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 27 | #include <miiphy.h> |
| 28 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 29 | #if !defined(CONFIG_PHY_CLK_FREQ) |
| 30 | #define CONFIG_PHY_CLK_FREQ 0 |
| 31 | #endif |
| 32 | |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 33 | /***********************************************************/ |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 34 | /* Dump out to the screen PHY regs */ |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 35 | /***********************************************************/ |
| 36 | |
Marian Balakowicz | aab8c49 | 2005-10-28 22:30:33 +0200 | [diff] [blame] | 37 | void miiphy_dump (char *devname, unsigned char addr) |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 38 | { |
| 39 | unsigned long i; |
| 40 | unsigned short data; |
| 41 | |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 42 | for (i = 0; i < 0x1A; i++) { |
Marian Balakowicz | aab8c49 | 2005-10-28 22:30:33 +0200 | [diff] [blame] | 43 | if (miiphy_read (devname, addr, i, &data)) { |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 44 | printf ("read error for reg %lx\n", i); |
| 45 | return; |
| 46 | } |
| 47 | printf ("Phy reg %lx ==> %4x\n", i, data); |
| 48 | |
| 49 | /* jump to the next set of regs */ |
| 50 | if (i == 0x07) |
| 51 | i = 0x0f; |
| 52 | |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 53 | } /* end for loop */ |
| 54 | } /* end dump */ |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 55 | |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 56 | /***********************************************************/ |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 57 | /* (Re)start autonegotiation */ |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 58 | /***********************************************************/ |
Marian Balakowicz | aab8c49 | 2005-10-28 22:30:33 +0200 | [diff] [blame] | 59 | int phy_setup_aneg (char *devname, unsigned char addr) |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 60 | { |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 61 | u16 bmcr; |
| 62 | |
| 63 | #if defined(CONFIG_PHY_DYNAMIC_ANEG) |
| 64 | /* |
| 65 | * Set up advertisement based on capablilities reported by the PHY. |
| 66 | * This should work for both copper and fiber. |
| 67 | */ |
| 68 | u16 bmsr; |
| 69 | #if defined(CONFIG_PHY_GIGE) |
| 70 | u16 exsr = 0x0000; |
| 71 | #endif |
| 72 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 73 | miiphy_read (devname, addr, MII_BMSR, &bmsr); |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 74 | |
| 75 | #if defined(CONFIG_PHY_GIGE) |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 76 | if (bmsr & BMSR_ESTATEN) |
| 77 | miiphy_read (devname, addr, MII_ESTATUS, &exsr); |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 78 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 79 | if (exsr & (ESTATUS_1000XF | ESTATUS_1000XH)) { |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 80 | /* 1000BASE-X */ |
| 81 | u16 anar = 0x0000; |
| 82 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 83 | if (exsr & ESTATUS_1000XF) |
Stefan Roese | 772696c | 2011-01-10 12:56:13 +0100 | [diff] [blame] | 84 | anar |= ADVERTISE_1000XFULL; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 85 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 86 | if (exsr & ESTATUS_1000XH) |
| 87 | anar |= ADVERTISE_1000XHALF; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 88 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 89 | miiphy_write (devname, addr, MII_ADVERTISE, anar); |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 90 | } else |
| 91 | #endif |
| 92 | { |
| 93 | u16 anar, btcr; |
| 94 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 95 | miiphy_read (devname, addr, MII_ADVERTISE, &anar); |
| 96 | anar &= ~(0x5000 | LPA_100BASE4 | LPA_100FULL | |
| 97 | LPA_100HALF | LPA_10FULL | LPA_10HALF); |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 98 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 99 | miiphy_read (devname, addr, MII_CTRL1000, &btcr); |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 100 | btcr &= ~(0x00FF | PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD); |
| 101 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 102 | if (bmsr & BMSR_100BASE4) |
| 103 | anar |= LPA_100BASE4; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 104 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 105 | if (bmsr & BMSR_100FULL) |
| 106 | anar |= LPA_100FULL; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 107 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 108 | if (bmsr & BMSR_100HALF) |
| 109 | anar |= LPA_100HALF; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 110 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 111 | if (bmsr & BMSR_10FULL) |
| 112 | anar |= LPA_10FULL; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 113 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 114 | if (bmsr & BMSR_10HALF) |
| 115 | anar |= LPA_10HALF; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 116 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 117 | miiphy_write (devname, addr, MII_ADVERTISE, anar); |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 118 | |
| 119 | #if defined(CONFIG_PHY_GIGE) |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 120 | if (exsr & ESTATUS_1000_TFULL) |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 121 | btcr |= PHY_1000BTCR_1000FD; |
| 122 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 123 | if (exsr & ESTATUS_1000_THALF) |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 124 | btcr |= PHY_1000BTCR_1000HD; |
| 125 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 126 | miiphy_write (devname, addr, MII_CTRL1000, btcr); |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 127 | #endif |
| 128 | } |
| 129 | |
| 130 | #else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */ |
| 131 | /* |
| 132 | * Set up standard advertisement |
| 133 | */ |
| 134 | u16 adv; |
| 135 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 136 | miiphy_read (devname, addr, MII_ADVERTISE, &adv); |
| 137 | adv |= (LPA_LPACK | LPA_100FULL | LPA_100HALF | |
| 138 | LPA_10FULL | LPA_10HALF); |
| 139 | miiphy_write (devname, addr, MII_ADVERTISE, adv); |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 140 | |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 141 | miiphy_read (devname, addr, MII_CTRL1000, &adv); |
Marian Balakowicz | 49d0eee | 2006-06-30 16:30:46 +0200 | [diff] [blame] | 142 | adv |= (0x0300); |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 143 | miiphy_write (devname, addr, MII_CTRL1000, adv); |
Marian Balakowicz | 49d0eee | 2006-06-30 16:30:46 +0200 | [diff] [blame] | 144 | |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 145 | #endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */ |
| 146 | |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 147 | /* Start/Restart aneg */ |
Mike Frysinger | d63ee71 | 2010-12-23 15:40:12 -0500 | [diff] [blame] | 148 | miiphy_read (devname, addr, MII_BMCR, &bmcr); |
| 149 | bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); |
| 150 | miiphy_write (devname, addr, MII_BMCR, bmcr); |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 151 | |
| 152 | return 0; |
| 153 | } |
| 154 | |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 155 | /***********************************************************/ |
| 156 | /* read a phy reg and return the value with a rc */ |
| 157 | /***********************************************************/ |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 158 | /* AMCC_TODO: |
| 159 | * Find out of the choice for the emac for MDIO is from the bridges, |
| 160 | * i.e. ZMII or RGMII as approporiate. If the bridges are not used |
| 161 | * to determine the emac for MDIO, then is the SDR0_ETH_CFG[MDIO_SEL] |
| 162 | * used? If so, then this routine below does not apply to the 460EX/GT. |
| 163 | * |
| 164 | * sr: Currently on 460EX only EMAC0 works with MDIO, so we always |
| 165 | * return EMAC0 offset here |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 166 | * vg: For 460EX/460GT if internal GPCS PHY address is specified |
| 167 | * return appropriate EMAC offset |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 168 | */ |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 169 | unsigned int miiphy_getemac_offset(u8 addr) |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 170 | { |
Mike Frysinger | a23230c | 2011-10-02 10:01:27 +0000 | [diff] [blame] | 171 | #if defined(CONFIG_440) && \ |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 172 | !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ |
Mike Frysinger | a23230c | 2011-10-02 10:01:27 +0000 | [diff] [blame] | 173 | !defined(CONFIG_460EX) && !defined(CONFIG_460GT) |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 174 | unsigned long zmii; |
| 175 | unsigned long eoffset; |
| 176 | |
| 177 | /* Need to find out which mdi port we're using */ |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 178 | zmii = in_be32((void *)ZMII0_FER); |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 179 | |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 180 | if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0))) |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 181 | /* using port 0 */ |
| 182 | eoffset = 0; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 183 | |
| 184 | else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1))) |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 185 | /* using port 1 */ |
| 186 | eoffset = 0x100; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 187 | |
| 188 | else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2))) |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 189 | /* using port 2 */ |
| 190 | eoffset = 0x400; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 191 | |
| 192 | else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3))) |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 193 | /* using port 3 */ |
| 194 | eoffset = 0x600; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 195 | |
| 196 | else { |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 197 | /* None of the mdi ports are enabled! */ |
| 198 | /* enable port 0 */ |
| 199 | zmii |= ZMII_FER_MDI << ZMII_FER_V (0); |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 200 | out_be32((void *)ZMII0_FER, zmii); |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 201 | eoffset = 0; |
| 202 | /* need to soft reset port 0 */ |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 203 | zmii = in_be32((void *)EMAC0_MR0); |
| 204 | zmii |= EMAC_MR0_SRST; |
| 205 | out_be32((void *)EMAC0_MR0, zmii); |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | return (eoffset); |
| 209 | #else |
Stefan Roese | 153b3e2 | 2007-10-05 17:10:59 +0200 | [diff] [blame] | 210 | |
Mike Frysinger | a23230c | 2011-10-02 10:01:27 +0000 | [diff] [blame] | 211 | #if defined(CONFIG_405EX) |
Stefan Roese | 153b3e2 | 2007-10-05 17:10:59 +0200 | [diff] [blame] | 212 | unsigned long rgmii; |
| 213 | int devnum = 1; |
| 214 | |
Stefan Roese | 69710095 | 2007-10-23 14:03:17 +0200 | [diff] [blame] | 215 | rgmii = in_be32((void *)RGMII_FER); |
Stefan Roese | 153b3e2 | 2007-10-05 17:10:59 +0200 | [diff] [blame] | 216 | if (rgmii & (1 << (19 - devnum))) |
| 217 | return 0x100; |
| 218 | #endif |
| 219 | |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 220 | #if defined(CONFIG_460EX) || defined(CONFIG_460GT) |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 221 | u32 eoffset = 0; |
| 222 | |
| 223 | switch (addr) { |
| 224 | #if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR) |
| 225 | case CONFIG_GPCS_PHY1_ADDR: |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 226 | if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x100))) |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 227 | eoffset = 0x100; |
| 228 | break; |
| 229 | #endif |
| 230 | #if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR) |
| 231 | case CONFIG_GPCS_PHY2_ADDR: |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 232 | if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x300))) |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 233 | eoffset = 0x300; |
| 234 | break; |
| 235 | #endif |
| 236 | #if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR) |
| 237 | case CONFIG_GPCS_PHY3_ADDR: |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 238 | if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x400))) |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 239 | eoffset = 0x400; |
| 240 | break; |
| 241 | #endif |
| 242 | default: |
| 243 | eoffset = 0; |
| 244 | break; |
| 245 | } |
| 246 | return eoffset; |
| 247 | #endif |
| 248 | |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 249 | return 0; |
| 250 | #endif |
| 251 | } |
| 252 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 253 | static int emac_miiphy_wait(u32 emac_reg) |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 254 | { |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 255 | u32 sta_reg; |
| 256 | int i; |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 257 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 258 | /* wait for completion */ |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 259 | i = 0; |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 260 | do { |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 261 | sta_reg = in_be32((void *)EMAC0_STACR + emac_reg); |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 262 | if (i++ > 5) { |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 263 | debug("%s [%d]: Timeout! EMAC0_STACR=0x%0x\n", __func__, |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 264 | __LINE__, sta_reg); |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 265 | return -1; |
| 266 | } |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 267 | udelay(10); |
| 268 | } while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK); |
| 269 | |
| 270 | return 0; |
| 271 | } |
| 272 | |
| 273 | static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value) |
| 274 | { |
| 275 | u32 emac_reg; |
| 276 | u32 sta_reg; |
| 277 | |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 278 | emac_reg = miiphy_getemac_offset(addr); |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 279 | |
| 280 | /* wait for completion */ |
| 281 | if (emac_miiphy_wait(emac_reg) != 0) |
| 282 | return -1; |
| 283 | |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 284 | sta_reg = reg; /* reg address */ |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 285 | |
Wolfgang Denk | af0501a | 2008-10-19 02:35:50 +0200 | [diff] [blame] | 286 | /* set clock (50MHz) and read flags */ |
Stefan Roese | 42fbddd | 2006-09-07 11:51:23 +0200 | [diff] [blame] | 287 | #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ |
Stefan Roese | 153b3e2 | 2007-10-05 17:10:59 +0200 | [diff] [blame] | 288 | defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 289 | defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ |
Stefan Roese | 153b3e2 | 2007-10-05 17:10:59 +0200 | [diff] [blame] | 290 | defined(CONFIG_405EX) |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 291 | #if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 292 | sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | cmd; |
Marian Balakowicz | 49d0eee | 2006-06-30 16:30:46 +0200 | [diff] [blame] | 293 | #else |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 294 | sta_reg |= cmd; |
Marian Balakowicz | 49d0eee | 2006-06-30 16:30:46 +0200 | [diff] [blame] | 295 | #endif |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 296 | #else |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 297 | sta_reg = (sta_reg | cmd) & ~EMAC_STACR_CLK_100MHZ; |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 298 | #endif |
| 299 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 300 | /* Some boards (mainly 405EP based) define the PHY clock freqency fixed */ |
wdenk | 232fe0b | 2003-09-02 22:48:03 +0000 | [diff] [blame] | 301 | sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 302 | sta_reg = sta_reg | ((u32)addr << 5); /* Phy address */ |
Marian Balakowicz | 49d0eee | 2006-06-30 16:30:46 +0200 | [diff] [blame] | 303 | sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */ |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 304 | if (cmd == EMAC_STACR_WRITE) |
| 305 | memcpy(&sta_reg, &value, 2); /* put in data */ |
| 306 | |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 307 | out_be32((void *)EMAC0_STACR + emac_reg, sta_reg); |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 308 | debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg); |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 309 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 310 | /* wait for completion */ |
| 311 | if (emac_miiphy_wait(emac_reg) != 0) |
| 312 | return -1; |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 313 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 314 | debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg); |
Larry Johnson | 50325a0 | 2007-12-27 10:50:55 -0500 | [diff] [blame] | 315 | if ((sta_reg & EMAC_STACR_PHYE) != 0) |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 316 | return -1; |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 317 | |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 318 | return 0; |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 319 | } |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 320 | |
Joe Hershberger | 0c33319 | 2016-08-08 11:28:39 -0500 | [diff] [blame] | 321 | int emac4xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg) |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 322 | { |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 323 | unsigned long sta_reg; |
Stefan Roese | 0c7ffc0 | 2005-08-16 18:18:00 +0200 | [diff] [blame] | 324 | unsigned long emac_reg; |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 325 | |
Victor Gallardo | 45a06ff | 2008-09-04 23:49:36 -0700 | [diff] [blame] | 326 | emac_reg = miiphy_getemac_offset(addr); |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 327 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 328 | if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0) |
| 329 | return -1; |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 330 | |
Niklaus Giger | 728bd0a | 2009-10-04 20:04:20 +0200 | [diff] [blame] | 331 | sta_reg = in_be32((void *)EMAC0_STACR + emac_reg); |
Joe Hershberger | 0c33319 | 2016-08-08 11:28:39 -0500 | [diff] [blame] | 332 | return sta_reg >> 16; |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 333 | } |
wdenk | affae2b | 2002-08-17 09:36:01 +0000 | [diff] [blame] | 334 | |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 335 | /***********************************************************/ |
| 336 | /* write a phy reg and return the value with a rc */ |
| 337 | /***********************************************************/ |
| 338 | |
Joe Hershberger | 0c33319 | 2016-08-08 11:28:39 -0500 | [diff] [blame] | 339 | int emac4xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg, |
| 340 | u16 value) |
Stefan Roese | 8b231b2 | 2008-02-19 21:58:25 +0100 | [diff] [blame] | 341 | { |
| 342 | return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value); |
| 343 | } |