From d1313e7896e932a92e21912850ef034e58571b66 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 23 Jan 2015 09:49:25 +0100 Subject: 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 Acked-by: Joerg Roedel Signed-off-by: Thierry Reding --- drivers/iommu/tegra-smmu.c | 109 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'drivers/iommu') 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 +#include #include #include #include @@ -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); +} -- cgit v1.2.3 From 242b1d713386e8e2fd7f62cc1ed4681a12290848 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 7 Nov 2014 16:10:41 +0100 Subject: memory: tegra: Add Tegra132 support The memory controller on Tegra132 is very similar to the one found on Tegra124. But the Denver CPUs don't have an outer cache, so dcache maintenance is done slightly differently. Signed-off-by: Thierry Reding --- drivers/iommu/Kconfig | 2 +- drivers/memory/tegra/Makefile | 1 + drivers/memory/tegra/mc.c | 3 +++ drivers/memory/tegra/mc.h | 4 ++++ drivers/memory/tegra/tegra124.c | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 1 deletion(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 1ae4e547b419..73f918d066c6 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -219,7 +219,7 @@ config TEGRA_IOMMU_SMMU select IOMMU_API help This driver supports the IOMMU hardware (SMMU) found on NVIDIA Tegra - SoCs (Tegra30 up to Tegra124). + SoCs (Tegra30 up to Tegra132). config EXYNOS_IOMMU bool "Exynos IOMMU Support" diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile index 0d9f497b786c..9d4f4319b527 100644 --- a/drivers/memory/tegra/Makefile +++ b/drivers/memory/tegra/Makefile @@ -3,5 +3,6 @@ tegra-mc-y := mc.o tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o +tegra-mc-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra124.o obj-$(CONFIG_TEGRA_MC) += tegra-mc.o diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index fe3c44e7e1d1..9b7c1645fd59 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c @@ -57,6 +57,9 @@ static const struct of_device_id tegra_mc_of_match[] = { #endif #ifdef CONFIG_ARCH_TEGRA_124_SOC { .compatible = "nvidia,tegra124-mc", .data = &tegra124_mc_soc }, +#endif +#ifdef CONFIG_ARCH_TEGRA_132_SOC + { .compatible = "nvidia,tegra132-mc", .data = &tegra132_mc_soc }, #endif { } }; diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index d5d21147fc77..b7361b0a6696 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h @@ -37,4 +37,8 @@ extern const struct tegra_mc_soc tegra114_mc_soc; extern const struct tegra_mc_soc tegra124_mc_soc; #endif +#ifdef CONFIG_ARCH_TEGRA_132_SOC +extern const struct tegra_mc_soc tegra132_mc_soc; +#endif + #endif /* MEMORY_TEGRA_MC_H */ diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c index e63e05769d0a..b996dfb9358b 100644 --- a/drivers/memory/tegra/tegra124.c +++ b/drivers/memory/tegra/tegra124.c @@ -993,3 +993,36 @@ const struct tegra_mc_soc tegra124_mc_soc = { .smmu = &tegra124_smmu_soc, }; #endif /* CONFIG_ARCH_TEGRA_124_SOC */ + +#ifdef CONFIG_ARCH_TEGRA_132_SOC +static void tegra132_flush_dcache(struct page *page, unsigned long offset, + size_t size) +{ + void *virt = page_address(page) + offset; + + __flush_dcache_area(virt, size); +} + +static const struct tegra_smmu_ops tegra132_smmu_ops = { + .flush_dcache = tegra132_flush_dcache, +}; + +static const struct tegra_smmu_soc tegra132_smmu_soc = { + .clients = tegra124_mc_clients, + .num_clients = ARRAY_SIZE(tegra124_mc_clients), + .swgroups = tegra124_swgroups, + .num_swgroups = ARRAY_SIZE(tegra124_swgroups), + .supports_round_robin_arbitration = true, + .supports_request_limit = true, + .num_asids = 128, + .ops = &tegra132_smmu_ops, +}; + +const struct tegra_mc_soc tegra132_mc_soc = { + .clients = tegra124_mc_clients, + .num_clients = ARRAY_SIZE(tegra124_mc_clients), + .num_address_bits = 34, + .atom_size = 32, + .smmu = &tegra132_smmu_soc, +}; +#endif /* CONFIG_ARCH_TEGRA_132_SOC */ -- cgit v1.2.3