msm: Build the memory topology by parsing smem.
The kernel needs a view of system memory topology for memory
hotplug. Add support to parse this information available in
shared memory to determine the memory banks and their sizes.
Signed-off-by: Naveen Ramaraj <nramaraj@codeaurora.org>
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index e92f151..97466bb 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -197,7 +197,7 @@
obj-$(CONFIG_ARCH_MSM8960) += clock-local.o clock-dss-8960.o clock-8960.o clock-rpm.o
obj-$(CONFIG_ARCH_MSM8960) += footswitch-8x60.o
obj-$(CONFIG_ARCH_MSM8960) += acpuclock-8960.o
-obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o rpm-regulator-8960.o
+obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o rpm-regulator-8960.o memory_topology.o
obj-$(CONFIG_MACH_MSM8960_SIM) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
obj-$(CONFIG_MACH_MSM8960_RUMI3) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
obj-$(CONFIG_MACH_MSM8960_CDP) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 9de3143..172d1f4 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -82,6 +82,7 @@
#include "mpm.h"
#include "acpuclock.h"
#include "rpm_log.h"
+#include "smd_private.h"
static struct platform_device msm_fm_platform_init = {
.name = "iris_fm",
@@ -4054,6 +4055,9 @@
if (socinfo_init() < 0)
pr_err("socinfo_init() failed!\n");
+ if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
+ pr_err("meminfo_init() failed!\n");
+
BUG_ON(msm_rpm_init(&msm_rpm_data));
BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
ARRAY_SIZE(msm_rpmrs_levels)));
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 8546703..3cf193e 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -22,6 +22,8 @@
#define MAX_PHYSMEM_BITS 32
#define SECTION_SIZE_BITS 28
+/* Maximum number of Memory Regions */
+#define MAX_NR_REGIONS 4
/* Certain configurations of MSM7x30 have multiple memory banks.
* One or more of these banks can contain holes in the memory map as well.
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 61c87f1..a51513f 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -18,12 +18,17 @@
#define __ASM_ARCH_MSM_MEMTYPES_H
#include <mach/memory.h>
+#include <linux/init.h>
+
+int __init meminfo_init(unsigned int, unsigned int);
/* Redundant check to prevent this from being included outside of 7x30 */
#if defined(CONFIG_ARCH_MSM7X30)
unsigned int get_num_populated_chipselects(void);
#endif
-#endif
+unsigned int get_num_memory_banks(void);
+unsigned int get_memory_bank_size(unsigned int);
+unsigned int get_memory_bank_start(unsigned int);
enum {
MEMTYPE_NONE = -1,
@@ -56,3 +61,4 @@
};
extern struct reserve_info *reserve_info;
+#endif
diff --git a/arch/arm/mach-msm/memory_topology.c b/arch/arm/mach-msm/memory_topology.c
index 866907c..423d626 100644
--- a/arch/arm/mach-msm/memory_topology.c
+++ b/arch/arm/mach-msm/memory_topology.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,11 +12,28 @@
#include <asm/setup.h>
+#include <asm/errno.h>
+#include <asm/sizes.h>
+#include <linux/mutex.h>
#include <mach/msm_memtypes.h>
+#include "smd_private.h"
+
+
+static struct mem_region_t {
+ u64 start;
+ u64 size;
+ /* reserved for future use */
+ u64 num_partitions;
+ int state;
+ struct mutex state_mutex;
+} mem_regions[MAX_NR_REGIONS];
+
+static unsigned int nr_mem_regions;
/* Return the number of chipselects populated with a memory bank */
-/* This is 7x30 only and will be extended in the future */
+/* This is 7x30 only and will be re-implemented in the future */
+#if defined(CONFIG_ARCH_MSM7X30)
unsigned int get_num_populated_chipselects()
{
/* Currently, Linux cannot determine the memory toplogy of a target */
@@ -32,4 +49,53 @@
}
return num_chipselects;
}
+#endif
+unsigned int get_num_memory_banks(void)
+{
+ return nr_mem_regions;
+}
+
+unsigned int get_memory_bank_size(unsigned int id)
+{
+ BUG_ON(id >= nr_mem_regions);
+ return mem_regions[id].size;
+}
+
+unsigned int get_memory_bank_start(unsigned int id)
+{
+ BUG_ON(id >= nr_mem_regions);
+ return mem_regions[id].start;
+}
+
+int __init meminfo_init(unsigned int type, unsigned int min_bank_size)
+{
+ unsigned int i;
+ struct smem_ram_ptable *ram_ptable;
+ nr_mem_regions = 0;
+
+ ram_ptable = smem_alloc(SMEM_USABLE_RAM_PARTITION_TABLE,
+ sizeof(struct smem_ram_ptable));
+
+ if (!ram_ptable) {
+ pr_err("Could not read ram partition table\n");
+ return -EINVAL;
+ }
+
+ pr_info("meminfo_init: smem ram ptable found: ver: %d len: %d\n",
+ ram_ptable->version, ram_ptable->len);
+
+ for (i = 0; i < ram_ptable->len; i++) {
+ if (ram_ptable->parts[i].type == type &&
+ ram_ptable->parts[i].size >= min_bank_size) {
+ mem_regions[nr_mem_regions].start =
+ ram_ptable->parts[i].start;
+ mem_regions[nr_mem_regions].size =
+ ram_ptable->parts[i].size;
+ mutex_init(&mem_regions[nr_mem_regions].state_mutex);
+ nr_mem_regions++;
+ }
+ }
+ pr_info("Found %d memory banks\n", nr_mem_regions);
+ return 0;
+}
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 6db8625..a4c60e8 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -133,6 +133,76 @@
unsigned head;
};
+struct smem_ram_ptn {
+ char name[16];
+ unsigned start;
+ unsigned size;
+
+ /* RAM Partition attribute: READ_ONLY, READWRITE etc. */
+ unsigned attr;
+
+ /* RAM Partition category: EBI0, EBI1, IRAM, IMEM */
+ unsigned category;
+
+ /* RAM Partition domain: APPS, MODEM, APPS & MODEM (SHARED) etc. */
+ unsigned domain;
+
+ /* RAM Partition type: system, bootloader, appsboot, apps etc. */
+ unsigned type;
+
+ /* reserved for future expansion without changing version number */
+ unsigned reserved2, reserved3, reserved4, reserved5;
+} __attribute__ ((__packed__));
+
+
+struct smem_ram_ptable {
+ #define _SMEM_RAM_PTABLE_MAGIC_1 0x9DA5E0A8
+ #define _SMEM_RAM_PTABLE_MAGIC_2 0xAF9EC4E2
+ unsigned magic[2];
+ unsigned version;
+ unsigned reserved1;
+ unsigned len;
+ struct smem_ram_ptn parts[32];
+ unsigned buf;
+} __attribute__ ((__packed__));
+
+/* SMEM RAM Partition */
+enum {
+ DEFAULT_ATTRB = ~0x0,
+ READ_ONLY = 0x0,
+ READWRITE,
+};
+
+enum {
+ DEFAULT_CATEGORY = ~0x0,
+ SMI = 0x0,
+ EBI1,
+ EBI2,
+ QDSP6,
+ IRAM,
+ IMEM,
+ EBI0_CS0,
+ EBI0_CS1,
+ EBI1_CS0,
+ EBI1_CS1,
+ SDRAM = 0xE,
+};
+
+enum {
+ DEFAULT_DOMAIN = 0x0,
+ APPS_DOMAIN,
+ MODEM_DOMAIN,
+ SHARED_DOMAIN,
+};
+
+enum {
+ SYS_MEMORY = 1, /* system memory*/
+ BOOT_REGION_MEMORY1, /* boot loader memory 1*/
+ BOOT_REGION_MEMORY2, /* boot loader memory 2,reserved*/
+ APPSBL_MEMORY, /* apps boot loader memory*/
+ APPS_MEMORY, /* apps usage memory*/
+};
+
extern spinlock_t smem_lock;