All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Burton <paul.burton@imgtec.com>
To: <linux-mips@linux-mips.org>, Ralf Baechle <ralf@linux-mips.org>
Cc: Paul Burton <paul.burton@imgtec.com>,
	Masahiro Yamada <yamada.masahiro@socionext.com>,
	Kees Cook <keescook@chromium.org>, <linux-kernel@vger.kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: [PATCH 05/12] MIPS: Malta: Use all available DDR by default
Date: Fri, 2 Sep 2016 16:48:51 +0100	[thread overview]
Message-ID: <20160902154859.24269-6-paul.burton@imgtec.com> (raw)
In-Reply-To: <20160902154859.24269-1-paul.burton@imgtec.com>

Malta boards can have more than 256MB DDR available, but we have
previously only made use of up to 256MB (ie. the DDR accessible via
kseg0) by default, without the user manually specifying mem= kernel
parameters. This patch causes all available DDR, as reported by the
bootloader via the ememsize or memsize environment variables or
optionally on the command line, to be used when possible without the
user needing to manually provide the memory ranges.

Malta now has 2 subtly different memory maps which have to be taken into
account when setting this up. The original memory map (referred to by
the code as v1) has up to 2GB of DDR aliased in both the upper & lower
halves of the 32 bit physical address space, with a 256MB I/O region
obscuring 0x10000000-0x1fffffff only in the lower alias. The revised v2
memory map is flat with up to 4GB DDR starting from 0x0, and the I/O
region obscures 256MB of DDR which becomes inacessible. The memory map
in use is indicated by a register provided by the rocit2 system
controller, which is checked in order to set up the kernels memory
ranges accordingly.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---

 arch/mips/mti-malta/malta-dtshim.c | 109 +++++++++++++++++++++++++++++++++++--
 1 file changed, 103 insertions(+), 6 deletions(-)

diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c
index 151f488..5d37b7e 100644
--- a/arch/mips/mti-malta/malta-dtshim.c
+++ b/arch/mips/mti-malta/malta-dtshim.c
@@ -13,18 +13,63 @@
 #include <linux/libfdt.h>
 #include <linux/of_fdt.h>
 #include <linux/sizes.h>
+#include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/fw/fw.h>
 #include <asm/page.h>
 
+#define ROCIT_REG_BASE			0x1f403000
+#define ROCIT_CONFIG_GEN1		(ROCIT_REG_BASE + 0x04)
+#define  ROCIT_CONFIG_GEN1_MEMMAP_SHIFT	8
+#define  ROCIT_CONFIG_GEN1_MEMMAP_MASK	(0xf << 8)
+
 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
+enum mem_map {
+	MEM_MAP_V1 = 0,
+	MEM_MAP_V2,
+};
+
+#define MAX_MEM_ARRAY_ENTRIES 2
+
+static __init int malta_scon(void)
+{
+	int scon = MIPS_REVISION_SCONID;
+
+	if (scon != MIPS_REVISION_SCON_OTHER)
+		return scon;
+
+	switch (MIPS_REVISION_CORID) {
+	case MIPS_REVISION_CORID_QED_RM5261:
+	case MIPS_REVISION_CORID_CORE_LV:
+	case MIPS_REVISION_CORID_CORE_FPGA:
+	case MIPS_REVISION_CORID_CORE_FPGAR2:
+		return MIPS_REVISION_SCON_GT64120;
+
+	case MIPS_REVISION_CORID_CORE_EMUL_BON:
+	case MIPS_REVISION_CORID_BONITO64:
+	case MIPS_REVISION_CORID_CORE_20K:
+		return MIPS_REVISION_SCON_BONITO;
+
+	case MIPS_REVISION_CORID_CORE_MSC:
+	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_24K:
+		return MIPS_REVISION_SCON_SOCIT;
+
+	case MIPS_REVISION_CORID_CORE_FPGA3:
+	case MIPS_REVISION_CORID_CORE_FPGA4:
+	case MIPS_REVISION_CORID_CORE_FPGA5:
+	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+	default:
+		return MIPS_REVISION_SCON_ROCIT;
+	}
+}
 
