183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
22e192b24SSimon Glass /*
32e192b24SSimon Glass * (C) Copyright 2001
42e192b24SSimon Glass * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
52e192b24SSimon Glass */
62e192b24SSimon Glass
72e192b24SSimon Glass /*
82e192b24SSimon Glass * MII Utilities
92e192b24SSimon Glass */
102e192b24SSimon Glass
112e192b24SSimon Glass #include <common.h>
122e192b24SSimon Glass #include <command.h>
132e192b24SSimon Glass #include <miiphy.h>
142e192b24SSimon Glass
152e192b24SSimon Glass typedef struct _MII_reg_desc_t {
162e192b24SSimon Glass ushort regno;
172e192b24SSimon Glass char * name;
182e192b24SSimon Glass } MII_reg_desc_t;
192e192b24SSimon Glass
202e192b24SSimon Glass static const MII_reg_desc_t reg_0_5_desc_tbl[] = {
212e192b24SSimon Glass { MII_BMCR, "PHY control register" },
222e192b24SSimon Glass { MII_BMSR, "PHY status register" },
232e192b24SSimon Glass { MII_PHYSID1, "PHY ID 1 register" },
242e192b24SSimon Glass { MII_PHYSID2, "PHY ID 2 register" },
252e192b24SSimon Glass { MII_ADVERTISE, "Autonegotiation advertisement register" },
262e192b24SSimon Glass { MII_LPA, "Autonegotiation partner abilities register" },
272e192b24SSimon Glass };
282e192b24SSimon Glass
292e192b24SSimon Glass typedef struct _MII_field_desc_t {
302e192b24SSimon Glass ushort hi;
312e192b24SSimon Glass ushort lo;
322e192b24SSimon Glass ushort mask;
332e192b24SSimon Glass char * name;
342e192b24SSimon Glass } MII_field_desc_t;
352e192b24SSimon Glass
362e192b24SSimon Glass static const MII_field_desc_t reg_0_desc_tbl[] = {
372e192b24SSimon Glass { 15, 15, 0x01, "reset" },
382e192b24SSimon Glass { 14, 14, 0x01, "loopback" },
392e192b24SSimon Glass { 13, 6, 0x81, "speed selection" }, /* special */
402e192b24SSimon Glass { 12, 12, 0x01, "A/N enable" },
412e192b24SSimon Glass { 11, 11, 0x01, "power-down" },
422e192b24SSimon Glass { 10, 10, 0x01, "isolate" },
432e192b24SSimon Glass { 9, 9, 0x01, "restart A/N" },
442e192b24SSimon Glass { 8, 8, 0x01, "duplex" }, /* special */
452e192b24SSimon Glass { 7, 7, 0x01, "collision test enable" },
462e192b24SSimon Glass { 5, 0, 0x3f, "(reserved)" }
472e192b24SSimon Glass };
482e192b24SSimon Glass
492e192b24SSimon Glass static const MII_field_desc_t reg_1_desc_tbl[] = {
502e192b24SSimon Glass { 15, 15, 0x01, "100BASE-T4 able" },
512e192b24SSimon Glass { 14, 14, 0x01, "100BASE-X full duplex able" },
522e192b24SSimon Glass { 13, 13, 0x01, "100BASE-X half duplex able" },
532e192b24SSimon Glass { 12, 12, 0x01, "10 Mbps full duplex able" },
542e192b24SSimon Glass { 11, 11, 0x01, "10 Mbps half duplex able" },
552e192b24SSimon Glass { 10, 10, 0x01, "100BASE-T2 full duplex able" },
562e192b24SSimon Glass { 9, 9, 0x01, "100BASE-T2 half duplex able" },
572e192b24SSimon Glass { 8, 8, 0x01, "extended status" },
582e192b24SSimon Glass { 7, 7, 0x01, "(reserved)" },
592e192b24SSimon Glass { 6, 6, 0x01, "MF preamble suppression" },
602e192b24SSimon Glass { 5, 5, 0x01, "A/N complete" },
612e192b24SSimon Glass { 4, 4, 0x01, "remote fault" },
622e192b24SSimon Glass { 3, 3, 0x01, "A/N able" },
632e192b24SSimon Glass { 2, 2, 0x01, "link status" },
642e192b24SSimon Glass { 1, 1, 0x01, "jabber detect" },
652e192b24SSimon Glass { 0, 0, 0x01, "extended capabilities" },
662e192b24SSimon Glass };
672e192b24SSimon Glass
682e192b24SSimon Glass static const MII_field_desc_t reg_2_desc_tbl[] = {
692e192b24SSimon Glass { 15, 0, 0xffff, "OUI portion" },
702e192b24SSimon Glass };
712e192b24SSimon Glass
722e192b24SSimon Glass static const MII_field_desc_t reg_3_desc_tbl[] = {
732e192b24SSimon Glass { 15, 10, 0x3f, "OUI portion" },
742e192b24SSimon Glass { 9, 4, 0x3f, "manufacturer part number" },
752e192b24SSimon Glass { 3, 0, 0x0f, "manufacturer rev. number" },
762e192b24SSimon Glass };
772e192b24SSimon Glass
782e192b24SSimon Glass static const MII_field_desc_t reg_4_desc_tbl[] = {
792e192b24SSimon Glass { 15, 15, 0x01, "next page able" },
802e192b24SSimon Glass { 14, 14, 0x01, "(reserved)" },
812e192b24SSimon Glass { 13, 13, 0x01, "remote fault" },
822e192b24SSimon Glass { 12, 12, 0x01, "(reserved)" },
832e192b24SSimon Glass { 11, 11, 0x01, "asymmetric pause" },
842e192b24SSimon Glass { 10, 10, 0x01, "pause enable" },
852e192b24SSimon Glass { 9, 9, 0x01, "100BASE-T4 able" },
862e192b24SSimon Glass { 8, 8, 0x01, "100BASE-TX full duplex able" },
872e192b24SSimon Glass { 7, 7, 0x01, "100BASE-TX able" },
882e192b24SSimon Glass { 6, 6, 0x01, "10BASE-T full duplex able" },
892e192b24SSimon Glass { 5, 5, 0x01, "10BASE-T able" },
902e192b24SSimon Glass { 4, 0, 0x1f, "xxx to do" },
912e192b24SSimon Glass };
922e192b24SSimon Glass
932e192b24SSimon Glass static const MII_field_desc_t reg_5_desc_tbl[] = {
942e192b24SSimon Glass { 15, 15, 0x01, "next page able" },
952e192b24SSimon Glass { 14, 14, 0x01, "acknowledge" },
962e192b24SSimon Glass { 13, 13, 0x01, "remote fault" },
972e192b24SSimon Glass { 12, 12, 0x01, "(reserved)" },
982e192b24SSimon Glass { 11, 11, 0x01, "asymmetric pause able" },
992e192b24SSimon Glass { 10, 10, 0x01, "pause able" },
1002e192b24SSimon Glass { 9, 9, 0x01, "100BASE-T4 able" },
1012e192b24SSimon Glass { 8, 8, 0x01, "100BASE-X full duplex able" },
1022e192b24SSimon Glass { 7, 7, 0x01, "100BASE-TX able" },
1032e192b24SSimon Glass { 6, 6, 0x01, "10BASE-T full duplex able" },
1042e192b24SSimon Glass { 5, 5, 0x01, "10BASE-T able" },
1052e192b24SSimon Glass { 4, 0, 0x1f, "xxx to do" },
1062e192b24SSimon Glass };
1072e192b24SSimon Glass typedef struct _MII_field_desc_and_len_t {
1082e192b24SSimon Glass const MII_field_desc_t *pdesc;
1092e192b24SSimon Glass ushort len;
1102e192b24SSimon Glass } MII_field_desc_and_len_t;
1112e192b24SSimon Glass
1122e192b24SSimon Glass static const MII_field_desc_and_len_t desc_and_len_tbl[] = {
1132e192b24SSimon Glass { reg_0_desc_tbl, ARRAY_SIZE(reg_0_desc_tbl) },
1142e192b24SSimon Glass { reg_1_desc_tbl, ARRAY_SIZE(reg_1_desc_tbl) },
1152e192b24SSimon Glass { reg_2_desc_tbl, ARRAY_SIZE(reg_2_desc_tbl) },
1162e192b24SSimon Glass { reg_3_desc_tbl, ARRAY_SIZE(reg_3_desc_tbl) },
1172e192b24SSimon Glass { reg_4_desc_tbl, ARRAY_SIZE(reg_4_desc_tbl) },
1182e192b24SSimon Glass { reg_5_desc_tbl, ARRAY_SIZE(reg_5_desc_tbl) },
1192e192b24SSimon Glass };
1202e192b24SSimon Glass
1212e192b24SSimon Glass static void dump_reg(
1222e192b24SSimon Glass ushort regval,
1232e192b24SSimon Glass const MII_reg_desc_t *prd,
1242e192b24SSimon Glass const MII_field_desc_and_len_t *pdl);
1252e192b24SSimon Glass
1262e192b24SSimon Glass static int special_field(
1272e192b24SSimon Glass ushort regno,
1282e192b24SSimon Glass const MII_field_desc_t *pdesc,
1292e192b24SSimon Glass ushort regval);
1302e192b24SSimon Glass
MII_dump_0_to_5(ushort regvals[6],uchar reglo,uchar reghi)1312e192b24SSimon Glass static void MII_dump_0_to_5(
1322e192b24SSimon Glass ushort regvals[6],
1332e192b24SSimon Glass uchar reglo,
1342e192b24SSimon Glass uchar reghi)
1352e192b24SSimon Glass {
1362e192b24SSimon Glass ulong i;
1372e192b24SSimon Glass
1382e192b24SSimon Glass for (i = 0; i < 6; i++) {
1392e192b24SSimon Glass if ((reglo <= i) && (i <= reghi))
1402e192b24SSimon Glass dump_reg(regvals[i], ®_0_5_desc_tbl[i],
1412e192b24SSimon Glass &desc_and_len_tbl[i]);
1422e192b24SSimon Glass }
1432e192b24SSimon Glass }
1442e192b24SSimon Glass
dump_reg(ushort regval,const MII_reg_desc_t * prd,const MII_field_desc_and_len_t * pdl)1452e192b24SSimon Glass static void dump_reg(
1462e192b24SSimon Glass ushort regval,
1472e192b24SSimon Glass const MII_reg_desc_t *prd,
1482e192b24SSimon Glass const MII_field_desc_and_len_t *pdl)
1492e192b24SSimon Glass {
1502e192b24SSimon Glass ulong i;
1512e192b24SSimon Glass ushort mask_in_place;
1522e192b24SSimon Glass const MII_field_desc_t *pdesc;
1532e192b24SSimon Glass
1542e192b24SSimon Glass printf("%u. (%04hx) -- %s --\n",
1552e192b24SSimon Glass prd->regno, regval, prd->name);
1562e192b24SSimon Glass
1572e192b24SSimon Glass for (i = 0; i < pdl->len; i++) {
1582e192b24SSimon Glass pdesc = &pdl->pdesc[i];
1592e192b24SSimon Glass
1602e192b24SSimon Glass mask_in_place = pdesc->mask << pdesc->lo;
1612e192b24SSimon Glass
1622e192b24SSimon Glass printf(" (%04hx:%04x) %u.",
1632e192b24SSimon Glass mask_in_place,
1642e192b24SSimon Glass regval & mask_in_place,
1652e192b24SSimon Glass prd->regno);
1662e192b24SSimon Glass
1672e192b24SSimon Glass if (special_field(prd->regno, pdesc, regval)) {
1682e192b24SSimon Glass }
1692e192b24SSimon Glass else {
1702e192b24SSimon Glass if (pdesc->hi == pdesc->lo)
1712e192b24SSimon Glass printf("%2u ", pdesc->lo);
1722e192b24SSimon Glass else
1732e192b24SSimon Glass printf("%2u-%2u", pdesc->hi, pdesc->lo);
1742e192b24SSimon Glass printf(" = %5u %s",
1752e192b24SSimon Glass (regval & mask_in_place) >> pdesc->lo,
1762e192b24SSimon Glass pdesc->name);
1772e192b24SSimon Glass }
1782e192b24SSimon Glass printf("\n");
1792e192b24SSimon Glass
1802e192b24SSimon Glass }
1812e192b24SSimon Glass printf("\n");
1822e192b24SSimon Glass }
1832e192b24SSimon Glass
1842e192b24SSimon Glass /* Special fields:
1852e192b24SSimon Glass ** 0.6,13
1862e192b24SSimon Glass ** 0.8
1872e192b24SSimon Glass ** 2.15-0
1882e192b24SSimon Glass ** 3.15-0
1892e192b24SSimon Glass ** 4.4-0
1902e192b24SSimon Glass ** 5.4-0
1912e192b24SSimon Glass */
1922e192b24SSimon Glass
special_field(ushort regno,const MII_field_desc_t * pdesc,ushort regval)1932e192b24SSimon Glass static int special_field(
1942e192b24SSimon Glass ushort regno,
1952e192b24SSimon Glass const MII_field_desc_t *pdesc,
1962e192b24SSimon Glass ushort regval)
1972e192b24SSimon Glass {
1982e192b24SSimon Glass if ((regno == MII_BMCR) && (pdesc->lo == 6)) {
1992e192b24SSimon Glass ushort speed_bits = regval & (BMCR_SPEED1000 | BMCR_SPEED100);
2002e192b24SSimon Glass printf("%2u,%2u = b%u%u speed selection = %s Mbps",
2012e192b24SSimon Glass 6, 13,
2022e192b24SSimon Glass (regval >> 6) & 1,
2032e192b24SSimon Glass (regval >> 13) & 1,
2042e192b24SSimon Glass speed_bits == BMCR_SPEED1000 ? "1000" :
2052e192b24SSimon Glass speed_bits == BMCR_SPEED100 ? "100" :
2062e192b24SSimon Glass "10");
2072e192b24SSimon Glass return 1;
2082e192b24SSimon Glass }
2092e192b24SSimon Glass
2102e192b24SSimon Glass else if ((regno == MII_BMCR) && (pdesc->lo == 8)) {
2112e192b24SSimon Glass printf("%2u = %5u duplex = %s",
2122e192b24SSimon Glass pdesc->lo,
2132e192b24SSimon Glass (regval >> pdesc->lo) & 1,
2142e192b24SSimon Glass ((regval >> pdesc->lo) & 1) ? "full" : "half");
2152e192b24SSimon Glass return 1;
2162e192b24SSimon Glass }
2172e192b24SSimon Glass
2182e192b24SSimon Glass else if ((regno == MII_ADVERTISE) && (pdesc->lo == 0)) {
2192e192b24SSimon Glass ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
2202e192b24SSimon Glass printf("%2u-%2u = %5u selector = %s",
2212e192b24SSimon Glass pdesc->hi, pdesc->lo, sel_bits,
2222e192b24SSimon Glass sel_bits == PHY_ANLPAR_PSB_802_3 ?
2232e192b24SSimon Glass "IEEE 802.3" :
2242e192b24SSimon Glass sel_bits == PHY_ANLPAR_PSB_802_9 ?
2252e192b24SSimon Glass "IEEE 802.9 ISLAN-16T" :
2262e192b24SSimon Glass "???");
2272e192b24SSimon Glass return 1;
2282e192b24SSimon Glass }
2292e192b24SSimon Glass
2302e192b24SSimon Glass else if ((regno == MII_LPA) && (pdesc->lo == 0)) {
2312e192b24SSimon Glass ushort sel_bits = (regval >> pdesc->lo) & pdesc->mask;
2322e192b24SSimon Glass printf("%2u-%2u = %u selector = %s",
2332e192b24SSimon Glass pdesc->hi, pdesc->lo, sel_bits,
2342e192b24SSimon Glass sel_bits == PHY_ANLPAR_PSB_802_3 ?
2352e192b24SSimon Glass "IEEE 802.3" :
2362e192b24SSimon Glass sel_bits == PHY_ANLPAR_PSB_802_9 ?
2372e192b24SSimon Glass "IEEE 802.9 ISLAN-16T" :
2382e192b24SSimon Glass "???");
2392e192b24SSimon Glass return 1;
2402e192b24SSimon Glass }
2412e192b24SSimon Glass
2422e192b24SSimon Glass return 0;
2432e192b24SSimon Glass }
2442e192b24SSimon Glass
2452e192b24SSimon Glass static char last_op[2];
2462e192b24SSimon Glass static uint last_data;
2472e192b24SSimon Glass static uint last_addr_lo;
2482e192b24SSimon Glass static uint last_addr_hi;
2492e192b24SSimon Glass static uint last_reg_lo;
2502e192b24SSimon Glass static uint last_reg_hi;
2512e192b24SSimon Glass static uint last_mask;
2522e192b24SSimon Glass
extract_range(char * input,unsigned char * plo,unsigned char * phi)2532e192b24SSimon Glass static void extract_range(
2542e192b24SSimon Glass char * input,
2552e192b24SSimon Glass unsigned char * plo,
2562e192b24SSimon Glass unsigned char * phi)
2572e192b24SSimon Glass {
2582e192b24SSimon Glass char * end;
2592e192b24SSimon Glass *plo = simple_strtoul(input, &end, 16);
2602e192b24SSimon Glass if (*end == '-') {
2612e192b24SSimon Glass end++;
2622e192b24SSimon Glass *phi = simple_strtoul(end, NULL, 16);
2632e192b24SSimon Glass }
2642e192b24SSimon Glass else {
2652e192b24SSimon Glass *phi = *plo;
2662e192b24SSimon Glass }
2672e192b24SSimon Glass }
2682e192b24SSimon Glass
2692e192b24SSimon Glass /* ---------------------------------------------------------------- */
do_mii(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])2702e192b24SSimon Glass static int do_mii(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2712e192b24SSimon Glass {
2722e192b24SSimon Glass char op[2];
2732e192b24SSimon Glass unsigned char addrlo, addrhi, reglo, reghi;
2742e192b24SSimon Glass unsigned char addr, reg;
2752e192b24SSimon Glass unsigned short data, mask;
2762e192b24SSimon Glass int rcode = 0;
2772e192b24SSimon Glass const char *devname;
2782e192b24SSimon Glass
2792e192b24SSimon Glass if (argc < 2)
2802e192b24SSimon Glass return CMD_RET_USAGE;
2812e192b24SSimon Glass
2822e192b24SSimon Glass #if defined(CONFIG_MII_INIT)
2832e192b24SSimon Glass mii_init ();
2842e192b24SSimon Glass #endif
2852e192b24SSimon Glass
2862e192b24SSimon Glass /*
2872e192b24SSimon Glass * We use the last specified parameters, unless new ones are
2882e192b24SSimon Glass * entered.
2892e192b24SSimon Glass */
2902e192b24SSimon Glass op[0] = last_op[0];
2912e192b24SSimon Glass op[1] = last_op[1];
2922e192b24SSimon Glass addrlo = last_addr_lo;
2932e192b24SSimon Glass addrhi = last_addr_hi;
2942e192b24SSimon Glass reglo = last_reg_lo;
2952e192b24SSimon Glass reghi = last_reg_hi;
2962e192b24SSimon Glass data = last_data;
2972e192b24SSimon Glass mask = last_mask;
2982e192b24SSimon Glass
2992e192b24SSimon Glass if ((flag & CMD_FLAG_REPEAT) == 0) {
3002e192b24SSimon Glass op[0] = argv[1][0];
3012e192b24SSimon Glass if (strlen(argv[1]) > 1)
3022e192b24SSimon Glass op[1] = argv[1][1];
3032e192b24SSimon Glass else
3042e192b24SSimon Glass op[1] = '\0';
3052e192b24SSimon Glass
3062e192b24SSimon Glass if (argc >= 3)
3072e192b24SSimon Glass extract_range(argv[2], &addrlo, &addrhi);
3082e192b24SSimon Glass if (argc >= 4)
3092e192b24SSimon Glass extract_range(argv[3], ®lo, ®hi);
3102e192b24SSimon Glass if (argc >= 5)
3112e192b24SSimon Glass data = simple_strtoul(argv[4], NULL, 16);
3122e192b24SSimon Glass if (argc >= 6)
3132e192b24SSimon Glass mask = simple_strtoul(argv[5], NULL, 16);
3142e192b24SSimon Glass }
3152e192b24SSimon Glass
316*fb265a74SHector Palacios if (addrhi > 31 && strncmp(op, "de", 2)) {
3172e192b24SSimon Glass printf("Incorrect PHY address. Range should be 0-31\n");
3182e192b24SSimon Glass return CMD_RET_USAGE;
3192e192b24SSimon Glass }
3202e192b24SSimon Glass
3212e192b24SSimon Glass /* use current device */
3222e192b24SSimon Glass devname = miiphy_get_current_dev();
3232e192b24SSimon Glass
3242e192b24SSimon Glass /*
3252e192b24SSimon Glass * check info/read/write.
3262e192b24SSimon Glass */
3272e192b24SSimon Glass if (op[0] == 'i') {
3282e192b24SSimon Glass unsigned char j, start, end;
3292e192b24SSimon Glass unsigned int oui;
3302e192b24SSimon Glass unsigned char model;
3312e192b24SSimon Glass unsigned char rev;
3322e192b24SSimon Glass
3332e192b24SSimon Glass /*
3342e192b24SSimon Glass * Look for any and all PHYs. Valid addresses are 0..31.
3352e192b24SSimon Glass */
3362e192b24SSimon Glass if (argc >= 3) {
3372e192b24SSimon Glass start = addrlo; end = addrhi;
3382e192b24SSimon Glass } else {
3392e192b24SSimon Glass start = 0; end = 31;
3402e192b24SSimon Glass }
3412e192b24SSimon Glass
3422e192b24SSimon Glass for (j = start; j <= end; j++) {
3432e192b24SSimon Glass if (miiphy_info (devname, j, &oui, &model, &rev) == 0) {
3442e192b24SSimon Glass printf("PHY 0x%02X: "
3452e192b24SSimon Glass "OUI = 0x%04X, "
3462e192b24SSimon Glass "Model = 0x%02X, "
3472e192b24SSimon Glass "Rev = 0x%02X, "
3482e192b24SSimon Glass "%3dbase%s, %s\n",
3492e192b24SSimon Glass j, oui, model, rev,
3502e192b24SSimon Glass miiphy_speed (devname, j),
3512e192b24SSimon Glass miiphy_is_1000base_x (devname, j)
3522e192b24SSimon Glass ? "X" : "T",
3532e192b24SSimon Glass (miiphy_duplex (devname, j) == FULL)
3542e192b24SSimon Glass ? "FDX" : "HDX");
3552e192b24SSimon Glass }
3562e192b24SSimon Glass }
3572e192b24SSimon Glass } else if (op[0] == 'r') {
3582e192b24SSimon Glass for (addr = addrlo; addr <= addrhi; addr++) {
3592e192b24SSimon Glass for (reg = reglo; reg <= reghi; reg++) {
3602e192b24SSimon Glass data = 0xffff;
3612e192b24SSimon Glass if (miiphy_read (devname, addr, reg, &data) != 0) {
3622e192b24SSimon Glass printf(
3632e192b24SSimon Glass "Error reading from the PHY addr=%02x reg=%02x\n",
3642e192b24SSimon Glass addr, reg);
3652e192b24SSimon Glass rcode = 1;
3662e192b24SSimon Glass } else {
3672e192b24SSimon Glass if ((addrlo != addrhi) || (reglo != reghi))
3682e192b24SSimon Glass printf("addr=%02x reg=%02x data=",
3692e192b24SSimon Glass (uint)addr, (uint)reg);
3702e192b24SSimon Glass printf("%04X\n", data & 0x0000FFFF);
3712e192b24SSimon Glass }
3722e192b24SSimon Glass }
3732e192b24SSimon Glass if ((addrlo != addrhi) && (reglo != reghi))
3742e192b24SSimon Glass printf("\n");
3752e192b24SSimon Glass }
3762e192b24SSimon Glass } else if (op[0] == 'w') {
3772e192b24SSimon Glass for (addr = addrlo; addr <= addrhi; addr++) {
3782e192b24SSimon Glass for (reg = reglo; reg <= reghi; reg++) {
3792e192b24SSimon Glass if (miiphy_write (devname, addr, reg, data) != 0) {
3802e192b24SSimon Glass printf("Error writing to the PHY addr=%02x reg=%02x\n",
3812e192b24SSimon Glass addr, reg);
3822e192b24SSimon Glass rcode = 1;
3832e192b24SSimon Glass }
3842e192b24SSimon Glass }
3852e192b24SSimon Glass }
3862e192b24SSimon Glass } else if (op[0] == 'm') {
3872e192b24SSimon Glass for (addr = addrlo; addr <= addrhi; addr++) {
3882e192b24SSimon Glass for (reg = reglo; reg <= reghi; reg++) {
3892e192b24SSimon Glass unsigned short val = 0;
3902e192b24SSimon Glass if (miiphy_read(devname, addr,
3912e192b24SSimon Glass reg, &val)) {
3922e192b24SSimon Glass printf("Error reading from the PHY");
3932e192b24SSimon Glass printf(" addr=%02x", addr);
3942e192b24SSimon Glass printf(" reg=%02x\n", reg);
3952e192b24SSimon Glass rcode = 1;
3962e192b24SSimon Glass } else {
3972e192b24SSimon Glass val = (val & ~mask) | (data & mask);
3982e192b24SSimon Glass if (miiphy_write(devname, addr,
3992e192b24SSimon Glass reg, val)) {
4002e192b24SSimon Glass printf("Error writing to the PHY");
4012e192b24SSimon Glass printf(" addr=%02x", addr);
4022e192b24SSimon Glass printf(" reg=%02x\n", reg);
4032e192b24SSimon Glass rcode = 1;
4042e192b24SSimon Glass }
4052e192b24SSimon Glass }
4062e192b24SSimon Glass }
4072e192b24SSimon Glass }
4082e192b24SSimon Glass } else if (strncmp(op, "du", 2) == 0) {
4092e192b24SSimon Glass ushort regs[6];
4102e192b24SSimon Glass int ok = 1;
4112e192b24SSimon Glass if ((reglo > 5) || (reghi > 5)) {
4122e192b24SSimon Glass printf(
4132e192b24SSimon Glass "The MII dump command only formats the "
4142e192b24SSimon Glass "standard MII registers, 0-5.\n");
4152e192b24SSimon Glass return 1;
4162e192b24SSimon Glass }
4172e192b24SSimon Glass for (addr = addrlo; addr <= addrhi; addr++) {
4182e192b24SSimon Glass for (reg = reglo; reg < reghi + 1; reg++) {
4192e192b24SSimon Glass if (miiphy_read(devname, addr, reg, ®s[reg]) != 0) {
4202e192b24SSimon Glass ok = 0;
4212e192b24SSimon Glass printf(
4222e192b24SSimon Glass "Error reading from the PHY addr=%02x reg=%02x\n",
4232e192b24SSimon Glass addr, reg);
4242e192b24SSimon Glass rcode = 1;
4252e192b24SSimon Glass }
4262e192b24SSimon Glass }
4272e192b24SSimon Glass if (ok)
4282e192b24SSimon Glass MII_dump_0_to_5(regs, reglo, reghi);
4292e192b24SSimon Glass printf("\n");
4302e192b24SSimon Glass }
4312e192b24SSimon Glass } else if (strncmp(op, "de", 2) == 0) {
4322e192b24SSimon Glass if (argc == 2)
4332e192b24SSimon Glass miiphy_listdev ();
4342e192b24SSimon Glass else
4352e192b24SSimon Glass miiphy_set_current_dev (argv[2]);
4362e192b24SSimon Glass } else {
4372e192b24SSimon Glass return CMD_RET_USAGE;
4382e192b24SSimon Glass }
4392e192b24SSimon Glass
4402e192b24SSimon Glass /*
4412e192b24SSimon Glass * Save the parameters for repeats.
4422e192b24SSimon Glass */
4432e192b24SSimon Glass last_op[0] = op[0];
4442e192b24SSimon Glass last_op[1] = op[1];
4452e192b24SSimon Glass last_addr_lo = addrlo;
4462e192b24SSimon Glass last_addr_hi = addrhi;
4472e192b24SSimon Glass last_reg_lo = reglo;
4482e192b24SSimon Glass last_reg_hi = reghi;
4492e192b24SSimon Glass last_data = data;
4502e192b24SSimon Glass last_mask = mask;
4512e192b24SSimon Glass
4522e192b24SSimon Glass return rcode;
4532e192b24SSimon Glass }
4542e192b24SSimon Glass
4552e192b24SSimon Glass /***************************************************/
4562e192b24SSimon Glass
4572e192b24SSimon Glass U_BOOT_CMD(
4582e192b24SSimon Glass mii, 6, 1, do_mii,
4592e192b24SSimon Glass "MII utility commands",
4602e192b24SSimon Glass "device - list available devices\n"
4612e192b24SSimon Glass "mii device <devname> - set current device\n"
4622e192b24SSimon Glass "mii info <addr> - display MII PHY info\n"
4632e192b24SSimon Glass "mii read <addr> <reg> - read MII PHY <addr> register <reg>\n"
4642e192b24SSimon Glass "mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
4652e192b24SSimon Glass "mii modify <addr> <reg> <data> <mask> - modify MII PHY <addr> register <reg>\n"
4662e192b24SSimon Glass " updating bits identified in <mask>\n"
4672e192b24SSimon Glass "mii dump <addr> <reg> - pretty-print <addr> <reg> (0-5 only)\n"
4682e192b24SSimon Glass "Addr and/or reg may be ranges, e.g. 2-7."
4692e192b24SSimon Glass );
470