summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra3_emc.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2012-02-17 23:25:06 -0800
committerVarun Colbert <vcolbert@nvidia.com>2012-03-13 15:30:38 -0700
commit86ce551a4633f387fc401c89f6bb97059d3ad75b (patch)
tree012e5c59d0c42eb5ad0767d822224b4b0b176076 /arch/arm/mach-tegra/tegra3_emc.c
parenta760dd3c9bb139e1abe65e28d6bc619fbf267d2a (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.c36
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;
}