summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/clock.h1
-rw-r--r--arch/arm/mach-tegra/tegra_emc.c145
-rw-r--r--arch/arm/mach-tegra/tegra_emc.h21
4 files changed, 168 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 0887d3796e1d..e542120655a5 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -110,6 +110,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra3_emc.o
obj-$(CONFIG_ARCH_TEGRA_11x_SOC) += tegra11_emc.o
obj-$(CONFIG_ARCH_TEGRA_14x_SOC) += tegra14_emc.o
+obj-y += tegra_emc.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-tegra20-tables.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pinmux-tegra30-tables.o
obj-$(CONFIG_ARCH_TEGRA_11x_SOC) += pinmux-t11-tables.o
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 697b0dee4f77..cb3d1777a99d 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -240,6 +240,7 @@ struct clk {
struct clk *client;
u32 client_div;
enum shared_bus_users_mode mode;
+ u32 usage_flag;
} shared_bus_user;
} u;
diff --git a/arch/arm/mach-tegra/tegra_emc.c b/arch/arm/mach-tegra/tegra_emc.c
new file mode 100644
index 000000000000..54c1cb66a73a
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_emc.c
@@ -0,0 +1,145 @@
+/*
+ * arch/arm/mach-tegra/tegra_emc.c
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "tegra_emc.h"
+
+static u8 emc_iso_share = 100;
+
+static struct emc_iso_usage emc_usage_table[TEGRA_EMC_ISO_USE_CASES_MAX_NUM];
+
+
+void __init tegra_emc_iso_usage_table_init(struct emc_iso_usage *table,
+ int size)
+{
+ size = min(size, TEGRA_EMC_ISO_USE_CASES_MAX_NUM);
+
+ if (size && table)
+ memcpy(emc_usage_table, table,
+ size * sizeof(struct emc_iso_usage));
+}
+
+u8 tegra_emc_get_iso_share(u32 usage_flags)
+{
+ int i;
+ u8 iso_share = 100;
+
+ if (usage_flags) {
+ for (i = 0; i < TEGRA_EMC_ISO_USE_CASES_MAX_NUM; i++) {
+ struct emc_iso_usage *iso_usage = &emc_usage_table[i];
+ u32 flags = iso_usage->emc_usage_flags;
+ u8 share = iso_usage->iso_usage_share;
+
+ if (!flags)
+ continue;
+ if (!share) {
+ WARN(1, "%s: entry %d: iso_share 0\n",
+ __func__, i);
+ continue;
+ }
+
+ if ((flags & usage_flags) == flags)
+ iso_share = min(iso_share,
+ iso_usage->iso_usage_share);
+ }
+ }
+ emc_iso_share = iso_share;
+ return iso_share;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+#define USER_NAME(module) \
+[EMC_USER_##module] = #module
+
+static const char *emc_user_names[EMC_USER_NUM] = {
+ USER_NAME(DC),
+ USER_NAME(VI),
+ USER_NAME(MSENC),
+ USER_NAME(2D),
+ USER_NAME(3D),
+};
+
+static int emc_usage_table_show(struct seq_file *s, void *data)
+{
+ int i, j;
+
+ seq_printf(s, "EMC USAGE\t\tISO SHARE %%\n");
+
+ for (i = 0; i < TEGRA_EMC_ISO_USE_CASES_MAX_NUM; i++) {
+ u32 flags = emc_usage_table[i].emc_usage_flags;
+ u8 share = emc_usage_table[i].iso_usage_share;
+ bool first = false;
+
+ seq_printf(s, "[%d]: ", i);
+ if (!flags) {
+ seq_printf(s, "reserved\n");
+ continue;
+ }
+
+ for (j = 0; j < EMC_USER_NUM; j++) {
+ u32 mask = 0x1 << j;
+ if (!(flags & mask))
+ continue;
+ seq_printf(s, "%s%s", first ? "+" : "",
+ emc_user_names[j]);
+ first = true;
+ }
+ seq_printf(s, "\r\t\t\t= %d\n", share);
+ }
+ return 0;
+}
+
+static int emc_usage_table_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, emc_usage_table_show, inode->i_private);
+}
+
+static const struct file_operations emc_usage_table_fops = {
+ .open = emc_usage_table_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+int __init tegra_emc_iso_usage_debugfs_init(struct dentry *emc_debugfs_root)
+{
+ struct dentry *d;
+
+ d = debugfs_create_file("emc_usage_table", S_IRUGO, emc_debugfs_root,
+ NULL, &emc_usage_table_fops);
+ if (!d)
+ return -ENOMEM;
+
+ d = debugfs_create_u8("emc_iso_share", S_IRUGO, emc_debugfs_root,
+ &emc_iso_share);
+ if (!d)
+ return -ENOMEM;
+
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-tegra/tegra_emc.h b/arch/arm/mach-tegra/tegra_emc.h
index 6e2a9300f14a..ea7cd68e426c 100644
--- a/arch/arm/mach-tegra/tegra_emc.h
+++ b/arch/arm/mach-tegra/tegra_emc.h
@@ -21,6 +21,8 @@
#ifndef _MACH_TEGRA_TEGRA_EMC_H
#define _MACH_TEGRA_TEGRA_EMC_H
+#define TEGRA_EMC_ISO_USE_CASES_MAX_NUM 8
+
extern u8 tegra_emc_bw_efficiency;
enum {
@@ -28,8 +30,27 @@ enum {
DRAM_OVER_TEMP_REFRESH,
};
+enum emc_user_id {
+ EMC_USER_DC = 0,
+ EMC_USER_VI,
+ EMC_USER_MSENC,
+ EMC_USER_2D,
+ EMC_USER_3D,
+
+ EMC_USER_NUM,
+};
+
+struct emc_iso_usage {
+ u32 emc_usage_flags;
+ u8 iso_usage_share;
+};
+
struct clk;
+struct dentry;
+void tegra_emc_iso_usage_table_init(struct emc_iso_usage *table, int size);
+int tegra_emc_iso_usage_debugfs_init(struct dentry *emc_debugfs_root);
+u8 tegra_emc_get_iso_share(u32 usage_flags);
void tegra_emc_dram_type_init(struct clk *c);
int tegra_emc_get_dram_type(void);
int tegra_emc_get_dram_temperature(void);