net: add support for extended registers to mdio command

Some phys (Micrel) have additional registers that can
be accessed using a special sequence. This patch allows
to use standard "mdio" command to accesss these registers.

Signed-off-by: Stefano Babic <sbabic@denx.de>
master
Stefano Babic 11 years ago committed by Joe Hershberger
parent 9ced16fefa
commit 26b807c4f8
  1. 75
      common/cmd_mdio.c

@ -41,9 +41,11 @@ static int extract_range(char *input, int *plo, int *phi)
return 0; return 0;
} }
static int mdio_write_ranges(struct mii_dev *bus, int addrlo, static int mdio_write_ranges(struct phy_device *phydev, struct mii_dev *bus,
int addrlo,
int addrhi, int devadlo, int devadhi, int addrhi, int devadlo, int devadhi,
int reglo, int reghi, unsigned short data) int reglo, int reghi, unsigned short data,
int extended)
{ {
int addr, devad, reg; int addr, devad, reg;
int err = 0; int err = 0;
@ -51,7 +53,12 @@ static int mdio_write_ranges(struct mii_dev *bus, int addrlo,
for (addr = addrlo; addr <= addrhi; addr++) { for (addr = addrlo; addr <= addrhi; addr++) {
for (devad = devadlo; devad <= devadhi; devad++) { for (devad = devadlo; devad <= devadhi; devad++) {
for (reg = reglo; reg <= reghi; reg++) { for (reg = reglo; reg <= reghi; reg++) {
err = bus->write(bus, addr, devad, reg, data); if (!extended)
err = bus->write(bus, addr, devad,
reg, data);
else
err = phydev->drv->writeext(phydev,
addr, devad, reg, data);
if (err) if (err)
goto err_out; goto err_out;
@ -63,9 +70,10 @@ err_out:
return err; return err;
} }
static int mdio_read_ranges(struct mii_dev *bus, int addrlo, static int mdio_read_ranges(struct phy_device *phydev, struct mii_dev *bus,
int addrlo,
int addrhi, int devadlo, int devadhi, int addrhi, int devadlo, int devadhi,
int reglo, int reghi) int reglo, int reghi, int extended)
{ {
int addr, devad, reg; int addr, devad, reg;
@ -77,7 +85,12 @@ static int mdio_read_ranges(struct mii_dev *bus, int addrlo,
for (reg = reglo; reg <= reghi; reg++) { for (reg = reglo; reg <= reghi; reg++) {
int val; int val;
val = bus->read(bus, addr, devad, reg); if (!extended)
val = bus->read(bus, addr, devad, reg);
else
val = phydev->drv->readext(phydev, addr,
devad, reg);
if (val < 0) { if (val < 0) {
printf("Error\n"); printf("Error\n");
@ -126,9 +139,10 @@ static int extract_reg_range(char *input, int *devadlo, int *devadhi,
} }
static int extract_phy_range(char *const argv[], int argc, struct mii_dev **bus, static int extract_phy_range(char *const argv[], int argc, struct mii_dev **bus,
struct phy_device **phydev,
int *addrlo, int *addrhi) int *addrlo, int *addrhi)
{ {
struct phy_device *phydev; struct phy_device *dev = *phydev;
if ((argc < 1) || (argc > 2)) if ((argc < 1) || (argc > 2))
return -1; return -1;
@ -154,11 +168,11 @@ static int extract_phy_range(char *const argv[], int argc, struct mii_dev **bus,
* device by the given name. If none are found, we call * device by the given name. If none are found, we call
* extract_range() on the string, and see if it's an address range. * extract_range() on the string, and see if it's an address range.
*/ */
phydev = mdio_phydev_for_ethname(argv[0]); dev = mdio_phydev_for_ethname(argv[0]);
if (phydev) { if (dev) {
*addrlo = *addrhi = phydev->addr; *addrlo = *addrhi = dev->addr;
*bus = phydev->bus; *bus = dev->bus;
return 0; return 0;
} }
@ -175,6 +189,8 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
unsigned short data; unsigned short data;
int pos = argc - 1; int pos = argc - 1;
struct mii_dev *bus; struct mii_dev *bus;
struct phy_device *phydev = NULL;
int extended = 0;
if (argc < 2) if (argc < 2)
return CMD_RET_USAGE; return CMD_RET_USAGE;
@ -197,6 +213,29 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (flag & CMD_FLAG_REPEAT) if (flag & CMD_FLAG_REPEAT)
op[0] = last_op[0]; op[0] = last_op[0];
if (strlen(argv[1]) > 1) {
op[1] = argv[1][1];
if (op[1] == 'x') {
phydev = mdio_phydev_for_ethname(argv[2]);
if (phydev) {
addrlo = phydev->addr;
addrhi = addrlo;
bus = phydev->bus;
extended = 1;
} else {
return -1;
}
if (!phydev->drv ||
(!phydev->drv->writeext && (op[0] == 'w')) ||
(!phydev->drv->readext && (op[0] == 'r'))) {
puts("PHY does not have extended functions\n");
return -1;
}
}
}
switch (op[0]) { switch (op[0]) {
case 'w': case 'w':
if (pos > 1) if (pos > 1)
@ -210,7 +249,7 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
default: default:
if (pos > 1) if (pos > 1)
if (extract_phy_range(&(argv[2]), pos - 1, &bus, if (extract_phy_range(&(argv[2]), pos - 1, &bus,
&addrlo, &addrhi)) &phydev, &addrlo, &addrhi))
return -1; return -1;
break; break;
@ -227,13 +266,13 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
switch (op[0]) { switch (op[0]) {
case 'w': case 'w':
mdio_write_ranges(bus, addrlo, addrhi, devadlo, devadhi, mdio_write_ranges(phydev, bus, addrlo, addrhi, devadlo, devadhi,
reglo, reghi, data); reglo, reghi, data, extended);
break; break;
case 'r': case 'r':
mdio_read_ranges(bus, addrlo, addrhi, devadlo, devadhi, mdio_read_ranges(phydev, bus, addrlo, addrhi, devadlo, devadhi,
reglo, reghi); reglo, reghi, extended);
break; break;
} }
@ -262,6 +301,10 @@ U_BOOT_CMD(
"read PHY's register at <devad>.<reg>\n" "read PHY's register at <devad>.<reg>\n"
"mdio write <phydev> [<devad>.]<reg> <data> - " "mdio write <phydev> [<devad>.]<reg> <data> - "
"write PHY's register at <devad>.<reg>\n" "write PHY's register at <devad>.<reg>\n"
"mdio rx <phydev> [<devad>.]<reg> - "
"read PHY's extended register at <devad>.<reg>\n"
"mdio wx <phydev> [<devad>.]<reg> <data> - "
"write PHY's extended register at <devad>.<reg>\n"
"<phydev> may be:\n" "<phydev> may be:\n"
" <busname> <addr>\n" " <busname> <addr>\n"
" <addr>\n" " <addr>\n"

Loading…
Cancel
Save