xref: /openbmc/u-boot/cmd/mii.c (revision 2f07a9a6)
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], &reg_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], &reglo, &reghi);
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, &regs[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