Skip to content

Commit

Permalink
MIPS: Malta: Setup RAM regions via DT
Browse files Browse the repository at this point in the history
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, a piece of
shim code (malta_dt_shim) is added 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.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: devicetree@vger.kernel.org
Cc: Kumar Gala <galak@codeaurora.org>
Cc: linux-kernel@vger.kernel.org
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Patchwork: https://patchwork.linux-mips.org/patch/11222/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Paul Burton authored and Ralf Baechle committed Nov 11, 2015
1 parent ea05071 commit e81a8c7
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 93 deletions.
2 changes: 2 additions & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@ config MIPS_MALTA
select SYS_SUPPORTS_ZBOOT
select USE_OF
select ZONE_DMA32 if 64BIT
select BUILTIN_DTB
select LIBFDT
help
This enables support for the MIPS Technologies Malta evaluation
board.
Expand Down
4 changes: 4 additions & 0 deletions arch/mips/boot/dts/mti/malta.dts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/dts-v1/;

/memreserve/ 0x00000000 0x00001000; /* YAMON exception vectors */
/memreserve/ 0x00001000 0x000ef000; /* YAMON */
/memreserve/ 0x000f0000 0x00010000; /* PIIX4 ISA memory */

/ {
#address-cells = <1>;
#size-cells = <1>;
Expand Down
29 changes: 29 additions & 0 deletions arch/mips/include/asm/mach-malta/malta-dtshim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2015 Imagination Technologies
* Author: Paul Burton <paul.burton@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/

#ifndef __MIPS_MALTA_DTSHIM_H__
#define __MIPS_MALTA_DTSHIM_H__

#include <linux/init.h>

#ifdef CONFIG_MIPS_MALTA

extern void __init *malta_dt_shim(void *fdt);

#else /* !CONFIG_MIPS_MALTA */

static inline void *malta_dt_shim(void *fdt)
{
return fdt;
}

#endif /* !CONFIG_MIPS_MALTA */

#endif /* __MIPS_MALTA_DTSHIM_H__ */
3 changes: 3 additions & 0 deletions arch/mips/mti-malta/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#
obj-y += malta-display.o
obj-y += malta-dt.o
obj-y += malta-dtshim.o
obj-y += malta-init.o
obj-y += malta-int.o
obj-y += malta-memory.o
Expand All @@ -17,3 +18,5 @@ obj-y += malta-time.o

obj-$(CONFIG_MIPS_CMP) += malta-amon.o
obj-$(CONFIG_MIPS_MALTA_PM) += malta-pm.o

CFLAGS_malta-dtshim.o = -I$(src)/../../../scripts/dtc/libfdt
162 changes: 162 additions & 0 deletions arch/mips/mti-malta/malta-dtshim.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* Copyright (C) 2015 Imagination Technologies
* Author: Paul Burton <paul.burton@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/

#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/libfdt.h>
#include <linux/of_fdt.h>
#include <linux/sizes.h>
#include <asm/bootinfo.h>
#include <asm/fw/fw.h>
#include <asm/page.h>

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)) {
/*
* The current Malta EVA configuration is "special" in that it
* always makes use of addresses in the upper half of the 32 bit
* physical address map, which gives it a contiguous region of
* DDR but limits it to 2GB.
*/
mem_array[1] = cpu_to_be32(size);
} else {
size_preio = min_t(unsigned long, size, SZ_256M);
mem_array[1] = cpu_to_be32(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);
}

void __init *malta_dt_shim(void *fdt)
{
int root_off, len, err;
const char *compat;

if (fdt_check_header(fdt))
panic("Corrupt DT");

err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf));
if (err)
panic("Unable to open FDT: %d", err);

root_off = fdt_path_offset(fdt_buf, "/");
if (root_off < 0)
panic("No / node in DT");

compat = fdt_getprop(fdt_buf, root_off, "compatible", &len);
if (!compat)
panic("No root compatible property in DT: %d", len);

/* if this isn't Malta, leave the DT alone */
if (strncmp(compat, "mti,malta", len))
return fdt;

append_memory(fdt_buf, root_off);

err = fdt_pack(fdt_buf);
if (err)
panic("Unable to pack FDT: %d\n", err);

return fdt_buf;
}
92 changes: 0 additions & 92 deletions arch/mips/mti-malta/malta-memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,101 +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;

/* Last 64K for HIGHMEM arithmetics */
if (memsize > 0x7fff0000)
memsize = 0x7fff0000;

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)
Expand Down
5 changes: 4 additions & 1 deletion arch/mips/mti-malta/malta-setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/time.h>

#include <asm/fw/fw.h>
#include <asm/mach-malta/malta-dtshim.h>
#include <asm/mips-cm.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/malta.h>
Expand Down Expand Up @@ -250,8 +251,10 @@ static void __init bonito_quirks_setup(void)
void __init plat_mem_setup(void)
{
unsigned int i;
void *fdt = __dtb_start;

__dt_setup_arch(__dtb_start);
fdt = malta_dt_shim(fdt);
__dt_setup_arch(fdt);

if (config_enabled(CONFIG_EVA))
/* EVA has already been configured in mach-malta/kernel-init.h */
Expand Down

0 comments on commit e81a8c7

Please sign in to comment.