From 6cc9f38c99f426a78e7c1e4977191968e9030782 Mon Sep 17 00:00:00 2001
From: Satyajit Desai <sadesai@codeaurora.org>
Date: Fri, 17 Feb 2017 17:43:17 -0800
Subject: [PATCH] dcc_parser: Add suppport for version 2 of DCC driver

This change adds support for version 2 of the DCC driver. Added
a new option '--v2' to identify the driver version used to
collect the trace data.

Change-Id: Ia39109051c6f12a64495cb6f07cdd990bac62859
---
 dcc_parser/dcc_parser.py | 110 +++++++++++++++++++++++++++++++--------
 1 file changed, 89 insertions(+), 21 deletions(-)

diff --git a/dcc_parser/dcc_parser.py b/dcc_parser/dcc_parser.py
index b296cd5..2eedcc7 100644
--- a/dcc_parser/dcc_parser.py
+++ b/dcc_parser/dcc_parser.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2015, The Linux Foundation. All rights reserved.
+# Copyright (c) 2015, 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
@@ -44,6 +44,12 @@ def add_addr(base, offset, length):
         address.append(addr)
 
 
+def add_loop_addr(loop_nr, loop_count):
+    for i in range(0, loop_count):
+        for j in range(len(address) - loop_nr, len(address)):
+            address.append(address[j])
+
+
 def read_data(data_pt):
     nr = count
     while nr > 0:
@@ -59,9 +65,28 @@ def read_data(data_pt):
 
 
 def read_config(config_pt):
-    nr = 0
+    list_nr = []
+    list_nr.append(0)
     offset = 0
     base = 0
+
+    if options.version is None:
+        address_descriptor = 0x1 << 31
+        link_descriptor = 0
+        loop_descriptor = None
+        rd_mod_wr_descriptor = None
+        link_second_arg = 8
+        # We return zero and fail
+        on_zero_link_len = 0
+    else:
+        address_descriptor = 0
+        link_descriptor = 0x3 << 30
+        loop_descriptor = 0x1 << 30
+        rd_mod_wr_descriptor = 0x1 << 31
+        link_second_arg = 7
+        #indicates end of list
+        on_zero_link_len = -1
+
     while True:
         word = config_pt.read(4)
         if len(word) != 4:
@@ -72,27 +97,61 @@ def read_config(config_pt):
         if val == 0:
             break
 
-        if val & (1 << 31):
+        descriptor = val & (0x3 << 30)
+
+        if descriptor == address_descriptor:
             base = ((val & 0x0FFFFFFF) << 4)
             offset = 0
-        else:
+        elif descriptor == link_descriptor:
             for i in range(0, 2):
                 offset = offset + (val & 0xFF) * 4
                 val = val >> 8
 
                 length = (val & 0x7f)
-                val = val >> 8
+                val = val >> link_second_arg
 
                 if length != 0:
-                    nr += length
+                    list_nr.append(length + list_nr[- 1])
                     add_addr(base, offset, length)
                 else:
-                    if (i == 0):
-                        log.error("Error! Found zero length!")
-                        return 0
+                    if (i == 0 ):
+                        return list_nr[on_zero_link_len]
                     else:
                         offset = 0
-    return nr
+        elif descriptor == loop_descriptor:
+            loop_offset = val & 0x1FFF
+            loop_count = (val & 0xFFFE000) >> 13
+
+            if loop_offset == 0:
+                continue
+
+            loop_nr = list_nr[-1] - list_nr[-loop_offset]
+            list_nr.append(loop_nr * loop_count + list_nr[-1])
+            add_loop_addr(loop_nr, loop_count)
+
+        elif descriptor == rd_mod_wr_descriptor:
+            '''
+            Skip over mask and value of rd_mod_wr.
+            There is no gaurantee of this being actually written
+            and we never read the value back to confirm.
+            '''
+            config_pt.seek(8, 1)
+
+    return list_nr[-1]
+
+
+def new_linked_list(config_pt):
+    word = config_pt.read(4)
+
+    if len(word)!= 4:
+        return False
+    else:
+        val = struct.unpack('<L', word)[0]
+        if val != 0:
+            config_pt.seek(-4, 1)
+            return True
+        else:
+            return False
 
 
 def dump_regs_json(options):
@@ -128,11 +187,16 @@ def dump_regs_xml(options):
 
 
 def dump_regs(options):
+    if not address:
+        log.error('No configuration found in SRAM!!')
+        sys.exit(1)
+
     if options.json is True:
         dump_regs_json(options)
     else:
         dump_regs_xml(options)
 
+
 if __name__ == '__main__':
     usage = 'usage: %prog [options to print]. Run with --help for more details'
     parser = OptionParser(usage)
@@ -148,6 +212,8 @@ if __name__ == '__main__':
     parser.add_option('', '--chip-name', dest='chipname', help='chip name')
     parser.add_option('', '--chip-version', dest='chipversion',
                       help='chip version')
+    parser.add_option('--v2', dest='version', action="store_const", const='2',
+                      help='DCC driver version 2')
 
     (options, args) = parser.parse_args()
 
@@ -199,18 +265,20 @@ if __name__ == '__main__':
             sys.exit(1)
 
     count = 0
-    count = read_config(sram_file)
-    if options.atbfile is None:
-        atb_file = sram_file
-    if count == 0:
-        log.error('No configuration found in SRAM!!')
-        sys.exit(1)
+    while True:
+        count = read_config(sram_file)
 
-    if read_data(atb_file):
-        log.error('Couldn\'t read complete data.')
-    else:
-        parsed_data = log_init('PARSED_DATA', options.outdir, options.outfile)
-        dump_regs(options)
+        if options.atbfile is None:
+            atb_file = sram_file
+
+        if read_data(sram_file):
+            log.error('Couldn\'t read complete data.')
+            break
+
+        if new_linked_list(sram_file) is False:
+            parsed_data = log_init('PARSED_DATA', options.outdir, options.outfile)
+            dump_regs(options)
+            break
 
     sram_file.close()
 
-- 
GitLab