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;