diff options
author | Thierry Reding <treding@nvidia.com> | 2015-01-23 09:49:25 +0100 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2015-05-04 12:54:23 +0200 |
commit | d1313e7896e932a92e21912850ef034e58571b66 (patch) | |
tree | 2a5dcedb4eb8c1a9e32c3769bf4c818c00fce89d /drivers/iommu/tegra-smmu.c | |
parent | e660df07ab90f4f61ed743522067a8dbaa6fa567 (diff) | |
download | blackbird-op-linux-d1313e7896e932a92e21912850ef034e58571b66.tar.gz blackbird-op-linux-d1313e7896e932a92e21912850ef034e58571b66.zip |
iommu/tegra-smmu: Add debugfs support
Provide clients and swgroups files in debugfs. These files show for
which clients IOMMU translation is enabled and which ASID is associated
with each SWGROUP.
Cc: Hiroshi Doyu <hdoyu@nvidia.com>
Acked-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/iommu/tegra-smmu.c')
-rw-r--r-- | drivers/iommu/tegra-smmu.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index c845d99ecf6b..c1f2e521dc52 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -7,6 +7,7 @@ */ #include <linux/bitops.h> +#include <linux/debugfs.h> #include <linux/err.h> #include <linux/iommu.h> #include <linux/kernel.h> @@ -31,6 +32,8 @@ struct tegra_smmu { struct mutex lock; struct list_head list; + + struct dentry *debugfs; }; struct tegra_smmu_as { @@ -673,6 +676,103 @@ static void tegra_smmu_ahb_enable(void) } } +static int tegra_smmu_swgroups_show(struct seq_file *s, void *data) +{ + struct tegra_smmu *smmu = s->private; + unsigned int i; + u32 value; + + seq_printf(s, "swgroup enabled ASID\n"); + seq_printf(s, "------------------------\n"); + + for (i = 0; i < smmu->soc->num_swgroups; i++) { + const struct tegra_smmu_swgroup *group = &smmu->soc->swgroups[i]; + const char *status; + unsigned int asid; + + value = smmu_readl(smmu, group->reg); + + if (value & SMMU_ASID_ENABLE) + status = "yes"; + else + status = "no"; + + asid = value & SMMU_ASID_MASK; + + seq_printf(s, "%-9s %-7s %#04x\n", group->name, status, + asid); + } + + return 0; +} + +static int tegra_smmu_swgroups_open(struct inode *inode, struct file *file) +{ + return single_open(file, tegra_smmu_swgroups_show, inode->i_private); +} + +static const struct file_operations tegra_smmu_swgroups_fops = { + .open = tegra_smmu_swgroups_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int tegra_smmu_clients_show(struct seq_file *s, void *data) +{ + struct tegra_smmu *smmu = s->private; + unsigned int i; + u32 value; + + seq_printf(s, "client enabled\n"); + seq_printf(s, "--------------------\n"); + + for (i = 0; i < smmu->soc->num_clients; i++) { + const struct tegra_mc_client *client = &smmu->soc->clients[i]; + const char *status; + + value = smmu_readl(smmu, client->smmu.reg); + + if (value & BIT(client->smmu.bit)) + status = "yes"; + else + status = "no"; + + seq_printf(s, "%-12s %s\n", client->name, status); + } + + return 0; +} + +static int tegra_smmu_clients_open(struct inode *inode, struct file *file) +{ + return single_open(file, tegra_smmu_clients_show, inode->i_private); +} + +static const struct file_operations tegra_smmu_clients_fops = { + .open = tegra_smmu_clients_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void tegra_smmu_debugfs_init(struct tegra_smmu *smmu) +{ + smmu->debugfs = debugfs_create_dir("smmu", NULL); + if (!smmu->debugfs) + return; + + debugfs_create_file("swgroups", S_IRUGO, smmu->debugfs, smmu, + &tegra_smmu_swgroups_fops); + debugfs_create_file("clients", S_IRUGO, smmu->debugfs, smmu, + &tegra_smmu_clients_fops); +} + +static void tegra_smmu_debugfs_exit(struct tegra_smmu *smmu) +{ + debugfs_remove_recursive(smmu->debugfs); +} + struct tegra_smmu *tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc, struct tegra_mc *mc) @@ -743,5 +843,14 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev, if (err < 0) return ERR_PTR(err); + if (IS_ENABLED(CONFIG_DEBUG_FS)) + tegra_smmu_debugfs_init(smmu); + return smmu; } + +void tegra_smmu_remove(struct tegra_smmu *smmu) +{ + if (IS_ENABLED(CONFIG_DEBUG_FS)) + tegra_smmu_debugfs_exit(smmu); +} |