Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe7a5bfe authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'tegra-for-4.2-memory' of...

Merge tag 'tegra-for-4.2-memory' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers

Merge "ARM: tegra: Memory controller updates for v4.2-rc1" from Thierry Reding:

Adds support for Tegra132 (which is mostly the same as for Tegra124,
except for cache maintenance). debugfs support is also introduced for
the SMMU part of the memory controller, which allows users to inspect
the translation state for SWGROUPs and memory clients.

* tag 'tegra-for-4.2-memory' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  memory: tegra: Disable ARBITRATION_EMEM interrupt
  memory: tegra: Add Tegra132 support
  iommu/tegra-smmu: Add debugfs support
  memory: tegra: Add SWGROUP names
parents 11f52002 6f0a4d0c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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"
+109 −0
Original line number Diff line number Diff line
@@ -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);
}
+1 −0
Original line number Diff line number Diff line
@@ -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
+5 −2
Original line number Diff line number Diff line
@@ -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
	{ }
};
@@ -273,8 +276,8 @@ static int tegra_mc_probe(struct platform_device *pdev)

	value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
		MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
		MC_INT_ARBITRATION_EMEM | MC_INT_SECURITY_VIOLATION |
		MC_INT_DECERR_EMEM;
		MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM;

	mc_writel(mc, value, MC_INTMASK);

	return 0;
+4 −0
Original line number Diff line number Diff line
@@ -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 */
Loading