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 | |
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>
-rw-r--r-- | arch/arm/mach-tegra/board-cardhu-memory.c | 42 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.c | 36 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_emc.h | 4 |
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) |