-static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
+static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size,
+					 enum mem_map map)
 {
 	unsigned long size_preio;
 	unsigned entries;
@@ -39,11 +84,47 @@ static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
 		 * DDR but limits it to 2GB.
 		 */
 		mem_array[1] = cpu_to_be32(size);
+		goto done;
+	}
+
+	size_preio = min_t(unsigned long, size, SZ_256M);
+	mem_array[1] = cpu_to_be32(size_preio);
+	size -= size_preio;
+	if (!size)
+		goto done;
+
+	if (map == MEM_MAP_V2) {
+		/*
+		 * We have a flat 32 bit physical memory map with DDR filling
+		 * all 4GB of the memory map, apart from the I/O region which
+		 * obscures 256MB from 0x10000000-0x1fffffff.
+		 *
+		 * Therefore we discard the 256MB behind the I/O region.
+		 */
+		if (size <= SZ_256M)
+			goto done;
+		size -= SZ_256M;
+
+		/* Make use of the memory following the I/O region */
+		entries++;
+		mem_array[2] = cpu_to_be32(PHYS_OFFSET + SZ_512M);
+		mem_array[3] = cpu_to_be32(size);
 	} else {
-		size_preio = min_t(unsigned long, size, SZ_256M);
-		mem_array[1] = cpu_to_be32(size_preio);
+		/*
+		 * We have a 32 bit physical memory map with a 2GB DDR region
+		 * aliased in the upper & lower halves of it. The I/O region
+		 * obscures 256MB from 0x10000000-0x1fffffff in the low alias
+		 * but the DDR it obscures is accessible via the high alias.
+		 *
+		 * Simply access everything beyond the lowest 256MB of DDR using
+		 * the high alias.
+		 */
+		entries++;
+		mem_array[2] = cpu_to_be32(PHYS_OFFSET + SZ_2G + SZ_256M);
+		mem_array[3] = cpu_to_be32(size);
 	}
 
+done:
 	BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
 	return entries;
 }
@@ -54,6 +135,8 @@ static void __init append_memory(void *fdt, int root_off)
 	unsigned long memsize;
 	unsigned mem_entries;
 	int i, err, mem_off;
+	enum mem_map mem_map;
+	u32 config;
 	char *var, param_name[10], *var_names[] = {
 		"ememsize", "memsize",
 	};
@@ -106,6 +189,20 @@ static void __init append_memory(void *fdt, int root_off)
 	/* if the user says there's more RAM than we thought, believe them */
 	physical_memsize = max_t(unsigned long, physical_memsize, memsize);
 
+	/* detect the memory map in use */
+	if (malta_scon() == MIPS_REVISION_SCON_ROCIT) {
+		/* ROCit has a register indicating the memory map in use */
+		config = readl((void __iomem *)CKSEG1ADDR(ROCIT_CONFIG_GEN1));
+		mem_map = config & ROCIT_CONFIG_GEN1_MEMMAP_MASK;
+		mem_map >>= ROCIT_CONFIG_GEN1_MEMMAP_SHIFT;
+	} else {
+		/* if not using ROCit, presume the v1 memory map */
+		mem_map = MEM_MAP_V1;
+	}
+	if (mem_map > MEM_MAP_V2)
+		panic("Unsupported physical memory map v%u detected",
+		      (unsigned int)mem_map);
+
 	/* append memory to the DT */
 	mem_off = fdt_add_subnode(fdt, root_off, "memory");
 	if (mem_off < 0)
@@ -115,13 +212,13 @@ static void __init append_memory(void *fdt, int root_off)
 	if (err)
 		panic("Unable to set memory node device_type: %d", err);
 
-	mem_entries = gen_fdt_mem_array(mem_array, physical_memsize);
+	mem_entries = gen_fdt_mem_array(mem_array, physical_memsize, mem_map);
 	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);
+	mem_entries = gen_fdt_mem_array(mem_array, memsize, mem_map);
 	err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
 			  mem_entries * 2 * sizeof(mem_array[0]));
 	if (err)
-- 
2.9.3

WARNING: multiple messages have this Message-ID (diff)
From: Paul Burton <paul.burton@imgtec.com>
To: linux-mips@linux-mips.org, Ralf Baechle <ralf@linux-mips.org>
Cc: Paul Burton <paul.burton@imgtec.com>,
	Masahiro Yamada <yamada.masahiro@socionext.com>,
	Kees Cook <keescook@chromium.org>,
	linux-kernel@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>
Subject: [PATCH 05/12] MIPS: Malta: Use all available DDR by default
Date: Fri, 2 Sep 2016 16:48:51 +0100	[thread overview]
Message-ID: <20160902154859.24269-6-paul.burton@imgtec.com> (raw)
Message-ID: <20160902154851.xH2ZU7kgsMh7JCe7wtD2gSZ05f8Kj4JkTkhCmgYcX8U@z> (raw)
In-Reply-To: <20160902154859.24269-1-paul.burton@imgtec.com>

Malta boards can have more than 256MB DDR available, but we have
previously only made use of up to 256MB (ie. the DDR accessible via
kseg0) by default, without the user manually specifying mem= kernel
parameters. This patch causes all available DDR, as reported by the
bootloader via the ememsize or memsize environment variables or
optionally on the command line, to be used when possible without the
user needing to manually provide the memory ranges.

