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.c166
1 files changed, 125 insertions, 41 deletions
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index a55ee06b83..701ca0ac1f 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -13,21 +13,24 @@
#include <linux/bitfield.h>
#include <asm/barebox-arm.h>
#include <asm/memory.h>
-#include <mach/esdctl.h>
-#include <mach/esdctl-v4.h>
-#include <mach/imx6-mmdc.h>
-#include <mach/imx1-regs.h>
-#include <mach/imx21-regs.h>
-#include <mach/imx25-regs.h>
-#include <mach/imx27-regs.h>
-#include <mach/imx31-regs.h>
-#include <mach/imx35-regs.h>
-#include <mach/imx51-regs.h>
-#include <mach/imx53-regs.h>
-#include <mach/imx6-regs.h>
-#include <mach/vf610-ddrmc.h>
-#include <mach/imx8m-regs.h>
-#include <mach/imx7-regs.h>
+#include <mach/imx/esdctl.h>
+#include <mach/imx/esdctl-v4.h>
+#include <mach/imx/imx6-mmdc.h>
+#include <mach/imx/imx1-regs.h>
+#include <mach/imx/imx21-regs.h>
+#include <mach/imx/imx25-regs.h>
+#include <mach/imx/imx27-regs.h>
+#include <mach/imx/imx31-regs.h>
+#include <mach/imx/imx35-regs.h>
+#include <mach/imx/imx51-regs.h>
+#include <mach/imx/imx53-regs.h>
+#include <mach/imx/imx6-regs.h>
+#include <mach/imx/vf610-ddrmc.h>
+#include <mach/imx/imx8m-regs.h>
+#include <mach/imx/imx7-regs.h>
+#include <mach/imx/imx9-regs.h>
+#include <mach/imx/scratch.h>
+#include <tee/optee.h>
struct imx_esdctl_data {
unsigned long base0;
@@ -510,16 +513,88 @@ static resource_size_t imx8m_ddrc_sdram_size(void __iomem *ddrc, unsigned buswid
reduced_adress_space, mstr);
}
+static int _imx8m_ddrc_add_mem(void *mmdcbase, struct imx_esdctl_data *data,
+ unsigned int buswidth)
+{
+ resource_size_t size = imx8m_ddrc_sdram_size(mmdcbase, buswidth);
+ resource_size_t size0, size1;
+ int ret;
+
+ /*
+ * Split the available memory into multiple banks if the device does
+ * have more RAM than 3G. At the moment this is necessary to prevent
+ * memory_bank_first_find_space() from finding free space near the end
+ * of the 4G barrier which is the case in a 6G/8G setup. This is
+ * important for larger barebox-pbl binaries (e.g. debug enabled) and
+ * the barebox chainloading mechanism since the pbl init the MMU to 4G.
+ * In this case a MMU exception will be thrown if the barebox-pbl is
+ * placed near the 4G barrier.
+ */
+ size0 = min_t(resource_size_t, SZ_4G - MX8M_DDR_CSD1_BASE_ADDR, size);
+ size1 = size - size0;
+
+ ret = arm_add_mem_device("ram0", data->base0, size0);
+ if (ret || size1 == 0)
+ return ret;
+
+#ifdef CONFIG_64BIT
+ /*
+ * Albeit this hook is called on 64bit machines only, the driver serves
+ * 32bit machines as well. Guard the code to avoid compiler warnings.
+ */
+ ret = arm_add_mem_device("ram1", SZ_4G, size1);
+#endif
+
+ return ret;
+}
+
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, 32));
+ return _imx8m_ddrc_add_mem(mmdcbase, data, 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));
+ return _imx8m_ddrc_add_mem(mmdcbase, data, 16);
+}
+
+#define IMX9_DDRC_CS_CONFIG(n) (0x80 + (n) * 4)
+#define IMX9_DDRC_CS_ROW_BITS GENMASK(10, 8)
+#define IMX9_DDRC_CS_COL_BITS GENMASK(2, 0)
+#define IMX9_DDRC_CS_EN BIT(31)
+
+resource_size_t imx9_ddrc_sdram_size(void)
+{
+ void __iomem *mmdcbase = IOMEM(MX9_DDR_CTL_BASE);
+ int width = 2;
+ int banks = 8;
+ resource_size_t mem = 0;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ int rows, cols;
+ u32 cs, col_bits;
+
+ cs = readl(mmdcbase + IMX9_DDRC_CS_CONFIG(i));
+ if (!(cs & IMX9_DDRC_CS_EN))
+ continue;
+
+ rows = FIELD_GET(IMX9_DDRC_CS_ROW_BITS, cs) + 12;
+ col_bits = FIELD_GET(IMX9_DDRC_CS_COL_BITS, cs);
+ if (col_bits == 7)
+ cols = 7;
+ else
+ cols = col_bits + 8;
+
+ mem += memory_sdram_size(cols, rows, banks, width);
+ }
+
+ return mem;
+}
+
+static int imx9_ddrc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
+{
+ return arm_add_mem_device("ram0", data->base0, imx9_ddrc_sdram_size());
}
static resource_size_t imx7d_ddrc_sdram_size(void __iomem *ddrc)
@@ -568,7 +643,7 @@ static int imx7d_ddrc_add_mem(void *mmdcbase, struct imx_esdctl_data *data)
imx7d_ddrc_sdram_size(mmdcbase));
}
-static int imx_esdctl_probe(struct device_d *dev)
+static int imx_esdctl_probe(struct device *dev)
{
struct resource *iores;
struct imx_esdctl_data *data;
@@ -652,7 +727,7 @@ static __maybe_unused struct imx_esdctl_data vf610_data = {
.add_mem = vf610_ddrmc_add_mem,
};
-static __maybe_unused struct imx_esdctl_data imx8mq_data = {
+static __maybe_unused struct imx_esdctl_data imx8m_data = {
.base0 = MX8M_DDR_CSD1_BASE_ADDR,
.add_mem = imx8m_ddrc_add_mem,
};
@@ -662,6 +737,11 @@ static __maybe_unused struct imx_esdctl_data imx8mn_data = {
.add_mem = imx8mn_ddrc_add_mem,
};
+static __maybe_unused struct imx_esdctl_data imx9_data = {
+ .base0 = MX9_DDR_CSD1_BASE_ADDR,
+ .add_mem = imx9_ddrc_add_mem,
+};
+
static __maybe_unused struct imx_esdctl_data imx7d_data = {
.base0 = MX7_DDR_BASE_ADDR,
.add_mem = imx7d_ddrc_add_mem,
@@ -732,14 +812,14 @@ static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = {
.compatible = "fsl,vf610-ddrmc",
.data = &vf610_data
}, {
- .compatible = "fsl,imx8mm-ddrc",
- .data = &imx8mq_data
+ .compatible = "fsl,imx8m-ddrc",
+ .data = &imx8m_data
}, {
.compatible = "fsl,imx8mn-ddrc",
.data = &imx8mn_data
}, {
- .compatible = "fsl,imx8mq-ddrc",
- .data = &imx8mq_data
+ .compatible = "fsl,imx93-ddrc",
+ .data = &imx9_data
}, {
.compatible = "fsl,imx7d-ddrc",
.data = &imx7d_data
@@ -747,25 +827,15 @@ static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx_esdctl_dt_ids);
-static struct driver_d imx_esdctl_driver = {
+static struct driver imx_esdctl_driver = {
.name = "imx-esdctl",
.probe = imx_esdctl_probe,
.id_table = imx_esdctl_ids,
.of_compatible = DRV_OF_COMPAT(imx_esdctl_dt_ids),
};
-
-static int imx_esdctl_init(void)
-{
- int ret;
-
- ret = platform_driver_register(&imx_esdctl_driver);
- if (ret)
- return ret;
-
- return of_devices_ensure_probed_by_dev_id(imx_esdctl_dt_ids);
-}
-mem_initcall(imx_esdctl_init);
+mem_platform_driver(imx_esdctl_driver);
/*
* The i.MX SoCs usually have two SDRAM chipselects. The following
@@ -923,7 +993,7 @@ void __noreturn vf610_barebox_entry(void *boarddata)
boarddata);
}
-static void __noreturn imx8m_barebox_entry(void *boarddata, unsigned buswidth)
+resource_size_t imx8m_barebox_earlymem_size(unsigned buswidth)
{
resource_size_t size;
@@ -937,8 +1007,15 @@ static void __noreturn imx8m_barebox_entry(void *boarddata, unsigned buswidth)
* pool placement. The rest of the system should be able to
* detect and utilize full amount of memory.
*/
- size = min_t(resource_size_t, SZ_4G - MX8M_DDR_CSD1_BASE_ADDR, size);
- barebox_arm_entry(MX8M_DDR_CSD1_BASE_ADDR, size, boarddata);
+ return min_t(resource_size_t, SZ_4G - MX8M_DDR_CSD1_BASE_ADDR, size);
+}
+
+static void __noreturn imx8m_barebox_entry(void *boarddata, unsigned buswidth)
+{
+ imx8m_init_scratch_space(buswidth, false);
+ optee_set_membase(imx_scratch_get_optee_hdr());
+ barebox_arm_entry(MX8M_DDR_CSD1_BASE_ADDR,
+ imx8m_barebox_earlymem_size(buswidth), boarddata);
}
void __noreturn imx8mm_barebox_entry(void *boarddata)
@@ -968,4 +1045,11 @@ void __noreturn imx7d_barebox_entry(void *boarddata)
boarddata);
}
+void __noreturn imx93_barebox_entry(void *boarddata)
+{
+ imx93_init_scratch_space(false);
+ optee_set_membase(imx_scratch_get_optee_hdr());
+ barebox_arm_entry(MX9_DDR_CSD1_BASE_ADDR,
+ imx9_ddrc_sdram_size(), boarddata);
+}