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')
......
This diff is collapsed.
......@@ -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
*/
......
This diff is collapsed.
#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