Malta now has 2 subtly different memory maps which have to be taken into
account when setting this up. The original memory map (referred to by
the code as v1) has up to 2GB of DDR aliased in both the upper & lower
halves of the 32 bit physical address space, with a 256MB I/O region
obscuring 0x10000000-0x1fffffff only in the lower alias. The revised v2
memory map is flat with up to 4GB DDR starting from 0x0, and the I/O
region obscures 256MB of DDR which becomes inacessible. The memory map
in use is indicated by a register provided by the rocit2 system
controller, which is checked in order to set up the kernels memory
ranges accordingly.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---

 arch/mips/mti-malta/malta-dtshim.c | 109 +++++++++++++++++++++++++++++++++++--
 1 file changed, 103 insertions(+), 6 deletions(-)

diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c
index 151f488..5d37b7e 100644
--- a/arch/mips/mti-malta/malta-dtshim.c
+++ b/arch/mips/mti-malta/malta-dtshim.c
@@ -13,18 +13,63 @@
 #include <linux/libfdt.h>
 #include <linux/of_fdt.h>
 #include <linux/sizes.h>
+#include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/fw/fw.h>
 #include <asm/page.h>
 
+#define ROCIT_REG_BASE			0x1f403000
+#define ROCIT_CONFIG_GEN1		(ROCIT_REG_BASE + 0x04)
+#define  ROCIT_CONFIG_GEN1_MEMMAP_SHIFT	8
+#define  ROCIT_CONFIG_GEN1_MEMMAP_MASK	(0xf << 8)
+
 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
+enum mem_map {
+	MEM_MAP_V1 = 0,
+	MEM_MAP_V2,
+};
+
+#define MAX_MEM_ARRAY_ENTRIES 2
+
+static __init int malta_scon(void)
+{
+	int scon = MIPS_REVISION_SCONID;
+
+	if (scon != MIPS_REVISION_SCON_OTHER)
+		return scon;
+
+	switch (MIPS_REVISION_CORID) {
+	case MIPS_REVISION_CORID_QED_RM5261:
+	case MIPS_REVISION_CORID_CORE_LV:
+	case MIPS_REVISION_CORID_CORE_FPGA:
+	case MIPS_REVISION_CORID_CORE_FPGAR2:
+		return MIPS_REVISION_SCON_GT64120;
+
+	case MIPS_REVISION_CORID_CORE_EMUL_BON:
+	case MIPS_REVISION_CORID_BONITO64:
+	case MIPS_REVISION_CORID_CORE_20K:
+		return MIPS_REVISION_SCON_BONITO;
+
+	case MIPS_REVISION_CORID_CORE_MSC:
+	case MIPS_REVISION_CORID_CORE_FPGA2:
+	case MIPS_REVISION_CORID_CORE_24K:
+		return MIPS_REVISION_SCON_SOCIT;
+
+	case MIPS_REVISION_CORID_CORE_FPGA3:
+	case MIPS_REVISION_CORID_CORE_FPGA4:
+	case MIPS_REVISION_CORID_CORE_FPGA5:
+	case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+	default:
+		return MIPS_REVISION_SCON_ROCIT;
+	}
+}
 
-static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
+static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size,
+					 enum mem_map map)
 {
 	unsigned long size_preio;
 	unsigned entries;
@@ -39,11 +84,47 @@ static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
 		 * DDR but limits it to 2GB.
 		 */
 		mem_array[1] = cpu_to_be32(size);
+		goto done;
+	}
+
+	size_preio = min_t(unsigned long, size, SZ_256M);
+	mem_array[1] = cpu_to_be32(size_preio);
+	size -= size_preio;
+	if (!size)
+		goto done;
+
+	if (map == MEM_MAP_V2) {
+		/*
+		 * We have a flat 32 bit physical memory map with DDR filling
+		 * all 4GB of the memory map, apart from the I/O region which
+		 * obscures 256MB from 0x10000000-0x1fffffff.
+		 *
+		 * Therefore we discard the 256MB behind the I/O region.
+		 */
+		if (size <= SZ_256M)
+			goto done;
+		size -= SZ_256M;
+
+		/* Make use of the memory following the I/O region */
+		entries++;
+		mem_array[2] = cpu_to_be32(PHYS_OFFSET + SZ_512M);
+		mem_array[3] = cpu_to_be32(size);
 	} else {
-		size_preio = min_t(unsigned long, size, SZ_256M);
-		mem_array[1] = cpu_to_be32(size_preio);
+		/*
+		 * We have a 32 bit physical memory map with a 2GB DDR region
+		 * aliased in the upper & lower halves of it. The I/O region
+		 * obscures 256MB from 0x10000000-0x1fffffff in the low alias
+		 * but the DDR it obscures is accessible via the high alias.
+		 *
+		 * Simply access everything beyond the lowest 256MB of DDR using
+		 * the high alias.
+		 */
+		entries++;
+		mem_array[2] = cpu_to_be32(PHYS_OFFSET + SZ_2G + SZ_256M);
+		mem_array[3] = cpu_to_be32(size);
 	}
 
