mirror of
https://github.com/torvalds/linux.git
synced 2026-06-10 23:53:52 +02:00
ARM: tegra: add generic memory vendor matching
Update tegra_init_emc to provide generic memory vendor matching. Read values from EMC_MRR_0, to uniquely identify memory types and compare them to table of memory passed in. Change-Id: Ie116fa6f497076149c87ff6c0ae0621309bac65f Signed-off-by: James Wylder <james.wylder@motorola.com>
This commit is contained in:
parent
8e15ee8536
commit
1bc517b59d
|
|
@ -25,6 +25,11 @@
|
|||
|
||||
#include "tegra2_emc.h"
|
||||
|
||||
#define TEGRA_MRR_DIVLD (1<<20)
|
||||
#define TEGRA_EMC_STATUS 0x02b4
|
||||
#define TEGRA_EMC_MRR 0x00ec
|
||||
static DEFINE_MUTEX(tegra_emc_mrr_lock);
|
||||
|
||||
#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
|
||||
static bool emc_enable = true;
|
||||
#else
|
||||
|
|
@ -46,6 +51,35 @@ static inline u32 emc_readl(unsigned long addr)
|
|||
return readl(emc + addr);
|
||||
}
|
||||
|
||||
/* read LPDDR2 memory modes */
|
||||
static int tegra_emc_read_mrr(unsigned long addr)
|
||||
{
|
||||
u32 value;
|
||||
int count = 100;
|
||||
|
||||
mutex_lock(&tegra_emc_mrr_lock);
|
||||
do {
|
||||
emc_readl(TEGRA_EMC_MRR);
|
||||
} while (--count && (emc_readl(TEGRA_EMC_STATUS) & TEGRA_MRR_DIVLD));
|
||||
if (count == 0) {
|
||||
pr_err("%s: Failed to read memory type\n", __func__);
|
||||
BUG();
|
||||
}
|
||||
value = (1 << 30) | (addr << 16);
|
||||
emc_writel(value, TEGRA_EMC_MRR);
|
||||
|
||||
count = 100;
|
||||
while (--count && !(emc_readl(TEGRA_EMC_STATUS) & TEGRA_MRR_DIVLD));
|
||||
if (count == 0) {
|
||||
pr_err("%s: Failed to read memory type\n", __func__);
|
||||
BUG();
|
||||
}
|
||||
value = emc_readl(TEGRA_EMC_MRR) & 0xFFFF;
|
||||
mutex_unlock(&tegra_emc_mrr_lock);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
|
||||
0x2c, /* RC */
|
||||
0x30, /* RFC */
|
||||
|
|
@ -165,8 +199,53 @@ int tegra_emc_set_rate(unsigned long rate)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
|
||||
void tegra_init_emc(const struct tegra_emc_chip *chips, int chips_size)
|
||||
{
|
||||
tegra_emc_table = table;
|
||||
tegra_emc_table_size = table_size;
|
||||
int i;
|
||||
int vid;
|
||||
int rev_id1;
|
||||
int rev_id2;
|
||||
int pid;
|
||||
int chip_matched = -1;
|
||||
|
||||
vid = tegra_emc_read_mrr(5);
|
||||
rev_id1 = tegra_emc_read_mrr(6);
|
||||
rev_id2 = tegra_emc_read_mrr(7);
|
||||
pid = tegra_emc_read_mrr(8);
|
||||
|
||||
for (i = 0; i < chips_size; i++) {
|
||||
if (chips[i].mem_manufacturer_id >= 0) {
|
||||
if (chips[i].mem_manufacturer_id != vid)
|
||||
continue;
|
||||
}
|
||||
if (chips[i].mem_revision_id1 >= 0) {
|
||||
if (chips[i].mem_revision_id1 != rev_id1)
|
||||
continue;
|
||||
}
|
||||
if (chips[i].mem_revision_id2 >= 0) {
|
||||
if (chips[i].mem_revision_id2 != rev_id2)
|
||||
continue;
|
||||
}
|
||||
if (chips[i].mem_pid >= 0) {
|
||||
if (chips[i].mem_pid != pid)
|
||||
continue;
|
||||
}
|
||||
|
||||
chip_matched = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chip_matched >= 0) {
|
||||
pr_info("%s: %s memory found\n", __func__,
|
||||
chips[chip_matched].description);
|
||||
tegra_emc_table = chips[chip_matched].table;
|
||||
tegra_emc_table_size = chips[chip_matched].table_size;
|
||||
} else {
|
||||
pr_err("%s: Memory not recognized, memory scaling disabled\n",
|
||||
__func__);
|
||||
pr_info("%s: Memory vid = 0x%04x", __func__, vid);
|
||||
pr_info("%s: Memory rev_id1 = 0x%04x", __func__, rev_id1);
|
||||
pr_info("%s: Memory rev_id2 = 0x%04x", __func__, rev_id2);
|
||||
pr_info("%s: Memory pid = 0x%04x", __func__, pid);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,17 @@ struct tegra_emc_table {
|
|||
u32 regs[TEGRA_EMC_NUM_REGS];
|
||||
};
|
||||
|
||||
struct tegra_emc_chip {
|
||||
const char *description;
|
||||
int mem_manufacturer_id; /* LPDDR2 MR5 or -1 to ignore */
|
||||
int mem_revision_id1; /* LPDDR2 MR6 or -1 to ignore */
|
||||
int mem_revision_id2; /* LPDDR2 MR7 or -1 to ignore */
|
||||
int mem_pid; /* LPDDR2 MR8 or -1 to ignore */
|
||||
|
||||
const struct tegra_emc_table *table;
|
||||
int table_size;
|
||||
};
|
||||
|
||||
int tegra_emc_set_rate(unsigned long rate);
|
||||
long tegra_emc_round_rate(unsigned long rate);
|
||||
void tegra_init_emc(const struct tegra_emc_table *table, int table_size);
|
||||
void tegra_init_emc(const struct tegra_emc_chip *chips, int chips_size);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user