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 <ioports.h> 31 #include <ppc_asm.tmpl> 32 33 /***************************************************************************** 34 * 35 * Utility to send the preamble, address, and register (common to read 36 * and write). 37 */ 38 static void miiphy_pre (char read, unsigned char addr, unsigned char reg) 39 { 40 int j; /* counter */ 41 #if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM)) 42 volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT); 43 #endif 44 45 /* 46 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure. 47 * The IEEE spec says this is a PHY optional requirement. The AMD 48 * 79C874 requires one after power up and one after a MII communications 49 * error. This means that we are doing more preambles than we need, 50 * but it is safer and will be much more robust. 51 */ 52 53 MDIO_ACTIVE; 54 MDIO (1); 55 for (j = 0; j < 32; j++) { 56 MDC (0); 57 MIIDELAY; 58 MDC (1); 59 MIIDELAY; 60 } 61 62 /* send the start bit (01) and the read opcode (10) or write (10) */ 63 MDC (0); 64 MDIO (0); 65 MIIDELAY; 66 MDC (1); 67 MIIDELAY; 68 MDC (0); 69 MDIO (1); 70 MIIDELAY; 71 MDC (1); 72 MIIDELAY; 73 MDC (0); 74 MDIO (read); 75 MIIDELAY; 76 MDC (1); 77 MIIDELAY; 78 MDC (0); 79 MDIO (!read); 80 MIIDELAY; 81 MDC (1); 82 MIIDELAY; 83 84 /* send the PHY address */ 85 for (j = 0; j < 5; j++) { 86 MDC (0); 87 if ((addr & 0x10) == 0) { 88 MDIO (0); 89 } else { 90 MDIO (1); 91 } 92 MIIDELAY; 93 MDC (1); 94 MIIDELAY; 95 addr <<= 1; 96 } 97 98 /* send the register address */ 99 for (j = 0; j < 5; j++) { 100 MDC (0); 101 if ((reg & 0x10) == 0) { 102 MDIO (0); 103 } else { 104 MDIO (1); 105 } 106 MIIDELAY; 107 MDC (1); 108 MIIDELAY; 109 reg <<= 1; 110 } 111 } 112 113 114 /***************************************************************************** 115 * 116 * Read a MII PHY register. 117 * 118 * Returns: 119 * 0 on success 120 */ 121 int bb_miiphy_read (char *devname, unsigned char addr, 122 unsigned char reg, unsigned short *value) 123 { 124 short rdreg; /* register working value */ 125 int j; /* counter */ 126 #if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM)) 127 volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT); 128 #endif 129 130 miiphy_pre (1, addr, reg); 131 132 /* tri-state our MDIO I/O pin so we can read */ 133 MDC (0); 134 MDIO_TRISTATE; 135 MIIDELAY; 136 MDC (1); 137 MIIDELAY; 138 139 /* check the turnaround bit: the PHY should be driving it to zero */ 140 if (MDIO_READ != 0) { 141 /* puts ("PHY didn't drive TA low\n"); */ 142 for (j = 0; j < 32; j++) { 143 MDC (0); 144 MIIDELAY; 145 MDC (1); 146 MIIDELAY; 147 } 148 return (-1); 149 } 150 151 MDC (0); 152 MIIDELAY; 153 154 /* read 16 bits of register data, MSB first */ 155 rdreg = 0; 156 for (j = 0; j < 16; j++) { 157 MDC (1); 158 MIIDELAY; 159 rdreg <<= 1; 160 rdreg |= MDIO_READ; 161 MDC (0); 162 MIIDELAY; 163 } 164 165 MDC (1); 166 MIIDELAY; 167 MDC (0); 168 MIIDELAY; 169 MDC (1); 170 MIIDELAY; 171 172 *value = rdreg; 173 174 #ifdef DEBUG 175 printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value); 176 #endif 177 178 return 0; 179 } 180 181 182 /***************************************************************************** 183 * 184 * Write a MII PHY register. 185 * 186 * Returns: 187 * 0 on success 188 */ 189 int bb_miiphy_write (char *devname, unsigned char addr, 190 unsigned char reg, unsigned short value) 191 { 192 int j; /* counter */ 193 #if !(defined(CONFIG_EP8248) || defined(CONFIG_EP82XXM)) 194 volatile ioport_t *iop = ioport_addr ((immap_t *) CONFIG_SYS_IMMR, MDIO_PORT); 195 #endif 196 197 miiphy_pre (0, addr, reg); 198 199 /* send the turnaround (10) */ 200 MDC (0); 201 MDIO (1); 202 MIIDELAY; 203 MDC (1); 204 MIIDELAY; 205 MDC (0); 206 MDIO (0); 207 MIIDELAY; 208 MDC (1); 209 MIIDELAY; 210 211 /* write 16 bits of register data, MSB first */ 212 for (j = 0; j < 16; j++) { 213 MDC (0); 214 if ((value & 0x00008000) == 0) { 215 MDIO (0); 216 } else { 217 MDIO (1); 218 } 219 MIIDELAY; 220 MDC (1); 221 MIIDELAY; 222 value <<= 1; 223 } 224 225 /* 226 * Tri-state the MDIO line. 227 */ 228 MDIO_TRISTATE; 229 MDC (0); 230 MIIDELAY; 231 MDC (1); 232 MIIDELAY; 233 234 return 0; 235 } 236