diff options
author | Andrey Smirnov <andrew.smirnov@gmail.com> | 2016-01-31 19:10:13 -0800 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-02-04 08:10:39 +0100 |
commit | ae2fb9b9184f9b9b70caf01ecbd0dcc64d7c1cc0 (patch) | |
tree | 6a4ae2fa332ff49e2d78c65ab86df6baebed7cf2 | |
parent | 993a28aa48f26da8d7e06ee4c3011c66c47df8c9 (diff) | |
download | barebox-ae2fb9b9184f9b9b70caf01ecbd0dcc64d7c1cc0.tar.gz barebox-ae2fb9b9184f9b9b70caf01ecbd0dcc64d7c1cc0.tar.xz |
miitool: Add code to register a PHY
This commit changes the behaviour of the 'miitool'. Now in order to show
PHY's link information 'miitool' should be invoked as such:
miitool -s [PHY]
Also, implment code to allow to register a dummy PHY device in order to
be able to perform raw MDIO bus access.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | commands/miitool.c | 94 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 9 | ||||
-rw-r--r-- | include/linux/phy.h | 1 |
3 files changed, 84 insertions, 20 deletions
diff --git a/commands/miitool.c b/commands/miitool.c index 9ea5ab5cd3..ba6e604633 100644 --- a/commands/miitool.c +++ b/commands/miitool.c @@ -260,53 +260,111 @@ static void mdiobus_show(struct device_d *dev, char *phydevname, int verbose) return; } +enum miitool_operations { + MIITOOL_NOOP, + MIITOOL_SHOW, + MIITOOL_REGISTER, +}; + static int do_miitool(int argc, char *argv[]) { - char *phydevname; + char *phydevname = NULL; + char *regstr = NULL; + char *endp; struct mii_bus *mii; - int opt; - int argc_min; - int verbose; + int opt, ret; + int verbose = 0; + struct phy_device *phydev; + enum miitool_operations action = MIITOOL_NOOP; + int addr, bus; - verbose = 0; - while ((opt = getopt(argc, argv, "v")) > 0) { + while ((opt = getopt(argc, argv, "vs:r:")) > 0) { switch (opt) { + case 'a': + addr = simple_strtol(optarg, NULL, 0); + break; + case 'b': + bus = simple_strtoul(optarg, NULL, 0); + break; + case 's': + action = MIITOOL_SHOW; + phydevname = xstrdup(optarg); + break; + case 'r': + action = MIITOOL_REGISTER; + regstr = optarg; + break; case 'v': verbose++; break; default: - return COMMAND_ERROR_USAGE; + ret = COMMAND_ERROR_USAGE; + goto free_phydevname; } } - argc_min = optind + 1; + switch (action) { + case MIITOOL_REGISTER: + bus = simple_strtoul(regstr, &endp, 0); + if (*endp != ':') { + printf("No colon between bus and address\n"); + return COMMAND_ERROR_USAGE; + } + endp++; + addr = simple_strtoul(endp, NULL, 0); + + if (addr >= PHY_MAX_ADDR) + printf("Address out of range (max %d)\n", PHY_MAX_ADDR - 1); - phydevname = NULL; - if (argc >= argc_min) { - phydevname = argv[optind]; - } + mii = mdiobus_get_bus(bus); + if (!mii) { + printf("Can't find MDIO bus #%d\n", bus); + ret = COMMAND_ERROR; + goto free_phydevname; + } - for_each_mii_bus(mii) { - mdiobus_detect(&mii->dev); - mdiobus_show(&mii->dev, phydevname, verbose); + phydev = phy_device_create(mii, addr, -1); + ret = phy_register_device(phydev); + if (ret) { + printf("failed to register phy %s: %s\n", + dev_name(&phydev->dev), strerror(-ret)); + goto free_phydevname; + } else { + printf("registered phy %s\n", dev_name(&phydev->dev)); + } + break; + default: + case MIITOOL_SHOW: + for_each_mii_bus(mii) { + mdiobus_detect(&mii->dev); + mdiobus_show(&mii->dev, phydevname, verbose); + } + break; } - return COMMAND_SUCCESS; + ret = COMMAND_SUCCESS; + +free_phydevname: + free(phydevname); + return ret; } BAREBOX_CMD_HELP_START(miitool) BAREBOX_CMD_HELP_TEXT("This utility checks or sets the status of a network interface's") -BAREBOX_CMD_HELP_TEXT("Media Independent Interface (MII) unit. Most fast ethernet") +BAREBOX_CMD_HELP_TEXT("Media Independent Interface (MII) unit as well as allowing to") +BAREBOX_CMD_HELP_TEXT("register dummy PHY devices for raw MDIO access. Most fast ethernet") BAREBOX_CMD_HELP_TEXT("adapters use an MII to autonegotiate link speed and duplex setting.") BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT("-v", "increase verbosity") +BAREBOX_CMD_HELP_OPT("-s <devname>", "show PHY status (not providing PHY prints status of all)") +BAREBOX_CMD_HELP_OPT("-r <busno>:<adr>", "register a PHY") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(miitool) .cmd = do_miitool, BAREBOX_CMD_DESC("view media-independent interface status") - BAREBOX_CMD_OPTS("[-v] PHY") + BAREBOX_CMD_OPTS("[-vsr]") BAREBOX_CMD_GROUP(CMD_GRP_NET) BAREBOX_CMD_HELP(cmd_miitool_help) BAREBOX_CMD_END diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index d128a5e8d5..be2c68bf68 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -147,8 +147,13 @@ int phy_scan_fixups(struct phy_device *phydev) return 0; } - -static struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id) +/** + * phy_device_create - creates a struct phy_device. + * @bus: the target MII bus + * @addr: PHY address on the MII bus + * @phy_id: PHY ID. + */ +struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id) { struct phy_device *phydev; diff --git a/include/linux/phy.h b/include/linux/phy.h index 4e88936bad..38b0670187 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -271,6 +271,7 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr); int phy_init(void); int phy_init_hw(struct phy_device *phydev); +struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id); int phy_register_device(struct phy_device* dev); void phy_unregister_device(struct phy_device *phydev); |