linux/drivers/soundwire/debugfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2// Copyright(c) 2017-2019 Intel Corporation.
   3
   4#include <linux/device.h>
   5#include <linux/debugfs.h>
   6#include <linux/mod_devicetable.h>
   7#include <linux/slab.h>
   8#include <linux/soundwire/sdw.h>
   9#include <linux/soundwire/sdw_registers.h>
  10#include "bus.h"
  11
  12static struct dentry *sdw_debugfs_root;
  13
  14void sdw_bus_debugfs_init(struct sdw_bus *bus)
  15{
  16        char name[16];
  17
  18        if (!sdw_debugfs_root)
  19                return;
  20
  21        /* create the debugfs master-N */
  22        snprintf(name, sizeof(name), "master-%d", bus->link_id);
  23        bus->debugfs = debugfs_create_dir(name, sdw_debugfs_root);
  24}
  25
  26void sdw_bus_debugfs_exit(struct sdw_bus *bus)
  27{
  28        debugfs_remove_recursive(bus->debugfs);
  29}
  30
  31#define RD_BUF (3 * PAGE_SIZE)
  32
  33static ssize_t sdw_sprintf(struct sdw_slave *slave,
  34                           char *buf, size_t pos, unsigned int reg)
  35{
  36        int value;
  37
  38        value = sdw_read(slave, reg);
  39
  40        if (value < 0)
  41                return scnprintf(buf + pos, RD_BUF - pos, "%3x\tXX\n", reg);
  42        else
  43                return scnprintf(buf + pos, RD_BUF - pos,
  44                                "%3x\t%2x\n", reg, value);
  45}
  46
  47static int sdw_slave_reg_show(struct seq_file *s_file, void *data)
  48{
  49        struct sdw_slave *slave = s_file->private;
  50        char *buf;
  51        ssize_t ret;
  52        int i, j;
  53
  54        buf = kzalloc(RD_BUF, GFP_KERNEL);
  55        if (!buf)
  56                return -ENOMEM;
  57
  58        ret = scnprintf(buf, RD_BUF, "Register  Value\n");
  59
  60        /* DP0 non-banked registers */
  61        ret += scnprintf(buf + ret, RD_BUF - ret, "\nDP0\n");
  62        for (i = SDW_DP0_INT; i <= SDW_DP0_PREPARECTRL; i++)
  63                ret += sdw_sprintf(slave, buf, ret, i);
  64
  65        /* DP0 Bank 0 registers */
  66        ret += scnprintf(buf + ret, RD_BUF - ret, "Bank0\n");
  67        ret += sdw_sprintf(slave, buf, ret, SDW_DP0_CHANNELEN);
  68        for (i = SDW_DP0_SAMPLECTRL1; i <= SDW_DP0_LANECTRL; i++)
  69                ret += sdw_sprintf(slave, buf, ret, i);
  70
  71        /* DP0 Bank 1 registers */
  72        ret += scnprintf(buf + ret, RD_BUF - ret, "Bank1\n");
  73        ret += sdw_sprintf(slave, buf, ret,
  74                        SDW_DP0_CHANNELEN + SDW_BANK1_OFFSET);
  75        for (i = SDW_DP0_SAMPLECTRL1 + SDW_BANK1_OFFSET;
  76                        i <= SDW_DP0_LANECTRL + SDW_BANK1_OFFSET; i++)
  77                ret += sdw_sprintf(slave, buf, ret, i);
  78
  79        /* SCP registers */
  80        ret += scnprintf(buf + ret, RD_BUF - ret, "\nSCP\n");
  81        for (i = SDW_SCP_INT1; i <= SDW_SCP_BANKDELAY; i++)
  82                ret += sdw_sprintf(slave, buf, ret, i);
  83        for (i = SDW_SCP_DEVID_0; i <= SDW_SCP_DEVID_5; i++)
  84                ret += sdw_sprintf(slave, buf, ret, i);
  85
  86        /*
  87         * SCP Bank 0/1 registers are read-only and cannot be
  88         * retrieved from the Slave. The Master typically keeps track
  89         * of the current frame size so the information can be found
  90         * in other places
  91         */
  92
  93        /* DP1..14 registers */
  94        for (i = 1; SDW_VALID_PORT_RANGE(i); i++) {
  95
  96                /* DPi registers */
  97                ret += scnprintf(buf + ret, RD_BUF - ret, "\nDP%d\n", i);
  98                for (j = SDW_DPN_INT(i); j <= SDW_DPN_PREPARECTRL(i); j++)
  99                        ret += sdw_sprintf(slave, buf, ret, j);
 100
 101                /* DPi Bank0 registers */
 102                ret += scnprintf(buf + ret, RD_BUF - ret, "Bank0\n");
 103                for (j = SDW_DPN_CHANNELEN_B0(i);
 104                     j <= SDW_DPN_LANECTRL_B0(i); j++)
 105                        ret += sdw_sprintf(slave, buf, ret, j);
 106
 107                /* DPi Bank1 registers */
 108                ret += scnprintf(buf + ret, RD_BUF - ret, "Bank1\n");
 109                for (j = SDW_DPN_CHANNELEN_B1(i);
 110                     j <= SDW_DPN_LANECTRL_B1(i); j++)
 111                        ret += sdw_sprintf(slave, buf, ret, j);
 112        }
 113
 114        seq_printf(s_file, "%s", buf);
 115        kfree(buf);
 116
 117        return 0;
 118}
 119DEFINE_SHOW_ATTRIBUTE(sdw_slave_reg);
 120
 121void sdw_slave_debugfs_init(struct sdw_slave *slave)
 122{
 123        struct dentry *master;
 124        struct dentry *d;
 125        char name[32];
 126
 127        master = slave->bus->debugfs;
 128
 129        /* create the debugfs slave-name */
 130        snprintf(name, sizeof(name), "%s", dev_name(&slave->dev));
 131        d = debugfs_create_dir(name, master);
 132
 133        debugfs_create_file("registers", 0400, d, slave, &sdw_slave_reg_fops);
 134
 135        slave->debugfs = d;
 136}
 137
 138void sdw_slave_debugfs_exit(struct sdw_slave *slave)
 139{
 140        debugfs_remove_recursive(slave->debugfs);
 141}
 142
 143void sdw_debugfs_init(void)
 144{
 145        sdw_debugfs_root = debugfs_create_dir("soundwire", NULL);
 146}
 147
 148void sdw_debugfs_exit(void)
 149{
 150        debugfs_remove_recursive(sdw_debugfs_root);
 151}
 152