linux: implement regdump of phys via debugfs

Allow a regdump of the phy register space via debugfs.
hexdump /sys/kernel/debug/mdio_bus/ag71xx_mdio/ag71xx-mdio.1:00/regdump
This commit is contained in:
Alexander Couzens 2015-05-26 18:52:49 +02:00
parent fe3973c6b1
commit 820cfa16a7
1 changed files with 160 additions and 0 deletions

View File

@ -0,0 +1,160 @@
Index: linux-3.10.49/drivers/net/phy/mdio_bus.c
===================================================================
--- linux-3.10.49.orig/drivers/net/phy/mdio_bus.c
+++ linux-3.10.49/drivers/net/phy/mdio_bus.c
@@ -36,6 +36,7 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/debugfs.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -127,6 +128,82 @@ struct mii_bus *of_mdio_find_bus(struct
EXPORT_SYMBOL(of_mdio_find_bus);
#endif
+struct dentry *mdiobus_debug_root;
+EXPORT_SYMBOL_GPL(mdiobus_debug_root);
+
+static int mdiobus_debugfs_init(void)
+{
+ mdiobus_debug_root = debugfs_create_dir("mdio_bus", NULL);
+ if (!mdiobus_debug_root)
+ return -ENOENT;
+ return 0;
+}
+
+static void mdiobus_debugfs_cleanup(void)
+{
+ debugfs_remove(mdiobus_debug_root);
+}
+
+
+static void mdiobus_debugfs_del(struct mii_bus *bus)
+{
+ debugfs_remove_recursive(bus->debugfs_dir);
+ bus->debugfs_dir = NULL;
+}
+
+static int mdiobus_debugfs_add(struct mii_bus *bus)
+{
+ bus->debugfs_dir = debugfs_create_dir(bus->name, mdiobus_debug_root);
+ if (!bus->debugfs_dir)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int phy_dump_show(struct seq_file *seq, void *v)
+{
+ int ret = 0, i;
+ u16 *buffer = NULL;
+ struct phy_device *phy = seq->private;
+
+ buffer = kzalloc(32 * sizeof(u16), GFP_KERNEL);
+ if (!buffer) {
+ return -ENOMEM;
+ }
+
+ for (i=0; i<32; i++) {
+ buffer[i] = mdiobus_read(phy->bus, phy->addr, i) & 0xffff;
+ }
+ ret = seq_write(seq, buffer, 32 * sizeof(*buffer));
+
+ kfree(buffer);
+ return ret;
+}
+
+static int phy_dump_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, phy_dump_show, inode->i_private);
+}
+
+static const struct file_operations phy_dump_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = phy_dump_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+
+void mdiobus_debugfs_add_phy(struct mii_bus *bus, struct phy_device *phydev)
+{
+ struct dentry *parent = debugfs_create_dir(dev_name(&phydev->dev), bus->debugfs_dir);
+ if (!parent)
+ return;
+
+ debugfs_create_file("regdump", S_IRUSR, parent,
+ (void *)phydev, &phy_dump_debugfs_fops);
+}
+
/**
* mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
* @bus: target mii_bus
@@ -159,6 +236,8 @@ int mdiobus_register(struct mii_bus *bus
return -EINVAL;
}
+ mdiobus_debugfs_add(bus);
+
mutex_init(&bus->mdio_lock);
if (bus->reset)
@@ -173,6 +252,8 @@ int mdiobus_register(struct mii_bus *bus
err = PTR_ERR(phydev);
goto error;
}
+ if (phydev)
+ mdiobus_debugfs_add_phy(bus, phydev);
}
}
@@ -185,6 +266,7 @@ error:
if (bus->phy_map[i])
device_unregister(&bus->phy_map[i]->dev);
}
+ mdiobus_debugfs_del(bus);
device_del(&bus->dev);
return err;
}
@@ -476,11 +558,14 @@ int __init mdio_bus_init(void)
{
int ret;
+ mdiobus_debugfs_init();
ret = class_register(&mdio_bus_class);
if (!ret) {
ret = bus_register(&mdio_bus_type);
- if (ret)
+ if (ret) {
class_unregister(&mdio_bus_class);
+ mdiobus_debugfs_cleanup();
+ }
}
return ret;
@@ -488,6 +573,7 @@ int __init mdio_bus_init(void)
void mdio_bus_exit(void)
{
+ mdiobus_debugfs_cleanup();
class_unregister(&mdio_bus_class);
bus_unregister(&mdio_bus_type);
}
Index: linux-3.10.49/include/linux/phy.h
===================================================================
--- linux-3.10.49.orig/include/linux/phy.h
+++ linux-3.10.49/include/linux/phy.h
@@ -128,6 +128,10 @@ struct mii_bus {
* interrupt at the index matching its address
*/
int *irq;
+#ifdef CONFIG_DEBUG_FS
+ /* debugfs directory node */
+ struct dentry *debugfs_dir;
+#endif
};
#define to_mii_bus(d) container_of(d, struct mii_bus, dev)