1 /* 2 * (C) Copyright 2009 Industrie Dial Face S.p.A. 3 * Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com> 4 * 5 * (C) Copyright 2001 6 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 /* 12 * This provides a bit-banged interface to the ethernet MII management 13 * channel. 14 */ 15 16 #include <common.h> 17 #include <ioports.h> 18 #include <ppc_asm.tmpl> 19 #include <miiphy.h> 20 21 #define BB_MII_RELOCATE(v,off) (v += (v?off:0)) 22 23 DECLARE_GLOBAL_DATA_PTR; 24 25 #ifndef CONFIG_BITBANGMII_MULTI 26 27 /* 28 * If CONFIG_BITBANGMII_MULTI is not defined we use a 29 * compatibility layer with the previous miiphybb implementation 30 * based on macros usage. 31 * 32 */ 33 static int bb_mii_init_wrap(struct bb_miiphy_bus *bus) 34 { 35 #ifdef MII_INIT 36 MII_INIT; 37 #endif 38 return 0; 39 } 40 41 static int bb_mdio_active_wrap(struct bb_miiphy_bus *bus) 42 { 43 #ifdef MDIO_DECLARE 44 MDIO_DECLARE; 45 #endif 46 MDIO_ACTIVE; 47 return 0; 48 } 49 50 static int bb_mdio_tristate_wrap(struct bb_miiphy_bus *bus) 51 { 52 #ifdef MDIO_DECLARE 53 MDIO_DECLARE; 54 #endif 55 MDIO_TRISTATE; 56 return 0; 57 } 58 59 static int bb_set_mdio_wrap(struct bb_miiphy_bus *bus, int v) 60 { 61 #ifdef MDIO_DECLARE 62 MDIO_DECLARE; 63 #endif 64 MDIO(v); 65 return 0; 66 } 67 68 static int bb_get_mdio_wrap(struct bb_miiphy_bus *bus, int *v) 69 { 70 #ifdef MDIO_DECLARE 71 MDIO_DECLARE; 72 #endif 73 *v = MDIO_READ; 74 return 0; 75 } 76 77 static int bb_set_mdc_wrap(struct bb_miiphy_bus *bus, int v) 78 { 79 #ifdef MDC_DECLARE 80 MDC_DECLARE; 81 #endif 82 MDC(v); 83 return 0; 84 } 85 86 static int bb_delay_wrap(struct bb_miiphy_bus *bus) 87 { 88 MIIDELAY; 89 return 0; 90 } 91 92 struct bb_miiphy_bus bb_miiphy_buses[] = { 93 { 94 .name = BB_MII_DEVNAME, 95 .init = bb_mii_init_wrap, 96 .mdio_active = bb_mdio_active_wrap, 97 .mdio_tristate = bb_mdio_tristate_wrap, 98 .set_mdio = bb_set_mdio_wrap, 99 .get_mdio = bb_get_mdio_wrap, 100 .set_mdc = bb_set_mdc_wrap, 101 .delay = bb_delay_wrap, 102 } 103 }; 104 105 int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) / 106 sizeof(bb_miiphy_buses[0]); 107 #endif 108 109 void bb_miiphy_init(void) 110 { 111 int i; 112 113 for (i = 0; i < bb_miiphy_buses_num; i++) { 114 #if defined(CONFIG_NEEDS_MANUAL_RELOC) 115 /* Relocate the hook pointers*/ 116 BB_MII_RELOCATE(bb_miiphy_buses[i].init, gd->reloc_off); 117 BB_MII_RELOCATE(bb_miiphy_buses[i].mdio_active, gd->reloc_off); 118 BB_MII_RELOCATE(bb_miiphy_buses[i].mdio_tristate, gd->reloc_off); 119 BB_MII_RELOCATE(bb_miiphy_buses[i].set_mdio, gd->reloc_off); 120 BB_MII_RELOCATE(bb_miiphy_buses[i].get_mdio, gd->reloc_off); 121 BB_MII_RELOCATE(bb_miiphy_buses[i].set_mdc, gd->reloc_off); 122 BB_MII_RELOCATE(bb_miiphy_buses[i].delay, gd->reloc_off); 123 #endif 124 if (bb_miiphy_buses[i].init != NULL) { 125 bb_miiphy_buses[i].init(&bb_miiphy_buses[i]); 126 } 127 } 128 } 129 130 static inline struct bb_miiphy_bus *bb_miiphy_getbus(const char *devname) 131 { 132 #ifdef CONFIG_BITBANGMII_MULTI 133 int i; 134 135 /* Search the correct bus */ 136 for (i = 0; i < bb_miiphy_buses_num; i++) { 137 if (!strcmp(bb_miiphy_buses[i].name, devname)) { 138 return &bb_miiphy_buses[i]; 139 } 140 } 141 return NULL; 142 #else 143 /* We have just one bitbanging bus */ 144 return &bb_miiphy_buses[0]; 145 #endif 146 } 147 148 /***************************************************************************** 149 * 150 * Utility to send the preamble, address, and register (common to read 151 * and write). 152 */ 153 static void miiphy_pre(struct bb_miiphy_bus *bus, char read, 154 unsigned char addr, unsigned char reg) 155 { 156 int j; 157 158 /* 159 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure. 160 * The IEEE spec says this is a PHY optional requirement. The AMD 161 * 79C874 requires one after power up and one after a MII communications 162 * error. This means that we are doing more preambles than we need, 163 * but it is safer and will be much more robust. 164 */ 165 166 bus->mdio_active(bus); 167 bus->set_mdio(bus, 1); 168 for (j = 0; j < 32; j++) { 169 bus->set_mdc(bus, 0); 170 bus->delay(bus); 171 bus->set_mdc(bus, 1); 172 bus->delay(bus); 173 } 174 175 /* send the start bit (01) and the read opcode (10) or write (10) */ 176 bus->set_mdc(bus, 0); 177 bus->set_mdio(bus, 0); 178 bus->delay(bus); 179 bus->set_mdc(bus, 1); 180 bus->delay(bus); 181 bus->set_mdc(bus, 0); 182 bus->set_mdio(bus, 1); 183 bus->delay(bus); 184 bus->set_mdc(bus, 1); 185 bus->delay(bus); 186 bus->set_mdc(bus, 0); 187 bus->set_mdio(bus, read); 188 bus->delay(bus); 189 bus->set_mdc(bus, 1); 190 bus->delay(bus); 191 bus->set_mdc(bus, 0); 192 bus->set_mdio(bus, !read); 193 bus->delay(bus); 194 bus->set_mdc(bus, 1); 195 bus->delay(bus); 196 197 /* send the PHY address */ 198 for (j = 0; j < 5; j++) { 199 bus->set_mdc(bus, 0); 200 if ((addr & 0x10) == 0) { 201 bus->set_mdio(bus, 0); 202 } else { 203 bus->set_mdio(bus, 1); 204 } 205 bus->delay(bus); 206 bus->set_mdc(bus, 1); 207 bus->delay(bus); 208 addr <<= 1; 209 } 210 211 /* send the register address */ 212 for (j = 0; j < 5; j++) { 213 bus->set_mdc(bus, 0); 214 if ((reg & 0x10) == 0) { 215 bus->set_mdio(bus, 0); 216 } else { 217 bus->set_mdio(bus, 1); 218 } 219 bus->delay(bus); 220 bus->set_mdc(bus, 1); 221 bus->delay(bus); 222 reg <<= 1; 223 } 224 } 225 226 /***************************************************************************** 227 * 228 * Read a MII PHY register. 229 * 230 * Returns: 231 * 0 on success 232 */ 233 int bb_miiphy_read(const char *devname, unsigned char addr, 234 unsigned char reg, unsigned short *value) 235 { 236 short rdreg; /* register working value */ 237 int v; 238 int j; /* counter */ 239 struct bb_miiphy_bus *bus; 240 241 bus = bb_miiphy_getbus(devname); 242 if (bus == NULL) { 243 return -1; 244 } 245 246 if (value == NULL) { 247 puts("NULL value pointer\n"); 248 return -1; 249 } 250 251 miiphy_pre (bus, 1, addr, reg); 252 253 /* tri-state our MDIO I/O pin so we can read */ 254 bus->set_mdc(bus, 0); 255 bus->mdio_tristate(bus); 256 bus->delay(bus); 257 bus->set_mdc(bus, 1); 258 bus->delay(bus); 259 260 /* check the turnaround bit: the PHY should be driving it to zero */ 261 bus->get_mdio(bus, &v); 262 if (v != 0) { 263 /* puts ("PHY didn't drive TA low\n"); */ 264 for (j = 0; j < 32; j++) { 265 bus->set_mdc(bus, 0); 266 bus->delay(bus); 267 bus->set_mdc(bus, 1); 268 bus->delay(bus); 269 } 270 /* There is no PHY, set value to 0xFFFF and return */ 271 *value = 0xFFFF; 272 return -1; 273 } 274 275 bus->set_mdc(bus, 0); 276 bus->delay(bus); 277 278 /* read 16 bits of register data, MSB first */ 279 rdreg = 0; 280 for (j = 0; j < 16; j++) { 281 bus->set_mdc(bus, 1); 282 bus->delay(bus); 283 rdreg <<= 1; 284 bus->get_mdio(bus, &v); 285 rdreg |= (v & 0x1); 286 bus->set_mdc(bus, 0); 287 bus->delay(bus); 288 } 289 290 bus->set_mdc(bus, 1); 291 bus->delay(bus); 292 bus->set_mdc(bus, 0); 293 bus->delay(bus); 294 bus->set_mdc(bus, 1); 295 bus->delay(bus); 296 297 *value = rdreg; 298 299 #ifdef DEBUG 300 printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value); 301 #endif 302 303 return 0; 304 } 305 306 307 /***************************************************************************** 308 * 309 * Write a MII PHY register. 310 * 311 * Returns: 312 * 0 on success 313 */ 314 int bb_miiphy_write (const char *devname, unsigned char addr, 315 unsigned char reg, unsigned short value) 316 { 317 struct bb_miiphy_bus *bus; 318 int j; /* counter */ 319 320 bus = bb_miiphy_getbus(devname); 321 if (bus == NULL) { 322 /* Bus not found! */ 323 return -1; 324 } 325 326 miiphy_pre (bus, 0, addr, reg); 327 328 /* send the turnaround (10) */ 329 bus->set_mdc(bus, 0); 330 bus->set_mdio(bus, 1); 331 bus->delay(bus); 332 bus->set_mdc(bus, 1); 333 bus->delay(bus); 334 bus->set_mdc(bus, 0); 335 bus->set_mdio(bus, 0); 336 bus->delay(bus); 337 bus->set_mdc(bus, 1); 338 bus->delay(bus); 339 340 /* write 16 bits of register data, MSB first */ 341 for (j = 0; j < 16; j++) { 342 bus->set_mdc(bus, 0); 343 if ((value & 0x00008000) == 0) { 344 bus->set_mdio(bus, 0); 345 } else { 346 bus->set_mdio(bus, 1); 347 } 348 bus->delay(bus); 349 bus->set_mdc(bus, 1); 350 bus->delay(bus); 351 value <<= 1; 352 } 353 354 /* 355 * Tri-state the MDIO line. 356 */ 357 bus->mdio_tristate(bus); 358 bus->set_mdc(bus, 0); 359 bus->delay(bus); 360 bus->set_mdc(bus, 1); 361 bus->delay(bus); 362 363 return 0; 364 } 365