diff options
author | Prashant Gaikwad <pgaikwad@nvidia.com> | 2013-10-15 13:25:28 +0530 |
---|---|---|
committer | Bharat Nihalani <bnihalani@nvidia.com> | 2013-10-16 05:14:51 -0700 |
commit | 43a5d6e79fca81114a5cf120a468ee569aa8392a (patch) | |
tree | 91953fbde4bb5912bc4ca460dd42f46cd74a8486 /arch/arm/mach-tegra/tegra12_emc.c | |
parent | f99440823a80471b872f514c0c3f23c17809676b (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.c | 78 |
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; |