+done:
 	BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
 	return entries;
 }
@@ -54,6 +135,8 @@ static void __init append_memory(void *fdt, int root_off)
 	unsigned long memsize;
 	unsigned mem_entries;
 	int i, err, mem_off;
+	enum mem_map mem_map;
+	u32 config;
 	char *var, param_name[10], *var_names[] = {
 		"ememsize", "memsize",
 	};
@@ -106,6 +189,20 @@ static void __init append_memory(void *fdt, int root_off)
 	/* if the user says there's more RAM than we thought, believe them */
 	physical_memsize = max_t(unsigned long, physical_memsize, memsize);
 
+	/* detect the memory map in use */
+	if (malta_scon() == MIPS_REVISION_SCON_ROCIT) {
+		/* ROCit has a register indicating the memory map in use */
+		config = readl((void __iomem *)CKSEG1ADDR(ROCIT_CONFIG_GEN1));
+		mem_map = config & ROCIT_CONFIG_GEN1_MEMMAP_MASK;
+		mem_map >>= ROCIT_CONFIG_GEN1_MEMMAP_SHIFT;
+	} else {
+		/* if not using ROCit, presume the v1 memory map */
+		mem_map = MEM_MAP_V1;
+	}
+	if (mem_map > MEM_MAP_V2)
+		panic("Unsupported physical memory map v%u detected",
+		      (unsigned int)mem_map);
+
 	/* append memory to the DT */
 	mem_off = fdt_add_subnode(fdt, root_off, "memory");
 	if (mem_off < 0)
@@ -115,13 +212,13 @@ static void __init append_memory(void *fdt, int root_off)
 	if (err)
 		panic("Unable to set memory node device_type: %d", err);
 
-	mem_entries = gen_fdt_mem_array(mem_array, physical_memsize);
+	mem_entries = gen_fdt_mem_array(mem_array, physical_memsize, mem_map);
 	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);
+	mem_entries = gen_fdt_mem_array(mem_array, memsize, mem_map);
 	err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
 			  mem_entries * 2 * sizeof(mem_array[0]));
 	if (err)
-- 
2.9.3

  parent reply	other threads:[~2016-09-02 15:51 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-02 15:48 [PATCH 00/12] Partial MIPS Malta DT conversion Paul Burton
2016-09-02 15:48 ` Paul Burton
2016-09-02 15:48 ` Paul Burton
2016-09-02 15:48 ` [PATCH 01/12] irqchip: i8259: Add domain before mapping parent irq Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 15:48 ` [PATCH 02/12] irqchip: i8259: Allow platforms to override poll function Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 15:48 ` [PATCH 03/12] irqchip: i8259: Remove unused i8259A_irq_pending Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 15:48 ` [PATCH 04/12] MIPS: Malta: Allow PCI devices DMA to lower 2GB physical Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 15:48 ` Paul Burton [this message]
2016-09-02 15:48   ` [PATCH 05/12] MIPS: Malta: Use all available DDR by default Paul Burton
2016-09-03 10:27   ` kbuild test robot
2016-09-03 10:27     ` kbuild test robot
2016-09-02 15:48 ` [PATCH 06/12] MIPS: Malta: Probe interrupt controllers via DT Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 15:48 ` [PATCH 07/12] MIPS: Malta: Probe RTC " Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-03 12:15   ` Sergei Shtylyov
2016-09-02 15:48 ` [PATCH 08/12] MIPS: Malta: Probe pflash " Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 15:48 ` [PATCH 09/12] MIPS: Malta: Use syscon-reboot driver to reboot Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 15:48 ` [PATCH 10/12] MIPS: Malta: Remove custom halt implementation Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 15:48 ` [PATCH 11/12] power: reset: Add Intel PIIX4 poweroff driver Paul Burton
2016-09-02 15:48   ` Paul Burton
2016-09-02 16:26   ` Sebastian Reichel
2016-09-02 15:48 ` [PATCH 12/12] MIPS: Malta: Use PIIX4 poweroff driver to power down Paul Burton
2016-09-02 15:48   ` Paul Burton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160902154859.24269-6-paul.burton@imgtec.com \
    --to=paul.burton@imgtec.com \
    --cc=akpm@linux-foundation.org \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@linux-mips.org \
    --cc=ralf@linux-mips.org \
    --cc=yamada.masahiro@socionext.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.