dsa: mv88x6xxx: Add debugfs interface for scratch registers
authorAndrew Lunn <andrew@lunn.ch>
Sat, 20 Jun 2015 16:42:33 +0000 (18:42 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 23 Jun 2015 13:33:42 +0000 (06:33 -0700)
Allow the contents of the scratch registers to be shown in debugfs.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx.c
drivers/net/dsa/mv88e6xxx.h

index 7e12a31e9dae4ccd0ee6e12851f6e75beb704f80..c938d7ce5215a93623a67acd634a4dc6d539f814 100644 (file)
@@ -901,6 +901,13 @@ static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
                               GLOBAL_ATU_OP_BUSY);
 }
 
+/* Must be called with SMI lock held */
+static int _mv88e6xxx_scratch_wait(struct dsa_switch *ds)
+{
+       return _mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SCRATCH_MISC,
+                              GLOBAL2_SCRATCH_BUSY);
+}
+
 /* Must be called with SMI mutex held */
 static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr,
                                        int regnum)
@@ -1825,6 +1832,50 @@ static const struct file_operations mv88e6xxx_device_map_fops = {
        .owner  = THIS_MODULE,
 };
 
+static int mv88e6xxx_scratch_show(struct seq_file *s, void *p)
+{
+       struct dsa_switch *ds = s->private;
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       int reg, ret;
+
+       seq_puts(s, "Register Value\n");
+
+       mutex_lock(&ps->smi_mutex);
+       for (reg = 0; reg < 0x80; reg++) {
+               ret = _mv88e6xxx_reg_write(
+                       ds, REG_GLOBAL2, GLOBAL2_SCRATCH_MISC,
+                       reg << GLOBAL2_SCRATCH_REGISTER_SHIFT);
+               if (ret < 0)
+                       goto out;
+
+               ret = _mv88e6xxx_scratch_wait(ds);
+               if (ret < 0)
+                       goto out;
+
+               ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL2,
+                                         GLOBAL2_SCRATCH_MISC);
+               seq_printf(s, "  %2x   %2x\n", reg,
+                          ret & GLOBAL2_SCRATCH_VALUE_MASK);
+       }
+out:
+       mutex_unlock(&ps->smi_mutex);
+
+       return 0;
+}
+
+static int mv88e6xxx_scratch_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mv88e6xxx_scratch_show, inode->i_private);
+}
+
+static const struct file_operations mv88e6xxx_scratch_fops = {
+       .open   = mv88e6xxx_scratch_open,
+       .read   = seq_read,
+       .llseek = no_llseek,
+       .release = single_release,
+       .owner  = THIS_MODULE,
+};
+
 int mv88e6xxx_setup_common(struct dsa_switch *ds)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -1853,6 +1904,9 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
 
        debugfs_create_file("device_map", S_IRUGO, ps->dbgfs, ds,
                            &mv88e6xxx_device_map_fops);
+
+       debugfs_create_file("scratch", S_IRUGO, ps->dbgfs, ds,
+                           &mv88e6xxx_scratch_fops);
        return 0;
 }
 
index a2c9ac0c54ab047d72699dc4d50e447da0266b5e..a650b2656de9f0c4b8181bc3d3b3a4c533b4aa7a 100644 (file)
 #define GLOBAL2_SMI_OP_45_READ_DATA    ((2 << 10) | GLOBAL2_SMI_OP_BUSY)
 #define GLOBAL2_SMI_DATA       0x19
 #define GLOBAL2_SCRATCH_MISC   0x1a
+#define GLOBAL2_SCRATCH_BUSY           BIT(15)
+#define GLOBAL2_SCRATCH_REGISTER_SHIFT 8
+#define GLOBAL2_SCRATCH_VALUE_MASK     0xff
 #define GLOBAL2_WDOG_CONTROL   0x1b
 #define GLOBAL2_QOS_WEIGHT     0x1c
 #define GLOBAL2_MISC           0x1d