diff --git a/linux-ramdump-parser-v2/cachedumplib.py b/linux-ramdump-parser-v2/cachedumplib.py
new file mode 100755
index 0000000000000000000000000000000000000000..fdb255fe4683d42713fc0bc9be5d7af9dda4f121
--- /dev/null
+++ b/linux-ramdump-parser-v2/cachedumplib.py
@@ -0,0 +1,336 @@
+# 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 struct
+from print_out import print_out_str, print_out_exception
+
+"""dictionary mapping from (hw_id, client_id, version) to class CacheDump"""
+lookuptable = {}
+
+def lookup_cache_type(hwid, client_id, version):
+    """defaults to CacheDump() if no match found"""
+    return lookuptable.get((hwid, client_id, version), CacheDump())
+
+def formatwidth(string, limit):
+    if len(string) >= limit:
+        return string[0:limit]
+    formatstr = '{{0:{0}}}'.format(limit)
+    return formatstr.format(string)
+
+class TableOutputFormat:
+    """ Not sure if using PrettyTable (python lib) is a good idea, since people
+    would need to install it"""
+
+    def __init__(self):
+        self.titlebar = []
+        self.datafmt = []
+        self.have_printed_title = False
+        self.separator = ' '
+
+    def addColumn(self, string, datafmt='{0}', width=0):
+        width = max(len(string), width)
+        string = formatwidth(string, width)
+        self.titlebar.append(string)
+        self.datafmt.append(datafmt)
+
+    def printline(self, array, outfile):
+        if (len(array) != len(self.titlebar)):
+            raise Exception('BadTableDataSize', array, self.titlebar)
+
+        if (not self.have_printed_title):
+            self.have_printed_title = True
+            outfile.write(self.separator.join(self.titlebar))
+            outfile.write('\n')
+
+        for item, title, fmt in zip(array, self.titlebar, self.datafmt):
+            item = fmt.format(item)
+            item = formatwidth(item, len(title))
+            outfile.write(item)
+            outfile.write(self.separator)
+
+        outfile.write('\n')
+
+class CacheDump(object):
+    """ Class to describe a method to parse a particular type of cachedump.
+    Users should not make instances of this class."""
+    def __init__(self):
+        """do nothing"""
+
+    def parse(self, start, end, ramdump, outfile):
+        """Called from debug_image_v2.py. Overriden by child classes"""
+        raise NotImplementedError
+
+struct_CacheDumpType_v1 = [
+    ('<I', 'status0'),     #Status Registers
+    ('I', 'status1'),
+    ('I', 'status2'),
+    ('I', 'status3'),
+    ('I', 'TagSize'),     #Tag Size in u32 words
+    ('I', 'LineSize'),    #Line Size in u32 words
+    ('I', 'NumSets'),     #Number of sets
+    ('I', 'NumWays'),     #Number of ways
+    ('Q', 'next'),        #unused
+    ('I', '__reserved0'),
+    ('I', '__reserved1'),
+    ('I', '__reserved2'),
+    ('I', '__reserved3'),
+]
+CacheDumpFormatStr_v1 = ''.join(zip(*struct_CacheDumpType_v1)[0])
+CacheDumpKeys_v1 = zip(*struct_CacheDumpType_v1)[1]
+
+class CacheDumpType_v1(CacheDump):
+    """Uses the format struct_CacheDumpType_v1, followed by an array of raw data"""
+
+    def __init__(self):
+        super(CacheDumpType_v1, self).__init__()
+        self.tableformat = TableOutputFormat()
+        self.tableformat.addColumn('Way', '{0:01x}')
+        self.tableformat.addColumn('Set', '{0:03x}')
+        self.ramdump = None
+        self.linefmt = None
+        self.HACK_HEADER_OFFSET = -1
+
+        for key in CacheDumpKeys_v1:
+            setattr(self, key, None)
+
+    def add_table_data_columns(self):
+        for i in range(0, self.LineSize):
+            str ="DATA{0}".format(i)
+            self.tableformat.addColumn(str, '{0:08x}', 8)
+
+    def read_line(self, start):
+        if self.linefmt is None:
+            self.linefmt = '<'
+            self.linefmt += 'I'*(self.TagSize + self.LineSize)
+        return self.ramdump.read_string(start, self.linefmt, virtual=False)
+
+    def parse_tag_fn(output, data, nset, nway):
+        """append data elements to output. Overriden by child classes"""
+        raise NotImplementedError
+
+    def parse_header(self, start, end):
+        """add the information from the header to this object. Returns
+        number of bytes read"""
+
+        if self.HACK_HEADER_OFFSET >= 0:
+            return self.HACK_HEADER_OFFSET
+
+        items = self.ramdump.read_string(start, CacheDumpFormatStr_v1, virtual=False)
+        if items is None:
+            raise Exception('Unable to read header information')
+
+        for i in range(len(items)):
+            setattr(self, CacheDumpKeys_v1[i], items[i])
+
+        struct_size = struct.calcsize(CacheDumpFormatStr_v1)
+        size = 0x4 * (self.LineSize + self.TagSize) * self.NumWays * self.NumSets
+        size = size + struct_size
+
+        if (size < 0x1000 or size > end - start):
+            raise Exception('Unable to read header information')
+
+        return struct_size
+
+    def parse(self, start, end, ramdump, outfile):
+        self.ramdump = ramdump
+
+        start = start + self.parse_header(start, end)
+        self.add_table_data_columns()
+
+        for nset in range(self.NumSets):
+            for nway in range(self.NumWays):
+                if start > end:
+                    raise Exception('past the end of array')
+
+                output = [nway, nset]
+                line = self.read_line(start)
+                self.parse_tag_fn(output, line[0:self.TagSize], nset, nway)
+                output.extend(line[self.TagSize:])
+                self.tableformat.printline(output, outfile)
+                start = start + (self.TagSize + self.LineSize) * 0x4
+
+class L1_DCache_A53(CacheDumpType_v1):
+    """Refer to ARM documentation:cortex_a53_trm"""
+    def __init__(self):
+        super(L1_DCache_A53, self).__init__()
+        self.tableformat.addColumn('P')
+        self.tableformat.addColumn('MOESI')
+        self.tableformat.addColumn('RAW_MOESI', '{0:04x}')
+        self.tableformat.addColumn('N')
+        self.tableformat.addColumn('Addr [39:12]', '{0:016x}', 16)
+        self.tableformat.addColumn('P')
+        self.tableformat.addColumn('DC', '{0:02b}')
+        self.tableformat.addColumn('0A', '{0:02b}')
+        self.tableformat.addColumn('0S', '{0:02b}')
+        self.HACK_HEADER_OFFSET = 0
+        self.TagSize = 2
+        self.LineSize = 16
+        self.NumSets = 0x80
+        self.NumWays = 4
+
+    def MOESI_to_string(self, num):
+        if (num & 0xC == 0x0):
+            return 'I'
+        if ((num & 0x4 == 0x4) and (num & 0x1 == 0x0)):
+            return 'S'
+        if ((num & 0x4 == 0x4) and (num & 0x1 == 0x1)):
+            return 'O'
+        if ((num & 0x8 == 0x8) and (num & 0x1 == 0x0)):
+            return 'E'
+        if ((num & 0x8 == 0x8) and (num & 0x1 == 0x1)):
+            return 'M'
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        p1 = (data[1] >> 31) & 0x1
+        m1 = (data[1] >> 29) & 0x3
+        n = (data[1] >> 28) & 0x1
+        addr1 = (data[1] >> 0) & 0xfffffff
+        addr2 = (data[0] >> 31) & 0x1
+        p2 = (data[0] >> 5) & 0x1
+        dc = (data[0] >> 4) & 0x1
+        oa = (data[0] >> 3) & 0x1
+        os = (data[0] >> 2) & 0x1
+        m2 = (data[0] >> 0) & 0x3
+
+        moesi = m1 << 2 | m2
+        addr = ((addr1 << 1 | addr2) << 11) | (nset << 6)
+        output.append(p1)
+        output.append(self.MOESI_to_string(moesi))
+        output.append(moesi)
+        output.append(n)
+        output.append(addr)
+        output.append(p2)
+        output.append(dc)
+        output.append(oa)
+        output.append(os)
+
+class L1_DCache_A57(CacheDumpType_v1):
+    """Refer to ARM documentation:cortex_a57_trm"""
+    def __init__(self):
+        super(L1_DCache_A57, self).__init__()
+        self.tableformat.addColumn('MESI')
+        self.tableformat.addColumn('RAW_MESI', '{0:02}')
+        self.tableformat.addColumn('N')
+        self.tableformat.addColumn('PA [43:14]', '{0:016x}', 16)
+        self.HACK_HEADER_OFFSET = 0xC
+        self.TagSize = 2
+        self.LineSize = 16
+        self.NumSets = 0x100
+        self.NumWays = 2
+
+    def MESI_to_string(self, num):
+        if (num == 0x0):
+            return 'I'
+        elif (num == 0x1):
+            return 'E'
+        elif (num == 0x2):
+            return 'S'
+        elif (num == 0x3):
+            return 'M'
+        else:
+            raise Exception('invalid MOESI value:{:x}'.format(num))
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        if self.TagSize != 2:
+            raise Exception('cache tag size mismatch')
+
+        mesi = (data[1] >> 0) & 0x3
+        n = (data[0] >> 30) & 0x1
+        addr = (data[0] >> 0) & 0x3fffffff
+
+        addr = (addr << 14) | (nset << 6)
+        output.append(self.MESI_to_string(mesi))
+        output.append(mesi)
+        output.append(n)
+        output.append(addr)
+
+class L1_ICache_A57(CacheDumpType_v1):
+    """Refer to ARM documentation:cortex_a57_trm"""
+    def __init__(self):
+        super(L1_ICache_A57, self).__init__()
+        self.tableformat.addColumn('VALID')
+        self.tableformat.addColumn('N')
+        self.tableformat.addColumn('PA [43:12]', '{0:016x}', 16)
+        self.HACK_HEADER_OFFSET = 0
+        self.TagSize = 2
+        self.LineSize = 16
+        self.NumSets = 0x100
+        self.NumWays = 2
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        if self.TagSize != 2:
+            raise Exception('cache tag size mismatch')
+
+        valid = (data[1] >> 1) & 0x1
+        n = (data[1] >> 0) & 0x1
+        addr = (data[0] >> 0) & 0xffffffff
+
+        addr = (addr << 12) | (nset << 6)
+        output.append(valid)
+        output.append(n)
+        output.append(addr)
+
+class L2_Cache_A57(CacheDumpType_v1):
+    """Refer to ARM documentation:cortex_a57_trm"""
+    def __init__(self):
+        super(L2_Cache_A57, self).__init__()
+        self.tableformat.addColumn('MESI')
+        self.tableformat.addColumn('Raw MESI', '{0:02}')
+        self.tableformat.addColumn('N')
+        self.tableformat.addColumn('PA [43:15]', '{0:016x}', 16)
+        self.HACK_HEADER_OFFSET = 0
+        self.TagSize = 4
+        self.LineSize = 16
+        self.NumSets = 0x800
+        self.NumWays = 0x10
+
+    def MOESI_to_string(self, num):
+        if (num == 0x0):
+            return 'I'
+        elif (num == 0x1):
+            return 'E or M'
+        elif (num == 0x2):
+            raise Exception('invalid MOESI value:{:x}'.format(num))
+        elif (num == 0x3):
+            return 'S or O'
+        else:
+            raise Exception('invalid MOESI value:{:x}'.format(num))
+
+    def parse_tag_fn(self, output, data, nset, nway):
+        if self.TagSize != 4:
+            raise Exception('cache tag size mismatch')
+
+        n = (data[0] >> 31) & 0x1
+        addr = (data[0] >> 2) & 0x1fffffff
+        moesi = (data[0] >> 0) & 0x3
+
+        addr = (addr << 15) | (nset << 6)
+        output.append(self.MOESI_to_string(moesi))
+        output.append(moesi)
+        output.append(n)
+        output.append(addr)
+
+#8994
+
+lookuptable[(8994, 0x80, 0)] = L1_DCache_A53()
+lookuptable[(8994, 0x81, 0)] = L1_DCache_A53()
+lookuptable[(8994, 0x82, 0)] = L1_DCache_A53()
+lookuptable[(8994, 0x83, 0)] = L1_DCache_A53()
+lookuptable[(8994, 0x84, 0)] = L1_DCache_A57()
+lookuptable[(8994, 0x85, 0)] = L1_DCache_A57()
+lookuptable[(8994, 0x86, 0)] = L1_DCache_A57()
+lookuptable[(8994, 0x87, 0)] = L1_DCache_A57()
+
+lookuptable[(8994, 0x64, 0)] = L1_ICache_A57()
+lookuptable[(8994, 0x65, 0)] = L1_ICache_A57()
+lookuptable[(8994, 0x66, 0)] = L1_ICache_A57()
+lookuptable[(8994, 0x67, 0)] = L1_ICache_A57()
+
+lookuptable[(8994, 0xC1, 0)] = L2_Cache_A57()
diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py
index ff2a425b5d8906617b62b0d89b331807f4f5ece9..07a181012322d30da6f61d5794f8dc284fed8ff6 100755
--- a/linux-ramdump-parser-v2/debug_image_v2.py
+++ b/linux-ramdump-parser-v2/debug_image_v2.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+# Copyright (c) 2012-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
@@ -18,9 +18,11 @@ import platform
 import subprocess
 
 from pmic import PmicRegDump
