diff --git a/linux-ramdump-parser-v2/parsers/mmcdoctor.py b/linux-ramdump-parser-v2/parsers/mmcdoctor.py
new file mode 100644
index 0000000000000000000000000000000000000000..977655bc29e8df0c04ee42b4d823e5f57dcf5cbc
--- /dev/null
+++ b/linux-ramdump-parser-v2/parsers/mmcdoctor.py
@@ -0,0 +1,317 @@
+# Copyright (c) 2017, 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 os
+from parser_util import register_parser, RamParser
+from parsers.irqstate import IrqParse
+from dmesglib import DmesgLib
+
+
+MMC0_IRQ = 0
+MMC1_IRQ = 0
+SDHCI_IRQ_NAME = "sdhci"
+SDHCI_IRQ_CD_NAME = "sdhci cd"
+
+F_MMCDEBUG = "mmcreport.txt"
+F_MMCTEMP = "mmctemp.txt"
+
+PATTERN_ST = "========== REGISTER DUMP (mmc0)=========="
+PATTERN_END = "sdhci: ===================="
+
+MMC_DATA_HEAD = "#################### MMC(mmc%d) INFO START #######################\n"
+MMC_DATA_FOOT = "#################### MMC(mmc%d) INFO END #########################\n\n"
+
+card_data = {
+    0x2: "SANDISK",
+    0x11: "TOSHIBA",
+    0x13: "MICRON",
+    0x15: "SAMSUNG",
+    0x70: "KINGSTON",
+    0x90: "HYNIX",
+}
+
+card_err_data = {
+    "Card Timeout"      : ["err: -110", "error: -110"],
+    "Soft Timeout"      : ["Timeout waiting for hardware interrupt", "request with tag"],
+    "CRC ERROR"         : ["err: -84", "error: -84"],
+    "Resp_error"        : ["status: 0x00000006", "status: 0x00000004"],
+    "Spurious_cmd_intr" : ["Got command interrupt", "even though no command"],
+    "Spurious_data_intr": ["Got data interrupt", "even though no data"],
+    "Spurious_intr"     : ["Unexpected interrupt", "Unexpected interrupt"],
+}
+
+
+#
+# This class defines parsing function
+# to parse for mmclog
+#
+class ParseMmcLog():
+
+    def __init__(self, ramdump):
+        self.ramdump = ramdump
+        self.error = 0
+        self.error_line = ""
+
+    def dumptemplog(self):
+        fd_temp = self.ramdump.open_file(F_MMCTEMP, "w+")
+        d = DmesgLib(self.ramdump, fd_temp)
+        d.extract_dmesg()
+        fd_temp.close()
+
+    def check_for_error(self, line):
+        if (self.error):
+            return
+        for key, item in card_err_data.iteritems():
+            if (item[0] in line or item[1] in line):
+                self.error = key
+                self.error_line = line
+                break
+
+    def dumpmemreport(self):
+        self.dumptemplog()
+        self.error = 0
+        self.error_line = ""
+        fdr = self.ramdump.open_file(F_MMCTEMP, "r")
+        fdw = self.ramdump.open_file(F_MMCDEBUG, "a")
+        line = fdr.readline()
+        while (line):
+            if ("mmc" in line):
+                fdw.write(line)
+                self.check_for_error(line)
+            if (PATTERN_ST in line):
+                line = fdr.readline()
+                while (line and (PATTERN_END not in line)):
+                    fdw.write("ERROR" + line)
+                    line = fdr.readline()
+                if (line and PATTERN_END in line):
+                    fdw.write("ERROR" + line)
+            line = fdr.readline()
+        self.ramdump.remove_file(F_MMCTEMP)
+
+
+#
+# Function definition to find all relevant structure
+#
+
+def get_sdhci_irqs(ram_dump):
+    irqs = IrqParse(RamParser)
+    count = 0
+    global MMC0_IRQ
+    global MMC1_IRQ
+    irq_action_offset = ram_dump.field_offset('struct irq_desc', 'action')
+    action_name_offset = ram_dump.field_offset('struct irqaction', 'name')
+    irq_desc_tree = ram_dump.address_of('irq_desc_tree')
+    nr_irqs = ram_dump.read_int(ram_dump.address_of('nr_irqs'))
+
+    if nr_irqs > 50000:
+        return
+    for i in range(0, nr_irqs):
+        irq_desc = irqs.radix_tree_lookup_element(
+            ram_dump, irq_desc_tree, i)
+        if irq_desc is None:
+            continue
+        action = ram_dump.read_word(irq_desc + irq_action_offset)
+        if action != 0 and count < 2:
+            name_addr = ram_dump.read_word(action + action_name_offset)
+            name = ram_dump.read_cstring(name_addr, 48)
+            if (not name):
+                continue
+            if (SDHCI_IRQ_NAME in name and not SDHCI_IRQ_CD_NAME in name):
+                if (count == 0):
+                    MMC0_IRQ = i
+                elif (count == 1):
+                    MMC1_IRQ = i
+                count += 1
+    return count
+
+def find_sdhci_host(ramdump, irq):
+    irq_desc_tree = ramdump.address_of('irq_desc_tree')
+    irq_action_offset = ramdump.field_offset('struct irq_desc', 'action')
+    dev_id = ramdump.field_offset('struct irqaction', 'dev_id')
+    irqs = IrqParse(RamParser)
+    sdhci_irq_desc = irqs.radix_tree_lookup_element(ramdump, irq_desc_tree, irq)
+    sdhci_irq_action = ramdump.read_word(sdhci_irq_desc + irq_action_offset)
+    sdhci_host = ramdump.read_word(sdhci_irq_action + dev_id)
+    return sdhci_host
+
+
+def find_mmc_host(ramdump, sdhci_host):
+    mmc_offset = ramdump.field_offset('struct sdhci_host', 'mmc')
+    mmc_host = ramdump.read_word(sdhci_host + mmc_offset)
+    return mmc_host
+
+
+def find_mmc_card(ramdump, mmc_host):
+    card_offset = ramdump.field_offset('struct mmc_host', 'card')
+    mmc_card = ramdump.read_word(mmc_host + card_offset)
+    return mmc_card
+
+
+def find_sdhci_msm_host(ramdump, sdhci_host):
+    sdhci_pltfm_host = (sdhci_host + ramdump.sizeof('struct sdhci_host'))
+    msm_offset = ramdump.field_offset('struct sdhci_pltfm_host', 'priv')
+    sdhci_msm_host = ramdump.read_word(sdhci_pltfm_host + msm_offset)
+    return sdhci_msm_host
+
+
+class MmcCardInfo():
+
+    def __init__(self, ramdump, mmc_card):
+        self.ramdump = ramdump
+        self.card = mmc_card
+        self.type = self.find_mmc_cid()
+        self.ext_csd_fwrev = self.find_ext_csd()
+        self.cmdq_init = self.find_cmdq_init()
+
+    def find_ext_csd(self):
+        if (not self.card):
+            return 0
+        ext_csd_off = self.card + \
+            self.ramdump.field_offset('struct mmc_card', 'ext_csd')
+        self.mmc_ext_csd = ext_csd_off
+        fw_version_offset = self.ramdump.field_offset('struct mmc_ext_csd', 'fw_version')
+        if (fw_version_offset is None):
+            return -2
+        ext_csd_fwrev = ext_csd_off + fw_version_offset
+        return self.ramdump.read_byte(ext_csd_fwrev)
+
+    def find_mmc_cid(self):
+        if (not self.card):
+            return 0
+        cid = self.card + self.ramdump.field_offset('struct mmc_card', 'cid')
+        self.mmc_cid = cid
+        manfid = self.ramdump.read_u32(cid)
+        if manfid in card_data.keys():
+            return card_data[manfid]
+        else:
+            return manfid
+
+    def find_cmdq_init(self):
+        if (not self.card):
+            return 0
+        cmdq_init = self.card + self.ramdump.field_offset('struct mmc_card', 'cmdq_init')
+        return self.ramdump.read_bool(cmdq_init)
+
+
+class MmcHostInfo():
+
+    def __init__(self, ramdump, mmc_host):
+        self.ramdump = ramdump
+        self.host = mmc_host
+        self.clk_gated = self.ramdump.read_bool(self.host +
+                    self.ramdump.field_offset('struct mmc_host', 'clk_gated'))
+        self.clk_requests = self.ramdump.read_int(self.host +
+                    self.ramdump.field_offset('struct mmc_host', 'clk_requests'))
+        self.clk_old = self.ramdump.read_int(self.host +
+                    self.ramdump.field_offset('struct mmc_host', 'clk_old'))
+        self.ios = self.find_ios()
+        self.ios_clock = self.ramdump.read_int(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'clock'))
+        self.ios_old_rate = self.ramdump.read_int(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'old_rate'))
+        self.ios_vdd = self.ramdump.read_u16(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'vdd'))
+        self.ios_bus_width = self.ramdump.read_byte(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'bus_width'))
+        self.ios_timing = self.ramdump.read_byte(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'timing'))
+        self.ios_signal_voltage = self.ramdump.read_byte(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'signal_voltage'))
+        self.ios_drv_type= self.ramdump.read_byte(self.ios +
+                    self.ramdump.field_offset('struct mmc_ios', 'drv_type'))
+
+    def find_ios(self):
+        return (self.host + self.ramdump.field_offset('struct mmc_host', 'ios'))
+
+
+#
+# Base class which save all mmc data structure info
+# This uses other classes for card and host related
+# info
+#
+class MmcDataStructure():
+    global MMC0_IRQ
+    global MMC1_IRQ
+
+    def __init__(self, ramdump, index):
+        self.mmclist_irq = {0 : MMC0_IRQ, 1 : MMC1_IRQ}
+        self.index = index
+        self.irq = self.mmclist_irq[index]
+        if (self.irq == 0):
+            return
+        self.ramdump = ramdump
+        self.sdhci_host = find_sdhci_host(self.ramdump, self.irq)
+        self.mmc_host = find_mmc_host(self.ramdump, self.sdhci_host)
+        self.mmc_card = find_mmc_card(self.ramdump, self.mmc_host)
+        self.sdhci_msm_host = find_sdhci_msm_host(self.ramdump, self.sdhci_host)
+        self.cardinfo = MmcCardInfo(self.ramdump, self.mmc_card)
+        self.hostinfo = MmcHostInfo(self.ramdump, self.mmc_host)
+        self.parse = ParseMmcLog(self.ramdump)
+        return
+
+    def dump_data(self, mode):
+        fd = self.ramdump.open_file(F_MMCDEBUG, mode)
+        fd.write(MMC_DATA_HEAD % self.index)
+        fd.write("mmc_card = 0x%x\n" % self.mmc_card)
+        fd.write("mmc_host = 0x%x\n" % self.mmc_host)
+        fd.write("sdhci_host = 0x%x\n" % self.sdhci_host)
+        fd.write("sdhci_msm_host = 0x%x\n\n" % self.sdhci_msm_host)
+        fd.write("\nGrep MMC_ERROR at End of File\n\n")
+        fd.write("CARD MANFID = %s\n" %self.cardinfo.type)
+        fd.write("CARD Fw_rev = 0x%x\n" %self.cardinfo.ext_csd_fwrev)
+        fd.write("CARD CMDQ INIT = %d\n\n" %self.cardinfo.cmdq_init)
+        fd.write("Host clk_requests = %d\n" %self.hostinfo.clk_requests)
+        fd.write("Host clk_gated = %d\n" %self.hostinfo.clk_gated)
+        fd.write("Host clk_old = %dHz\n" %self.hostinfo.clk_old)
+        fd.write("Host ios_clock = %dHz\n" %self.hostinfo.ios_clock)
+        fd.write("Host ios_old_rate = %uHz\n" %self.hostinfo.ios_old_rate)
+        fd.write("Host ios_vdd = %d\n" %self.hostinfo.ios_vdd)
+        fd.write("Host ios_bus_width = %d\n" %self.hostinfo.ios_bus_width)
+        fd.write("Host ios_timing = %d\n" %self.hostinfo.ios_timing)
+        fd.write("Host ios_signal_voltage = %d\n" %self.hostinfo.ios_signal_voltage)
+        fd.write("Host ios_drv_type = %d\n" %self.hostinfo.ios_drv_type)
+        fd.write(MMC_DATA_FOOT % self.index)
+        fd.close()
+        return
+
+
+def dump_mmc_info(ramdump, count):
+    mmc0 = MmcDataStructure(ramdump, 0)
+    mmc0.dump_data("w+")
+
+    if (count > 1):
+        mmc1 = MmcDataStructure(ramdump, 1)
+        mmc1.dump_data("a")
+
+    mmc0.parse.dumpmemreport()
+    fd = ramdump.open_file(F_MMCDEBUG, "a")
+    fd.write("\n\n\n#########MMC_ERROR#########\n")
+    if (mmc0.parse.error):
+        fd.write("ERROR TYPE = %s\n" %mmc0.parse.error)
+    else:
+       fd.write("ERROR TYPE = Unkwown Error\n")
+    fd.write("ERROR SIGN = %s\n\n" % mmc0.parse.error_line)
+    fd.close()
+
+
+@register_parser('--mmcdoctor', 'Generate MMC diagnose report')
+class MmcDebug(RamParser):
+    def parse(self):
+        count_irq = 0
+        if self.ramdump.is_config_defined('CONFIG_SPARSE_IRQ'):
+            count_irq = get_sdhci_irqs(self.ramdump)
+            if (count_irq == 0):
+                return
+            dump_mmc_info(self.ramdump, count_irq)
+        else:
+            print_out_string("\n Could not generate MMC diagnose report\n")
+            return