summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx/esdctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-imx/esdctl.c')
-rw-r--r--arch/arm/mach-imx/esdctl.c71
1 files changed, 52 insertions, 19 deletions
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index b070ebc62a..a55ee06b83 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -317,6 +317,7 @@ static int vf610_ddrmc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
#define DDRC_ADDRMAP0_CS_BIT0 GENMASK(4, 0)
#define DDRC_MSTR 0x0000
+#define DDRC_MSTR_DDR4 BIT(4)
#define DDRC_MSTR_LPDDR4 BIT(5)
#define DDRC_MSTR_DATA_BUS_WIDTH GENMASK(13, 12)
#define DDRC_MSTR_ACTIVE_RANKS GENMASK(27, 24)
@@ -370,9 +371,8 @@ static resource_size_t
imx_ddrc_sdram_size(void __iomem *ddrc, const u32 addrmap[DDRC_ADDRMAP_LENGTH],
u8 col_max, const u8 col_b[], unsigned int col_b_num,
u8 row_max, const u8 row_b[], unsigned int row_b_num,
- bool reduced_adress_space, bool is_imx8)
+ bool reduced_adress_space, unsigned int mstr)
{
- const u32 mstr = readl(ddrc + DDRC_MSTR);
unsigned int banks, ranks, columns, rows, active_ranks, width;
resource_size_t size;
@@ -393,11 +393,13 @@ imx_ddrc_sdram_size(void __iomem *ddrc, const u32 addrmap[DDRC_ADDRMAP_LENGTH],
BUG();
}
- /* Bus width in bytes, 0 means half byte or 4-bit mode */
- if (is_imx8 && !(mstr & DDRC_MSTR_LPDDR4))
- width = (1 << FIELD_GET(DDRC_MSTR_DEVICE_CONFIG, mstr)) >> 1;
- else
- width = 4;
+ /*
+ * mstr is ignored for some SoCs/RAM types and may yield wrong
+ * results when used for calculation. Callers of this function
+ * are expected to fix it up as necessary.
+ * Bus width in bytes, 0 means half byte or 4-bit mode
+ */
+ width = (1 << FIELD_GET(DDRC_MSTR_DEVICE_CONFIG, mstr)) >> 1;
switch (FIELD_GET(DDRC_MSTR_DATA_BUS_WIDTH, mstr)) {
case 0b00: /* Full DQ bus */
@@ -423,7 +425,12 @@ imx_ddrc_sdram_size(void __iomem *ddrc, const u32 addrmap[DDRC_ADDRMAP_LENGTH],
if (FIELD_GET(DDRC_ADDRMAP1_BANK_B2, addrmap[1]) != 0b11111)
banks++;
- if (addrmap[8]) {
+ if (mstr & DDRC_MSTR_DDR4) {
+ /* FIXME: DDR register spreasheet claims this to be
+ * 6-bit and 63 meaning bank group address bit 0 is 0,
+ * but reference manual claims 5-bit without 'neutral' value
+ * See MX8M_Mini_DDR4_RPA_v17, MX8M_Nano_DDR4_RPA_v8
+ */
if (FIELD_GET(DDRC_ADDRMAP8_BG_B0, addrmap[8]) != 0b11111)
banks++;
if (FIELD_GET(DDRC_ADDRMAP8_BG_B1, addrmap[8]) != 0b111111)
@@ -446,7 +453,13 @@ imx_ddrc_sdram_size(void __iomem *ddrc, const u32 addrmap[DDRC_ADDRMAP_LENGTH],
return reduced_adress_space ? size * 3 / 4 : size;
}
-static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc)
+static void imx_ddrc_set_mstr_device_config(u32 *mstr, unsigned bits)
+{
+ *mstr &= ~DDRC_MSTR_DEVICE_CONFIG;
+ *mstr |= FIELD_PREP(DDRC_MSTR_DEVICE_CONFIG, fls(bits / 8));
+}
+
+static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswidth)
{
const u32 addrmap[DDRC_ADDRMAP_LENGTH] = {
readl(ddrc + DDRC_ADDRMAP(0)),
@@ -485,17 +498,28 @@ static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc)
};
const bool reduced_adress_space =
FIELD_GET(DDRC_ADDRMAP6_LPDDR4_6GB_12GB_24GB, addrmap[6]);
+ u32 mstr = readl(ddrc + DDRC_MSTR);
+
+ /* Device config is ignored and taken as 32-bit for LPDDR4 */
+ if (mstr & DDRC_MSTR_LPDDR4)
+ imx_ddrc_set_mstr_device_config(&mstr, buswidth);
return imx_ddrc_sdram_size(ddrc, addrmap,
12, ARRAY_AND_SIZE(col_b),
18, ARRAY_AND_SIZE(row_b),
- reduced_adress_space, true);
+ reduced_adress_space, mstr);
}
static int imx8m_ddrc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
{
return arm_add_mem_device("ram0", data->base0,
- imx8m_ddrc_sdram_size(mmdcbase));
+ imx8m_ddrc_sdram_size(mmdcbase, 32));
+}
+
+static int imx8mn_ddrc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
+{
+ return arm_add_mem_device("ram0", data->base0,
+ imx8m_ddrc_sdram_size(mmdcbase, 16));
}
static resource_size_t imx7d_ddrc_sdram_size(void __iomem *ddrc)
@@ -527,11 +551,15 @@ static resource_size_t imx7d_ddrc_sdram_size(void __iomem *ddrc)
};
const bool reduced_adress_space =
FIELD_GET(DDRC_ADDRMAP6_LPDDR3_6GB_12GB, addrmap[6]);
+ u32 mstr = readl(ddrc + DDRC_MSTR);
+
+ /* Device config is unused on i.MX7, so rewrite it as 32-bit wide */
+ imx_ddrc_set_mstr_device_config(&mstr, 32);
return imx_ddrc_sdram_size(ddrc, addrmap,
11, ARRAY_AND_SIZE(col_b),
15, ARRAY_AND_SIZE(row_b),
- reduced_adress_space, false);
+ reduced_adress_space, mstr);
}
static int imx7d_ddrc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
@@ -629,6 +657,11 @@ static __maybe_unused struct imx_esdctl_data imx8mq_data = {
.add_mem = imx8m_ddrc_add_mem,
};
+static __maybe_unused struct imx_esdctl_data imx8mn_data = {
+ .base0 = MX8M_DDR_CSD1_BASE_ADDR,
+ .add_mem = imx8mn_ddrc_add_mem,
+};
+
static __maybe_unused struct imx_esdctl_data imx7d_data = {
.base0 = MX7_DDR_BASE_ADDR,
.add_mem = imx7d_ddrc_add_mem,
@@ -703,7 +736,7 @@ static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = {
.data = &imx8mq_data
}, {
.compatible = "fsl,imx8mn-ddrc",
- .data = &imx8mq_data
+ .data = &imx8mn_data
}, {
.compatible = "fsl,imx8mq-ddrc",
.data = &imx8mq_data
@@ -890,11 +923,11 @@ void __noreturn vf610_barebox_entry(void *boarddata)
boarddata);
}
-static void __noreturn imx8m_barebox_entry(void *boarddata)
+static void __noreturn imx8m_barebox_entry(void *boarddata, unsigned buswidth)
{
resource_size_t size;
- size = imx8m_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR));
+ size = imx8m_ddrc_sdram_size(IOMEM(MX8M_DDRC_CTL_BASE_ADDR), buswidth);
/*
* We artificially limit detected memory size to force malloc
* pool placement to be within 4GiB address space, so as to
@@ -910,22 +943,22 @@ static void __noreturn imx8m_barebox_entry(void *boarddata)
void __noreturn imx8mm_barebox_entry(void *boarddata)
{
- imx8m_barebox_entry(boarddata);
+ imx8m_barebox_entry(boarddata, 32);
}
void __noreturn imx8mn_barebox_entry(void *boarddata)
{
- imx8m_barebox_entry(boarddata);
+ imx8m_barebox_entry(boarddata, 16);
}
void __noreturn imx8mp_barebox_entry(void *boarddata)
{
- imx8m_barebox_entry(boarddata);
+ imx8m_barebox_entry(boarddata, 32);
}
void __noreturn imx8mq_barebox_entry(void *boarddata)
{
- imx8m_barebox_entry(boarddata);
+ imx8m_barebox_entry(boarddata, 32);
}
void __noreturn imx7d_barebox_entry(void *boarddata)