summaryrefslogtreecommitdiff
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
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>
-rw-r--r--arch/arm/mach-tegra/board-cardhu-memory.c42
-rw-r--r--arch/arm/mach-tegra/tegra3_emc.c36
-rw-r--r--arch/arm/mach-tegra/tegra3_emc.h4
3 files changed, 78 insertions, 4 deletions
diff --git a/arch/arm/mach-tegra/board-cardhu-memory.c b/arch/arm/mach-tegra/board-cardhu-memory.c
index a2492b147155..019014c787d2 100644
--- a/arch/arm/mach-tegra/board-cardhu-memory.c
+++ b/arch/arm/mach-tegra/board-cardhu-memory.c
@@ -4828,6 +4828,45 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = {
},
};
+static const u32 pm269_bit_swap_map[32] = {
+ /* DDR bit # SoC bit # */
+ [0] = 0x1 << 1,
+ [1] = 0x1 << 2,
+ [2] = 0x1 << 3,
+ [3] = 0x1 << 0,
+ [4] = 0x1 << 7,
+ [5] = 0x1 << 5,
+ [6] = 0x1 << 6,
+ [7] = 0x1 << 4,
+
+ [8] = 0x1 << 13,
+ [9] = 0x1 << 9,
+ [10] = 0x1 << 8,
+ [11] = 0x1 << 12,
+ [12] = 0x1 << 11,
+ [13] = 0x1 << 10,
+ [14] = 0x1 << 14,
+ [15] = 0x1 << 15,
+
+ [16] = 0x1 << 20,
+ [17] = 0x1 << 23,
+ [18] = 0x1 << 16,
+ [19] = 0x1 << 19,
+ [20] = 0x1 << 18,
+ [21] = 0x1 << 21,
+ [22] = 0x1 << 22,
+ [23] = 0x1 << 17,
+
+ [24] = 0x1 << 27,
+ [25] = 0x1 << 30,
+ [26] = 0x1 << 31,
+ [27] = 0x1 << 28,
+ [28] = 0x1 << 26,
+ [29] = 0x1 << 25,
+ [30] = 0x1 << 24,
+ [31] = 0x1 << 29,
+};
+
int cardhu_emc_init(void)
{
struct board_info board;
@@ -4836,6 +4875,9 @@ int cardhu_emc_init(void)
switch (board.board_id) {
case BOARD_PM269:
+ tegra_init_dram_bit_map(pm269_bit_swap_map,
+ ARRAY_SIZE(pm269_bit_swap_map));
+ /* fall through */
case BOARD_E1257:
if (MEMORY_TYPE(board.sku) == SKU_MEMORY_ELPIDA)
tegra_init_emc(cardhu_emc_tables_edb8132b2ma,
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;
}
diff --git a/arch/arm/mach-tegra/tegra3_emc.h b/arch/arm/mach-tegra/tegra3_emc.h
index 48b2d9cbe78a..cfde92c1355a 100644
--- a/arch/arm/mach-tegra/tegra3_emc.h
+++ b/arch/arm/mach-tegra/tegra3_emc.h
@@ -54,6 +54,7 @@ struct clk;
void tegra_init_emc(const struct tegra_emc_table *table, int table_size);
+void tegra_init_dram_bit_map(const u32 *bit_map, int map_size);
void tegra_emc_dram_type_init(struct clk *c);
int tegra_emc_get_dram_type(void);
int tegra_emc_get_dram_temperature(void);
@@ -158,7 +159,8 @@ enum {
#define EMC_MRR_MA_SHIFT 16
#define EMC_MRR_MA_MASK (0xFF << EMC_MRR_MA_SHIFT)
#define EMC_MRR_DATA_MASK ((0x1 << EMC_MRR_MA_SHIFT) - 1)
-#define LPDDR2_MR4_TEMP_MASK 0x7
+#define LPDDR2_MR4_TEMP_SHIFT 0
+#define LPDDR2_MR4_TEMP_MASK (0x7 << LPDDR2_MR4_TEMP_SHIFT)
#define EMC_XM2DQSPADCTRL3 0xf8
#define EMC_XM2DQSPADCTRL3_VREF_ENABLE (0x1 << 5)