diff options
Diffstat (limited to 'arch/arm/mach-imx/esdctl.c')
-rw-r--r-- | arch/arm/mach-imx/esdctl.c | 166 |
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); +} |