summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra12_emc.c
diff options
context:
space:
mode:
authorPrashant Gaikwad <pgaikwad@nvidia.com>2013-10-15 13:25:28 +0530
committerBharat Nihalani <bnihalani@nvidia.com>2013-10-16 05:14:51 -0700
commit43a5d6e79fca81114a5cf120a468ee569aa8392a (patch)
tree91953fbde4bb5912bc4ca460dd42f46cd74a8486 /arch/arm/mach-tegra/tegra12_emc.c
parentf99440823a80471b872f514c0c3f23c17809676b (diff)
arm: tegra: add PASR support for T124
This supports only LPDDR2/3 DRAM parts. Bug 1347784 Change-Id: I5772a552938ac7c3cb20543e2b096587e0531f77 Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com> Reviewed-on: http://git-master/r/299363 Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra12_emc.c')
-rw-r--r--arch/arm/mach-tegra/tegra12_emc.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra12_emc.c b/arch/arm/mach-tegra/tegra12_emc.c
index 1f705bb3e673..db07dda60580 100644
--- a/arch/arm/mach-tegra/tegra12_emc.c
+++ b/arch/arm/mach-tegra/tegra12_emc.c
@@ -29,6 +29,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/hrtimer.h>
+#include <linux/pasr.h>
#include <asm/cputime.h>
@@ -45,6 +46,8 @@ static bool emc_enable;
#endif
module_param(emc_enable, bool, 0644);
+static int pasr_enable;
+
u8 tegra_emc_bw_efficiency = 100;
static struct emc_iso_usage tegra12_emc_iso_usage[] = {
@@ -65,6 +68,11 @@ static struct emc_iso_usage tegra12_emc_iso_usage[] = {
#define EMC_STATUS_UPDATE_TIMEOUT 100
#define TEGRA_EMC_TABLE_MAX_SIZE 16
+#define TEGRA_EMC_MODE_REG_17 0x00110000
+#define TEGRA_EMC_MRW_DEV_SHIFT 30
+#define TEGRA_EMC_MRW_DEV1 2
+#define TEGRA_EMC_MRW_DEV2 1
+
enum {
DLL_CHANGE_NONE = 0,
DLL_CHANGE_ON,
@@ -1210,6 +1218,76 @@ static int init_emc_table(const struct tegra12_emc_table *table, int table_size)
return 0;
}
+#ifdef CONFIG_PASR
+static bool tegra12_is_lpddr3(void)
+{
+ return (dram_type == DRAM_TYPE_LPDDR2);
+}
+
+static void tegra12_pasr_apply_mask(u16 *mem_reg, void *cookie)
+{
+ u32 val = 0;
+ int device = (int)cookie;
+
+ val = TEGRA_EMC_MODE_REG_17 | *mem_reg;
+ val |= device << TEGRA_EMC_MRW_DEV_SHIFT;
+
+ emc_writel(val, EMC_MRW);
+
+ pr_debug("%s: cookie = %d mem_reg = 0x%04x val = 0x%08x\n", __func__,
+ (int)cookie, *mem_reg, val);
+}
+
+static int tegra12_pasr_enable(const char *arg, const struct kernel_param *kp)
+{
+ unsigned int old_pasr_enable;
+ void *cookie;
+ u16 mem_reg;
+
+ if (!tegra12_is_lpddr3())
+ return -ENOSYS;
+
+ old_pasr_enable = pasr_enable;
+ param_set_int(arg, kp);
+
+ if (old_pasr_enable == pasr_enable)
+ return 0;
+
+ /* Cookie represents the device number to write to MRW register.
+ * 0x2 to for only dev0, 0x1 for dev1.
+ */
+ if (pasr_enable == 0) {
+ mem_reg = 0;
+
+ cookie = (void *)(int)TEGRA_EMC_MRW_DEV1;
+ if (!pasr_register_mask_function(TEGRA_DRAM_BASE,
+ NULL, cookie))
+ tegra12_pasr_apply_mask(&mem_reg, cookie);
+
+ cookie = (void *)(int)TEGRA_EMC_MRW_DEV2;
+ if (!pasr_register_mask_function(TEGRA_DRAM_BASE + SZ_1G,
+ NULL, cookie))
+ tegra12_pasr_apply_mask(&mem_reg, cookie);
+ } else {
+ cookie = (void *)(int)TEGRA_EMC_MRW_DEV1;
+ pasr_register_mask_function(TEGRA_DRAM_BASE,
+ &tegra12_pasr_apply_mask, cookie);
+
+ cookie = (void *)(int)TEGRA_EMC_MRW_DEV2;
+ pasr_register_mask_function(TEGRA_DRAM_BASE + SZ_1G,
+ &tegra12_pasr_apply_mask, cookie);
+ }
+
+ return 0;
+}
+
+static struct kernel_param_ops tegra12_pasr_enable_ops = {
+ .set = tegra12_pasr_enable,
+ .get = param_get_int,
+};
+module_param_cb(pasr_enable, &tegra12_pasr_enable_ops, &pasr_enable, 0644);
+#endif
+
static int tegra12_emc_probe(struct platform_device *pdev)
{
struct tegra12_emc_pdata *pdata;