Re: [PATCH 14/15] MIPS: malta: setup RAM regions via DT

From: Rob Herring
Date: Thu Oct 29 2015 - 00:39:39 EST


On Fri, May 22, 2015 at 10:51 AM, Paul Burton <paul.burton@xxxxxxxxxx> wrote:
> Move memory configuration to be performed via device tree for the Malta
> board. This moves more Malta specific code to malta-dtshim.c, leaving
> the rest of the mti-malta code a little more board-agnostic. This will
> be useful to share more code between boards, with the device tree
> providing the board specifics as intended.
>
> Since we can't rely upon Malta boards running a bootloader capable of
> handling devictrees & filling in the required information, the
> malta_dt_shim code is extended to consume the (e)memsize variables
> provided as part of the bootloader environment (or on the kernel command
> line) then generate the DT memory node using the provided values.

IMO, I think this all belongs in a shim outside of the kernel. This is
how ARM and powerpc generally deal with old or broken bootloaders. But
then MIPS is such a mess of DT code with every platform doing things
their own way.

Rob

>
> Signed-off-by: Paul Burton <paul.burton@xxxxxxxxxx>
> ---
>
> arch/mips/boot/dts/mti/malta.dts | 4 ++
> arch/mips/mti-malta/malta-dtshim.c | 104 +++++++++++++++++++++++++++++++++++++
> arch/mips/mti-malta/malta-memory.c | 88 -------------------------------
> 3 files changed, 108 insertions(+), 88 deletions(-)
>
> diff --git a/arch/mips/boot/dts/mti/malta.dts b/arch/mips/boot/dts/mti/malta.dts
> index 9720c66..2fe2364 100644
> --- a/arch/mips/boot/dts/mti/malta.dts
> +++ b/arch/mips/boot/dts/mti/malta.dts
> @@ -1,5 +1,9 @@
> /dts-v1/;
>
> +/memreserve/ 0x00000000 0x00001000; /* reserved */
> +/memreserve/ 0x00001000 0x000ef000; /* YAMON */
> +/memreserve/ 0x000f0000 0x00010000; /* PIIX4 ISA memory */
> +
> #include <dt-bindings/interrupt-controller/irq.h>
> #include <dt-bindings/interrupt-controller/mips-gic.h>
>
> diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c
> index ca33201..9074951 100644
> --- a/arch/mips/mti-malta/malta-dtshim.c
> +++ b/arch/mips/mti-malta/malta-dtshim.c
> @@ -20,6 +20,109 @@
>
> static unsigned char fdt_buf[16 << 10] __initdata;
>
> +/* determined physical memory size, not overridden by command line args */
> +extern unsigned long physical_memsize;
> +
> +#define MAX_MEM_ARRAY_ENTRIES 1
> +
> +static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
> +{
> + unsigned long size_preio;
> + unsigned entries;
> +
> + entries = 1;
> + mem_array[0] = cpu_to_be32(PHYS_OFFSET);
> + if (config_enabled(CONFIG_EVA)) {
> + mem_array[1] = cpu_to_be32(PHYS_OFFSET + size);
> + } else {
> + size_preio = min_t(unsigned long, size, 256 << 20);
> + mem_array[1] = cpu_to_be32(PHYS_OFFSET + size_preio);
> + }
> +
> + BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
> + return entries;
> +}
> +
> +static void __init append_memory(void *fdt, int root_off)
> +{
> + __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
> + unsigned long memsize;
> + unsigned mem_entries;
> + int i, err, mem_off;
> + char *var, param_name[10], *var_names[] = {
> + "ememsize", "memsize",
> + };
> +
> + /* if a memory node already exists, leave it alone */
> + mem_off = fdt_path_offset(fdt, "/memory");
> + if (mem_off >= 0)
> + return;
> +
> + /* find memory size from the bootloader environment */
> + for (i = 0; i < ARRAY_SIZE(var_names); i++) {
> + var = fw_getenv(var_names[i]);
> + if (!var)
> + continue;
> +
> + err = kstrtoul(var, 0, &physical_memsize);
> + if (!err)
> + break;
> +
> + pr_warn("Failed to read the '%s' env variable '%s'\n",
> + var_names[i], var);
> + }
> +
> + if (!physical_memsize) {
> + pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
> + physical_memsize = 32 << 20;
> + }
> +
> + if (config_enabled(CONFIG_CPU_BIG_ENDIAN)) {
> + /*
> + * SOC-it swaps, or perhaps doesn't swap, when DMA'ing
> + * the last word of physical memory.
> + */
> + physical_memsize -= PAGE_SIZE;
> + }
> +
> + /* default to using all available RAM */
> + memsize = physical_memsize;
> +
> + /* allow the user to override the usable memory */
> + for (i = 0; i < ARRAY_SIZE(var_names); i++) {
> + snprintf(param_name, sizeof(param_name), "%s=", var_names[i]);
> + var = strstr(arcs_cmdline, param_name);
> + if (!var)
> + continue;
> +
> + memsize = memparse(var + strlen(param_name), NULL);
> + }
> +
> + /* if the user says there's more RAM than we thought, believe them */
> + physical_memsize = max_t(unsigned long, physical_memsize, memsize);
> +
> + /* append memory to the DT */
> + mem_off = fdt_add_subnode(fdt, root_off, "memory");
> + if (mem_off < 0)
> + panic("Unable to add memory node to DT: %d", mem_off);
> +
> + err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
> + if (err)
> + panic("Unable to set memory node device_type: %d", err);
> +
> + mem_entries = gen_fdt_mem_array(mem_array, physical_memsize);
> + err = fdt_setprop(fdt, mem_off, "reg", mem_array,
> + mem_entries * 2 * sizeof(mem_array[0]));
> + if (err)
> + panic("Unable to set memory regs property: %d", err);
> +
> + mem_entries = gen_fdt_mem_array(mem_array, memsize);
> + err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
> + mem_entries * 2 * sizeof(mem_array[0]));
> + if (err)
> + panic("Unable to set linux,usable-memory property: %d", err);
> +}
> +
> static void __init remove_gic(void *fdt)
> {
> int err, gic_off, i8259_off, cpu_off;
> @@ -118,6 +221,7 @@ void __init *malta_dt_shim(void *fdt)
> if (strncmp(compat, "mti,malta", len))
> return fdt;
>
> + append_memory(fdt_buf, root_off);
> remove_gic(fdt_buf);
>
> err = fdt_pack(fdt_buf);
> diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
> index 831f583..5203241 100644
> --- a/arch/mips/mti-malta/malta-memory.c
> +++ b/arch/mips/mti-malta/malta-memory.c
> @@ -32,97 +32,9 @@ static void free_init_pages_eva_malta(void *begin, void *end)
>
> void __init fw_meminit(void)
> {
> - char *memsize_str, *ememsize_str = NULL, *ptr;
> - unsigned long memsize = 0, ememsize = 0;
> - unsigned long kernel_start_phys, kernel_end_phys;
> - static char cmdline[COMMAND_LINE_SIZE] __initdata;
> bool eva = config_enabled(CONFIG_EVA);
> - int tmp;
>
> free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL;
> -
> - memsize_str = fw_getenv("memsize");
> - if (memsize_str) {
> - tmp = kstrtoul(memsize_str, 0, &memsize);
> - if (tmp)
> - pr_warn("Failed to read the 'memsize' env variable.\n");
> - }
> - if (eva) {
> - /* Look for ememsize for EVA */
> - ememsize_str = fw_getenv("ememsize");
> - if (ememsize_str) {
> - tmp = kstrtoul(ememsize_str, 0, &ememsize);
> - if (tmp)
> - pr_warn("Failed to read the 'ememsize' env variable.\n");
> - }
> - }
> - if (!memsize && !ememsize) {
> - pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
> - physical_memsize = 0x02000000;
> - } else {
> - if (memsize > (256 << 20)) { /* memsize should be capped to 256M */
> - pr_warn("Unsupported memsize value (0x%lx) detected! "
> - "Using 0x10000000 (256M) instead\n",
> - memsize);
> - memsize = 256 << 20;
> - }
> - /* If ememsize is set, then set physical_memsize to that */
> - physical_memsize = ememsize ? : memsize;
> - }
> -
> -#ifdef CONFIG_CPU_BIG_ENDIAN
> - /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
> - word of physical memory */
> - physical_memsize -= PAGE_SIZE;
> -#endif
> -
> - /* Check the command line for a memsize directive that overrides
> - the physical/default amount */
> - strcpy(cmdline, arcs_cmdline);
> - ptr = strstr(cmdline, "memsize=");
> - if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
> - ptr = strstr(ptr, " memsize=");
> - /* And now look for ememsize */
> - if (eva) {
> - ptr = strstr(cmdline, "ememsize=");
> - if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
> - ptr = strstr(ptr, " ememsize=");
> - }
> -
> - if (ptr)
> - memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr);
> - else
> - memsize = physical_memsize;
> -
> - add_memory_region(PHYS_OFFSET, 0x00001000, BOOT_MEM_RESERVED);
> -
> - /*
> - * YAMON may still be using the region of memory from 0x1000 to 0xfffff
> - * if it has started secondary CPUs.
> - */
> - add_memory_region(PHYS_OFFSET + 0x00001000, 0x000ef000,
> - BOOT_MEM_ROM_DATA);
> -
> - /*
> - * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
> - * south bridge and PCI access always forwarded to the ISA Bus and
> - * BIOSCS# is always generated.
> - * This mean that this area can't be used as DMA memory for PCI
> - * devices.
> - */
> - add_memory_region(PHYS_OFFSET + 0x000f0000, 0x00010000,
> - BOOT_MEM_RESERVED);
> -
> - /*
> - * Reserve the memory used by kernel code, and allow the rest of RAM to
> - * be used.
> - */
> - kernel_start_phys = PHYS_OFFSET + 0x00100000;
> - kernel_end_phys = PHYS_OFFSET + CPHYSADDR(PFN_ALIGN(&_end));
> - add_memory_region(kernel_start_phys, kernel_end_phys,
> - BOOT_MEM_RESERVED);
> - add_memory_region(kernel_end_phys, memsize - kernel_end_phys,
> - BOOT_MEM_RAM);
> }
>
> void __init prom_free_prom_memory(void)
> --
> 2.4.1
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/