1*2e192b24SSimon Glass /* 2*2e192b24SSimon Glass * (C) Copyright 2001 3*2e192b24SSimon Glass * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com 4*2e192b24SSimon Glass * 5*2e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6*2e192b24SSimon Glass */ 7*2e192b24SSimon Glass 8*2e192b24SSimon Glass /* 9*2e192b24SSimon Glass * MII Utilities 10*2e192b24SSimon Glass */ 11*2e192b24SSimon Glass 12*2e192b24SSimon Glass #include <common.h> 13*2e192b24SSimon Glass #include <command.h> 14*2e192b24SSimon Glass #include <miiphy.h> 15*2e192b24SSimon Glass 16*2e192b24SSimon Glass typedef struct _MII_reg_desc_t { 17*2e192b24SSimon Glass ushort regno; 18*2e192b24SSimon Glass char * name; 19*2e192b24SSimon Glass } MII_reg_desc_t; 20*2e192b24SSimon Glass 21*2e192b24SSimon Glass static const MII_reg_desc_t reg_0_5_desc_tbl[] = { 22*2e192b24SSimon Glass { MII_BMCR, "PHY control register" }, 23*2e192b24SSimon Glass { MII_BMSR, "PHY status register" }, 24*2e192b24SSimon Glass { MII_PHYSID1, "PHY ID 1 register" }, 25*2e192b24SSimon Glass { MII_PHYSID2, "PHY ID 2 register" }, 26*2e192b24SSimon Glass { MII_ADVERTISE, "Autonegotiation advertisement register" }, 27*2e192b24SSimon Glass { MII_LPA, "Autonegotiation partner abilities register" }, 28*2e192b24SSimon Glass }; 29*2e192b24SSimon Glass 30*2e192b24SSimon Glass typedef struct _MII_field_desc_t { 31*2e192b24SSimon Glass ushort hi; 32*2e192b24SSimon Glass ushort lo; 33*2e192b24SSimon Glass ushort mask; 34*2e192b24SSimon Glass char * name; 35*2e192b24SSimon Glass } MII_field_desc_t; 36*2e192b24SSimon Glass 37*2e192b24SSimon Glass static const MII_field_desc_t reg_0_desc_tbl[] = { 38*2e192b24SSimon Glass { 15, 15, 0x01, "reset" }, 39*2e192b24SSimon Glass { 14, 14, 0x01, "loopback" }, 40*2e192b24SSimon Glass { 13, 6, 0x81, "speed selection" }, /* special */ 41*2e192b24SSimon Glass { 12, 12, 0x01, "A/N enable" }, 42*2e192b24SSimon Glass { 11, 11, 0x01, "power-down" }, 43*2e192b24SSimon Glass { 10, 10, 0x01, "isolate" }, 44*2e192b24SSimon Glass { 9, 9, 0x01, "restart A/N" }, 45*2e192b24SSimon Glass { 8, 8, 0x01, "duplex" }, /* special */ 46*2e192b24SSimon Glass { 7, 7, 0x01, "collision test enable" }, 47*2e192b24SSimon Glass { 5, 0, 0x3f, "(reserved)" } 48*2e192b24SSimon Glass }; 49*2e192b24SSimon Glass 50*2e192b24SSimon Glass static const MII_field_desc_t reg_1_desc_tbl[] = { 51*2e192b24SSimon Glass { 15, 15, 0x01, "100BASE-T4 able" }, 52*2e192b24SSimon Glass { 14, 14, 0x01, "100BASE-X full duplex able" }, 53*2e192b24SSimon Glass { 13, 13, 0x01, "100BASE-X half duplex able" }, 54*2e192b24SSimon Glass { 12, 12, 0x01, "10 Mbps full duplex able" }, 55*2e192b24SSimon Glass { 11, 11, 0x01, "10 Mbps half duplex able" }, 56*2e192b24SSimon Glass { 10, 10, 0x01, "100BASE-T2 full duplex able" }, 57*2e192b24SSimon Glass { 9, 9, 0x01, "100BASE-T2 half duplex able" }, 58*2e192b24SSimon Glass { 8, 8, 0x01, "extended status" }, 59*2e192b24SSimon Glass { 7, 7, 0x01, "(reserved)" }, 60*2e192b24SSimon Glass { 6, 6, 0x01, "MF preamble suppression" }, 61*2e192b24SSimon Glass { 5, 5, 0x01, "A/N complete" }, 62*2e192b24SSimon Glass { 4, 4, 0x01, "remote fault" }, 63*2e192b24SSimon Glass { 3, 3, 0x01, "A/N able" }, 64*2e192b24SSimon Glass { 2, 2, 0x01, "link status" }, 65*2e192b24SSimon Glass { 1, 1, 0x01, "jabber detect" }, 66*2e192b24SSimon Glass { 0, 0, 0x01, "extended capabilities" }, 67*2e192b24SSimon Glass }; 68*2e192b24SSimon Glass 69*2e192b24SSimon Glass static const MII_field_desc_t reg_2_desc_tbl[] = { 70*2e192b24SSimon Glass { 15, 0, 0xffff, "OUI portion" }, 71*2e192b24SSimon Glass }; 72*2e192b24SSimon Glass 73*2e192b24SSimon Glass static const MII_field_desc_t reg_3_desc_tbl[] = { 74*2e192b24SSimon Glass { 15, 10, 0x3f, "OUI portion" }, 75*2e192b24SSimon Glass { 9, 4, 0x3f, "manufacturer part number" }, 76*2e192b24SSimon Glass { 3, 0, 0x0f, "manufacturer rev. number" }, 77*2e192b24SSimon Glass }; 78*2e192b24SSimon Glass 79*2e192b24SSimon Glass static const MII_field_desc_t reg_4_desc_tbl[] = { 80*2e192b24SSimon Glass { 15, 15, 0x01, "next page able" }, 81*2e192b24SSimon Glass { 14, 14, 0x01, "(reserved)" }, 82*2e192b24SSimon Glass { 13, 13, 0x01, "remote fault" }, 83*2e192b24SSimon Glass { 12, 12, 0x01, "(reserved)" }, 84*2e192b24SSimon Glass { 11, 11, 0x01, "asymmetric pause" }, 85*2e192b24SSimon Glass { 10, 10, 0x01, "pause enable" }, 86*2e192b24SSimon Glass { 9, 9, 0x01, "100BASE-T4 able" }, 87*2e192b24SSimon Glass { 8, 8, 0x01, "100BASE-TX full duplex able" }, 88*2e192b24SSimon Glass { 7, 7, 0x01, "100BASE-TX able" }, 89*2e192b24SSimon Glass { 6, 6, 0x01, "10BASE-T full duplex able" }, 90*2e192b24SSimon Glass { 5, 5, 0x01, "10BASE-T able" }, 91*2e192b24SSimon Glass { 4, 0, 0x1f, "xxx to do" }, 92*2e192b24SSimon Glass }; 93*2e192b24SSimon Glass 94*2e192b24SSimon Glass static const MII_field_desc_t reg_5_desc_tbl[] = { 95*2e192b24SSimon Glass { 15, 15, 0x01, "next page able" }, 96*2e192b24SSimon Glass { 14, 14, 0x01, "acknowledge" }, 97*2e192b24SSimon Glass { 13, 13, 0x01, "remote fault" }, 98*2e192b24SSimon Glass { 12, 12, 0x01, "(reserved)" }, 99*2e192b24SSimon Glass { 11, 11, 0x01, "asymmetric pause able" }, 100*2e192b24SSimon Glass { 10, 10, 0x01, "pause able" }, 101*2e192b24SSimon Glass { 9, 9, 0x01, "100BASE-T4 able" }, 102*2e192b24SSimon Glass { 8, 8, 0x01, "100BASE-X full duplex able" }, 103*2e192b24SSimon Glass { 7, 7, 0x01, "100BASE-TX able" }, 104*2e192b24SSimon Glass { 6, 6, 0x01, "10BASE-T full duplex able" }, 105*2e192b24SSimon Glass { 5, 5, 0x01, "10BASE-T able" }, 106*2e192b24SSimon Glass { 4, 0, 0x1f, "xxx to do" }, 107*2e192b24SSimon Glass }; 108*2e192b24SSimon Glass typedef struct _MII_field_desc_and_len_t { 109*2e192b24SSimon Glass const MII_field_desc_t *pdesc; 110*2e192b24SSimon Glass ushort len; 111*2e192b24SSimon Glass } MII_field_desc_and_len_t; 112*2e192b24SSimon Glass 113*2e192b24SSimon Glass static const MII_field_desc_and_len_t desc_and_len_tbl[] = { 114*2e192b24SSimon Glass { reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl) }, 115*2e192b24SSimon Glass { reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl) }, 116*2e192b24SSimon Glass { reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl) }, 117*2e192b24SSimon Glass { reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl) }, 118*2e192b24SSimon Glass { reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl) }, 119*2e192b24SSimon Glass { reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl) }, 120*2e192b24SSimon Glass }; 121*2e192b24SSimon Glass 122*2e192b24SSimon Glass static void dump_reg( 123*2e192b24SSimon Glass ushort regval, 124*2e192b24SSimon Glass const MII_reg_desc_t *prd, 125*2e192b24SSimon Glass const MII_field_desc_and_len_t *pdl); 126*2e192b24SSimon Glass 127*2e192b24SSimon Glass static int special_field( 128*2e192b24SSimon Glass ushort regno, 129*2e192b24SSimon Glass const MII_field_desc_t *pdesc, 130*2e192b24SSimon Glass ushort regval); 131*2e192b24SSimon Glass 132*2e192b24SSimon Glass static void MII_dump_0_to_5( 133*2e192b24SSimon Glass ushort regvals[6], 134*2e192b24SSimon Glass uchar reglo, 135*2e192b24SSimon Glass uchar reghi) 136*2e192b24SSimon Glass { 137*2e192b24SSimon Glass ulong i; 138*2e192b24SSimon Glass 139*2e192b24SSimon Glass for (i = 0; i < 6; i++) { 140*2e192b24SSimon Glass if ((reglo <= i) && (i <= reghi)) 141*2e192b24SSimon Glass dump_reg(regvals[i], ®_0_5_desc_tbl[i], 142*2e192b24SSimon Glass &desc_and_len_tbl[i]); 143*2e192b24SSimon Glass } 144*2e192b24SSimon Glass } 145*2e192b24SSimon Glass 146*2e192b24SSimon Glass static void dump_reg( 147*2e192b24SSimon Glass ushort regval, 148*2e192b24SSimon Glass const MII_reg_desc_t *prd, 149*2e192b24SSimon Glass const MII_field_desc_and_len_t *pdl) 150*2e192b24SSimon Glass { 151*2e192b24SSimon Glass ulong i; 152*2e192b24SSimon Glass ushort mask_in_place; 153*2e192b24SSimon Glass const MII_field_desc_t *pdesc; 154*2e192b24SSimon Glass 155*2e192b24SSimon Glass printf("%u. (%04hx) -- %s --\n", 156*2e192b24SSimon Glass prd->regno, regval, prd->name); 157*2e192b24SSimon Glass 158*2e192b24SSimon Glass for (i = 0; i < pdl->len; i++) { 159*2e192b24SSimon Glass pdesc = &pdl->pdesc[i]; 160*2e192b24SSimon Glass 161*2e192b24SSimon Glass mask_in_place = pdesc->mask << pdesc->lo; 162*2e192b24SSimon Glass 163*2e192b24SSimon Glass printf(" (%04hx:%04x) %u.", 164*2e192b24SSimon Glass mask_in_place, 165*2e192b24SSimon Glass regval & mask_in_place, 166*2e192b24SSimon Glass prd->regno); 167*2e192b24SSimon Glass 168*2e192b24SSimon Glass if (special_field(prd->regno, pdesc, regval)) { 169*2e192b24SSimon Glass } 170*2e192b24SSimon Glass else { 171*2e192b24SSimon Glass if (pdesc->hi == pdesc->lo) 172*2e192b24SSimon Glass printf("%2u ", pdesc->lo); 173*2e192b24SSimon Glass else 174*2e192b24SSimon Glass printf("%2u-%2u", pdesc->hi, pdesc->lo); 175*2e192b24SSimon Glass printf(" = %5u %s", 176*2e192b24SSimon Glass (regval & mask_in_place) >> pdesc->lo, 177*2e192b24SSimon Glass pdesc->name); 178*2e192b24SSimon Glass } 179*2e192b24SSimon Glass printf("\n"); 180*2e192b24SSimon Glass 181*2e192b24SSimon Glass } 182*2e192b24SSimon Glass printf("\n"); 183*2e192b24SSimon Glass } 184*2e192b24SSimon Glass 185*2e192b24SSimon Glass /* Special fields: 186*2e192b24SSimon Glass ** 0.6,13 187*2e192b24SSimon Glass ** 0.8 188*2e192b24SSimon Glass ** 2.15-0 189*2e192b24SSimon Glass ** 3.15-0 190*2e192b24SSimon Glass ** 4.4-0 191*2e192b24SSimon Glass ** 5.4-0 192*2e192b24SSimon Glass */ 193*2e192b24SSimon Glass 194*2e192b24SSimon Glass static int special_field( 195*2e192b24SSimon Glass ushort regno, 196*2e192b24SSimon Glass const MII_field_desc_t *pdesc, 197*2e192b24SSimon Glass ushort regval) 198*2e192b24SSimon Glass { 199*2e192b24SSimon Glass if ((regno == MII_BMCR) && (pdesc->lo == 6)) { 200*2e192b24SSimon Glass ushort speed_bits = regval & (BMCR_SPEED1000 | BMCR_SPEED100); 201*2e192b24SSimon Glass printf("%2u,%2u = b%u%u speed selection = %s Mbps", 202*2e192b24SSimon Glass 6, 13, 203*2e192b24SSimon Glass (regval >> 6) & 1, 204*2e192b24SSimon Glass (regval >> 13) & 1, 205*2e192b24SSimon Glass speed_bits == BMCR_SPEED1000 ? "1000" : 206*2e192b24SSimon Glass speed_bits == BMCR_SPEED100 ? "100" : 207*2e192b24SSimon Glass "10"); 208*2e192b24SSimon Glass return 1; 209*2e192b24SSimon Glass } 210*2e192b24SSimon Glass 211*2e192b24SSimon Glass else if ((regno == MII_BMCR) && (pdesc->lo == 8)) { 212*2e192b24SSimon Glass printf("%2u = %5u duplex = %s", 213*2e192b24SSimon Glass pdesc->lo, 214*2e192b24SSimon Glass (regval >> pdesc->lo) & 1, 215*2e192b24SSimon Glass ((regval >> pdesc->lo) & 1) ? "full" : "half"); 216*2e192b24SSimon Glass return 1; 217*2e192b24SSimon Glass } 218*2e192b24SSimon Glass 219*2e192b24SSimon Glass else if ((regno == MII_ADVERTISE) && (pdesc->lo == 0)) { 220*2e192b24SSimon Glass ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask; 221*2e192b24SSimon Glass printf("%2u-%2u = %5u selector = %s", 222*2e192b24SSimon Glass pdesc->hi, pdesc->lo, sel_bits, 223*2e192b24SSimon Glass sel_bits == PHY_ANLPAR_PSB_802_3 ? 224*2e192b24SSimon Glass "IEEE 802.3" : 225*2e192b24SSimon Glass sel_bits == PHY_ANLPAR_PSB_802_9 ? 226*2e192b24SSimon Glass "IEEE 802.9 ISLAN-16T" : 227*2e192b24SSimon Glass "???"); 228*2e192b24SSimon Glass return 1; 229*2e192b24SSimon Glass } 230*2e192b24SSimon Glass 231*2e192b24SSimon Glass else if ((regno == MII_LPA) && (pdesc->lo == 0)) { 232*2e192b24SSimon Glass ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask; 233*2e192b24SSimon Glass printf("%2u-%2u = %u selector = %s", 234*2e192b24SSimon Glass pdesc->hi, pdesc->lo, sel_bits, 235*2e192b24SSimon Glass sel_bits == PHY_ANLPAR_PSB_802_3 ? 236*2e192b24SSimon Glass "IEEE 802.3" : 237*2e192b24SSimon Glass sel_bits == PHY_ANLPAR_PSB_802_9 ? 238*2e192b24SSimon Glass "IEEE 802.9 ISLAN-16T" : 239*2e192b24SSimon Glass "???"); 240*2e192b24SSimon Glass return 1; 241*2e192b24SSimon Glass } 242*2e192b24SSimon Glass 243*2e192b24SSimon Glass return 0; 244*2e192b24SSimon Glass } 245*2e192b24SSimon Glass 246*2e192b24SSimon Glass static char last_op[2]; 247*2e192b24SSimon Glass static uint last_data; 248*2e192b24SSimon Glass static uint last_addr_lo; 249*2e192b24SSimon Glass static uint last_addr_hi; 250*2e192b24SSimon Glass static uint last_reg_lo; 251*2e192b24SSimon Glass static uint last_reg_hi; 252*2e192b24SSimon Glass static uint last_mask; 253*2e192b24SSimon Glass 254*2e192b24SSimon Glass static void extract_range( 255*2e192b24SSimon Glass char * input, 256*2e192b24SSimon Glass unsigned char * plo, 257*2e192b24SSimon Glass unsigned char * phi) 258*2e192b24SSimon Glass { 259*2e192b24SSimon Glass char * end; 260*2e192b24SSimon Glass *plo = simple_strtoul(input, &end, 16); 261*2e192b24SSimon Glass if (*end == '-') { 262*2e192b24SSimon Glass end++; 263*2e192b24SSimon Glass *phi = simple_strtoul(end, NULL, 16); 264*2e192b24SSimon Glass } 265*2e192b24SSimon Glass else { 266*2e192b24SSimon Glass *phi = *plo; 267*2e192b24SSimon Glass } 268*2e192b24SSimon Glass } 269*2e192b24SSimon Glass 270*2e192b24SSimon Glass /* ---------------------------------------------------------------- */ 271*2e192b24SSimon Glass static int do_mii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 272*2e192b24SSimon Glass { 273*2e192b24SSimon Glass char op[2]; 274*2e192b24SSimon Glass unsigned char addrlo, addrhi, reglo, reghi; 275*2e192b24SSimon Glass unsigned char addr, reg; 276*2e192b24SSimon Glass unsigned short data, mask; 277*2e192b24SSimon Glass int rcode = 0; 278*2e192b24SSimon Glass const char *devname; 279*2e192b24SSimon Glass 280*2e192b24SSimon Glass if (argc < 2) 281*2e192b24SSimon Glass return CMD_RET_USAGE; 282*2e192b24SSimon Glass 283*2e192b24SSimon Glass #if defined(CONFIG_MII_INIT) 284*2e192b24SSimon Glass mii_init (); 285*2e192b24SSimon Glass #endif 286*2e192b24SSimon Glass 287*2e192b24SSimon Glass /* 288*2e192b24SSimon Glass * We use the last specified parameters, unless new ones are 289*2e192b24SSimon Glass * entered. 290*2e192b24SSimon Glass */ 291*2e192b24SSimon Glass op[0] = last_op[0]; 292*2e192b24SSimon Glass op[1] = last_op[1]; 293*2e192b24SSimon Glass addrlo = last_addr_lo; 294*2e192b24SSimon Glass addrhi = last_addr_hi; 295*2e192b24SSimon Glass reglo = last_reg_lo; 296*2e192b24SSimon Glass reghi = last_reg_hi; 297*2e192b24SSimon Glass data = last_data; 298*2e192b24SSimon Glass mask = last_mask; 299*2e192b24SSimon Glass 300*2e192b24SSimon Glass if ((flag & CMD_FLAG_REPEAT) == 0) { 301*2e192b24SSimon Glass op[0] = argv[1][0]; 302*2e192b24SSimon Glass if (strlen(argv[1]) > 1) 303*2e192b24SSimon Glass op[1] = argv[1][1]; 304*2e192b24SSimon Glass else 305*2e192b24SSimon Glass op[1] = '\0'; 306*2e192b24SSimon Glass 307*2e192b24SSimon Glass if (argc >= 3) 308*2e192b24SSimon Glass extract_range(argv[2], &addrlo, &addrhi); 309*2e192b24SSimon Glass if (argc >= 4) 310*2e192b24SSimon Glass extract_range(argv[3], ®lo, ®hi); 311*2e192b24SSimon Glass if (argc >= 5) 312*2e192b24SSimon Glass data = simple_strtoul(argv[4], NULL, 16); 313*2e192b24SSimon Glass if (argc >= 6) 314*2e192b24SSimon Glass mask = simple_strtoul(argv[5], NULL, 16); 315*2e192b24SSimon Glass } 316*2e192b24SSimon Glass 317*2e192b24SSimon Glass if (addrhi > 31) { 318*2e192b24SSimon Glass printf("Incorrect PHY address. Range should be 0-31\n"); 319*2e192b24SSimon Glass return CMD_RET_USAGE; 320*2e192b24SSimon Glass } 321*2e192b24SSimon Glass 322*2e192b24SSimon Glass /* use current device */ 323*2e192b24SSimon Glass devname = miiphy_get_current_dev(); 324*2e192b24SSimon Glass 325*2e192b24SSimon Glass /* 326*2e192b24SSimon Glass * check info/read/write. 327*2e192b24SSimon Glass */ 328*2e192b24SSimon Glass if (op[0] == 'i') { 329*2e192b24SSimon Glass unsigned char j, start, end; 330*2e192b24SSimon Glass unsigned int oui; 331*2e192b24SSimon Glass unsigned char model; 332*2e192b24SSimon Glass unsigned char rev; 333*2e192b24SSimon Glass 334*2e192b24SSimon Glass /* 335*2e192b24SSimon Glass * Look for any and all PHYs. Valid addresses are 0..31. 336*2e192b24SSimon Glass */ 337*2e192b24SSimon Glass if (argc >= 3) { 338*2e192b24SSimon Glass start = addrlo; end = addrhi; 339*2e192b24SSimon Glass } else { 340*2e192b24SSimon Glass start = 0; end = 31; 341*2e192b24SSimon Glass } 342*2e192b24SSimon Glass 343*2e192b24SSimon Glass for (j = start; j <= end; j++) { 344*2e192b24SSimon Glass if (miiphy_info (devname, j, &oui, &model, &rev) == 0) { 345*2e192b24SSimon Glass printf("PHY 0x%02X: " 346*2e192b24SSimon Glass "OUI = 0x%04X, " 347*2e192b24SSimon Glass "Model = 0x%02X, " 348*2e192b24SSimon Glass "Rev = 0x%02X, " 349*2e192b24SSimon Glass "%3dbase%s, %s\n", 350*2e192b24SSimon Glass j, oui, model, rev, 351*2e192b24SSimon Glass miiphy_speed (devname, j), 352*2e192b24SSimon Glass miiphy_is_1000base_x (devname, j) 353*2e192b24SSimon Glass ? "X" : "T", 354*2e192b24SSimon Glass (miiphy_duplex (devname, j) == FULL) 355*2e192b24SSimon Glass ? "FDX" : "HDX"); 356*2e192b24SSimon Glass } 357*2e192b24SSimon Glass } 358*2e192b24SSimon Glass } else if (op[0] == 'r') { 359*2e192b24SSimon Glass for (addr = addrlo; addr <= addrhi; addr++) { 360*2e192b24SSimon Glass for (reg = reglo; reg <= reghi; reg++) { 361*2e192b24SSimon Glass data = 0xffff; 362*2e192b24SSimon Glass if (miiphy_read (devname, addr, reg, &data) != 0) { 363*2e192b24SSimon Glass printf( 364*2e192b24SSimon Glass "Error reading from the PHY addr=%02x reg=%02x\n", 365*2e192b24SSimon Glass addr, reg); 366*2e192b24SSimon Glass rcode = 1; 367*2e192b24SSimon Glass } else { 368*2e192b24SSimon Glass if ((addrlo != addrhi) || (reglo != reghi)) 369*2e192b24SSimon Glass printf("addr=%02x reg=%02x data=", 370*2e192b24SSimon Glass (uint)addr, (uint)reg); 371*2e192b24SSimon Glass printf("%04X\n", data & 0x0000FFFF); 372*2e192b24SSimon Glass } 373*2e192b24SSimon Glass } 374*2e192b24SSimon Glass if ((addrlo != addrhi) && (reglo != reghi)) 375*2e192b24SSimon Glass printf("\n"); 376*2e192b24SSimon Glass } 377*2e192b24SSimon Glass } else if (op[0] == 'w') { 378*2e192b24SSimon Glass for (addr = addrlo; addr <= addrhi; addr++) { 379*2e192b24SSimon Glass for (reg = reglo; reg <= reghi; reg++) { 380*2e192b24SSimon Glass if (miiphy_write (devname, addr, reg, data) != 0) { 381*2e192b24SSimon Glass printf("Error writing to the PHY addr=%02x reg=%02x\n", 382*2e192b24SSimon Glass addr, reg); 383*2e192b24SSimon Glass rcode = 1; 384*2e192b24SSimon Glass } 385*2e192b24SSimon Glass } 386*2e192b24SSimon Glass } 387*2e192b24SSimon Glass } else if (op[0] == 'm') { 388*2e192b24SSimon Glass for (addr = addrlo; addr <= addrhi; addr++) { 389*2e192b24SSimon Glass for (reg = reglo; reg <= reghi; reg++) { 390*2e192b24SSimon Glass unsigned short val = 0; 391*2e192b24SSimon Glass if (miiphy_read(devname, addr, 392*2e192b24SSimon Glass reg, &val)) { 393*2e192b24SSimon Glass printf("Error reading from the PHY"); 394*2e192b24SSimon Glass printf(" addr=%02x", addr); 395*2e192b24SSimon Glass printf(" reg=%02x\n", reg); 396*2e192b24SSimon Glass rcode = 1; 397*2e192b24SSimon Glass } else { 398*2e192b24SSimon Glass val = (val & ~mask) | (data & mask); 399*2e192b24SSimon Glass if (miiphy_write(devname, addr, 400*2e192b24SSimon Glass reg, val)) { 401*2e192b24SSimon Glass printf("Error writing to the PHY"); 402*2e192b24SSimon Glass printf(" addr=%02x", addr); 403*2e192b24SSimon Glass printf(" reg=%02x\n", reg); 404*2e192b24SSimon Glass rcode = 1; 405*2e192b24SSimon Glass } 406*2e192b24SSimon Glass } 407*2e192b24SSimon Glass } 408*2e192b24SSimon Glass } 409*2e192b24SSimon Glass } else if (strncmp(op, "du", 2) == 0) { 410*2e192b24SSimon Glass ushort regs[6]; 411*2e192b24SSimon Glass int ok = 1; 412*2e192b24SSimon Glass if ((reglo > 5) || (reghi > 5)) { 413*2e192b24SSimon Glass printf( 414*2e192b24SSimon Glass "The MII dump command only formats the " 415*2e192b24SSimon Glass "standard MII registers, 0-5.\n"); 416*2e192b24SSimon Glass return 1; 417*2e192b24SSimon Glass } 418*2e192b24SSimon Glass for (addr = addrlo; addr <= addrhi; addr++) { 419*2e192b24SSimon Glass for (reg = reglo; reg < reghi + 1; reg++) { 420*2e192b24SSimon Glass if (miiphy_read(devname, addr, reg, ®s[reg]) != 0) { 421*2e192b24SSimon Glass ok = 0; 422*2e192b24SSimon Glass printf( 423*2e192b24SSimon Glass "Error reading from the PHY addr=%02x reg=%02x\n", 424*2e192b24SSimon Glass addr, reg); 425*2e192b24SSimon Glass rcode = 1; 426*2e192b24SSimon Glass } 427*2e192b24SSimon Glass } 428*2e192b24SSimon Glass if (ok) 429*2e192b24SSimon Glass MII_dump_0_to_5(regs, reglo, reghi); 430*2e192b24SSimon Glass printf("\n"); 431*2e192b24SSimon Glass } 432*2e192b24SSimon Glass } else if (strncmp(op, "de", 2) == 0) { 433*2e192b24SSimon Glass if (argc == 2) 434*2e192b24SSimon Glass miiphy_listdev (); 435*2e192b24SSimon Glass else 436*2e192b24SSimon Glass miiphy_set_current_dev (argv[2]); 437*2e192b24SSimon Glass } else { 438*2e192b24SSimon Glass return CMD_RET_USAGE; 439*2e192b24SSimon Glass } 440*2e192b24SSimon Glass 441*2e192b24SSimon Glass /* 442*2e192b24SSimon Glass * Save the parameters for repeats. 443*2e192b24SSimon Glass */ 444*2e192b24SSimon Glass last_op[0] = op[0]; 445*2e192b24SSimon Glass last_op[1] = op[1]; 446*2e192b24SSimon Glass last_addr_lo = addrlo; 447*2e192b24SSimon Glass last_addr_hi = addrhi; 448*2e192b24SSimon Glass last_reg_lo = reglo; 449*2e192b24SSimon Glass last_reg_hi = reghi; 450*2e192b24SSimon Glass last_data = data; 451*2e192b24SSimon Glass last_mask = mask; 452*2e192b24SSimon Glass 453*2e192b24SSimon Glass return rcode; 454*2e192b24SSimon Glass } 455*2e192b24SSimon Glass 456*2e192b24SSimon Glass /***************************************************/ 457*2e192b24SSimon Glass 458*2e192b24SSimon Glass U_BOOT_CMD( 459*2e192b24SSimon Glass mii, 6, 1, do_mii, 460*2e192b24SSimon Glass "MII utility commands", 461*2e192b24SSimon Glass "device - list available devices\n" 462*2e192b24SSimon Glass "mii device <devname> - set current device\n" 463*2e192b24SSimon Glass "mii info <addr> - display MII PHY info\n" 464*2e192b24SSimon Glass "mii read <addr> <reg> - read MII PHY <addr> register <reg>\n" 465*2e192b24SSimon Glass "mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n" 466*2e192b24SSimon Glass "mii modify <addr> <reg> <data> <mask> - modify MII PHY <addr> register <reg>\n" 467*2e192b24SSimon Glass " updating bits identified in <mask>\n" 468*2e192b24SSimon Glass "mii dump <addr> <reg> - pretty-print <addr> <reg> (0-5 only)\n" 469*2e192b24SSimon Glass "Addr and/or reg may be ranges, e.g. 2-7." 470*2e192b24SSimon Glass ); 471