diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_emc.c | 145 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_emc.h | 21 |
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); |