-from print_out import print_out_str
+from print_out import print_out_str, print_out_exception
 from qdss import QDSSDump
 from watchdog_v2 import TZRegDump_v2
+from cachedumplib import lookup_cache_type
+
 
 MEMDUMPV2_MAGIC = 0x42445953
 MAX_NUM_ENTRIES = 0x130
@@ -47,9 +49,9 @@ client_table = {
     'MSM_DUMP_DATA_CPU_CTX': 'parse_cpu_ctx',
     'MSM_DUMP_DATA_L1_INST_TLB': 'parse_l1_inst_tlb',
     'MSM_DUMP_DATA_L1_DATA_TLB': 'parse_l1_data_tlb',
-    'MSM_DUMP_DATA_L1_INST_CACHE': 'parse_l1_inst_cache',
-    'MSM_DUMP_DATA_L1_DATA_CACHE': 'parse_l1_data_cache',
-    'MSM_DUMP_DATA_L2_CACHE': 'parse_l2_cache',
+    'MSM_DUMP_DATA_L1_INST_CACHE': 'parse_cache_common',
+    'MSM_DUMP_DATA_L1_DATA_CACHE': 'parse_cache_common',
+    'MSM_DUMP_DATA_L2_CACHE': 'parse_cache_common',
     'MSM_DUMP_DATA_L3_CACHE': 'parse_l3_cache',
     'MSM_DUMP_DATA_OCMEM': 'parse_ocmem',
     'MSM_DUMP_DATA_PMIC': 'parse_pmic',
@@ -108,6 +110,19 @@ class DebugImage_v2():
         else:
             setattr(self.qdss, qdss_tag_to_field_name[client_name], start)
 
+    def parse_cache_common(self, version, start, end, client_id, ramdump):
+        client_name = self.dump_data_id_lookup_table[client_id]
+        core = client_id & 0xF
+        filename = '{0}_0x{1:x}'.format(client_name, core)
+        outfile = ramdump.open_file(filename)
+        cache_type = lookup_cache_type(ramdump.hw_id, client_id, version)
+        try:
+            cache_type.parse(start, end, ramdump, outfile)
+        except:
+            print_out_str('!!! Exception while running {0}'.format(client_name))
+            print_out_exception()
+        outfile.close()
+
     def ftrace_field_func(self, common_list, ram_dump):
         name_offset = ram_dump.field_offset('struct ftrace_event_field', 'name')
         type_offset = ram_dump.field_offset('struct ftrace_event_field', 'type')
@@ -254,6 +269,8 @@ class DebugImage_v2():
                     client.MSM_DUMP_DATA_L1_INST_CACHE + i] = 'MSM_DUMP_DATA_L1_INST_CACHE'
                 self.dump_data_id_lookup_table[
                     client.MSM_DUMP_DATA_L1_DATA_CACHE + i] = 'MSM_DUMP_DATA_L1_DATA_CACHE'
+                self.dump_data_id_lookup_table[
+                    client.MSM_DUMP_DATA_L2_CACHE + i] = 'MSM_DUMP_DATA_L2_CACHE'
                 self.dump_data_id_lookup_table[
                     client.MSM_DUMP_DATA_ETM_REG + i] = 'MSM_DUMP_DATA_ETM_REG'
         # 0x100 - tmc-etr registers and 0x101 - for tmc-etf registers