root/sound/soc/renesas/rcar/debugfs.c
// SPDX-License-Identifier: GPL-2.0
//
// // Renesas R-Car debugfs support
//
// Copyright (c) 2021 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
//
//      > mount -t debugfs none /sys/kernel/debug
//      > cd /sys/kernel/debug/asoc/rcar-sound/ec500000.sound/rdai{N}/
//      > cat playback/xxx
//      > cat capture/xxx
//
#ifdef CONFIG_DEBUG_FS

#include <linux/debugfs.h>
#include "rsnd.h"

static int rsnd_debugfs_show(struct seq_file *m, void *v)
{
        struct rsnd_dai_stream *io = m->private;
        struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
        int i;

        /* adg is out of mods */
        rsnd_adg_clk_dbg_info(priv, m);

        for_each_rsnd_mod(i, mod, io) {
                u32 *status = mod->ops->get_status(mod, io, mod->type);

                seq_printf(m, "name: %s\n", rsnd_mod_name(mod));
                seq_printf(m, "status: %08x\n", *status);

                if (mod->ops->debug_info)
                        mod->ops->debug_info(m, io, mod);
        }

        return 0;
}
DEFINE_SHOW_ATTRIBUTE(rsnd_debugfs);

void rsnd_debugfs_reg_show(struct seq_file *m, phys_addr_t _addr,
                           void __iomem *base, int offset, int size)
{
        int i, j;

        for (i = 0; i < size; i += 0x10) {
                phys_addr_t addr = _addr + offset + i;

                seq_printf(m, "%pa:", &addr);
                for (j = 0; j < 0x10; j += 0x4)
                        seq_printf(m, " %08x", __raw_readl(base + offset + i + j));
                seq_puts(m, "\n");
        }
}

void rsnd_debugfs_mod_reg_show(struct seq_file *m, struct rsnd_mod *mod,
                               int reg_id, int offset, int size)
{
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);

        rsnd_debugfs_reg_show(m,
                              rsnd_gen_get_phy_addr(priv, reg_id),
                              rsnd_gen_get_base_addr(priv, reg_id),
                              offset, size);
}

int rsnd_debugfs_probe(struct snd_soc_component *component)
{
        struct rsnd_priv *priv = dev_get_drvdata(component->dev);
        struct rsnd_dai *rdai;
        struct dentry *dir;
        char name[64];
        int i;

        /* Gen1 is not supported */
        if (rsnd_is_gen1(priv))
                return 0;

        for_each_rsnd_dai(rdai, priv, i) {
                /*
                 * created debugfs will be automatically
                 * removed, nothing to do for _remove.
                 * see
                 *      soc_cleanup_component_debugfs()
                 */
                snprintf(name, sizeof(name), "rdai%d", i);
                dir = debugfs_create_dir(name, component->debugfs_root);

                debugfs_create_file("playback", 0444, dir, &rdai->playback, &rsnd_debugfs_fops);
                debugfs_create_file("capture",  0444, dir, &rdai->capture,  &rsnd_debugfs_fops);
        }

        return 0;
}

#endif /* CONFIG_DEBUG_FS */