diff options
author | Alex Frid <afrid@nvidia.com> | 2012-02-17 23:25:06 -0800 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2012-03-13 15:30:38 -0700 |
commit | 86ce551a4633f387fc401c89f6bb97059d3ad75b (patch) | |
tree | 012e5c59d0c42eb5ad0767d822224b4b0b176076 /arch/arm/mach-tegra/tegra3_emc.c | |
parent | a760dd3c9bb139e1abe65e28d6bc619fbf267d2a (diff) |
ARM: tegra: clock: Add SoC-to-DDR bit swap support
Since Tegra3 allows bit swapping when routing SoC-to-DDR data bus,
added the respective decoding mechanism for reading LPDDR2 mode
registers. Populated mapping table for PM269 board.
Bug 939626
Signed-off-by: Alex Frid <afrid@nvidia.com>
(cherry picked from commit 5f5329596167681b528c87fd088d60030eee6fdc)
Change-Id: I6670110a828df4264b8f7a8c8e6e67611a830033
Reviewed-on: http://git-master/r/89350
Tested-by: Aleksandr Frid <afrid@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra3_emc.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/tegra3_emc.c b/arch/arm/mach-tegra/tegra3_emc.c index 746caea11634..0ceed669fa5c 100644 --- a/arch/arm/mach-tegra/tegra3_emc.c +++ b/arch/arm/mach-tegra/tegra3_emc.c @@ -192,6 +192,7 @@ static struct tegra_emc_table start_timing; static const struct tegra_emc_table *emc_timing; static unsigned long dram_over_temp_state = DRAM_OVER_TEMP_NONE; +static const u32 *dram_to_soc_bit_map; static const struct tegra_emc_table *tegra_emc_table; static int tegra_emc_table_size; @@ -1051,6 +1052,12 @@ void tegra_emc_timing_invalidate(void) emc_timing = NULL; } +void tegra_init_dram_bit_map(const u32 *bit_map, int map_size) +{ + BUG_ON(map_size != 32); + dram_to_soc_bit_map = bit_map; +} + void tegra_emc_dram_type_init(struct clk *c) { emc = c; @@ -1069,6 +1076,29 @@ int tegra_emc_get_dram_type(void) return dram_type; } +static u32 soc_to_dram_bit_swap(u32 soc_val, u32 dram_mask, u32 dram_shift) +{ + int bit; + u32 dram_val = 0; + + /* tegra clocks definitions use shifted mask always */ + if (!dram_to_soc_bit_map) + return soc_val & dram_mask; + + for (bit = dram_shift; bit < 32; bit++) { + u32 dram_bit_mask = 0x1 << bit; + u32 soc_bit_mask = dram_to_soc_bit_map[bit]; + + if (!(dram_bit_mask & dram_mask)) + break; + + if (soc_bit_mask & soc_val) + dram_val |= dram_bit_mask; + } + + return dram_val; +} + static int emc_read_mrr(int dev, int addr) { int ret; @@ -1089,7 +1119,6 @@ static int emc_read_mrr(int dev, int addr) if (ret) return ret; - /* FIXME: bit swap decoding */ val = emc_readl(EMC_MRR) & EMC_MRR_DATA_MASK; return val; } @@ -1106,9 +1135,10 @@ int tegra_emc_get_dram_temperature(void) spin_unlock_irqrestore(&emc_access_lock, flags); return mr4; } - - mr4 &= LPDDR2_MR4_TEMP_MASK; spin_unlock_irqrestore(&emc_access_lock, flags); + + mr4 = soc_to_dram_bit_swap( + mr4, LPDDR2_MR4_TEMP_MASK, LPDDR2_MR4_TEMP_SHIFT); return mr4; } |