script: Initial version of the IOdelay autogen script
[glsdk/iodelay-config.git] / iodelay-autogen.py
1 #!/usr/bin/python
2 #Python script to automatically generate the IO pad and delay data
3 #Author:- Nikhil Devshatwar
5 # This script uses regdump of the pad registers to figure out the muxmodes
6 # Based on the pad and muxmode, it find out all possible virtual/manual modes
7 # by referring to the PCT XML model. Using the, selection file, script
8 # decides which modes to be selected. Finally it dumps the required array entries
10 # This script depends on following files:-
11 # * XML data files      - Shipped with the DRA7xx PCT tool
12 # * Pad register dump   - Generate using omapconf dump 0x4a003400 0x4a00380c
13 # * selection file      - List of selected virtual/manual modes to be used
15 pad_data_xml = "XMLFiles/CTRL_MODULE_CORE.xml"
16 iod_data_xml = "XMLFiles/IODELAYCONFIG.xml"
17 model_data_xml = "XMLFiles/model_DRA75x_DRA74x_SR1.1_v1.0.6.xml"
18 gdl_file = "guidelines.txt"
20 pad_file = "ctrl-core.dump"
21 sel_file = "selected-modes.txt"
22 config_file = "config-iodelay-autogen"
24 import xml.etree.ElementTree as ET
25 import ConfigParser as CP
26 import re
28 pad_xml = ET.parse(pad_data_xml).getroot()
29 iod_xml = ET.parse(iod_data_xml).getroot()
30 model_xml = ET.parse(model_data_xml).getroot()
31 config = CP.RawConfigParser()
32 config.read(config_file)
34 def read_pad_file(file):
35         regmap = {}
36         pattern = re.compile('.*(0x[0-9A-F]+).*(0x[0-9A-F]+).*')
37         f = open(file, 'r')
38         for line in f:
39                 list = re.match(pattern, line)
40                 if ( list == None):
41                         continue
42                 addr = int(list.groups(0)[0], 16)
43                 val = int(list.groups(0)[1], 16)
44                 #print "PADDUMP: Addr = %08x Value = %08x" % (addr, val)
45                 regmap[addr] = val
46         return regmap
48 def pad_get_name(offset):
49         padlist = pad_xml.findall("register[@offset='0x%X']" % offset)
50         if (len(padlist) == 0):
51                 return "Unknown"
52         else:
53                 return padlist[0].get("id")
55 def pad_get_pin(offset, muxmode):
56         padlist = pad_xml.findall("register[@offset='0x%X']" % offset)
57         if (len(padlist) == 0):
58                 return "Unknown"
59         else:
60                 mux_field = padlist[0].findall("./bitfield[@end='0']")
61                 if (len(mux_field) == 0):
62                         return "Unknown"
63                 modes = mux_field[0].findall("./bitenum[@value='%d']" % muxmode)
64                 if (len(modes) == 0):
65                         return "Unknown"
66                 return modes[0].get("id")
68 def pad_dump_gpio(addr, offset, pin_name):
69         gpio_data_addrs = (0, 0x4ae10138, 0x48055138, 0x48057138, 0x48059138, 0x4805b138, 0x4805d138, 0x48051138, 0x48053138)
70         gpio_name = pad_get_pin(offset, 14)
71         matchlist = re.match("GPIO(.)_(.)", gpio_name)
72         if (matchlist == None):
73                 return
74         inst = int(matchlist.groups(0)[0])
75         bit = int(matchlist.groups(0)[1])
76         gpio_addr = gpio_data_addrs[inst]
77         print "GPIO: echo %d > /sys/class/gpio/export 2>/dev/null; val=`omapconf read 0x%x 2>&1 | grep -v \"support\"`; status=$((0x$val >> %d & 0x1)); echo -e \"%s (%s)\t = $status\";" % ((inst - 1) * 32, gpio_addr, bit, pin_name, gpio_name)
79 def iodelay_get_reg(name):
80         delaylist = iod_xml.findall("register[@id='%s']" % name)
81         if (len(delaylist) == 0):
82                 return 0
83         else:
84                 offset = delaylist[0].get("offset")
85                 #print "IOD: Name = %s Offset = %s" % (del_reg, offset)
86                 return int(offset, 16)
88 def virtual_get_modes(mode):
89         list = []
90         signal = mode.findtext("signal")
91         for virt in mode.findall("virtualmode/mode"):
92                 virt_mode = virt.findtext("value")
93                 virt_name = virt.findtext("name")
94                 if (virt_name == "NA"):
95                         continue
96                 found = (virt_mode, virt_name)
97                 list.append(found)
98                 if (config.get("general", "dump_virtual") == "1"):
99                         print ("VIRTUAL: %s %s" % found) + " %s" % signal
100         return list
102 def manual_get_modes(mode):
103         list = []
104         signal = mode.findtext("signal")
105         for man in mode.findall("manualmode"):
106                 regname = man.findtext("cfgreg/name")
107                 for sel in man.findall("cfgreg/mode"):
108                         adel = sel.findtext("adelay")
109                         gdel = sel.findtext("gdelay")
110                         man_name = sel.findtext("name")
111                         if (man_name == "NA"):
112                                 continue
113                         found = (regname, adel, gdel, man_name)
114                         list.append(found)
115                         if (config.get("general", "dump_manual") == "1"):
116                                 print ("MANUAL: %s %s %s %s" % found) + " %s" % signal
117         return list
118                 
120 def model_find_delaymodes(pad_name, muxmode):
121         padlist = model_xml.findall("padDB/clockNode/type/pad")
122         for pad in padlist:
123                 if (pad_name == pad.findtext("confregisters/regbit/register")):
124                         muxmodes = pad.findall("muxmode")
125                         break
126         if not muxmodes:
127                 return None
128         for mode in muxmodes:
129                 if ("%d" % muxmode == mode.findtext("mode")):
130                         virt = virtual_get_modes(mode)
131                         man = manual_get_modes(mode)
132                         return (virt, man)
133         return None
135 def get_pin_info(val):
136         inp_en = (val >> 18) & 0x1
137         pulltype = (val >> 17) & 0x1
138         pull_dis = (val >> 16) & 0x1
139         pin = "PIN"
140         if (inp_en):
141                 pin += "_INPUT"
142         else:
143                 pin += "_OUTPUT"
144         if (pull_dis == 0):
145                 if (pulltype):
146                         pin += "_PULLUP"
147                 else:
148                         pin += "_PULLDOWN"
149         return pin
151 def read_guidelines(fname):
152         gdl = {}
153         pattern = re.compile('(.+\w)\t+(.+)')
154         f = open(fname)
155         for line in f.readlines():
156                 list = re.match(pattern, line)
157                 if ( list == None):
158                         continue
159                 mode = list.groups(0)[0]
160                 info = list.groups(0)[1]
161                 gdl[mode] = info
162                 #print "GDL: Parsed info<%s> <%s>" % ( mode, info)
163         return gdl
165 def read_selection(fname):
166         sel = {}
167         pattern = re.compile('(\w+)\W*,\W*(\w*)')
168         f = open(fname)
169         for line in f.readlines():
170                 list = re.match(pattern, line)
171                 if ( list == None):
172                         continue
173                 group = list.groups(0)[0]
174                 mode = list.groups(0)[1]
175                 sel[group] = mode
176                 #print "SEL: Parsed info<%s> <%s>" % (mode, group)
177         return sel
179 def find_selection(pad, pin, modes, gdl, sel):
180         group = re.match("([^_]+)_.*", pin).groups(0)[0]
181         if (group in sel.keys()):
182                 if (sel[group] == "SKIP"):
183                         return sel[group]
184                 for mode in modes:
185                         if (sel[group] == mode):
186                                 #print "DBG: Found %s mode in selection for %s" % (mode, group)
187                                 return mode
189         if (config.get("gui", "interactive") == "0"):
190                 return "SKIP"
192         #print "\nDBG: Selected modes"
193         #print sel
194         while True:
195                 print ""
196                 print "MENU: Select delay mode for %s -> %s" % (pad, pin)
197                 i = 0
198                 print "MENU: %d: %s \t\t\t%s" % (i, "SKIP", "Skips this group for now")
199                 for mode in modes:
200                         i += 1
201                         print "MENU: %d: %s \t\t%s" % (i, mode, gdl[mode])
202                 try:
203                         choice = int(raw_input("Select delay mode #> "))
204                         if (choice == 0):
205                                 mode = "SKIP"
206                                 break
207                         elif (choice >=0 and choice <= len(modes)):
208                                 mode = modes.keys()[choice - 1]
209                                 break
210                         print "ERROR: Invalid choice"
211                 except ValueError:
212                         print "ERROR: Invalid choice"
213         print "MENU: Selected mode is %s" % mode
214         print ""
215         return mode
217 #Main execution starts here
218 print "IOdelay autogen - Python script to generate the IOdelay data"
219 print "Generate the MUX mode data based on the register dumps"
220 print ""
222 gdl = read_guidelines(gdl_file)
223 sel = read_selection(sel_file)
224 regmap = read_pad_file(pad_file)
225 reglist = regmap.keys()
227 pad_count = 0
228 delay_count = 0
230 for i in range(0, 281):
231         addr = 0x4a003400 + i * 4
232         offset = 0x1400 + i * 4
233         dts_offset = offset - 0x1400
235         if (addr not in reglist):
236                 print "WARN: Register dump for pad 0x%X not found" % addr
237                 continue
238         val = regmap[addr]
239         muxmode = val & 0xf
240         pad_name = pad_get_name(offset)
241         pin_name = pad_get_pin(offset, muxmode)
242         if (pad_name == "Unknown" or pin_name == "Unknown"):
243                 print "ERROR: Cannot find out Pad/Pin name for PAD address 0x%X (%s[%s] = %s)" \
244                 % (addr, pad_name, muxmode, pin_name)
245                 continue
246         if (config.get("general", "dump_all") == "1"):
247                 print "DUMP: %30s: Address = 0x%X \tOffset = 0x%X Value = 0x%08X \"%s\"" \
248                 % (pad_name, addr, offset, val, pin_name)
250         if (config.get("general", "dump_gpio") == "1"):
251                 pad_dump_gpio(addr, offset, pin_name)
252 #Find out all the possible virtual, manual modes fot the specific pad -> pin combination
253         (virt, man) = model_find_delaymodes(pad_name, muxmode)
254         modes = {}
255         for option in virt:
256                 (virt_mode, virt_name) = option
257                 extramode = "VIRTUAL_MODE%s" % virt_mode
258                 modes[virt_name] = extramode
260         for option in man:
261                 (regname, a_del, g_del, man_name) = option
262                 extramode = "MANUAL_MODE"
263                 modes[man_name] = extramode
265 #Decide the mode to be used:-
266         if (len(modes) == 0):
267                 if (config.get("general", "auto_decide") == "0"):
268                         continue
269                 #Use Legacy mode
270                 extramode = ""
271         else:
272                 #Need to select one out of allowed modes
273                 mode = find_selection(pad_name, pin_name, modes, gdl, sel)
274                 if (mode == "unknown"):
275                         print "ERROR: Unresolved delay modes for %s -> %s" % (pad_name, pin_name)
276                         print modes
277                         break
279                 #Update the selection for that module
280                 group = re.match("([^_]+)_.*", pin_name).groups(0)[0]
281                 #print "DBG: Adding %s mode for group %s" % (mode, group)
282                 if (mode != "SKIP" or  group not in sel.keys()):
283                         sel[group] = mode
284                 if (mode == "SKIP"):
285                         continue
286                 extramode = modes[mode]
288 #Generate the u-boot header for PAD mux array
289         if (extramode == ""):
290                 delaymode = ""
291         else:
292                 delaymode = " | %s" % extramode
293         pin_info = get_pin_info(val) + delaymode
294         pad_short = re.sub("CTRL_CORE_PAD_", "", pad_name)
295         comment = (pad_short + "." + pin_name).lower()
296         print "PAD:\t{ %s, (M%d | %s) },\t/* %s */" % (pad_short, muxmode, pin_info, comment)
297         pad_count += 1
299 #Generate the u-boot header for IO delay array
300         if (extramode != "MANUAL_MODE"):
301                 continue
302         for option in man:
303                 (regname, a_del, g_del, man_name) = option
304                 if (man_name != mode):
305                         continue
306                 del_offset = iodelay_get_reg(regname)
307                 if (del_offset == 0):
308                         print "ERROR: Can't find delay offset of register %s" % regname
309                         break
310                 a_del = int(a_del)
311                 g_del = int(g_del)
312                 print "DELAY:\t{0x%04X, %d, %d},\t/* %s */" \
313                         % (del_offset, a_del, g_del, regname)
315         delay_count += 1
316 print ""
317 print "Total PAD registers: %d, Total DELAY registers: %d" % (pad_count, delay_count)
318 #Dump the final selection for reuse
319 for group in sel:
320         print "%s,\t%s" % (group, sel[group])
321 print ""