Commit 01e77ff5 authored by Andrey Filippov's avatar Andrey Filippov

Working on UART support for dumping registers before DDR initialization

parent 9cfda386
......@@ -101,6 +101,8 @@ class EzynqClk:
return
html_file.write('<h2>Clock configuration parameters</h2>\n')
self.features.html_list_features(html_file)
def get_clocks(self):
return self.iface_divs
def calculate_dependent_pars(self):
speed_grade=self.features.get_par_value_or_default("SPEED_GRADE")
ddr_type=self.ddr_type
......@@ -408,6 +410,8 @@ class EzynqClk:
html_file.write('</table>')
def get_ddr_mhz(self):
return self.f_in*self.pll_fdivs[self.iface_divs['DDR']['PLL']]/self.iface_divs['DDR']['DIV']
def get_uart_mhz(self):
return self.iface_divs['UART']['FREQ']
def get_new_register_sets(self):
return self.clk_register_set.get_register_sets(True,True)
......@@ -417,37 +421,22 @@ class EzynqClk:
clk_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
if unlock_needed:
self.slcr_unlock()
_ = clk_register_set.get_register_sets(True,True) # close previous register settings
clk_register_set.flush() # close previous register settings
# Bypass used PLL-s - stage 1 of PLL setup
self.clocks_pll_bypass(force=False,warn=False)
_ = clk_register_set.get_register_sets(True,True) # close previous register settings
clk_register_set.flush() # close previous register settings
# Turn on PLL reset and program feedback - stage 2 of PLL setup
self.clocks_pll_reset_and_fdiv(force=False,warn=False)
_ = clk_register_set.get_register_sets(True,True) # close previous register settings
clk_register_set.flush() # close previous register settings
# Configure PLL parameters - stage 3 of PLL setup
self.clocks_pll_conf(force=False,warn=False)
_ = clk_register_set.get_register_sets(True,True) # close previous register settings
clk_register_set.flush() # close previous register settings
# Release reset of the PLLs (let them start) - stage 4 of PLL setup
self.clocks_pll_start(force=False,warn=False)
_ = clk_register_set.get_register_sets(True,True) # close previous register settings
clk_register_set.flush() # close previous register settings
# stage 5 of clocks setup
self.clocks_program(force=False,warn=False)
# #Trying toggle feature (but actually for now it can be left in reset state - is this on/off/on needed?
# _ = ddriob_register_set.get_register_sets(True,True) # close previous register settings
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',1),force,warn)
# _ = ddriob_register_set.get_register_sets(True,True) # close previous register settings
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',0),force,warn)
# _ = ddriob_register_set.get_register_sets(True,True) # close previous register settings
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', (('reset', 1),
# ('enable',1),
# ('nref_opt1',0),
# ('nref_opt2',0),
# ('nref_opt4',1),
# ('pref_opt2',0),
# ('update_control',0)),force,warn)
return self.get_new_register_sets()
#Unlock SLCR (if the code is running after RBL) - stage 0 of PLL setup
def slcr_unlock(self):
......@@ -528,6 +517,17 @@ class EzynqClk:
def clocks_pll_bypass_off(self,current_reg_sets,force=False,warn=False):
clk_register_set=self.clk_register_set
clk_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
# add wait for DCI calibration DONE
# ddriob_register_set.wait_reg_field_values('ddriob_dci_status',('done',1), True, warn)
bits=[]
if 'ARM' in self.pll_fdivs:
bits.append(('arm_pll_lock',1))
if 'DDR' in self.pll_fdivs:
bits.append(('ddr_pll_lock',1))
if 'IO' in self.pll_fdivs:
bits.append(('io_pll_lock',1))
clk_register_set.wait_reg_field_values('pll_status',tuple(bits), True, warn)
if 'DDR' in self.pll_fdivs:
clk_register_set.set_bitfields('ddr_pll_ctrl',(('pll_bypass_force', 0),
......@@ -538,6 +538,8 @@ class EzynqClk:
if 'ARM' in self.pll_fdivs:
clk_register_set.set_bitfields('arm_pll_ctrl',(('pll_bypass_force', 0),
('pll_bypass_qual', 0)),force,warn)
return self.get_new_register_sets()
#clocks setup
def clocks_program(self,force=False,warn=False):
......@@ -869,6 +871,7 @@ class EzynqClk:
# reg uart_clk_ctrl, offs=0x154 dflt:0x3f03 actual: 0xa02
if 'UART' in self.iface_divs:
print self.iface_divs['UART']
if self.iface_divs['UART']['PLL']=='ARM':
uart_srcsel= 2
elif self.iface_divs['UART']['PLL']=='DDR':
......
......@@ -253,6 +253,8 @@ class EzynqDDR:
ddrc_register_set=self.ddrc_register_set
ddrc_register_set.set_initial_state(current_reg_sets, True)
ddrc_register_set.set_bitfields('ddrc_ctrl',(('reg_ddrc_soft_rstb', 0x1)),force,warn)
# add wait for DDR ready
ddrc_register_set.wait_reg_field_values('mode_sts_reg',('ddrc_reg_operating_mode',0), False, warn)
return ddrc_register_set.get_register_sets(True,True)
def ddr_init_memory(self,current_reg_sets,force=False,warn=False):
......@@ -1328,9 +1330,9 @@ class EzynqDDR:
ddriob_register_set=self.ddriob_register_set
ddriob_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',1),force,warn)
_ = ddriob_register_set.get_register_sets(True,True) # close previous register settings
ddriob_register_set.flush() # close previous register settings
ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',0),force,warn)
_ = ddriob_register_set.get_register_sets(True,True) # close previous register settings
ddriob_register_set.flush()# close previous register settings
ddriob_register_set.set_bitfields('ddriob_dci_ctrl', (('reset', 1),
('enable',1),
('nref_opt1',0),
......@@ -1338,6 +1340,9 @@ class EzynqDDR:
('nref_opt4',1),
('pref_opt2',0),
('update_control',0)),force,warn)
# add wait for DCI calibration DONE
ddriob_register_set.wait_reg_field_values('ddriob_dci_status',('done',1), True, warn)
return ddriob_register_set.get_register_sets(True,True) # close previous register settings, return new result
......@@ -1443,24 +1448,6 @@ class EzynqDDR:
('slew_p', self.features.get_par_value('BIDIR_SLEW_POS')),
('drive_n',self.features.get_par_value('BIDIR_DRIVE_NEG')),
('drive_p',self.features.get_par_value('BIDIR_DRIVE_POS'))),force,warn) #0xf9861c
#
# #Trying toggle feature (but actually for now it can be left in reset state - is this on/off/on needed?
# _ = ddriob_register_set.get_register_sets(True,True) # close previous register settings
# # ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('vrn_out',0),force,warn) # default value shows 1, actual settings - 0 (first time only?)
# #
# # Do in u-boot. When moving - use UG585 table 10-7 to set options
# #
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',1),force,warn)
# _ = ddriob_register_set.get_register_sets(True,True) # close previous register settings
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',0),force,warn)
# _ = ddriob_register_set.get_register_sets(True,True) # close previous register settings
# ddriob_register_set.set_bitfields('ddriob_dci_ctrl', (('reset', 1),
# ('enable',1),
# ('nref_opt1',0),
# ('nref_opt2',0),
# ('nref_opt4',1),
# ('pref_opt2',0),
# ('update_control',0)),force,warn)
#TODO: Remove?
......
......@@ -194,7 +194,7 @@ DDRC_DEFS={ #not all fields are defined currently
'reg_phy_rdc_we_to_re_delay': {'r':( 8,11),'d':0x2,'c':'use for fixed delay, when reg_phy_use_fixed_re==1'}, #0x8
'reg_phy_wr_cmd_to_data': {'r':( 4, 7),'d':0,'c':'Not used in DFI PHY'},
'reg_phy_rd_cmd_to_data': {'r':( 0, 3),'d':0,'c':'Not used in DFI PHY'}}},
'mode_sts_reg': {'OFFS': 0x054,'DFLT':0x00000000,'RW':'R','FIELDS':{
'mode_sts_reg': {'OFFS': 0x054,'DFLT':0x00000000,'RW':'R','COMMENTS':'DDR Controller status','FIELDS':{
'ddrc_reg_dbg_hpr_q_depth': {'r':(16,20),'d':0,'m':'R','c':'number in high priority read CAM'},
'ddrc_reg_dbg_lpr_q_depth': {'r':(10,15),'d':0,'m':'R','c':'number in low priority read CAM'},
'ddrc_reg_dbg_wr_q_depth': {'r':( 4, 9),'d':0,'m':'R','c':'number in write CAM '},
......
......@@ -287,6 +287,9 @@ class EzynqFeatures:
else:
par_type={'H':'Integer','I':'Integer','F':'Float','B':'Boolean','T':'Text'}[feature['TYPE']]
# if name=='BAUD_RATE':
# print value
html_file.write('<tr><th>'+feature['CONF_NAME']+'</th><td>'+str(value)+'</td><td>'+par_type+
'</td><td>'+('-','Y')[feature['MANDATORY']]+'</td><td>'+origin+'</td><td>'+str(feature['DEFAULT'])+'</td><td>'+feature['DESCRIPTION']+'</td></tr>\n')
html_file.write('</table>\n')
......
......@@ -42,35 +42,47 @@ def print_html_reg_footer(html_file):
html_file.write('</table>\n')
def print_html_registers(html_file, reg_sets, from_index, show_bit_fields=True, show_comments=True,filter_fields=True,all_used_fields=False):
def opt_hex(d):
if d <10:
return str(d)
else:
return hex(d)
if not html_file:
return
# new_sets.append((addr,data,mask,self.module_name,register_name,self.registers[register_name]))
current_reg_state={} #address: (data,mask)
for index, (addr, data, mask, module_name, register_name, r_def) in enumerate (reg_sets):
for index, (op,addr, data, mask, module_name, register_name, r_def) in enumerate (reg_sets):
# if (op != 's'):
# continue # TODO: add handling of test conditions later
# if addr==0xf8000100:
# print 'index=',index,' addr=',hex(addr),' data=',hex(data),' mask=',hex(mask)
if mask!=0:
try:
dflt_data=r_def['DFLT']
except:
dflt_data=0
try:
rw=r_def['RW']
except:
rw='RW'
try:
old_data,old_mask=current_reg_state[addr]
if not all_used_fields:
old_mask=0
prev_sdata=hex(old_data)
except:
old_data=dflt_data
old_mask=0
prev_sdata='-'
new_data=((old_data ^ data) & mask) ^ old_data
new_mask= old_mask | mask
current_reg_state[addr]=(new_data,new_mask)
if (op == 's'):
try:
dflt_data=r_def['DFLT']
except:
dflt_data=0
try:
rw=r_def['RW']
except:
rw='RW'
try:
old_data,old_mask=current_reg_state[addr]
if not all_used_fields:
old_mask=0
prev_sdata=opt_hex(old_data)
except:
old_data=dflt_data
old_mask=0
prev_sdata='-'
new_data=((old_data ^ data) & mask) ^ old_data
new_mask= old_mask | mask
current_reg_state[addr]=(new_data,new_mask)
else:
new_data= data
new_mask= mask
if index<from_index: # just accumulate previous history of the register mask/values, no output
continue
......@@ -82,16 +94,22 @@ def print_html_registers(html_file, reg_sets, from_index, show_bit_fields=True,
comments=''
if show_bit_fields:
html_file.write(' <th>'+hex(addr)+'</th><th>'+module_name+'.'+register_name+'</th><th>'+rw+'</th><th>'+
hex(new_data)+'</th><th>'+prev_sdata+'</th><th>'+hex(dflt_data)+'</th>')
if op == 's':
html_file.write(' <th>0x%8x</th><th>%s.%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th>'%
(addr, module_name,register_name,rw, opt_hex(new_data), prev_sdata, opt_hex(dflt_data)))
elif op == '=':
html_file.write(' <th>0x%8x</th><th>%s.%s</th><th colspan="4">Wait for (reg & %s) == %s</th>'%
(addr, module_name,register_name, opt_hex(mask), opt_hex(data)))
elif op == '!':
html_file.write(' <th>0x%8x</th><th>%s.%s</th><th colspan="4">Wait for (reg & %s) != %s</th>'%
(addr, module_name,register_name, opt_hex(mask), opt_hex(data)))
else:
raise Exception ('Invalid register operation: %s for register 0x%08x'%(op,addr))
if show_comments:
html_file.write('<th>'+comments+'</th>')
html_file.write('<th>%s</th>'%comments)
html_file.write('\n</tr>\n')
if 'FIELDS' in r_def:
#sort bit fields
# name_addr= [(n,r_def['FIELDS'][n]['r'][0]) for n in r_def['FIELDS']]
# names=[pair[0] for pair in sorted(name_addr, key = lambda rr: -rr[1])]
# names=[pair[0] for pair in sorted([(n,r_def['FIELDS'][n]['r'][0]) for n in r_def['FIELDS']], key = lambda rr: -rr[1])]
for f_name in [pair[0] for pair in sorted([(nam,r_def['FIELDS'][nam]['r'][0]) for nam in r_def['FIELDS']], key = lambda rr: -rr[1])]:
field=r_def['FIELDS'][f_name]
try:
......@@ -104,58 +122,58 @@ def print_html_registers(html_file, reg_sets, from_index, show_bit_fields=True,
f_mask|=(1<<i)
if (not filter_fields) or (f_mask & mask):
f_data=(new_data & f_mask) >> r[0]
f_dflt=(dflt_data & f_mask) >> r[0]
f_prev=(old_data & f_mask) >> r[0]
field_prev=('-', hex(f_prev))[prev_sdata!='-']
modified=f_data != f_prev
html_file.write(' <tr><td>'+str(r[0])+":"+str(r[1])+'</td><td>'+f_name+'</td><td>'+f_rw+'</td>')
html_file.write('<td>'+('','<b>')[modified]+hex(f_data)+('','</b>')[modified]+'</td><td>'+field_prev+'</td><td>'+hex(f_dflt)+'</td>')
if op == 's':
f_dflt=(dflt_data & f_mask) >> r[0]
f_prev=(old_data & f_mask) >> r[0]
field_prev=('-', opt_hex(f_prev))[prev_sdata!='-']
modified=f_data != f_prev
html_file.write(' <tr><td>%i:%i</td><td>%s</td><td>%s</td><td>%s%s%s</td><td>%s</td><td>%s</td>'%
(r[0],r[1], f_name, f_rw,('','<b>')[modified],opt_hex(f_data),('','</b>')[modified],field_prev,opt_hex(f_dflt)))
elif op == '=':
html_file.write(' <tr><td>%i:%i</td><td>%s</td><td colspan="4">Wait for bit(s) == %s</th>'%
(r[0],r[1], f_name, opt_hex(f_data)))
elif op == '!':
html_file.write(' <tr><td>%i:%i</td><td>%s</td><td colspan="4">Wait for bit(s) != %s</th>'%
(r[0],r[1], f_name, opt_hex(f_data)))
else:
raise Exception ('Invalid register operation: %s for register 0x%08x'%(op,addr))
if show_comments:
try:
f_comments=field['c']
except:
f_comments=''
html_file.write('<td>'+f_comments+'</td>')
html_file.write('<td>%s</td>'%f_comments)
html_file.write('\n</tr>\n')
else:
html_file.write(' <th>'+hex(addr)+'</th><td>'+module_name+'.'+register_name+'</td><td>'+rw+'</td><td><b>'+
hex(new_data)+'</th><th>'+prev_sdata+'</b></td><td>'+hex(dflt_data)+'</td>')
if op == 's':
html_file.write(' <th>0x%8x</th><td>%s.%s</td><td>%s</td><td><b>%s</b></td><td>%s</td><td>%s</td>'%
(addr, module_name,register_name,rw,opt_hex(new_data), prev_sdata, opt_hex(dflt_data)))
elif op == '=':
html_file.write(' <th>0x%8x</th><td>%s.%s</td><tdcolspan="4"><b>Wait for (reg & %s) == %s</b></td>'%
(addr, module_name,register_name,opt_hex(mask),opt_hex(data)))
elif op == '!':
html_file.write(' <th>0x%8x</th><td>%s.%s</td><tdcolspan="4"><b>Wait for (reg & %s) != %s</b></td>'%
(addr, module_name,register_name,opt_hex(mask),opt_hex(data)))
else:
raise Exception ('Invalid register operation: %s for register 0x%08x'%(op,addr))
if show_comments:
html_file.write('<td>'+comments+'</td>')
html_file.write('<td>%s</td>'%comments)
html_file.write('\n</tr>\n')
# for i,_ in enumerate
# def set_initial_state(self,added_reg_sets, init=True):
# if init:
# self.initial_state={}
# self.previous_reg_sets=[]
# try:
# self.initial_register_count=len(added_reg_sets)
# except:
# self.initial_register_count=0
# if not added_reg_sets:
# return
# # print added_reg_sets
# self.previous_reg_sets+=added_reg_sets # appends, not overwrites
# for addr,data,mask,_,_,_ in added_reg_sets: # Do not need to care about default values - they will have 0 in the mask bits.
# if addr in self.initial_state:
# old_data,old_mask=self.initial_state[addr]
# data=((old_data ^ data) & mask) ^ old_data
# mask |= old_mask
# self.initial_state[addr]=(data,mask)
def accumulate_reg_data(reg_sets,accumulate_mask=False):
initial_state={}
cumulative_regs=[() for _ in reg_sets]
for index, (addr, data, mask, module_name, register_name, r_def) in enumerate (reg_sets):
if addr in initial_state:
for index, (op, addr, data, mask, module_name, register_name, r_def) in enumerate (reg_sets):
if (op == 's') and (addr in initial_state): # only accumulate register set operations, not wait for equal ('=') or wait for not-equal ('!')
old_data,old_mask=initial_state[addr]
data=((old_data ^ data) & mask) ^ old_data
if accumulate_mask:
mask |= old_mask
initial_state[addr]=(data,mask)
cumulative_regs[index]=(addr, data, mask, module_name, register_name, r_def)
cumulative_regs[index]=(op, addr, data, mask, module_name, register_name, r_def)
return cumulative_regs
......@@ -212,16 +230,15 @@ class EzynqRegisters:
self.initial_register_count=0
if not added_reg_sets:
return
# print added_reg_sets
self.previous_reg_sets+=added_reg_sets # appends, not overwrites
for addr,data,mask,_,_,_ in added_reg_sets: # Do not need to care about default values - they will have 0 in the mask bits.
if addr in self.initial_state:
for op,addr,data,mask,_,_,_ in added_reg_sets: # Do not need to care about default values - they will have 0 in the mask bits.
if (op == 's') and (addr in self.initial_state):
# old_data,old_mask=self.initial_state[addr]
old_data,_=self.initial_state[addr]
data=((old_data ^ data) & mask) ^ old_data
# mask |= old_mask
# self.initial_state[addr]=(data,mask)
self.initial_state[addr]=(data,0) # ignoring old mask - only accumulating newely set bits in this set
self.initial_state[addr]=(data,0) # ignoring old mask - only accumulating newly set bits in this set
def get_reg_names(self):
return [n[0] for n in sorted([(name,self.defs[name]['OFFS']) for name in self.registers], key = lambda l: l[1])]
......@@ -247,7 +264,11 @@ class EzynqRegisters:
#number of registers set before this module (can be removed from the result of get_register_sets(sort_addr=True,apply_new=True))
def get_initial_count(self):
return self.initial_register_count
return self.initial_register_count
def flush(self):
_= self.get_register_sets(sort_addr=True,apply_new=True)
def get_register_sets(self, sort_addr=True,apply_new=True):
new_sets=[]
# for register_name in self.registers:
......@@ -258,7 +279,8 @@ class EzynqRegisters:
if mask == 0:
continue # no bits set
data,_= self._final_data_mask(register_name) # combined data
new_sets.append((addr,data,mask,self.module_name,register_name,self.defs[register_name]))
op='s' # register set
new_sets.append((op,addr,data,mask,self.module_name,register_name,self.defs[register_name]))
if apply_new:
self.set_initial_state(new_sets, False)
self.registers={} # delete the applied registers
......@@ -305,7 +327,6 @@ class EzynqRegisters:
def set_word(self,register_name,data,force=False):
if not register_name in self.defs:
raise Exception (self.ERRORS['ERR_REG']+' '+register_name)
# addr=self.base_addr+self.defs[register_name]['OFFS']
# see if that register at this address was previously set
default_mask=(self.ro_masks[register_name] ^ 0xffffffff) & 0xffffffff # write enabled bits in the register
#no need to look at self.initial_state - it will be combined later. When handling never-defined-fields will use data from the first use of the address
......@@ -321,12 +342,39 @@ class EzynqRegisters:
else:
raise Exception (self.ERRORS['ERR_RO'] + " " + msg)
data= ((data ^ old_data) & default_mask) ^ old_data
# mask= old_mask | default_mask
# self.registers[register_name]=(data,mask)
#assuming that writing words overwrites all defined bitfields
self.registers[register_name]=(data,default_mask) # that does not include old mask, will have to be combined for the next state of the registers
# old_data,old_mask=self.initial_state[addr]
def _combine_bitfields(self,register_name,field_data, warn=False):
if not register_name in self.defs:
raise Exception (self.ERRORS['ERR_REG']+' '+register_name)
if (len(field_data)==2) and not isinstance(field_data[1],tuple):
field_data=(field_data,)
data=0
mask=0
for f_name,f_data in field_data:
try:
field=self.defs[register_name]['FIELDS'][f_name]
except:
print self.defs[register_name]
raise Exception (self.ERRORS['ERR_FIELD']+': '+register_name+'.'+f_name)
shifted_data,shifted_mask=self._data(field['r'],f_data,warn)
mask |= shifted_mask
data ^= (data ^ shifted_data) & shifted_data
return (data,mask)
def wait_reg_value(self,register_name, data, mask, equals):
if not register_name in self.defs:
raise Exception (self.ERRORS['ERR_REG']+' '+register_name)
addr=self.base_addr+self.defs[register_name]['OFFS']
op=('!','=')[equals]
new_entry=(op, addr, data, mask, self.module_name, register_name, self.defs[register_name])
self.flush() # so self.previous_reg_sets have no all registers set so far
self.previous_reg_sets.append(new_entry)
def wait_reg_field_values(self,register_name,field_data, equals, warn=False):
data,mask=self._combine_bitfields(register_name,field_data, warn)
self.wait_reg_value(register_name,data,mask, equals)
def unset_word(self,register):
if not register in self.defs:
......@@ -339,6 +387,8 @@ class EzynqRegisters:
# force - force readonly/undefined, warn - if data does n ot fit into the bit field
def set_bitfield(self,register_name,field_name,data,force=False,warn=False):
if not register_name in self.defs:
print 'register_name=',register_name
print 'self.defs=',self.defs
raise Exception (self.ERRORS['ERR_REG']+' '+register_name)
try:
old_data,old_mask=self.registers[register_name] # already in the list of registers?
......@@ -356,12 +406,6 @@ class EzynqRegisters:
new_data,new_mask=self._data(field['r'],data,warn)
combined_data= ((new_data ^ old_data) & new_mask) ^ old_data # new data applied to old data
combined_mask=old_mask | new_mask
# print "field['r']=",field['r']
# print 'register_name=',register_name,' field_name=', field_name,
# print 'new_data=',hex(new_data),' new_mask=',hex(new_mask)
# print 'old_data=',hex(old_data),' old_mask=',hex(old_mask)
# print 'combined_data=',hex(combined_data),' combined_mask=',hex(combined_mask)
# print
diff = (combined_data ^ old_data) & self.ro_masks[register_name]
if diff:
msg= register_name+" readonly mask="+hex(self.ro_masks[register_name])+" old data="+hex(old_data)+" new data = "+combined_data+" force="+force
......@@ -377,8 +421,7 @@ class EzynqRegisters:
# print field_data
for field_name,data in field_data:
self.set_bitfield(register_name,field_name,data,force,warn)
# combine multiple bit-fields into (data, mask) pair
def unset_bitfield(self,register_name,field_name):
......
......@@ -46,14 +46,26 @@ class EzynqUBoot:
self.sections=['license','include']
def get_c_file(self):
return self.cfile
def _opt_hex(self,d):
if d <10:
return str(d)
else:
return hex(d)
def _add_reg_writes(self,reg_sets):
for addr, data, _, module_name, register_name, r_def in reg_sets:
for op, addr, data, mask, module_name, register_name, r_def in reg_sets:
try:
comments=r_def['COMMENTS']
except:
comments=''
self.cfile+='\twritel(0x%08x, 0x%08x); /* %s.%s %s */\n'%(data,addr,module_name,register_name,comments)
if op == 's':
self.cfile+='\twritel(0x%08x, 0x%08x); /* %s.%s %s */\n'%(data,addr,module_name,register_name,comments)
elif op == '=':
self.cfile+='\twhile((readl(0x%08x) & %s) != %s); /* %s.%s %s */\n'%(addr,self._opt_hex(mask),self._opt_hex(data),module_name,register_name,comments)
elif op == '!':
self.cfile+='\twhile((readl(0x%08x) & %s) == %s); /* %s.%s %s */\n'%(addr,self._opt_hex(mask),self._opt_hex(data),module_name,register_name,comments)
else:
raise Exception('Invalid register operation "%s" specified for register 0x%08x, data=0x%08x, mask=0x%08x'%(op,addr,data,mask))
def registers_setup (self, reg_sets,clk,num_rbl_regs): #clk is an instance of ezynq_clk.EzynqClk
self.sections.append('registers_setup')
......@@ -69,71 +81,66 @@ inline void register_setup(void)
self.cfile+='}\n\n'
def pll_setup (self, reg_sets,clk): #clk is an instance of ezynq_clk.EzynqClk
pll_status_comment=clk.clk_register_set.get_register_comments('pll_status')
pll_arm=clk.clk_register_set.get_bitfield_address_mask_comments('pll_status','arm_pll_lock')
pll_ddr=clk.clk_register_set.get_bitfield_address_mask_comments('pll_status','ddr_pll_lock')
pll_io= clk.clk_register_set.get_bitfield_address_mask_comments('pll_status', 'io_pll_lock')
address=pll_arm[0]
mask=0
pll_used=clk.get_plls_used()
for pll, pll_tuple in zip(['ARM','DDR','IO'],[pll_arm,pll_ddr,pll_io]):
if pll in pll_used:
mask |= pll_tuple[1]
if mask==0 :
print 'No PLLs are used, skipping generating pll_setup()'
return
self.sections.append('pll_setup')
self.cfile+='''/* Wait for PLLs locked: %s */
self.cfile+='''/* Wait for PLLs locked:*/
inline void pll_setup(void)
{
\t/* Wait for all PLLs locked */
\twhile ((readl (0x%x) & 0x%x) != 0x%x); /* slcr.pll_status %s */
\t/* release PLL bypass on each PLL */
'''%(str(pll_used),address,mask,mask,pll_status_comment)
\t/* Wait for all used PLLs locked, then release PLL bypass on each PLL */
'''
self._add_reg_writes(reg_sets)
self.cfile+='}\n\n'
def uart_init (self, reg_sets,clk):
self.sections.append('uart_init')
self.cfile+='''/* Initilize UART to output debug info during boot */
inline void uart_init(void)
{
\t/* Wait for all used PLLs locked, then release PLL bypass on each PLL */
'''
self._add_reg_writes(reg_sets)
self.cfile+='}\n\n'
def dci_calibration (self, reg_sets,ddr): #ddr is an instance of ezynq_ddr.EzynqDDR
if len(reg_sets)==0:
print 'No DCI calibration register data is provided, skipping generating dci_calibration()'
return
dci_status_comment=ddr.ddriob_register_set.get_register_comments('ddriob_dci_status')
address,mask,_=ddr.ddriob_register_set.get_bitfield_address_mask_comments('ddriob_dci_status','done')
self.cfile+='''/* Calibrate DDR DCI, wait for completion */
inline void dci_calibration(void)
{
\t/* Toggle active-low DCI reset, initialize DCI calibration */
\t/* Toggle active-low DCI reset, initialize DCI calibration, wait for DONE */
'''
self._add_reg_writes(reg_sets)
self.cfile+='''\t/* Wait DCI calibration is DONE */
\twhile ((readl (0x%x) & 0x%x) != 0x%x); /* slcr.ddriob_dci_status %s */
'''%(address,mask,mask,dci_status_comment)
self.cfile+='}\n\n'
self.sections.append('dci_calibration')
def ddr_start (self, reg_sets,ddr): #ddr is an instance of ezynq_ddr.EzynqDDR
if len(reg_sets)==0:
print 'No DDR start data is provided, skipping generating ddr_start()'
return
ddrc_status_comment=ddr.ddrc_register_set.get_register_comments('mode_sts_reg')
address,mask,_=ddr.ddrc_register_set.get_bitfield_address_mask_comments('mode_sts_reg','ddrc_reg_operating_mode')
self.cfile+='''/* Start DDRC, wait for initialization complete */
inline void ddr_start(void)
{
\t/* Release DDRC active-low reset */
'''
self._add_reg_writes(reg_sets)
self.cfile+='''\t/* DDRC operation mode is INITIALIZED */
\twhile ((readl (0x%x) & 0x%x) == 0); /* ddrc.mode_sts_reg %s */
'''%(address,mask,ddrc_status_comment)
self.cfile+='}\n\n'
self.sections.append('ddr_start')
def make_lowlevel_init (self):
self.cfile+='''/* Initialize clocks, DDR memory, copy OCM to DDR */
void lowlevel_init(void)
{
/*
'''
if 'uart_init' in self.sections:
self.cfile+='''/* Initialize UART fdro debug information output */
\tuart_init();
'''
self.cfile+='''/*
Unlock SLCR and write PLL and clocks registers as the code is now running in the OCM and no
peripherals are needed
*/
......
......@@ -29,6 +29,7 @@ import ezynq_registers
import ezynq_mio
import ezynq_clk
import ezynq_uboot
import ezynq_uart
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbosity', action='count', help='increase output verbosity')
parser.add_argument('-c', '--configs', help='Configuration file (such as autoconf.mk)')
......@@ -248,8 +249,11 @@ def image_generator (image,
# new_sets.append((addr,data,mask,self.module_name,register_name,self.defs[register_name]))
for register in reg_sets:
addr=register[0]
data=register[1]
op=register[0]
addr=register[1]
data=register[2]
if (op != 's'):
raise Exception ('Can not test registers (0x%08x) in RBL, it should be done in user code'%addr)
if not verify_register_accessible (addr):
print 'Tried to set non-accessible register', hex(addr),' with data ', hex(data)
exit (ERROR_DEFS['NONACCESSIBLE_REGISTER'])
......@@ -263,19 +267,7 @@ def image_generator (image,
waddr+=1
image[waddr]=0
waddr+=1
# for addr, data, mask, module_name, register_name, r_def in reg_sets:
def write_include(filename,reg_sets):
incl_file=open(filename,'w')
# for addr, data, mask, module_name, register_name, r_def in reg_sets:
for addr, data, _, module_name, register_name, r_def in reg_sets:
try:
comments=r_def['COMMENTS']
except:
comments=''
incl_file.write(' writel(0x%08x, 0x%08x); /* %s.%s %s */\n'%(data,addr,module_name,register_name,comments))
incl_file.close()
def write_image(image,name):
bf=open(name,'wb')
data=struct.pack('I' * len(image), *image)
......@@ -317,7 +309,8 @@ clk.check_ds_compliance()
clk.setup_clocks()
ddr_mhz=clk.get_ddr_mhz()
if MIO_HTML:
f=open(MIO_HTML,'w')
else:
......@@ -337,105 +330,95 @@ ddr.calculate_dependent_pars(ddr_mhz)
ddr.pre_validate() # before applying default values (some timings should be undefined, not defaults)
ddr.check_missing_features() #and apply default values
ddr.html_list_features(f) #verify /fix values after defaults are applied
#ddr.ddr_init_memory(current_reg_sets,force=False,warn=False): # will program to sequence 'MAIN'
#clk.calculate_dependent_pars()
clk.html_list_features(f)
reg_sets=[]
segments=[]
reg_sets=mio_regs.setregs_mio(reg_sets,force) # reg Sets include now MIO
num_mio_regs=len(reg_sets)
# should be always True, probably
clk_in_uboot= not (raw_config_value('CONFIG_EZYNQ_SKIP_CLK', raw_configs) is None)
segments.append({'TO':len(reg_sets),'RBL':True,'NAME':'MIO','TITLE':'MIO registers configuration'})
#adding ddr registers
if raw_config_value('CONFIG_EZYNQ_SKIP_DDR', raw_configs) is None:
ddr.ddr_init_memory(reg_sets,False,False)
reg_sets=ddr.get_new_register_sets() # mio, ddr
segments.append({'TO':len(reg_sets),'RBL':True,'NAME':'DDR0','TITLE':'DDR registers configuration'})
else:
print 'Debug mode: skipping DDR-related configuration'
num_ddr_regs=len(reg_sets)-num_mio_regs
#define CONFIG_EZYNQ_SKIP_DDR
#define CONFIG_EZYNQ_SKIP_CLK
#initialize clocks
# unlock slcr - it is locked by RBL, but attempt to unlock in RBL will fail (and hang the system)
clk.clocks_regs_setup(reg_sets,clk_in_uboot,force) # reg Sets include now MIO and CLK
reg_sets=clk.get_new_register_sets() # mio, ddr and clk
num_clk_regs=len(reg_sets)-num_mio_regs-num_ddr_regs
len_before_pll=len(reg_sets)
len_before_dci_calibrate=len(reg_sets)
len_before_ddr_start=len(reg_sets)
if clk_in_uboot:
num_rbl_regs=len_before_pll-num_clk_regs
print 'Debug mode: CLK/PLL configuration by u-boot'
clk.clocks_pll_bypass_off(reg_sets,force) # reg Sets include now MIO and CLK
reg_sets=clk.get_new_register_sets() # mio, ddr and clk, pll
len_before_dci_calibrate=len(reg_sets)
num_pll_regs=len_before_dci_calibrate-len_before_pll
reg_sets=ddr.ddr_dci_calibrate(reg_sets,False,False)
len_before_ddr_start=len(reg_sets)
num_dci_init_regs=len_before_ddr_start-len_before_dci_calibrate
reg_sets=ddr.ddr_start(reg_sets,False,False)
reg_sets=clk.clocks_regs_setup(reg_sets,True,force)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'CLK','TITLE':'Clock registers configuration'})
#print 'Debug mode: CLK/PLL configuration by u-boot'
reg_sets=clk.clocks_pll_bypass_off(reg_sets,force)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'PLL','TITLE':'Registers to switch to PLL'})
if not raw_config_value('CONFIG_EZYNQ_BOOT_DEBUG', raw_configs) is None:
uart=ezynq_uart.EzynqUART()
uart.parse_parameters(raw_configs,used_mio_interfaces,False)
uart.check_missing_features()
else:
num_rbl_regs=len(reg_sets)
print 'Debug mode: CLK/PLL configuration by RBL'
num_pll_regs=0
uart_channel=uart.channel
if not uart_channel is None:
try:
uart_mhz=clk.get_uart_mhz()
except:
print 'UART reference clock is not defined, can not generate boot debug code'
uart_channel=None
uart.set_refclk_mhz(uart_mhz)
# print 'uart_channel=',uart_channel,' uart_mhz=',uart_mhz
else:
uart_channel=None
if not uart_channel is None:
uart.html_list_features(f)
# Generate UART initialization, putc and wait FIFO empty code
#clocks_pll_bypass_off(self,force=False,warn=False):
# def clocks_pll_bypass_off(self,current_reg_sets,force=False,warn=False):
reg_sets=uart.setup_uart(reg_sets,force=False,warn=False)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'UART_INIT','TITLE':'Registers to initialize UART'})
if raw_config_value('CONFIG_EZYNQ_SKIP_DDR', raw_configs) is None:
reg_sets=ddr.ddr_dci_calibrate(reg_sets,False,False)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DCI','TITLE':'DDR DCI Calibration'})
reg_sets=ddr.ddr_start(reg_sets,False,False)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DDR_START','TITLE':'DDR initialization start'})
# make reg_sets data cumulative
reg_sets=ezynq_registers.accumulate_reg_data(reg_sets)
ezynq_registers.print_html_reg_header(f, 'MIO registers configuration', MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
#ezynq_registers.print_html_registers(f, reg_sets[:num_mio_regs], MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_registers(f, reg_sets[:num_mio_regs], 0, MIO_HTML_MASK & 0x800, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_reg_footer(f)
ezynq_registers.print_html_reg_header(f, 'DDR Configuration', MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_registers(f, reg_sets[:num_mio_regs+num_ddr_regs], num_mio_regs, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_reg_footer(f)
ezynq_registers.print_html_reg_header(f, 'CLOCK registers configuration', MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_registers(f, reg_sets[:num_rbl_regs], num_mio_regs+num_ddr_regs, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_reg_footer(f)
if len(reg_sets)>num_rbl_regs:
ezynq_registers.print_html_reg_header(f, 'Registers configuration in u-boot', MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_registers(f, reg_sets[:len_before_pll], num_rbl_regs, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_reg_footer(f)
if len(reg_sets)>len_before_pll:
ezynq_registers.print_html_reg_header(f, 'Registers configuration in u-boot after PLLs are locked', MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_registers(f, reg_sets[:len_before_dci_calibrate],len_before_pll, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_reg_footer(f)
if len(reg_sets)>len_before_pll:
ezynq_registers.print_html_reg_header(f, 'Registers configuration in u-boot for DDR DCI calibration', MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_registers(f, reg_sets[:len_before_ddr_start],len_before_dci_calibrate, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_reg_footer(f)
if len(reg_sets)>len_before_ddr_start:
ezynq_registers.print_html_reg_header(f, 'Registers configuration in u-boot to start DDR initialization', MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
ezynq_registers.print_html_registers(f, reg_sets,len_before_ddr_start, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
num_rbl_regs=0
for segment in segments:
if segment['RBL']:
num_rbl_regs=segment['TO']
segment_dict={}
for index,segment in enumerate(segments):
if index==0:
start=0
else:
start=segments[index-1]['TO']
segment['FROM']=start
segment_dict[segment['NAME']]=segment
#for index,segment in enumerate(segments):
# print index,':', segment
for segment in segments:
start=segment['FROM']
end=segment['TO']
show_bit_fields= (MIO_HTML_MASK & 0x100,MIO_HTML_MASK & 0x800)[segment['NAME']=='MIO']
show_comments= MIO_HTML_MASK & 0x200
filter_fields=not MIO_HTML_MASK & 0x400
all_used_fields= False
ezynq_registers.print_html_reg_header(f,
segment['TITLE']+" (%s)"%(('U-BOOT','RBL')[segment['RBL']]),
show_bit_fields, show_comments, filter_fields)
# print segment['TITLE']+" (%s)"%(('U-BOOT','RBL')[segment['RBL']]), start,end
ezynq_registers.print_html_registers(f,
reg_sets[:end],
start,
show_bit_fields,
show_comments,
filter_fields,
all_used_fields)
ezynq_registers.print_html_reg_footer(f)
#TODO: Need to be modified for the new format
# if 'CONFIG_EZYNQ_UART_LOOPBACK_0' in raw_options: uart_remote_loopback(registers,f, 0,MIO_HTML_MASK)
# if 'CONFIG_EZYNQ_UART_LOOPBACK_1' in raw_options: uart_remote_loopback(registers,f, 1,MIO_HTML_MASK)
if f:
f.write('<h4>Total number of registers set up in the RBL header is <b>'+str(num_rbl_regs)+"</b> of maximal 256</h4>")
if num_rbl_regs<len(reg_sets):
......@@ -464,15 +447,27 @@ image_generator (image,
if args.outfile:
write_image(image,args.outfile)
# if args.include and (num_rbl_regs<len(reg_sets)):
# write_include(args.include,reg_sets[num_rbl_regs:])
# print 'Debug mode: writing u-boot setup registers to ',args.include
u_boot=ezynq_uboot.EzynqUBoot(args.verbosity)
u_boot.registers_setup (reg_sets[num_rbl_regs:len_before_pll],clk,num_rbl_regs)
u_boot.pll_setup (reg_sets[len_before_pll:len_before_dci_calibrate],clk)
u_boot.dci_calibration(reg_sets[len_before_dci_calibrate:len_before_ddr_start],ddr)
u_boot.ddr_start (reg_sets[len_before_ddr_start:],ddr)
# segments.append({'TO':len(reg_sets),'RBL':True,'NAME':'MIO','TITLE':'MIO registers configuration'})
# segments.append({'TO':len(reg_sets),'RBL':True,'NAME':'DDR0','TITLE':'DDR registers configuration'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'CLK','TITLE':'Clock registers configuration'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'PLL','TITLE':'Registers to switch to PLL'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'UART_INIT','TITLE':'Registers to initialize UART'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DCI','TITLE':'DDR DCI Calibration'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DDR_START','TITLE':'DDR initialization start'})
u_boot=ezynq_uboot.EzynqUBoot(args.verbosity)
if 'CLK' in segment_dict:
u_boot.registers_setup (reg_sets[segment_dict['CLK']['FROM']:segment_dict['CLK']['TO']],clk,num_rbl_regs)
if 'PLL' in segment_dict:
u_boot.pll_setup (reg_sets[segment_dict['PLL']['FROM']:segment_dict['PLL']['TO']],clk)
if 'UART_INIT' in segment_dict:
u_boot.uart_init (reg_sets[segment_dict['UART_INIT']['FROM']:segment_dict['UART_INIT']['TO']],clk)
if 'DCI' in segment_dict:
u_boot.dci_calibration(reg_sets[segment_dict['DCI']['FROM']:segment_dict['DCI']['TO']],ddr)
if 'DDR' in segment_dict:
u_boot.ddr_start (reg_sets[segment_dict['DDR']['FROM']:segment_dict['DDR']['TO']],ddr)
u_boot.make_lowlevel_init()
u_boot.output_c_file(args.lowlevel)
#print u_boot.get_c_file()
#COnfiguration for the microzed board
CONFIG_EZYNQ_BOOT_DEBUG=y # configure UARTx and send register dumps there
CONFIG_EZYNQ_LED_DEBUG=47 # toggle LED during boot
CONFIG_EZYNQ_UART1_BAUD_RATE=115200
#Configuration for the microzed board
CONFIG_EZYNQ_MIO_0_VOLT=3.3
CONFIG_EZYNQ_MIO_1_VOLT=1.8
#CONFIG_EZYNQ_MIO_0_PULLUP=y #default pullup for MIO0 - may be overwritten for individual pins
......@@ -86,20 +90,6 @@ CONFIG_EZYNQ_START_EXEC= 0x00 # start of execution address
#just software testing - remove later
#CONFIG_EZYNQ_DDR_SETREG_ctrl_reg1__reg_ddrc_selfref_en_PRE = 1
#CONFIG_EZYNQ_DDR_SETREG_ctrl_reg1__reg_ddrc_lpr_num_entries_PRE = 5
#CONFIG_EZYNQ_DDR_SETREG_phy_wr_dqs_cfg0_PRE = 0xAAAAA
#CONFIG_EZYNQ_DDR_SETREG_phy_wr_dqs_cfg0__reg_phy_wr_dqs_slave_delay_PRE = 0x77
#CONFIG_EZYNQ_DDR_ARB_PAGE_BANK = N # Y # default N, testing
# not yet processed
CONFIG_EZYNQ_DCI_PERIPHERAL_FREQMHZ = 10.158731 # Taking available CLK and divisors into account?
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment