diff --git a/linux-ramdump-parser-v2/parsers/lpm.py b/linux-ramdump-parser-v2/parsers/lpm.py
new file mode 100644
index 0000000000000000000000000000000000000000..150ccc03ab8035f05033203a25d4327ece3c751e
--- /dev/null
+++ b/linux-ramdump-parser-v2/parsers/lpm.py
@@ -0,0 +1,344 @@
+# Copyright (c) 2015, The Linux Foundation. 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
+# only version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+import linux_list
+from parser_util import register_parser, RamParser
+from operator import itemgetter
+
+@register_parser('--lpm', 'Parse LPM Driver info')
+class lpm(RamParser):
+    def __init__(self, *args):
+        super(lpm, self).__init__(*args)
+        self.head = ''
+        self.output = []
+        self.clusters = []
+        self.cpu_possible_bits = None
+        self.cpu_online_bits = None
+        self.lpm_debug = []
+
+    def get_bits(self):
+        bits_addr = self.ramdump.addr_lookup('cpu_possible_bits')
+        if bits_addr is None:
+                self.output.append("NOTE: 'cpu_possible_bits' not found")
+                return
+
+        self.cpu_possible_bits = self.ramdump.read_int(bits_addr)
+        cpus = bin(self.cpu_possible_bits).count('1')
+        self.output.append("{}\n".format('Available CPUs'))
+        for i in range(0, cpus):
+                self.output.append("{:10}{}:{}\n".format("", "CPU", i))
+        self.output.append("\n")
+
+        bits_addr = self.ramdump.addr_lookup('cpu_online_bits')
+        if bits_addr is None:
+                self.output.append("NOTE: 'cpu_online_bits' not found")
+                return
+
+        self.cpu_online_bits = self.ramdump.read_int(bits_addr)
+        cpus = bin(self.cpu_online_bits).count('1')
+        self.output.append("{}\n".format('Online CPUs'))
+        for i in range(0, cpus):
+                self.output.append("{:10}{}:{}\n".format("", "CPU", i))
+        self.output.append("{}{}{}".format("\n", "-" * 81, "\n"))
+
+    def get_cluster_level_info(self, lpm_cluster):
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'nlevels')
+        nlevels = self.ramdump.read_int(lpm_cluster + offset)
+        self.output.append("{:20}:{}\n".format("number of levels", nlevels))
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'min_child_level')
+        node = self.ramdump.read_int(lpm_cluster + offset)
+        self.output.append("{:20}:{}\n".format("min child level", node))
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'default_level')
+        node = self.ramdump.read_int(lpm_cluster + offset)
+        self.output.append("{:20}:{}\n".format("default level", node))
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'last_level')
+        node = self.ramdump.read_int(lpm_cluster + offset)
+        self.output.append("{:20}:{}\n".format("last_level", node))
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'levels')
+        levels = lpm_cluster + offset
+        self.output.append("\n")
+
+        cluster_level_size = self.ramdump.sizeof('struct lpm_cluster_level')
+
+        for i in xrange(nlevels):
+                # ToDo: Need a better way to arrive at the next level info.
+                level = levels + (i * cluster_level_size)
+
+                offset = self.ramdump.field_offset('struct lpm_cluster_level', 'mode')
+                addr = self.ramdump.read_word(level + offset, True)
+                node = self.ramdump.read_int(addr)
+                self.output.append("{:20}:{}\n".format("level mode", node))
+
+                offset = self.ramdump.field_offset('struct lpm_cluster_level', 'level_name')
+                addr = self.ramdump.read_word(level + offset, True)
+                name = self.ramdump.read_cstring(addr, 48)
+                self.output.append("{:20}:{}\n".format("level name", name))
+
+                offset = self.ramdump.field_offset('struct lpm_cluster_level', 'min_child_level')
+                addr = level + offset
+                node = self.ramdump.read_int(addr)
+                self.output.append("{:20}:{}\n".format("min child level", node))
+
+                offset = self.ramdump.field_offset('struct lpm_cluster_level', 'num_cpu_votes')
+                addr = level + offset
+                node = self.ramdump.read_int(addr)
+                self.output.append("{:20}:{}({})\n".format("num cpu votes", hex(node).rstrip("L"), bin(node).lstrip("0b")))
+
+                offset = self.ramdump.field_offset('struct lpm_cluster_level', 'available')
+                addr = level + offset
+
+                offset = self.ramdump.field_offset('struct lpm_level_avail', 'idle_enabled')
+                node = self.ramdump.read_bool(addr + offset)
+                self.output.append("{:20}:{}\n".format("idle_enabled", node))
+
+                offset = self.ramdump.field_offset('struct lpm_level_avail', 'suspend_enabled')
+                node = self.ramdump.read_bool(addr + offset)
+                self.output.append("{:20}:{}\n".format("suspend_enabled", node))
+                self.output.append("\n")
+
+    def get_cluster_info(self, lpm_cluster):
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'cluster_name')
+        addr = self.ramdump.read_word(lpm_cluster + offset, True)
+        node = self.ramdump.read_cstring(addr, 48)
+        self.output.append("{:20}:{}\n".format("Cluster Name", node))
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'child_cpus')
+        node = self.ramdump.read_int(lpm_cluster + offset)
+        self.output.append("{:20}:{}({})\n".format("child_cpus", hex(node).rstrip("L"), bin(node).lstrip("0b")))
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'num_childs_in_sync')
+        node = self.ramdump.read_int(lpm_cluster + offset)
+        self.output.append("{:20}:{}({})\n".format("num_childs_in_sync", hex(node).rstrip("L"), bin(node).lstrip("0b")))
+        self.output.append("\n")
+
+    def lpm_walker(self, lpm_cluster):
+        if lpm_cluster == self.head:
+                return
+        self.clusters.append(lpm_cluster)
+
+    def get_clusters(self):
+        lpm_root_node = self.ramdump.read_word(self.ramdump.addr_lookup('lpm_root_node'), True)
+        if lpm_root_node is None:
+                self.output_file.write("NOTE: 'lpm_root_node' not found\n")
+                return
+
+        self.clusters.append(lpm_root_node)
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'child')
+        lpm_cluster = self.ramdump.read_word(lpm_root_node + offset, True)
+        self.head = lpm_root_node + offset
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'list')
+        lpm_walker = linux_list.ListWalker(self.ramdump, lpm_cluster, offset)
+        lpm_walker.walk(lpm_cluster, self.lpm_walker)
+
+    def get_cpu_level_info(self, cpu_cluster_base, cpu):
+        self.output.append("{:20}:{}\n".format("CPU", cpu))
+
+        cpu_cluster = self.ramdump.read_word(cpu_cluster_base, cpu=cpu)
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'cpu')
+        cpu_level = self.ramdump.read_word(cpu_cluster + offset, True)
+
+        offset = self.ramdump.field_offset('struct lpm_cpu', 'nlevels')
+        nlevels = self.ramdump.read_int(cpu_level + offset, True)
+        self.output.append("{:20}:{}\n".format("number of levels", nlevels))
+
+        offset = self.ramdump.field_offset('struct lpm_cpu', 'levels')
+        levels = cpu_level + offset
+
+        self.output.append("\n")
+
+        cpu_level_available = self.ramdump.addr_lookup('cpu_level_available')
+        if cpu_level_available is None:
+                self.output.append("NOTE: 'cpu_level_available' not found\n")
+                return
+        cpu_level_available = cpu_level_available + self.ramdump.sizeof('long') * cpu
+        cpu_level_available = self.ramdump.read_word(cpu_level_available, True)
+
+        for i in range(0, nlevels):
+                level = levels + (i * self.ramdump.sizeof('struct lpm_cpu_level'))
+
+                offset = self.ramdump.field_offset('struct lpm_cpu_level', 'name')
+                addr = self.ramdump.read_word(level + offset, True)
+                node = self.ramdump.read_cstring(addr, 48)
+                self.output.append("{:20}:{}\n".format("level name", node))
+
+                offset = self.ramdump.field_offset('struct lpm_cpu_level', 'mode')
+                node = self.ramdump.read_int(level + offset, True)
+                self.output.append("{:20}:{}\n".format("level mode", node))
+
+                level_available = cpu_level_available + i * self.ramdump.sizeof('struct lpm_level_avail')
+                offset = self.ramdump.field_offset('struct lpm_level_avail', 'idle_enabled')
+                node = self.ramdump.read_bool(level_available + offset)
+                self.output.append("{:20}:{}\n".format("idle enabled", node))
+
+                offset = self.ramdump.field_offset('struct lpm_level_avail', 'suspend_enabled')
+                node = self.ramdump.read_bool(level_available + offset, True)
+                self.output.append("{:20}:{}\n".format("suspend enabled", node))
+
+                self.output.append("\n")
+
+        self.output.append("{}{}".format("-" * 81, "\n"))
+
+    def get_lpm(self):
+        self.get_clusters()
+        for i in self.clusters:
+                self.get_cluster_info(i)
+                self.get_cluster_level_info(i)
+                self.output.append("{}{}".format("-" * 81, "\n"))
+
+        cpu_cluster_base = self.ramdump.addr_lookup('cpu_cluster')
+        if cpu_cluster_base is None:
+                self.output.append("NOTE: 'cpu_cluster' not found\n")
+                return
+
+        cpus = bin(self.cpu_possible_bits).count('1')
+        for i in range(0, cpus):
+                self.get_cpu_level_info(cpu_cluster_base, i)
+
+    def get_time_stats(self, tstats, nlevels):
+        for i in range(nlevels):
+                lstats = tstats + i * self.ramdump.sizeof('struct level_stats')
+
+                offset = self.ramdump.field_offset('struct level_stats', 'name')
+                addr = self.ramdump.read_word(lstats + offset, True)
+                self.output.append("{:20}:{}\n".format("lpm name", self.ramdump.read_cstring(addr + offset, 48)))
+
+                offset = self.ramdump.field_offset('struct level_stats', 'success_count')
+                self.output.append("{:20}:{}\n".format("success_count", self.ramdump.read_int(lstats + offset, True)))
+
+                offset = self.ramdump.field_offset('struct level_stats', 'failed_count')
+                self.output.append("{:20}:{}\n".format("failed_count", self.ramdump.read_int(lstats + offset, True)))
+
+                self.output.append("\n")
+
+    def get_cluster_stats(self, cluster):
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'stats')
+        stats = self.ramdump.read_word(cluster + offset, True)
+
+        offset = self.ramdump.field_offset('struct lpm_stats', 'name')
+        self.output.append("{} {}\n\n".format(self.ramdump.read_cstring(stats + offset, 48), "lpm stats"))
+
+        offset = self.ramdump.field_offset('struct lpm_stats', 'num_levels')
+        nlevels = self.ramdump.read_int(stats + offset, True)
+
+        offset = self.ramdump.field_offset('struct lpm_stats', 'time_stats')
+        tstats = self.ramdump.read_word(stats + offset, True)
+
+        self.get_time_stats(tstats, nlevels)
+        self.output.append("{}{}".format("-" * 81, "\n"))
+
+    def get_cpu_stats(self, cpu_stats_base, cpu):
+        stats = cpu_stats_base + self.ramdump.per_cpu_offset(cpu)
+
+        offset = self.ramdump.field_offset('struct lpm_stats', 'name')
+        self.output.append("{} {}\n\n".format(self.ramdump.read_cstring(stats + offset, 48), "lpm stats"))
+
+        offset = self.ramdump.field_offset('struct lpm_stats', 'num_levels')
+        nlevels = self.ramdump.read_int(stats + offset, True)
+
+        offset = self.ramdump.field_offset('struct lpm_stats', 'time_stats')
+        tstats = self.ramdump.read_word(stats + offset, True)
+
+        self.get_time_stats(tstats, nlevels)
+        self.output.append("{}{}".format("-" * 81, "\n"))
+
+    def get_stats(self):
+        for i in self.clusters:
+                self.get_cluster_stats(i)
+
+        cpu_stats_base = self.ramdump.addr_lookup('cpu_stats')
+        if cpu_stats_base is None:
+                self.output.append("NOTE: 'cpu_stats' not found\n")
+                return
+
+        cpus = bin(self.cpu_possible_bits).count('1')
+        for i in range(0, cpus):
+                self.get_cpu_stats(cpu_stats_base, i)
+
+    def get_debug_phys(self):
+        lpm_debug_phys = self.ramdump.addr_lookup('lpm_debug_phys')
+        if lpm_debug_phys is None:
+                self.output.append("NOTE: 'lpm_debug data' not found\n")
+                return
+        lpm_debug_phys = self.ramdump.read_word(lpm_debug_phys, True)
+
+        for i in range(0, 256):
+                debug = []
+
+                addr = lpm_debug_phys + i * self.ramdump.sizeof('struct lpm_debug')
+
+                offset = self.ramdump.field_offset('struct lpm_debug', 'time')
+                time = self.ramdump.read_word(addr + offset, False)
+                debug.append(time)
+
+                offset = self.ramdump.field_offset('struct lpm_debug', 'evt')
+                evt = self.ramdump.read_int(addr + offset, False)
+                debug.append(evt)
+
+                offset = self.ramdump.field_offset('struct lpm_debug', 'cpu')
+                cpu = self.ramdump.read_int(addr + offset, False)
+                debug.append(cpu)
+
+                offset = self.ramdump.field_offset('struct lpm_debug', 'arg1')
+                arg1 = self.ramdump.read_int(addr + offset, False)
+                debug.append(arg1)
+
+                offset = self.ramdump.field_offset('struct lpm_debug', 'arg2')
+                arg2 = self.ramdump.read_int(addr + offset, False)
+                debug.append(arg2)
+
+                offset = self.ramdump.field_offset('struct lpm_debug', 'arg3')
+                arg3 = self.ramdump.read_int(addr + offset, False)
+                debug.append(arg3)
+
+                offset = self.ramdump.field_offset('struct lpm_debug', 'arg4')
+                arg4 = self.ramdump.read_int(addr + offset, False)
+                debug.append(arg4)
+
+                self.lpm_debug.append(debug)
+
+    def print_debug_phys(self):
+        debug = []
+        lpm_debug = []
+
+        self.output.append("\n")
+        self.output.append("{:16}".format("TimeStamp"))
+        self.output.append("{:8} {:8} {:8} ".format("Event", "CPU", "arg1"))
+        self.output.append("{:16}{:16}{:16}\n".format("arg2", "arg3", "arg4"))
+        self.output.append("{}{}".format("-" * 81, "\n"))
+
+        lpm_debug = sorted(self.lpm_debug, key=itemgetter(0))
+
+        for i in range(len(lpm_debug)):
+                debug = lpm_debug[i]
+                for j in range(len(debug)):
+                        if j == 0 or j > 3:
+                                self.output.append("{:16}".format(hex(debug[j]).rstrip("L")))
+                        else:
+                                self.output.append("{}{:8}".format(debug[j], ""))
+
+                self.output.append("\n")
+
+    def parse(self):
+        self.output_file = self.ramdump.open_file('lpm.txt')
+        self.get_bits()
+        self.get_lpm()
+        self.get_stats()
+        self.get_debug_phys()
+        self.print_debug_phys()
+        for i in self.output:
+                self.output_file.write(i)
+        self.output_file.close()
diff --git a/linux-ramdump-parser-v2/parsers/spm.py b/linux-ramdump-parser-v2/parsers/spm.py
new file mode 100644
index 0000000000000000000000000000000000000000..076a435f3adc8ac433a4bb8b0baa9ec486b2c0e3
--- /dev/null
+++ b/linux-ramdump-parser-v2/parsers/spm.py
@@ -0,0 +1,112 @@
+# Copyright (c) 2015, The Linux Foundation. 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
+# only version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+import linux_list
+from parser_util import register_parser, RamParser
+
+@register_parser('--spm', 'Parse SPM Driver info')
+class spm(RamParser):
+    def __init__(self, *args):
+        super(spm, self).__init__(*args)
+        self.head = ''
+        self.output = []
+        self.spm_reg_2_1 = ('MSM_SPM_REG_SAW2_SECURE', 'MSM_SPM_REG_SAW2_ID',
+                        'MSM_SPM_REG_SAW2_CFG', 'MSM_SPM_REG_SAW2_SPM_STS',
+                        'MSM_SPM_REG_SAW2_AVS_STS', 'MSM_SPM_REG_SAW2_PMIC_STS',
+                        'MSM_SPM_REG_SAW2_RST', 'MSM_SPM_REG_SAW2_VCTL',
+                        'MSM_SPM_REG_SAW2_AVS_CTL', 'MSM_SPM_REG_SAW2_AVS_LIMIT',
+                        'MSM_SPM_REG_SAW2_AVS_DLY', 'MSM_SPM_REG_SAW2_AVS_HYSTERESIS',
+                        'MSM_SPM_REG_SAW2_SPM_CTL', 'MSM_SPM_REG_SAW2_SPM_DLY',
+                        'MSM_SPM_REG_SAW2_PMIC_DATA_0', 'MSM_SPM_REG_SAW2_PMIC_DATA_1',
+                        'MSM_SPM_REG_SAW2_PMIC_DATA_2', 'MSM_SPM_REG_SAW2_PMIC_DATA_3',
+                        'MSM_SPM_REG_SAW2_PMIC_DATA_4', 'MSM_SPM_REG_SAW2_PMIC_DATA_5',
+                        'MSM_SPM_REG_SAW2_PMIC_DATA_6', 'MSM_SPM_REG_SAW2_PMIC_DATA_7',
+                        'MSM_SPM_REG_SAW2_SEQ_ENTRY', 'MSM_SPM_REG_SAW2_VERSION')
+
+        self.spm_reg_3_0 = ('MSM_SPM_REG_SAW2_SECURE', 'MSM_SPM_REG_SAW2_ID',
+                        'MSM_SPM_REG_SAW2_CFG', 'MSM_SPM_REG_SAW2_SPM_STS',
+                        'MSM_SPM_REG_SAW2_AVS_STS', 'MSM_SPM_REG_SAW2_PMIC_STS',
+                        'MSM_SPM_REG_SAW2_RST', 'MSM_SPM_REG_SAW2_VCTL',
+                        'MSM_SPM_REG_SAW2_AVS_CTL', 'MSM_SPM_REG_SAW2_AVS_LIMIT',
+                        'MSM_SPM_REG_SAW2_AVS_DLY', 'MSM_SPM_REG_SAW2_AVS_HYSTERESIS',
+                        'MSM_SPM_REG_SAW2_SPM_CTL', 'MSM_SPM_REG_SAW2_SPM_DLY',
+                        'MSM_SPM_REG_SAW2_STS2', 'MSM_SPM_REG_SAW2_PMIC_DATA_0',
+                        'MSM_SPM_REG_SAW2_PMIC_DATA_1', 'MSM_SPM_REG_SAW2_PMIC_DATA_2',
+                        'MSM_SPM_REG_SAW2_PMIC_DATA_3', 'MSM_SPM_REG_SAW2_PMIC_DATA_4',
+                        'MSM_SPM_REG_SAW2_PMIC_DATA_5', 'MSM_SPM_REG_SAW2_PMIC_DATA_6',
+                        'MSM_SPM_REG_SAW2_PMIC_DATA_7', 'MSM_SPM_REG_SAW2_SEQ_ENTRY',
+                        'MSM_SPM_REG_SAW2_VERSION')
+
+    def spm_walker(self, spm):
+        if spm == self.head:
+                return
+
+        offset = self.ramdump.field_offset('struct msm_spm_device', 'initialized')
+        if self.ramdump.read_bool(spm + offset) is False:
+                return
+
+        offset = self.ramdump.field_offset('struct msm_spm_device', 'name')
+        name = self.ramdump.read_cstring(self.ramdump.read_word(spm + offset, True), 48)
+        self.output.append("{:35}:{}\n".format("SPM Device Name", name))
+
+        offset = self.ramdump.field_offset('struct msm_spm_device', 'reg_data')
+        reg_data = spm + offset
+
+        offset = self.ramdump.field_offset('struct msm_spm_driver_data', 'major')
+        addr = reg_data + offset
+        major = self.ramdump.read_int(addr)
+        self.output.append("{:35}:{}".format("version", major))
+
+        offset = self.ramdump.field_offset('struct msm_spm_driver_data', 'minor')
+        addr = reg_data + offset
+        minor = self.ramdump.read_int(addr)
+        self.output.append(".{}\n".format(minor))
+
+        self.output.append("\n{}\n".format("Shadow Registers"))
+
+        offset = self.ramdump.field_offset('struct msm_spm_driver_data', 'reg_shadow')
+
+        if major is 2 and minor is 1:
+                rList = self.spm_reg_2_1
+        else:
+                rList = self.spm_reg_3_0
+
+        for i in range(len(rList)):
+                addr = reg_data + offset + i * self.ramdump.sizeof('uint32_t')
+                val = self.ramdump.read_int(addr)
+                self.output.append("{:35}:{}\n".format(rList[i], hex(val).rstrip("L")))
+
+        self.output.append("{}{}".format("-" * 81, "\n\n"))
+
+    def get_spm(self):
+        lpm_root_node = self.ramdump.read_word(self.ramdump.addr_lookup('lpm_root_node'), True)
+        if lpm_root_node is None:
+                self.output_file.write("NOTE: 'lpm_root_node' not found\n")
+                return
+
+        offset = self.ramdump.field_offset('struct lpm_cluster', 'lpm_dev')
+        lpm_dev = self.ramdump.read_word(lpm_root_node + offset, True)
+
+        offset = self.ramdump.field_offset('struct low_power_ops', 'spm')
+        spm = self.ramdump.read_word(lpm_dev + offset, True)
+
+        self.head = lpm_dev + offset
+
+        offset = self.ramdump.field_offset('struct msm_spm_device', 'list')
+        spm_walker = linux_list.ListWalker(self.ramdump, spm, offset)
+        spm_walker.walk(spm, self.spm_walker)
+
+    def parse(self):
+        self.output_file = self.ramdump.open_file('spm.txt')
+        self.get_spm()
+        for i in self.output:
+                self.output_file.write(i)
+        self.output_file.close()