|
9 | 9 | #include <linux/pm_runtime.h> |
10 | 10 | #include <linux/slab.h> |
11 | 11 | #include <linux/soundwire/sdw.h> |
| 12 | +#include <linux/soundwire/sdw_type.h> |
12 | 13 | #include <linux/soundwire/sdw_registers.h> |
13 | 14 | #include <linux/string_choices.h> |
14 | 15 | #include "bus.h" |
15 | 16 |
|
16 | 17 | static struct dentry *sdw_debugfs_root; |
17 | 18 |
|
| 19 | +#define SDW_PERIPH_HEADER_FMT "%-28s %-7s %-16s %-6s %-7s %-8s %-9s %-11s\n" |
| 20 | +#define SDW_PERIPH_ENTRY_FMT "%-28s %-7u %#016llx %-6.4x %-7.4x %-8.2x %-9.2x %-11.1x\n" |
| 21 | + |
| 22 | +static u64 sdw_slave_addr_from_id(struct sdw_bus *bus, |
| 23 | + const struct sdw_slave_id *id) |
| 24 | +{ |
| 25 | + u64 addr = 0; |
| 26 | + u8 unique_id = id->unique_id; |
| 27 | + |
| 28 | + if (unique_id == SDW_IGNORED_UNIQUE_ID) |
| 29 | + unique_id = 0; |
| 30 | + |
| 31 | + addr |= FIELD_PREP(SDW_DISCO_LINK_ID_MASK, bus->link_id); |
| 32 | + addr |= FIELD_PREP(SDW_VERSION_MASK, id->sdw_version); |
| 33 | + addr |= FIELD_PREP(SDW_UNIQUE_ID_MASK, unique_id); |
| 34 | + addr |= FIELD_PREP(SDW_MFG_ID_MASK, id->mfg_id); |
| 35 | + addr |= FIELD_PREP(SDW_PART_ID_MASK, id->part_id); |
| 36 | + addr |= FIELD_PREP(SDW_CLASS_ID_MASK, id->class_id); |
| 37 | + |
| 38 | + return addr; |
| 39 | +} |
| 40 | + |
| 41 | +static void sdw_dump_bus_peripherals(struct seq_file *s_file, struct sdw_bus *bus) |
| 42 | +{ |
| 43 | + struct sdw_slave *slave; |
| 44 | + u64 addr; |
| 45 | + |
| 46 | + seq_printf(s_file, "master-%d-%d\n", |
| 47 | + bus->controller_id, bus->link_id); |
| 48 | + seq_printf(s_file, SDW_PERIPH_HEADER_FMT, |
| 49 | + "name", "dev_num", "addr", "mfg_id", "part_id", |
| 50 | + "class_id", "unique_id", "sdw_version"); |
| 51 | + |
| 52 | + mutex_lock(&bus->bus_lock); |
| 53 | + list_for_each_entry(slave, &bus->slaves, node) { |
| 54 | + addr = sdw_slave_addr_from_id(bus, &slave->id); |
| 55 | + seq_printf(s_file, SDW_PERIPH_ENTRY_FMT, |
| 56 | + dev_name(&slave->dev), slave->dev_num, |
| 57 | + addr, |
| 58 | + slave->id.mfg_id, slave->id.part_id, |
| 59 | + slave->id.class_id, slave->id.unique_id, |
| 60 | + slave->id.sdw_version); |
| 61 | + } |
| 62 | + mutex_unlock(&bus->bus_lock); |
| 63 | + |
| 64 | + seq_putc(s_file, '\n'); |
| 65 | +} |
| 66 | + |
| 67 | +static int sdw_root_peripherals_dump(struct device *dev, void *data) |
| 68 | +{ |
| 69 | + struct sdw_master_device *md; |
| 70 | + struct seq_file *s_file = data; |
| 71 | + |
| 72 | + if (dev->type != &sdw_master_type) |
| 73 | + return 0; |
| 74 | + |
| 75 | + md = dev_to_sdw_master_device(dev); |
| 76 | + sdw_dump_bus_peripherals(s_file, md->bus); |
| 77 | + |
| 78 | + return 0; |
| 79 | +} |
| 80 | + |
| 81 | +static int sdw_root_peripherals_show(struct seq_file *s_file, void *data) |
| 82 | +{ |
| 83 | + return bus_for_each_dev(&sdw_bus_type, NULL, s_file, |
| 84 | + sdw_root_peripherals_dump); |
| 85 | +} |
| 86 | +DEFINE_SHOW_ATTRIBUTE(sdw_root_peripherals); |
| 87 | + |
18 | 88 | void sdw_bus_debugfs_init(struct sdw_bus *bus) |
19 | 89 | { |
20 | 90 | char name[16]; |
@@ -375,6 +445,8 @@ void sdw_debugfs_init(void) |
375 | 445 | firmware_file = kstrdup("", GFP_KERNEL); |
376 | 446 |
|
377 | 447 | sdw_debugfs_root = debugfs_create_dir("soundwire", NULL); |
| 448 | + debugfs_create_file("peripherals", 0400, sdw_debugfs_root, NULL, |
| 449 | + &sdw_root_peripherals_fops); |
378 | 450 | } |
379 | 451 |
|
380 | 452 | void sdw_debugfs_exit(void) |
|
0 commit comments