Commit a3f7f58e authored by Eyesisbox Elphel's avatar Eyesisbox Elphel

continue on DDR initialization

parent 496a0d6f
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2013, Elphel.inc.
# configuration of the DDR-related registers
# This program is free software: you can redistribute it and/or modify
......@@ -21,39 +22,419 @@ __version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
import math
import ezynq_ddrc_defs
import ezynq_registers
import ezynq_ddrcfg_defs
import ezynq_feature_config
import ezynq_ddriob_def
class EzynqDDR:
def __init__(self,permit_undefined_bits=False,force=False,warn=False):
self.DDRC_DEFS=ezynq_ddrc_defs.DDRC_DEFS
self.register_sets= {'PRE':ezynq_registers.EzynqRegisters(self.DDRC_DEFS,0,permit_undefined_bits),
'MAIN':ezynq_registers.EzynqRegisters(self.DDRC_DEFS,0,permit_undefined_bits),
'POST':ezynq_registers.EzynqRegisters(self.DDRC_DEFS,0,permit_undefined_bits)}
def __init__(self,regs_masked,permit_undefined_bits=False,force=False,warn=False):
self.DDRC_DEFS= ezynq_ddrc_defs.DDRC_DEFS
self.DDRIOB_DEFS=ezynq_ddriob_def.DDRIOB_DEFS
self.DDR_CFG_DEFS=ezynq_ddrcfg_defs.DDR_CFG_DEFS
self.ddrc_register_sets= {'PRE': ezynq_registers.EzynqRegisters(self.DDRC_DEFS,0,regs_masked,permit_undefined_bits), # all now start from the same registers
'MAIN':ezynq_registers.EzynqRegisters(self.DDRC_DEFS,0,regs_masked,permit_undefined_bits),
'POST':ezynq_registers.EzynqRegisters(self.DDRC_DEFS,0,regs_masked,permit_undefined_bits)}
self.ddriob_register_sets= {'PRE': ezynq_registers.EzynqRegisters(self.DDRIOB_DEFS,0,regs_masked,permit_undefined_bits), # all now start from the same registers
'MAIN':ezynq_registers.EzynqRegisters(self.DDRIOB_DEFS,0,regs_masked,permit_undefined_bits),
'POST':ezynq_registers.EzynqRegisters(self.DDRIOB_DEFS,0,regs_masked,permit_undefined_bits)}
# self.set_names=('PRE','MAIN','POST')
self.set_attribs=(
self.set_ddrc_attribs=(
{'NAME':'PRE','POSTFIX':'_PRE','PREFIX':'CONFIG_EZYNQ_DDR_SETREG_','TITLE':"DDR Controller Register Pre-Set"},
{'NAME':'MAIN','POSTFIX':'','PREFIX':'CONFIG_EZYNQ_DDR_SETREG_','TITLE':"DDR Controller Register Set"},
{'NAME':'POST','POSTFIX':'_POST','PREFIX':'CONFIG_EZYNQ_DDR_SETREG_','TITLE':"DDR Controller Register Post-Set"})
self.postfixes=[attrib['POSTFIX'] for attrib in self.set_attribs]
def parse_raw_register_set(self,raw_configs,qualifier_char,force=True,warn=True):
self.set_ddiob_attribs=(
{'NAME':'PRE','POSTFIX':'_PRE','PREFIX':'CONFIG_EZYNQ_DDRIOB_SETREG_','TITLE':"DDR I/O Buffer Register Pre-Set"},
{'NAME':'MAIN','POSTFIX':'','PREFIX':'CONFIG_EZYNQ_DDRIOB_SETREG_','TITLE':"DDR I/O Buffer Register Set"},
{'NAME':'POST','POSTFIX':'_POST','PREFIX':'CONFIG_EZYNQ_DDRIOB_SETREG_','TITLE':"DDR I/O Buffer Register Post-Set"})
self.postfixes=[attrib['POSTFIX'] for attrib in self.set_ddrc_attribs]
self.features=ezynq_feature_config.EzynqFeatures(self.DDR_CFG_DEFS,0) #DDR_CFG_DEFS
def parse_parameters(self,raw_configs):
self.features.parse_features(raw_configs)
def check_missing_features(self):
self.features.check_missing_features()
def html_list_features(self,html_file):
html_file.write('<h2>DDR memory configuration parameters</h2>\n')
self.features.html_list_features(html_file)
# def ddr_init_memory(self,current_reg_sets,force=False,warn=False,html_file, show_bit_fields=True, show_comments=True,filter_fields=True): # will program to sequence 'MAIN'
def get_new_register_sets(self):
# def get_register_sets(self, sort_addr=True,apply_new=True):
return self.ddrc_register_sets['MAIN'].get_register_sets(True,True)
# regs1=self.ddriob_register_sets['MAIN'].get_register_sets(True,True)
# regs2=self.ddrc_register_sets['MAIN'].get_register_sets(True,True)
# return regs1+regs2
def ddr_init_memory(self,current_reg_sets,force=False,warn=False): # will program to sequence 'MAIN'
# print 'ddr_init_memory, len(current_reg_sets)=',len(current_reg_sets),'\n'
if not self.features.get_par_value('ENABLE'):
print 'DDR configuration is disabled'
# do some stuff (write regs, output)
return
ddriob_register_set=self.ddriob_register_sets['MAIN']
ddrc_register_set= self.ddrc_register_sets['MAIN']
ddriob_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
self.ddr_init_ddriob(force,warn) # will program to sequence 'MAIN'
regs1=ddriob_register_set.get_register_sets(True,True)
ddrc_register_set.set_initial_state(regs1, True)# add
self.ddr_init_ddrc(force,warn) # will program to sequence 'MAIN'
return ddrc_register_set.get_register_sets(True,True)
# ddrc_register_set= self.ddrc_register_sets['MAIN']
#TODO make some of (possibly) derived, leave '_T_' for ns only!
# CONFIG_EZYNQ_DDR_FREQ_MHZ = 533.333333 *
# CONFIG_EZYNQ_DDR_CL = 7 *
# CONFIG_EZYNQ_DDR_CWL = 6 *
# CONFIG_EZYNQ_DDR_RCD = 7 (was CONFIG_EZYNQ_DDR_T_RCD = 7) *
# CONFIG_EZYNQ_DDR_RP = 7 (was CONFIG_EZYNQ_DDR_T_RP = 7) *
# CONFIG_EZYNQ_DDR_T_RC = 48.75 *
# CONFIG_EZYNQ_DDR_T_RAS_MIN = 35.0 *
# CONFIG_EZYNQ_DDR_T_RFC = 350.0
# CONFIG_EZYNQ_DDR_T_FAW = 40.0 *
# CONFIG_EZYNQ_DDR_AL = 0 *
# CONFIG_EZYNQ_DDR_BANK_ADDR_COUNT = 3 *
# CONFIG_EZYNQ_DDR_ROW_ADDR_COUNT = 15 *
# CONFIG_EZYNQ_DDR_COL_ADDR_COUNT = 10 *
# CONFIG_EZYNQ_DDR_ENABLE = 1 *
# CONFIG_EZYNQ_DDR_MEMORY_TYPE = DDR3 *
# CONFIG_EZYNQ_DDR_ECC = Disabled *
# CONFIG_EZYNQ_DDR_BUS_WIDTH = 32 *
# CONFIG_EZYNQ_DDR_BL = 8 *
# CONFIG_EZYNQ_DDR_HIGH_TEMP = Normal *
# CONFIG_EZYNQ_DDR_PARTNO = MT41K256M16RE-125 *
# CONFIG_EZYNQ_DDR_DRAM_WIDTH = 16 *
# CONFIG_EZYNQ_DDR_SPEED_BIN = DDR3_1066F *
# CONFIG_EZYNQ_DDR_TRAIN_WRITE_LEVEL = 0
# CONFIG_EZYNQ_DDR_TRAIN_READ_GATE = 0
# CONFIG_EZYNQ_DDR_TRAIN_DATA_EYE = 0
# CONFIG_EZYNQ_DDR_CLOCK_STOP_EN = 0
# CONFIG_EZYNQ_DDR_USE_INTERNAL_VREF = 0
def ddr_init_ddrc(self,force=False,warn=False): # will program to sequence 'MAIN'
ddrc_register_set=self.ddrc_register_sets['MAIN']
is_LPDDR2= (self.features.get_par_value('MEMORY_TYPE')=='LPDDR2')
is_DDR3L= (self.features.get_par_value('MEMORY_TYPE')=='DDR3L')
is_DDR3_15= (self.features.get_par_value('MEMORY_TYPE')=='DDR3')
is_DDR3= is_DDR3_15 or is_DDR3L
is_DDR2= (self.features.get_par_value('MEMORY_TYPE')=='DDR2')
# is_32= (self.features.get_par_value('BUS_WIDTH') > 16)
# is_int_vref= self.features.get_par_value('INTERNAL_VREF')
tCK=1000.0/self.features.get_par_value('FREQ_MHZ')
tREFI= 1000*self.features.get_par_value('T_REFI_US')/(1,2)[self.features.get_par_value('HIGH_TEMP')] # ns
tWR= self.features.get_par_value('T_WR')
#lock ddr
ddrc_register_set.set_word('ddrc_ctrl',0x80,force) # active low soft reset
#two rank, values 0x1081, 0x81081, 0x81081 (added reg_ddrc_wr_odt_block=1)
tREFI_c32= int(tREFI/tCK/32)
ddrc_register_set.set_bitfields('two_rank_cfg',(('reg_ddrc_wr_odt_block',0), # shown as 1/do not modify, but actual set value==0
('reg_ddrc_addrmap_cs_bit0',0),
('reg_ddrc_t_rfc_nom_x32',tREFI_c32),
('reg_ddrc_active_ranks',1)),force,warn) # *** not documented
#reg HPR, values 0x3c0780f - all 3 times, DEFAULT
ddrc_register_set.set_bitfields('hpr_reg',(('reg_ddrc_hpr_xact_run_length', 0xf),
('reg_ddrc_hpr_max_starve_x32', 0xf),
('reg_ddrc_hpr_min_non_critical_x32',0xf)),force,warn)
#reg LPR, values 0x2001001 - all 3 times, DEFAULT
ddrc_register_set.set_bitfields('lpr_reg',(('reg_ddrc_lpr_xact_run_length', 0x8),
('reg_ddrc_lpr_max_starve_x32', 0x2),
('reg_ddrc_lpr_min_non_critical_x32',0x1)),force,warn)
#reg WR_REG, values 0x14001 - all 3 times, DEFAULT
ddrc_register_set.set_bitfields('wr_reg',(('reg_ddrc_w_max_starve_x32', 0x2), # opposite sequence from HPR,LPR
('reg_ddrc_w_xact_run_length', 0x8),
('reg_ddrc_w_min_non_critical_x32',0x1)),force,warn)
#reg DRAM_param_reg0, values 0x4281a all 3 times
tXSx1=512 # clock cycles
tXSx32=tXSx1/32
tRFCx1=int(math.ceil(self.features.get_par_value('T_RFC')/tCK))
tRCx1= int(math.ceil(self.features.get_par_value('T_RC')/tCK))
ddrc_register_set.set_bitfields('dram_param_reg0',(('reg_ddrc_post_selfref_gap_x32',tXSx32), # Default - OK, Micron tXSDLL=tDLLK=512 /32
('reg_ddrc_t_rfc_min', tRFCx1),
('reg_ddrc_t_rc', tRCx1)),force,warn)
# reg DRAM_param_reg1, 0x44e458d2
tCKEx1=4 # good default
tRAS_MINx1= int(math.ceil(self.features.get_par_value('T_RAS_MIN')/tCK))
tRAS_MAX=9*tREFI # for Micron
tRAS_MAX_x1024=int(tRAS_MAX/tCK/1024)
tFAWx1=int(math.ceil(self.features.get_par_value('T_FAW')/tCK))
inactiveToPDx32=6 # cycles 'Power down after this many clocks of NOP/DESELECT (if enabled in mcr). Make configurable?
tWRx1=int(math.ceil(tWR/tCK))
WL=self.features.get_par_value('CWL')
BL=self.features.get_par_value('BL')
wr2pre=WL+BL/2+tWRx1
if is_LPDDR2:
wr2pre+=1
ddrc_register_set.set_bitfields('dram_param_reg1',(('reg_ddrc_t_cke', tCKEx1), # Default - OK, Micron tXSDLL=tDLLK=512 /32
('reg_ddrc_t_ras_min', tRAS_MINx1),
('reg_ddrc_t_ras_max', tRAS_MAX_x1024),
('reg_ddrc_t_faw', tFAWx1),
('reg_ddrc_powerdown_to_x32',inactiveToPDx32),
('reg_ddrc_wr2pre', wr2pre)),force,warn)
# reg DRAM_param_reg2, 0x720238e5
AL= self.features.get_par_value('AL')
tRCDx1= max(self.features.get_par_value('RCD') - AL,1)
tRTPx1=max(self.features.get_par_value('RTP'), int(math.ceil(self.features.get_par_value('T_RTP')/tCK))) # tRTPx1= 4 # good default
if is_DDR2:
RD2PRE=AL+BL/2+max(tRTPx1,2)-2
elif is_DDR3:
RD2PRE=AL+max(tRTPx1,4)
elif is_LPDDR2:
RD2PRE=BL/2+tRTPx1-1
padPD=0 # ???
XP= self.features.get_par_value('XP') # 4
tWTRx1=max(self.features.get_par_value('WTR'), int(math.ceil(self.features.get_par_value('T_WTR')/tCK))) # tWTRx1= 4 # good default
if is_DDR2 or is_DDR3:
WR2RD=WL+tWTRx1+BL/2
elif is_LPDDR2:
WR2RD=WL+tWTRx1+BL/2+1
CL= self.features.get_par_value('CL')
RL= CL+AL
if is_DDR2 or is_DDR3:
RD2WR=RL+BL/2+2-WL
elif is_LPDDR2:
RD2WR=RL+BL/2+int(math.ceil(self.features.get_par_value('T_DQSCK_MAX')/tCK))+1-WL
if is_DDR2 or is_DDR3:
write_latency=WL-1
elif is_LPDDR2:
write_latency=WL
if is_LPDDR2:
if WL<1:
raise Exception('Minimal Write Latency supported for LPDDR2 is 1, while CONFIG_EZYNQ_DDR_CWL='+str(WL))
else:
if WL<3:
raise Exception('Minimal Write Latency supported for DDR2/DDR3 is 3, while CONFIG_EZYNQ_DDR_CWL='+str(WL))
ddrc_register_set.set_bitfields('dram_param_reg2',(('reg_ddrc_t_rcd', tRCDx1), # 0x7
('reg_ddrc_rd2pre', RD2PRE), # 0x4
('reg_ddrc_pad_pd', padPD), # 0x0
('reg_ddrc_t_xp', XP), # 0x4
('reg_ddrc_wr2rd', WR2RD), # 0xe
('reg_ddrc_rd2wr', RD2WR), # 0x7
('reg_ddrc_write_latency', write_latency)),force,warn) #5
# reg DRAM_param_reg3, 0x272872d0
ddrc_register_set.set_bitfields('dram_param_reg3',(('reg_ddrc_loopback', ?), #0
('reg_ddrc_dis_pad_pd', ?), #0
('reg_phy_mode_ddr1_ddr2', ?), #1
('reg_ddrc_read_latency', ?), #7
('reg_ddrc_en_dfi_dram_clk_disable', ?), #0
('reg_ddrc_mobile', ?), # 0
('reg_ddrc_sdram', ?), # 1
('reg_ddrc_refresh_to_x32', ?), # 8
('reg_ddrc_t_rp', ?), # 7
('reg_ddrc_refresh_margin', ?), # 2
('reg_ddrc_t_rrd', ?), # 6
('reg_ddrc_t_ccd', ?)),force,warn) #4
# CONFIG_EZYNQ_DDR_XP = 4
# CONFIG_EZYNQ_DDR_RCD = 7 (was CONFIG_EZYNQ_DDR_T_RCD = 7) *
# CONFIG_EZYNQ_DDR_RP = 7 (was CONFIG_EZYNQ_DDR_T_RP = 7) *
# CONFIG_EZYNQ_DDR_T_RC = 48.75 *
# CONFIG_EZYNQ_DDR_T_RAS_MIN = 35.0 *
# CONFIG_EZYNQ_DDR_T_RFC = 350.0
# CONFIG_EZYNQ_DDR_T_FAW = 40.0 *
# CONFIG_EZYNQ_DDR_RTP = 4
# CONFIG_EZYNQ_DDR_T_RTP = 7.5
# CONFIG_EZYNQ_DDR_WTR = 4
# CONFIG_EZYNQ_DDR_T_WTR = 7.5
# reg_ddrc_wr2pre 4:0 1f 12 12
# reg_ddrc_powerdown_to_x32 9:5 3e0 6 c0
# reg_ddrc_t_faw 15:10 fc00 16 5800
# reg_ddrc_t_ras_max 21:16 3f0000 24 240000
# reg_ddrc_t_ras_min 26:22 7c00000 13 4c00000
# reg_ddrc_t_cke 31:28 f0000000 4 40000000
# DRAM_param_reg1 @ 0XF8006018 f7ffffff 44e458d2
# 'dram_param_reg3': {'OFFS': 0x020,'DFLT':0x250882D0,'RW':'M','FIELDS':{ #272872d0
# 'reg_ddrc_loopback': {'r':(31,31),'d': 0,'c':'reserved'},
# 'reg_ddrc_dis_pad_pd': {'r':(30,30),'d': 0,'c':'Disable pad power down'},
# 'reg_phy_mode_ddr1_ddr2': {'r':(29,29),'d': 1,'c':'Unused'}, # 0x1
# 'reg_ddrc_read_latency': {'r':(24,28),'d': 0x5,'c':'Read Latency, clocks'}, # 0x7
# 'reg_ddrc_en_dfi_dram_clk_disable': {'r':(23,23),'d': 0,'c':'Enables clock disable...'},
# 'reg_ddrc_mobile': {'r':(22,22),'d': 0,'c':'0 - DDR2/DDR3, 1 - LPDDR2'},
# 'reg_ddrc_sdram': {'r':(21,21),'d': 0,'c':'reserved'}, # 0x1
# 'reg_ddrc_refresh_to_x32': {'r':(16,20),'d': 0x8,'c':'Dynamic, "speculative refresh"'},
# 'reg_ddrc_t_rp': {'r':(12,15),'d': 0x8,'c':'tRP'}, # 0x7
# 'reg_ddrc_refresh_margin': {'r':( 8,11),'d': 0x2,'c':'do refresh this cycles before timer expires'},
# 'reg_ddrc_t_rrd': {'r':( 5, 7),'d': 0x6,'c':'tRRD Minimal time between activates of different banks'},
# 'reg_ddrc_t_ccd': {'r':( 2, 4),'d': 0x4,'c':'tCCD One less than minimal time between reads of writes to different banks'},
# 'reserved2': {'r':( 0, 1),'d': 0,'m':'R','c':'reserved'}}},
# 'dram_param_reg4': {'OFFS': 0x024,'DFLT':0x0000003C,'RW':'M','FIELDS':{ #0x3c
# 'reg_ddrc_mr_rdata_valid': {'r':(27,27),'d': 0,'m':'R','c':'cleared by reading mode_reg_read (0x2a4), set when mode_reg_read gets new data'},
# 'reg_ddrc_mr_type': {'r':(26,26),'d': 0,'c':'0 - mode register write, 1 - mode register read'},
# 'ddrc_reg_mr_wr_busy': {'r':(25,25),'d': 0,'m':'R','c':'1 - do not issue mode register R/W (wait 0)'},
# 'reg_ddrc_mr_data': {'r':( 9,24),'d': 0,'c':'DDR2/3: Mode Register Write data'},
# 'reg_ddrc_mr_addr': {'r':( 7, 8),'d': 0,'c':'DDR2/3: Mode Register address (0 - MR0, ... 3 - MR3)'},
# 'reg_ddrc_mr_wr': {'r':( 6, 6),'d': 0,'m':'W','c':'low-to-high starts mode reg r/w (if not ddrc_reg_mr_wr_busy)'},
# 'reg_ddrc_max_rank_rd': {'r':( 2, 5),'d': 0xF,'c':'reserved'},
# 'reg_ddrc_prefer_write': {'r':( 1, 1),'d': 0,'c':'1: Bank selector prefers writes over reads'},
# 'reg_ddrc_en_2t_timing_mode': {'r':( 0, 0),'d': 0,'c':'0 - DDRC uses 1T timing, 1 - 2T timing'}}},
def ddr_init_ddriob(self,force=False,warn=False): # will program to sequence 'MAIN'
# print 'ddr_init_ddriob\n'
ddriob_register_set=self.ddriob_register_sets['MAIN']
# DDRIOB configuration UG585.268
is_LPDDR2= (self.features.get_par_value('MEMORY_TYPE')=='LPDDR2')
is_DDR3L= (self.features.get_par_value('MEMORY_TYPE')=='DDR3L')
is_DDR3_15= (self.features.get_par_value('MEMORY_TYPE')=='DDR3')
is_DDR3= is_DDR3_15 or is_DDR3L
is_DDR2= (self.features.get_par_value('MEMORY_TYPE')=='DDR2')
is_32= (self.features.get_par_value('BUS_WIDTH') > 16)
is_int_vref= self.features.get_par_value('INTERNAL_VREF')
# Set the IOB configuration as follows:
for reg_name in ('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1','ddriob_clock'):
ddriob_register_set.set_word(reg_name,0,force) # disable all
# ddriob_register_set.set_bitfields(reg_name,(('dco_type',0)),force,warn) # disable all - add other fields?
# 1. Set DCI_TYPE to DCI Drive for all LPDDR2 I/Os.
if is_LPDDR2:
for reg_name in (('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_diff0','ddriob_clock')
('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1','ddriob_clock'))[is_32]:
ddriob_register_set.set_bitfields(reg_name,(('dco_type',1)),force,warn)
# 2. Set DCI_TYPE to DCI Termination for DDR2/DDR3 bidirectional I/Os.
if is_DDR2 or is_DDR3:
for reg_name in (('ddriob_data0','ddriob_diff0'),
('ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1'))[is_32]:
ddriob_register_set.set_bitfields(reg_name,(('dci_type',3)),force,warn) # 3 - DCI term (DDR2/3/3L DQ, DQS'
# 3. Set OUTPUT_EN = obuf to enable outputs.
for reg_name in (('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_diff0','ddriob_clock'),
('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1','ddriob_clock'))[is_32]:
ddriob_register_set.set_bitfields(reg_name,(('output_en',3)),force,warn) # 3 - obuf
# 4. Set TERM_DISABLE_MODE and IBUF_DISABLE_MODE to enable power saving input modes. The
# TERM_DISABLE_MODE and IBUF_DISABLE_MODE fields should not be set before DDR training
# has completed.
# do nothing now
# 5. Set INP_TYPE to VREF based differential receiver for SSTL, HSTL for single ended inputs.
for reg_name in (('ddriob_data0'),
('ddriob_data0','ddriob_data1'))[is_32]:
ddriob_register_set.set_bitfields(reg_name,(('inp_type',1)),force,warn) # 1 - Vref based (sstl, hstl)
# 6. Set INP_TYPE to Differential input receiver for differential inputs.
for reg_name in (('ddriob_diff0'),
('ddriob_diff0','ddriob_diff1'))[is_32]:
ddriob_register_set.set_bitfields(reg_name,(('inp_type',2)),force,warn) # 2 - diff rcv
# 7. Set TERM_EN to enabled for DDR3 and DDR2 bidirectional I/Os (Outputs and LPRDDR2 IOs are
# un terminated).
if is_DDR2 or is_DDR3:
for reg_name in (('ddriob_data0','ddriob_diff0'),
('ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1'))[is_32]:
ddriob_register_set.set_bitfields(reg_name,(('term_en',1)),force,warn)
# 8. Set DDRIOB_DATA1 and DDRIOB_DIFF1 registers to power down if only 16 bits of DQ DDR are
# used (including ECC bits).
## TODO: find out - what "power down" means - bit 0? or other bits that are already set according tu bus width
# 9. For DDR2 and DDR3 – DCI only affects termination strength, so address and clock outputs do not
# use DCI.
# 10. For LPDDR2 – DCI affects drive strength, so all I/Os use DCI.
# To enable internal VREF
pass
# ° Set DDRIOB_DDR_CTRL.VREF_EXT_EN to 00 (disconnect I/Os from external signal)
if is_int_vref:
ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', ('vref_ext_en',0),force,warn)
# ° Set DDRIOB_DDR_CTRL.VREF_SEL to the appropriate voltage setting depending on the DDR
# standard (V REF=VCCO_DDR/2)
if is_LPDDR2:
vref_sel=1
elif is_DDR3L:
vref_sel=2
elif is_DDR3_15:
vref_sel=4
elif is_DDR2:
vref_sel=8
else:
print '*** Invalid memory type ***'
ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', ('vref_sel',vref_sel),force,warn)
# ° Set DDRIOB_DDR_CTRL.VREF_INT_EN to 1 to enable the internal VREF generator
ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', ('vref_int_en',1),force,warn)
# To enable external VREF
else: # if is_int_vref:
# ° Set DDRIOB_DDR_CTRL.VREF_INT_EN to 0 to disable the internal VREF generator
# ° Set DDRIOB_DDR_CTRL.VREF_SEL to 0000
# ° Set DDRIOB_DDR_CTRL.VREF_EXT_EN to 11 to connect the IOBs VREF input to the external
# pad for a 32-bit interface
# °Set DDRIOB_DDR_CTRL.VREF_EXT_EN to 01 to connect the IOBs VREF input to the external
# pad for a 16-bit interface
ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', (('vref_int_en',0),
('vref_sel',0),
('vref_ext_en',(1,3)[is_32])),force,warn)
#not in UG585, but used
ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', ('refio_en',1),force,warn)
#configuring drive strength/slew rate. Seems to be the same for addr and clock, and DQ and DQS
for reg_name in ('ddriob_drive_slew_addr','ddriob_drive_slew_clock'):
ddriob_register_set.set_bitfields(reg_name,(
('slew_n', self.features.get_par_value('OUT_SLEW_NEG')),
('slew_p', self.features.get_par_value('OUT_SLEW_POS')),
('drive_n',self.features.get_par_value('OUT_DRIVE_NEG')),
('drive_p',self.features.get_par_value('OUT_DRIVE_POS'))),force,warn) # 0xd6861c
for reg_name in ('ddriob_drive_slew_data','ddriob_drive_slew_diff'):
ddriob_register_set.set_bitfields(reg_name,(
('slew_n', self.features.get_par_value('BIDIR_SLEW_NEG')),
('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?)
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)
def parse_ddrc_raw_register_set(self,raw_configs,qualifier_char,force=True,warn=True):
# for i,attribs in enumerate(self.set_attribs):
for attribs in self.set_attribs:
for attribs in self.set_ddrc_attribs:
reg_set_name=attribs['NAME']
reg_set= self.register_sets[reg_set_name]
prefix= attribs['PREFIX']
postfix= attribs['POSTFIX']
reg_set.parse_options_set(raw_configs,prefix,postfix,self.postfixes,qualifier_char,force,warn) #force - readonly/undefined fields, warn: data does not fit in the bit field
def print_html_registers(self, html_file, show_bit_fields=True, show_comments=True):
for attribs in self.set_attribs:
def parse_ddriob_raw_register_set(self,raw_configs,qualifier_char,force=True,warn=True):
# for i,attribs in enumerate(self.set_attribs):
for attribs in self.set_ddriob_attribs:
reg_set_name=attribs['NAME']
reg_set= self.register_sets[reg_set_name]
prefix= attribs['PREFIX']
postfix= attribs['POSTFIX']
reg_set.parse_options_set(raw_configs,prefix,postfix,self.postfixes,qualifier_char,force,warn) #force - readonly/undefined fields, warn: data does not fit in the bit field
def print_ddrc_html_registers(self, html_file, show_bit_fields=True, show_comments=True,filter_fields=True):
for attribs in self.set_ddrc_attribs:
reg_set_name=attribs['NAME']
reg_set= self.ddrc_register_sets[reg_set_name]
if len(reg_set.get_reg_names())>0:
html_file.write('<h2>'+attribs['TITLE']+'</h2>\n')
reg_set.print_html_registers(html_file, show_bit_fields, show_comments,filter_fields)
html_file.write('<br/>\n')
def print_ddriob_html_registers(self, html_file, show_bit_fields=True, show_comments=True,filter_fields=True):
for attribs in self.set_ddrc_attribs:
reg_set_name=attribs['NAME']
reg_set= self.ddrc_register_sets[reg_set_name]
if len(reg_set.get_reg_names())>0:
html_file.write('<h2>'+attribs['TITLE']+'</h2>\n')
reg_set.print_html_registers(html_file, show_bit_fields, show_comments)
reg_set.print_html_registers(html_file, show_bit_fields, show_comments,filter_fields)
html_file.write('<br/>\n')
#ddr=Ezynq_DDR()
#print ddr.DDRC_DEFS
# def __init__(self,defines,channel=0,permit_undefined_bits=False):
# def parse_options_set(self,raw_configs,prefix,postfix,qualifier_char,force=True,warn=True): #force - readonly/undefined fields, warn: data does not fit in the bit field
\ No newline at end of file
......@@ -23,115 +23,116 @@ __email__ = "andrey@elphel.com"
__status__ = "Development"
# DDRC Registers
DDRC_DEFS={ #not all fields are defined currently
'BASE_ADDR':(0xF8006000,),
'ddrc_ctrl': {'OFFS': 0x000,'DFLT':0x00000200,'RW':'RW','FIELDS':{
'BASE_ADDR':(0xF8006000,),
'MODULE_NAME':('ddrc',),
'ddrc_ctrl': {'OFFS': 0x000,'DFLT':0x00000200,'RW':'RW','FIELDS':{ #0x81
'reg_ddrc_dis_auto_refresh':{'r':(16,16),'d':0,'c':'Dynamic. 1 - disable autorefresh'},
'reg_ddrc_dis_act_bypass': {'r':(15,15),'d':0,'c':'Debug. 1 - disable bypass for high priority read activity'},
'reg_ddrc_dis_rd_bypass': {'r':(14,14),'d':0,'c':'Debug. 1 - disable bypass for high priority read page hits'},
'reg_ddrc_dis_rd_bypass': {'r':( 7,13),'d':0x4,'c':'Switch to alternative transactions store after this inactivity'},
'reg_ddrc_rdwr_idle_gap': {'r':( 7,13),'d':0x4,'c':'Switch to alternative transactions store after this inactivity'}, #1
'reg_ddrc_burst8_refresh': {'r':( 4, 6),'d':0,'c':'Refresh accumulate: 0 - single refresh, 1 - burst of 2 refresh, 7 - burst of 8 refresh'},
'reg_ddrc_data_bus_width': {'r':( 2, 3),'d':0,'c':'DDR bus width: 0 - 32, 1 - 16, >=2 - reserved'},
'reg_ddrc_powerdown_en': {'r':( 1, 1),'d':0,'c':'Dynamic: 1 - enable power down on idle'},
'reg_ddrc_soft_rstb': {'r':( 0, 0),'d':0,'c':'Dynamic: Active low soft DDRC reset (and update non-dynamic registers/bit fields'}}},
'two_rank_cfg': {'OFFS': 0x004,'DFLT':0x000C1076,'RW':'RW','FIELDS':{
'reserved1': {'r':(28,28),'d':0,'c':'reserved'},
'reserved2': {'r':(27,27),'d':0,'c':'reserved'},
'reserved3': {'r':(22,26),'d':0,'c':'reserved'},
'reserved4': {'r':(21,21),'d':0,'c':'reserved'},
'reserved5': {'r':(19,20),'d':0x1,'c':'reserved'},
'reg_ddrc_addrmap_cs_ bit0':{'r':(14,18),'d':0x10,'c':'must be manually set to 0'},
'reserved6': {'r':(12,13),'d':0x1,'c':'reserved'},
'reg_ddrc_t_rfc_nom_x32': {'r':( 0,11),'d':0x76,'c':'Dynamic. tREFI, default set for DDR3'}}},
'hpr_reg': {'OFFS': 0x008,'DFLT':0x03C0780F,'RW':'RW','FIELDS':{
'reg_ddrc_soft_rstb': {'r':( 0, 0),'d':0,'c':'Dynamic: Active low soft DDRC reset (and update non-dynamic registers/bit fields'}}}, #1
'two_rank_cfg': {'OFFS': 0x004,'DFLT':0x000C1076,'RW':'RW','FIELDS':{ #0x81081
'reg_ddrc_addrmap_4bank_ram':{'r':(28,28),'d':0,'c':'reserved'},
'reg_ddrc_addrmap_open_bank':{'r':(27,27),'d':0,'c':'reserved'},
'reg_ddrc_addrmap_cs_bit1': {'r':(22,26),'d':0,'c':'reserved'},
'reg_ddrc_diff_rank_rd_2cycle_gap': {'r':(21,21),'d':0,'c':'reserved'},
'reg_ddrc_wr_odt_block': {'r':(19,20),'d':0x1,'c':'reserved'},
'reg_ddrc_addrmap_cs_bit0': {'r':(14,18),'d':0x10,'c':'must be manually set to 0'}, #0
'reg_ddrc_active_ranks': {'r':(12,13),'d':0x1,'c':'reserved'},
'reg_ddrc_t_rfc_nom_x32': {'r':( 0,11),'d':0x76,'c':'Dynamic. tREFI, default set for DDR3'}}}, #0x81
'hpr_reg': {'OFFS': 0x008,'DFLT':0x03C0780F,'RW':'RW','FIELDS':{ #0x3c0780f
'reg_ddrc_hpr_xact_run_length': {'r':(22,25),'d':0xF,'c':'HPR queue transactions to be served after going critical'},
'reg_ddrc_hpr_max_starve_x32': {'r':(11,21),'d':0xF,'c':'Number of 32x clocks HPR may be starved before going critical'},
'reg_ddrc_hpr_min_non_critical_x32':{'r':( 0,10),'d':0xF,'c':'Number off 32x clocks HPR queue is guaranteed to be non-critical'}}},
'lpr_reg': {'OFFS': 0x00C,'DFLT':0x03C0780F,'RW':'RW','FIELDS':{
'reg_ddrc_lpr_xact_run_length': {'r':(22,25),'d':0xF,'c':'LPR queue transactions to be served after going critical'},
'reg_ddrc_lpr_max_starve_x32': {'r':(11,21),'d':0xF,'c':'Number of 32x clocks LPR may be starved before going critical'},
'reg_ddrc_lpr_min_non_critical_x32':{'r':( 0,10),'d':0xF,'c':'Number off 32x clocks LPR queue is guaranteed to be non-critical'}}},
'wr_reg': {'OFFS': 0x010,'DFLT':0x0007F80F,'RW':'RW','FIELDS':{
'reg_ddrc_w_max_starve_x32': {'r':(15,25),'d':0xF,'c':'Number of 32x clocks write queue may be starved before going critical'},
'reg_ddrc_w_xact_run_length': {'r':(11,14),'d':0xF,'c':'write queue transactions to be served after going critical'},
'reg_ddrc_w_min_non_critical_x32': {'r':( 0,10),'d':0xF,'c':'Number off 32x clocks write queue is guaranteed to be non-critical'}}},
'dram_param_reg0': {'OFFS': 0x014,'DFLT':0x00041016,'RW':'RW','FIELDS':{
'reg_ddrc_post_selfref_ gap_x32': {'r':(14,20),'d':0x10,'c':'DRAM-related, minimal time after self refresh'},
'reg_ddrc_t_rfc_min': {'r':( 6,15),'d':0x40,'c':'Dynamic, tRFC'},
'reg_ddrc_t_rc': {'r':( 0, 5),'d':0x16,'c':'DRAM-related tRC'}}},
'dram_param_reg1': {'OFFS': 0x018,'DFLT':0x351B48D9,'RW':'RW','FIELDS':{
'reg_ddrc_t_cke': {'r':(28,31),'d': 0x3,'c':'tCKE'},
'reg_ddrc_t_ras_min': {'r':(22,26),'d': 0x14,'c':'tRAS min (clocks)'},
'reg_ddrc_t_ras_max': {'r':(16,21),'d': 0x1b,'c':'tRAS max (x1024 clocks)'},
'reg_ddrc_t_faw': {'r':(10,15),'d': 0x12,'c':'tFAW (not more than 4 banks activated in this rolling time, clocks'},
'reg_ddrc_powerdown_ to_x32': {'r':( 5, 9),'d': 0x6,'c':'power down after this many clocks of NOP/DESELECT (if enabled in mcr)'},
'reg_ddrc_wr2pre': {'r':( 0, 4),'d': 0x19,'c':'minimal write-to-precharge, clocks'}}},
'dram_param_reg2': {'OFFS': 0x01C,'DFLT':0x83015904,'RW':'RW','FIELDS':{
'reg_ddrc_t_rcd': {'r':(28,31),'d': 0x8,'c':'tRCD-AL'},
'reg_ddrc_rd2pre': {'r':(23,27),'d': 0x6,'c':'Read to precharge in the same bank'},
'reg_ddrc_pad_pd': {'r':(20,22),'d': 0x0,'c':'non-DFI only: pads in/out powersave, in clocks'},
'reg_ddrc_t_xp': {'r':(15,19),'d': 0x2,'c':'tXP - power down exit to any operation'},
'reg_ddrc_wr2rd': {'r':(10,13),'d': 0x16,'c':'tWTR - write -to -read (clocks)'},
'reg_ddrc_rd2wr': {'r':( 5, 9),'d': 0x8,'c':'tRTW - read -to -write (clocks)'},
'reg_ddrc_write_latency': {'r':( 0, 4),'d': 0x4,'c':'one clock less than actual DDR write latency'}}},
'dram_param_reg3': {'OFFS': 0x020,'DFLT':0x250882D0,'RW':'M','FIELDS':{
'reserved': {'r':(31,31),'d': 0,'c':'reserved'},
'lpr_reg': {'OFFS': 0x00C,'DFLT':0x03C0780F,'RW':'RW','FIELDS':{ #0x2001001
'reg_ddrc_lpr_xact_run_length': {'r':(22,25),'d':0xF,'c':'LPR queue transactions to be served after going critical'}, # 0x8
'reg_ddrc_lpr_max_starve_x32': {'r':(11,21),'d':0xF,'c':'Number of 32x clocks LPR may be starved before going critical'}, # 0x2
'reg_ddrc_lpr_min_non_critical_x32':{'r':( 0,10),'d':0xF,'c':'Number off 32x clocks LPR queue is guaranteed to be non-critical'}}}, #0x1
'wr_reg': {'OFFS': 0x010,'DFLT':0x0007F80F,'RW':'RW','FIELDS':{ #0x14001
'reg_ddrc_w_max_starve_x32': {'r':(15,25),'d':0xF,'c':'Number of 32x clocks write queue may be starved before going critical'},#0 x2 # opposite sequence from HPR,LPR
'reg_ddrc_w_xact_run_length': {'r':(11,14),'d':0xF,'c':'write queue transactions to be served after going critical'}, # 0x8
'reg_ddrc_w_min_non_critical_x32': {'r':( 0,10),'d':0xF,'c':'Number off 32x clocks write queue is guaranteed to be non-critical'}}}, # 0x2
'dram_param_reg0': {'OFFS': 0x014,'DFLT':0x00041016,'RW':'RW','FIELDS':{ # 0x4281a
'reg_ddrc_post_selfref_gap_x32': {'r':(14,20),'d':0x10,'c':'DRAM-related, minimal time after self refresh'}, #0x10
'reg_ddrc_t_rfc_min': {'r':( 6,15),'d':0x40,'c':'Dynamic, tRFC'}, #0xa0
'reg_ddrc_t_rc': {'r':( 0, 5),'d':0x16,'c':'DRAM-related tRC'}}}, #0x1a
'dram_param_reg1': {'OFFS': 0x018,'DFLT':0x351B48D9,'RW':'RW','FIELDS':{ # 0x44e458d2
'reg_ddrc_t_cke': {'r':(28,31),'d': 0x3,'c':'tCKE'}, #0x4
'reg_ddrc_t_ras_min': {'r':(22,26),'d': 0x14,'c':'tRAS min (clocks)'},#0x13
'reg_ddrc_t_ras_max': {'r':(16,21),'d': 0x1b,'c':'tRAS max (x1024 clocks)'},#0x24
'reg_ddrc_t_faw': {'r':(10,15),'d': 0x12,'c':'tFAW (not more than 4 banks activated in this rolling time, clocks'}, #0x16
'reg_ddrc_powerdown_to_x32': {'r':( 5, 9),'d': 0x6,'c':'power down after this many clocks of NOP/DESELECT (if enabled in mcr)'}, #0x6
'reg_ddrc_wr2pre': {'r':( 0, 4),'d': 0x19,'c':'minimal write-to-precharge, clocks'}}}, # 0x12
'dram_param_reg2': {'OFFS': 0x01C,'DFLT':0x83015904,'RW':'RW','FIELDS':{ # 0x720238e5
'reg_ddrc_t_rcd': {'r':(28,31),'d': 0x8,'c':'tRCD-AL'}, #0x7
'reg_ddrc_rd2pre': {'r':(23,27),'d': 0x6,'c':'Read to precharge in the same bank'}, #0x4
'reg_ddrc_pad_pd': {'r':(20,22),'d': 0x0,'c':'non-DFI only: pads in/out powersave, in clocks'}, #0x0
'reg_ddrc_t_xp': {'r':(15,19),'d': 0x2,'c':'tXP - power down exit to any operation'}, #0x4
'reg_ddrc_wr2rd': {'r':(10,13),'d': 0x16,'c':'tWTR - write -to -read (clocks)'}, #0xe
'reg_ddrc_rd2wr': {'r':( 5, 9),'d': 0x8,'c':'tRTW - read -to -write (clocks)'}, #0x7
'reg_ddrc_write_latency': {'r':( 0, 4),'d': 0x4,'c':'one clock less than actual DDR write latency'}}}, #0x5
'dram_param_reg3': {'OFFS': 0x020,'DFLT':0x250882D0,'RW':'M','FIELDS':{ #272872d0
'reg_ddrc_loopback': {'r':(31,31),'d': 0,'c':'reserved'},
'reg_ddrc_dis_pad_pd': {'r':(30,30),'d': 0,'c':'Disable pad power down'},
'reg_phy_mode_ddr1_d dr2': {'r':(29,29),'d': 1,'c':'Unused'},
'reg_ddrc_read_latency': {'r':(24,28),'d': 0x5,'c':'Read Latency, clocks'},
'reg_phy_mode_ddr1_ddr2': {'r':(29,29),'d': 1,'c':'Unused'}, # 0x1
'reg_ddrc_read_latency': {'r':(24,28),'d': 0x5,'c':'Read Latency, clocks'}, # 0x7
'reg_ddrc_en_dfi_dram_clk_disable': {'r':(23,23),'d': 0,'c':'Enables clock disable...'},
'reg_ddrc_mobile': {'r':(22,22),'d': 0,'c':'0 - DDR2/DDR3, 1 - LPDDR2'},
'reserved1': {'r':(21,21),'d': 0,'c':'reserved'},
'reg_ddrc_mobile': {'r':(22,22),'d': 0,'c':'0 - DDR2/DDR3, 1 - LPDDR2'},
'reg_ddrc_sdram': {'r':(21,21),'d': 0,'c':'reserved'}, # 0x1
'reg_ddrc_refresh_to_x32': {'r':(16,20),'d': 0x8,'c':'Dynamic, "speculative refresh"'},
'reg_ddrc_t_rp': {'r':(12,15),'d': 0x8,'c':'tRP'},
'reg_ddrc_refresh_margin': {'r':( 8,11),'d': 0x2,'c':'do refresh this cycles before timer expires'},
'reg_ddrc_t_rp': {'r':(12,15),'d': 0x8,'c':'tRP'}, # 0x7
'reg_ddrc_refresh_margin': {'r':( 8,11),'d': 0x2,'c':'do refresh this cycles before timer expires'},
'reg_ddrc_t_rrd': {'r':( 5, 7),'d': 0x6,'c':'tRRD Minimal time between activates of different banks'},
'reg_ddrc_t_ccd': {'r':( 2, 4),'d': 0x4,'c':'tCCD One less than minimal time between reads of writes to different banks'},
'reserved2': {'r':( 0, 1),'d': 0,'m':'R','c':'reserved'}}},
'dram_param_reg4': {'OFFS': 0x024,'DFLT':0x0000003C,'RW':'M','FIELDS':{
'dram_param_reg4': {'OFFS': 0x024,'DFLT':0x0000003C,'RW':'M','FIELDS':{ #0x3c
'reg_ddrc_mr_rdata_valid': {'r':(27,27),'d': 0,'m':'R','c':'cleared by reading mode_reg_read (0x2a4), set when mode_reg_read gets new data'},
'reg_ddrc_mr_type': {'r':(26,26),'d': 0,'c':'0 - mode register write, 1 - mode register read'},
'ddrc_reg_mr_wr_busy': {'r':(25,25),'d': 0,'m':'R','c':'1 - do not issue mode register R/W (wait 0)'},
'reg_ddrc_mr_data': {'r':( 9,24),'d': 0,'c':'DDR2/3: Mode Register Write data'},
'reg_ddrc_mr_addr': {'r':( 7, 8),'d': 0,'c':'DDR2/3: Mode Register address (0 - MR0, ... 3 - MR3)'},
'reg_ddrc_mr_wr': {'r':( 6, 6),'d': 0,'m':'W','c':'low-to-high starts mode reg r/w (if not ddrc_reg_mr_wr_busy)'},
'reserved1': {'r':( 2, 5),'d': 0xF,'c':'reserved'},
'reg_ddrc_max_rank_rd': {'r':( 2, 5),'d': 0xF,'c':'reserved'},
'reg_ddrc_prefer_write': {'r':( 1, 1),'d': 0,'c':'1: Bank selector prefers writes over reads'},
'reg_ddrc_en_2t_timing_mode': {'r':( 0, 0),'d': 0,'c':'0 - DDRC uses 1T timing, 1 - 2T timing'}}},
'dram_init_param': {'OFFS': 0x028,'DFLT':0x00002007,'RW':'RW','FIELDS':{
'dram_init_param': {'OFFS': 0x028,'DFLT':0x00002007,'RW':'RW','FIELDS':{ # 0x2007
'reg_ddrc_t_mrd': {'r':(11,13),'d': 0x4,'c':'tMRD - cycles between Load Mode commands (default is set for DDR3)'},
'reg_ddrc_pre_ocd_x32': {'r':( 7,10),'d': 0,'c':'OCD complete delay (may be 0)'},
'reg_ddrc_final_wait_x32': {'r':( 0, 6),'d': 0x7,'c':'Wait after DDR INIT (set for DDR3)'}}},
'dram_emr_reg': {'OFFS': 0x02C,'DFLT':0x00000008,'RW':'RW','FIELDS':{
'dram_emr_reg': {'OFFS': 0x02C,'DFLT':0x00000008,'RW':'RW','FIELDS':{ # 0x8
'reg_ddrc_emr3': {'r':(16,31),'d': 0,'c':'DDR3: Value loaded into MR3 reg, DDR2: EMR3, LPDDR2 - unused'},
'reg_ddrc_emr2': {'r':( 0,15),'d': 0x8,'c':'DDR3: Value loaded into MR2 reg, DDR2: EMR2, LPDDR2 - MR3'}}},
'dram_emr_mr_reg': {'OFFS': 0x030,'DFLT':0x00000940,'RW':'RW','FIELDS':{
'reg_ddrc_emr': {'r':(16,31),'d': 0,'c':'DDR3: Value loaded into MR1 reg, DDR2: EMR1, LPDDR2 - MR2'},
'reg_ddrc_mr': {'r':( 0,15),'d': 0x940,'c':'DDR3: Value loaded into MR0 reg, DDR2: MR, LPDDR2 - MR1'}}},
'dram_emr_mr_reg': {'OFFS': 0x030,'DFLT':0x00000940,'RW':'RW','FIELDS':{ # 0x40930
'reg_ddrc_emr': {'r':(16,31),'d': 0,'c':'DDR3: Value loaded into MR1 reg, DDR2: EMR1, LPDDR2 - MR2'}, # 0x4
'reg_ddrc_mr': {'r':( 0,15),'d': 0x940,'c':'DDR3: Value loaded into MR0 reg, DDR2: MR, LPDDR2 - MR1'}}}, # 0x930
'dram_burst8_rdwr': {'OFFS': 0x034,'DFLT':0x00020304,'RW':'M','FIELDS':{
'dram_burst8_rdwr': {'OFFS': 0x034,'DFLT':0x00020304,'RW':'M','FIELDS':{ # 0x10694
'reg_ddrc_burstchop': {'r':(28,28),'d':0,'c':' Not supported, 1 - burstchop mode'},
'reserved1': {'r':(26,27),'d':0,'m':'R','c':'reserved'},
'reg_ddrc_post_cke_x1024': {'r':(16,25),'d':0x2,'c':'CKE high to initialization'},
'reg_ddrc_post_cke_x1024': {'r':(16,25),'d':0x2,'c':'CKE high to initialization'}, # 0x1
'reserved2': {'r':(15,14),'d':0,'m':'R','c':'reserved'},
'reg_ddrc_post_cke_x1024': {'r':( 4,13),'d':0x3,'c':'soft reset to CKE high'},
'reg_ddrc_pre_cke_x1024': {'r':( 4,13),'d':0x3,'c':'soft reset to CKE high'}, #0x69
'reg_ddrc_burst_rdwr': {'r':( 0, 3),'d':0x4,'c':'2 - burst length 4, 4 - b.l. 8, 0x10 - b.l. 16, others reserved'}}},
'dram_disable_dq': {'OFFS': 0x038,'DFLT':0x00000000,'RW':'M','FIELDS':{
'reserved1': {'r':( 9,12),'d':0,'c':'reserved'},
'reserved2': {'r':( 8, 8),'d':0,'c':'reserved'},
'reserved3': {'r':( 7, 7),'d':0,'c':'reserved'},
'reserved4': {'r':( 6, 6),'d':0,'c':'reserved'},
'dram_disable_dq': {'OFFS': 0x038,'DFLT':0x00000000,'RW':'M','FIELDS':{ # 0
'reg_phy_dq0_wait_t': {'r':( 9,12),'d':0,'c':'reserved'},
'reg_phy_rd_level_start': {'r':( 8, 8),'d':0,'c':'reserved'},
'reg_phy_wr_level_start': {'r':( 7, 7),'d':0,'c':'reserved'},
'reg_phy_debug_mode': {'r':( 6, 6),'d':0,'c':'reserved'},
'reserved5': {'r':( 2, 5),'d':0,'m':'R','c':''},
'reg_ddrc_dis_dq': {'r':( 1, 1),'d':0,'c':'Dynamic, debug. Stop dequeue transactions, no DDR operations'},
'reg_ddrc_force_low_pri_n': {'r':( 0, 0),'d':0,'c':'0 - read transactions low priority (1 - high read priority if enabled in AXI pri read)'}}},
'dram_addr_map_bank': {'OFFS': 0x03C,'DFLT':0x00000F77,'RW':'RW','FIELDS':{
'dram_addr_map_bank': {'OFFS': 0x03C,'DFLT':0x00000F77,'RW':'RW','FIELDS':{ #0x777
'reg_ddrc_addrmap_col_b6': {'r':(16,19),'d':0,'c':'Selects address bits for column address bit 7, half bus width - column address bits 8, int. base=9'},
'reg_ddrc_addrmap_col_b5': {'r':(12,15),'d':0,'c':'Selects address bits for column address bit 6, half bus width - column address bits 7, int. base=8'},
'reg_ddrc_addrmap_ba nk_b2': {'r':( 8,11),'d':0xf,'c':'Selects AXI address bit for bank2. Valid 0..15. Int. base=7. If 15, bank2 is set to 0'},
'reg_ddrc_addrmap_ba nk_b2': {'r':( 8,11),'d':0xf,'c':'Selects AXI address bit for bank2. Valid 0..15. Int. base=7. If 15, bank2 is set to 0'}, #7
'reg_ddrc_addrmap_ba nk_b2': {'r':( 4, 7),'d':0x7,'c':'Selects AXI address bit for bank1. Valid 0..14. Int. base=6.'},
'reg_ddrc_addrmap_ba nk_b2': {'r':( 0, 3),'d':0x7,'c':'Selects AXI address bit for bank0. Valid 0..14. Int. base=5.'}}},
'dram_addr_map_col': {'OFFS': 0x040,'DFLT':0xFFF00000,'RW':'RW','FIELDS':{
'dram_addr_map_col': {'OFFS': 0x040,'DFLT':0xFFF00000,'RW':'RW','FIELDS':{ # 0xfff00000
'reg_ddrc_addrmap_col_b11': {'r':(28,31),'d':0xF,'c':'Selects address bits for col. addr. bit 13 (LP - 12), Valid 0..7 and 15, half width - unused (LP-13), int. base=14'},
'reg_ddrc_addrmap_col_b10': {'r':(24,27),'d':0xF,'c':'Selects address bits for col. addr. bit 12 (LP - 11), Valid 0..7 and 15, half width - 13 (LP-12), int. base=13'},
'reg_ddrc_addrmap_col_b9': {'r':(20,23),'d':0xF,'c':'Selects address bits for col. addr. bit 11 (LP - 10), Valid 0..7 and 15, half width - 12 (LP-11), int. base=12'},
......@@ -140,27 +141,27 @@ DDRC_DEFS={ #not all fields are defined currently
'reg_ddrc_addrmap_col_b4': {'r':( 8,11),'d':0,'c':'Selects address bits for col. addr. bit 5, Valid 0..7, half width - bit 6, int. base=7'},
'reg_ddrc_addrmap_col_b3': {'r':( 4, 7),'d':0,'c':'Selects address bits for col. addr. bit 4, Valid 0..7, half width - bit 5, int. base=6'},
'reg_ddrc_addrmap_col_b2': {'r':( 0, 3),'d':0,'c':'Selects address bits for col. addr. bit 3, Valid 0..7, half width - bit 4, int. base=5'}}},
'dram_addr_map_row': {'OFFS': 0x044,'DFLT':0x0FF55555,'RW':'RW','FIELDS':{
'reg_ddrc_addrmap_row_b15': {'r':(24,27),'d':0xF,'c':'Selects address bits for row. addr. bit 15, Valid 0..5 and 15, int. base=24 if 15 - address bit 15 is set to 0'},
'reg_ddrc_addrmap_row_b14': {'r':(20,23),'d':0xF,'c':'Selects address bits for row. addr. bit 14, Valid 0..6 and 15, int. base=23 if 15 - address bit 14 is set to 0'},
'reg_ddrc_addrmap_row_b13': {'r':(16,19),'d':0x5,'c':'Selects address bits for row. addr. bit 13, Valid 0..7 and 15, int. base=22 if 15 - address bit 13 is set to 0'},
'reg_ddrc_addrmap_row_b12': {'r':(12,15),'d':0x5,'c':'Selects address bits for row. addr. bit 12, Valid 0..8 and 15, int. base=21 if 15 - address bit 12 is set to 0'},
'reg_ddrc_addrmap_row_b2_11': {'r':( 8,11),'d':0x5,'c':'Selects address bits for row. addr. bits 2 to 11, Valid 0..11, int. base=11 (for a2) to 20 (for a 11)'},
'reg_ddrc_addrmap_row_b1': {'r':( 4, 7),'d':0x5,'c':'Selects address bits for row. addr. bit 1, Valid 0..11, int. base=10'},
'reg_ddrc_addrmap_row_b0': {'r':( 0, 3),'d':0x5,'c':'Selects address bits for row. addr. bit 0, Valid 0..11, int. base=9'}}},
'dram_addr_map_row': {'OFFS': 0x044,'DFLT':0x0FF55555,'RW':'RW','FIELDS':{ # 0xf666666
'reg_ddrc_addrmap_row_b15': {'r':(24,27),'d':0xF,'c':'Selects address bits for row. addr. bit 15, Valid 0..5 and 15, int. base=24 if 15 - address bit 15 is set to 0'}, # 0xf
'reg_ddrc_addrmap_row_b14': {'r':(20,23),'d':0xF,'c':'Selects address bits for row. addr. bit 14, Valid 0..6 and 15, int. base=23 if 15 - address bit 14 is set to 0'}, # 0x6
'reg_ddrc_addrmap_row_b13': {'r':(16,19),'d':0x5,'c':'Selects address bits for row. addr. bit 13, Valid 0..7 and 15, int. base=22 if 15 - address bit 13 is set to 0'}, # 0x6
'reg_ddrc_addrmap_row_b12': {'r':(12,15),'d':0x5,'c':'Selects address bits for row. addr. bit 12, Valid 0..8 and 15, int. base=21 if 15 - address bit 12 is set to 0'}, # 0x6
'reg_ddrc_addrmap_row_b2_11': {'r':( 8,11),'d':0x5,'c':'Selects address bits for row. addr. bits 2 to 11, Valid 0..11, int. base=11 (for a2) to 20 (for a 11)'}, # 0x6
'reg_ddrc_addrmap_row_b1': {'r':( 4, 7),'d':0x5,'c':'Selects address bits for row. addr. bit 1, Valid 0..11, int. base=10'}, # 0x6
'reg_ddrc_addrmap_row_b0': {'r':( 0, 3),'d':0x5,'c':'Selects address bits for row. addr. bit 0, Valid 0..11, int. base=9'}}}, # 0x6
'dram_odt_reg': {'OFFS': 0x048,'DFLT':0x00000249,'RW':'RW','FIELDS':{
'reserved1': {'r':(29,27),'d':0,'c':'reserved'},
'reserved2': {'r':(24,26),'d':0,'c':'reserved'},
'reserved3': {'r':(21,23),'d':0,'c':'reserved'},
'reserved4': {'r':(18,20),'d':0,'c':'reserved'},
'reg_phy_idle_local_odt': {'r':(16,17),'d':0,'c':'2-bit drive ODT when OE is inactive and no read (power save)'},
'reg_phy_wr_local_odt': {'r':(14,15),'d':0,'c':'ODT strength during write leveling'},
'dram_odt_reg': {'OFFS': 0x048,'DFLT':0x00000249,'RW':'RW','FIELDS':{ # 0x3c248
'reg_ddrc_rank3_wr_odt': {'r':(29,27),'d':0,'c':'reserved'},
'reg_ddrc_rank3_rd_odt': {'r':(24,26),'d':0,'c':'reserved'},
'reg_ddrc_rank2_wr_odt': {'r':(21,23),'d':0,'c':'reserved'},
'reg_ddrc_rank2_rd_odt': {'r':(18,20),'d':0,'c':'reserved'},
'reg_phy_idle_local_odt': {'r':(16,17),'d':0,'c':'2-bit drive ODT when OE is inactive and no read (power save)'}, # 0x3
'reg_phy_wr_local_odt': {'r':(14,15),'d':0,'c':'ODT strength during write leveling'}, #0x3
'reg_phy_rd_local_odt': {'r':(12,13),'d':0,'c':'ODT strength during read'},
'reserved5': {'r':( 9,11),'d':0x1,'c':'reserved'},
'reserved6': {'r':( 6, 8),'d':0x1,'c':'reserved'},
'reserved7': {'r':( 3, 5),'d':0x1,'c':'reserved'},
'reserved8': {'r':( 0, 2),'d':0x1,'c':'reserved'}}},
'reg_ddrc_rank1_wr_odt': {'r':( 9,11),'d':0x1,'c':'reserved'},
'reg_ddrc_rank1_rd_odt': {'r':( 6, 8),'d':0x1,'c':'reserved'},
'reg_ddrc_rank0_wr_odt': {'r':( 3, 5),'d':0x1,'c':'reserved'},
'reg_ddrc_rank0_rd_odt': {'r':( 0, 2),'d':0x1,'c':'reserved'}}}, # 0x0
'phy_dbg_reg': {'OFFS': 0x04C,'DFLT':0x00000000,'RW':'R','FIELDS':{
'phy_reg_bc_fifo_re3': {'r':(19,19),'d':0,'m':'R','c':'Debug read capture FIFO read enable for data slice 3'},
'phy_reg_bc_fifo_we3': {'r':(18,18),'d':0,'m':'R','c':'Debug read capture FIFO write enable for data slice 3'},
......@@ -179,9 +180,9 @@ DDRC_DEFS={ #not all fields are defined currently
'phy_reg_bc_dqs_oe0': {'r':( 5, 5),'d':0,'m':'R','c':'Debug DQS output enable for data slice 0'},
'phy_reg_bc_dq_oe0': {'r':( 4, 4),'d':0,'m':'R','c':'Debug DQ output enable for data slice 0'},
'phy_reg_rdc_fifo_rst_err_cnt': {'r':( 0, 3),'d':0,'m':'R','c':'FIFO read pointers mismatch counter'}}},
'phy_cmd_timeout_rddata_cpt':{'OFFS': 0x050,'DFLT':0x00010200,'RW':'M','FIELDS':{
'reg_phy_wrlvl_num_of_dq0': {'r':(28,31),'d':0,'c':'Number of sample for ratio increment during write leveling (recommended 8)'},
'reg_phy_gatelvl_num_of_dq0': {'r':(24,27),'d':0,'c':'Number of sample for ratio increment during gate training (recommended 8)'},
'phy_cmd_timeout_rddata_cpt':{'OFFS': 0x050,'DFLT':0x00010200,'RW':'M','FIELDS':{ # 0x77010800
'reg_phy_wrlvl_num_of_dq0': {'r':(28,31),'d':0,'c':'Number of sample for ratio increment during write leveling (recommended 8)'},# 0x7
'reg_phy_gatelvl_num_of_dq0': {'r':(24,27),'d':0,'c':'Number of sample for ratio increment during gate training (recommended 8)'}, # 0x7
'reserved1': {'r':(20,23),'d':0,'m':'R','c':'reserved'},
'reg_phy_clk_stall_level': {'r':(19,19),'d':0,'c':'1- Stall clock for DLL aging control'},
'reg_phy_dis_phy_ctrl_rstn': {'r':(18,18),'d':0,'c':'1 - disable reset to PHY control'},
......@@ -189,7 +190,7 @@ DDRC_DEFS={ #not all fields are defined currently
'reg_phy_use_fixed_re': {'r':(16,16),'d':0x1,'c':'... (should be high during training/leveling'},
'reg_phy_rdc_fifo_rst_disable': {'r':(15,15),'d':0,'c':'1 - disable counting phy_dbg_reg.phy_reg_rdc_fifo_rst_err_cnt'},
'reserved2': {'r':(12,14),'d':0,'m':'R','c':'reserved'},
'reg_phy_rdc_we_to_re_delay': {'r':( 8,11),'d':0x2,'c':'use for fixed delay, when reg_phy_use_fixed_re==1'},
'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':{
......@@ -198,16 +199,16 @@ DDRC_DEFS={ #not all fields are defined currently
'ddrc_reg_dbg_wr_q_depth': {'r':( 4, 9),'d':0,'m':'R','c':'number in write CAM '},
'ddrc_reg_dbg_stall': {'r':( 3, 3),'d':0,'m':'R','c':'1 - commands accepted by controller'},
'ddrc_reg_operating_mode': {'r':( 0, 2),'d':0,'m':'R','c':'DDRC init, 1 - normal, 2 - power down, 3 - self refresh, >=4 - deep power down LPDDR2'}}},
'dll_calib': {'OFFS': 0x058,'DFLT':0x00000101,'RW':'RW','FIELDS':{
'dll_calib': {'OFFS': 0x058,'DFLT':0x00000101,'RW':'RW','FIELDS':{ # 0x101
'reg_ddrc_dis_dll_calib': {'r':(16,16),'d':0,'c':'Dynamic: 1- disable DLL_calib, 0 - issue DLL_calib periodically'},
'reserved1': {'r':( 8,15),'d':0,'c':'reserved'},
'reserved2': {'r':( 0, 7),'d':0,'c':'reserved'}}},
'odt_delay_hold': {'OFFS': 0x05C,'DFLT':0x00000023,'RW':'RW','FIELDS':{
'reg_ddrc_wr_odt_hold': {'r':(12,15),'d':0,'c':'(Cycles to hold ODT for write command-1). For burst4 - 2, for burst8 - 4'},
'reg_ddrc_dll_calib_to_max_x1024': {'r':( 8,15),'d':0x1,'c':'reserved'},
'reg_ddrc_dll_calib_to_min_x1024': {'r':( 0, 7),'d':0x1,'c':'reserved'}}},
'odt_delay_hold': {'OFFS': 0x05C,'DFLT':0x00000023,'RW':'RW','FIELDS':{ # 0x5003
'reg_ddrc_wr_odt_hold': {'r':(12,15),'d':0,'c':'(Cycles to hold ODT for write command-1). For burst4 - 2, for burst8 - 4'}, # 0x5
'reg_ddrc_rd_odt_hold': {'r':( 8,11),'d':0,'c':'unused'},
'reg_ddrc_wr_odt_delay': {'r':( 4, 7),'d':0x2,'c':'From issuing write to setting ODT for write. Recommended for DDR3 - 0, for DDR2 (WL-5)'},
'reg_ddrc_wr_odt_delay': {'r':( 4, 7),'d':0x2,'c':'From issuing write to setting ODT for write. Recommended for DDR3 - 0, for DDR2 (WL-5)'}, # 0
'reg_ddrc_rd_odt_delay': {'r':( 0, 3),'d':0x3,'c':'unused'}}},
'ctrl_reg1': {'OFFS': 0x060,'DFLT':0x0000003E,'RW':'M','FIELDS':{
'ctrl_reg1': {'OFFS': 0x060,'DFLT':0x0000003E,'RW':'M','FIELDS':{ #0x3e
'reg_ddrc_selfref_en': {'r':(12,12),'d':0,'c':'Dynamic - 1 - go to Self Refresh when transaction store is empty'},
'reserved1': {'r':(11,11),'d':0,'m':'R','c':'reserved'},
'reg_ddrc_dis_collision_page_opt': {'r':(10,10),'d':0,'c':'Disable autoprecharge for collisions (write+write or read+write to the same address) when reg_ddrc_dis_wc==1'},
......@@ -216,29 +217,29 @@ DDRC_DEFS={ #not all fields are defined currently
'reg_ddrc_auto_pre_en': {'r':( 7, 7),'d':0,'c':'1 - most R/W will be with autoprecharge'},
'reg_ddrc_lpr_num_entries': {'r':( 1, 6),'d':0x1F,'c':'(bit 6 ignored) (Size of low priority transaction store+1). HPR - 32 - this value'},
'reg_ddrc_pageclose': {'r':( 0, 0),'d':0,'c':'1 - close bank if no transactions in the store for it, 0 - keep open until not needed by other'}}},
'ctrl_reg2': {'OFFS': 0x064,'DFLT':0x00020000,'RW':'M','FIELDS':{
'ctrl_reg2': {'OFFS': 0x064,'DFLT':0x00020000,'RW':'M','FIELDS':{ # 0x20000
'reg_arb_go2critical_en': {'r':(17,17),'d':0x1,'c':'0 - ignore "urgent" from AXI master, 1 - grant'},
'reserved1': {'r':(13,16),'d':0,'m':'R','c':'reserved'},
'reg_ddrc_go2critical_hysteresis': {'r':( 5,12),'d':0,'c':'Latency of moving to critical state'},
'reserved2': {'r':( 0, 4),'d':0,'m':'R','c':'reserved'}}},
'ctrl_reg3': {'OFFS': 0x068,'DFLT':0x00284027,'RW':'RW','FIELDS':{ # in code it was called 'rd_dll_force' TODO: Update hardware.h
'reg_ddrc_dfi_t_wlmrd': {'r':(16,25),'d':0x28,'c':'DDR3 only: tMLRD from DRAM specs'},
'reg_ddrc_rdlvl_rr': {'r':( 8,15),'d':0x40,'c':'DDR3 read leveling read-to-read delay'},
'reg_ddrc_wrlvl_ww': {'r':( 0, 7),'d':0x27,'c':'DDR3 and LPDDR2 - write leveling write-to-write delay'}}},
'ctrl_reg4': {'OFFS': 0x06C,'DFLT':0x00001610,'RW':'RW','FIELDS':{ # in code it was called 'rd_dll_force0'
'ctrl_reg3': {'OFFS': 0x068,'DFLT':0x00284027,'RW':'RW','FIELDS':{ # 0x284141 TODO: Update hardware.h
'reg_ddrc_dfi_t_wlmrd': {'r':(16,25),'d':0x28,'c':'DDR3 only: tMLRD from DRAM specs'},
'reg_ddrc_rdlvl_rr': {'r':( 8,15),'d':0x40,'c':'DDR3 read leveling read-to-read delay'}, #0x41
'reg_ddrc_wrlvl_ww': {'r':( 0, 7),'d':0x27,'c':'DDR3 and LPDDR2 - write leveling write-to-write delay'}}}, #0x41
'ctrl_reg4': {'OFFS': 0x06C,'DFLT':0x00001610,'RW':'RW','FIELDS':{ # 0x610 in code it was called 'rd_dll_force0'
'dfi_t_ctrlupd_interval_max_x1024': {'r':( 8,15),'d':0x16,'c':'maximal time between DFI update requests in 1024 clocks'},
'dfi_t_ctrlupd_interval_min_x1024': {'r':( 0, 7),'d':0x10,'c':'minimal time between DFI update requests in 1024 clocks'}}},
'rd_dll_force1': {'OFFS': 0x070},
'wr_ratio_reg': {'OFFS': 0x074},
'ctrl_reg5': {'OFFS': 0x078,'DFLT':0x00455111,'RW':'M','FIELDS':{# in code it was called 'rd_ratio_reg'
'ctrl_reg5': {'OFFS': 0x078,'DFLT':0x00455111,'RW':'M','FIELDS':{# 0x466111 in code it was called 'rd_ratio_reg'
'reserved1': {'r':(26,31),'d':0,'m':'R','c':'reserved'},
'reg_ddrc_t_ckesr': {'r':(20,25),'d':0x4,'c':'Min CKE low for self refresh, recomm.: DDR3:tCKE+1,DDR2:tCKE,LPDDR2:tCKESR'},
'reg_ddrc_t_cksrx': {'r':(16,19),'d':0x5,'c':'CK valid before self refresh exit, recomm. DDR3:tCKSRX,DDR2:1,LPDDR2:2'},
'reg_ddrc_t_cksre': {'r':(12,15),'d':0x5,'c':'CK valid after self refresh entry, recomm. DDR3:tCKSRE,DDR2:1,LPDDR2:2'},
'reg_ddrc_t_cksrx': {'r':(16,19),'d':0x5,'c':'CK valid before self refresh exit, recomm. DDR3:tCKSRX,DDR2:1,LPDDR2:2'}, # 0x6
'reg_ddrc_t_cksre': {'r':(12,15),'d':0x5,'c':'CK valid after self refresh entry, recomm. DDR3:tCKSRE,DDR2:1,LPDDR2:2'}, # 0x6
'reg_ddrc_dfi_t_dram_clk_enable': {'r':( 8,11),'d':0x1,'c':'deassert dfi_dram_clock disable to PHY clock enable in DFI clock cycles'},
'reg_ddrc_dfi_t_dram_clk_disable': {'r':( 4, 7),'d':0x1,'c':'assert dfi_dram_clock disable to PHY clock disable in DFI clock cycles'},
'reg_ddrc_dfi_t_ctrl_delay': {'r':( 0, 3),'d':0x1,'c':'assert/deassert DFI control signals to PHY-DRAM control signals'}}},
'ctrl_reg6': {'OFFS': 0x07C,'DFLT':0x00032222,'RW':'M','FIELDS':{# in code it was called 'mstr_dll_status1_reg'
'ctrl_reg6': {'OFFS': 0x07C,'DFLT':0x00032222,'RW':'M','FIELDS':{# 0x32222 in code it was called 'mstr_dll_status1_reg'
'reserved1': {'r':(20,31),'d':0,'m':'R','c':'reserved'},
'reg_ddrc_t_ckcsx': {'r':(16,19),'d':0x3,'c':'Clock stable before exiting clock stop. Recommended for LPDDR2: tXP+2'},
'reg_ddrc_t_ckdpdx': {'r':(12,15),'d':0x2,'c':'Clock stable before Deep Power Down exit. Recommended for LPDDR2: 2'},
......@@ -253,44 +254,44 @@ DDRC_DEFS={ #not all fields are defined currently
'of_status3_reg': {'OFFS': 0x094},
'mstr_dll_status2_reg': {'OFFS': 0x098},
'wr_dll_force1_reg': {'OFFS': 0x09C},
'refresh_timer01_reg': {'OFFS': 0x0A0,'DFLT':0x00008000,'RW':'RW','FIELDS':{
'reserved1': {'r':(12,23),'d':0x8,'c':'reserved'},
'reserved2': {'r':( 0,11),'d':0,'c':'reserved'}}},
't_zq_reg': {'OFFS': 0x0A4,'DFLT':0x10300802,'RW':'RW','FIELDS':{
'che_refresh_timer01_reg': {'OFFS': 0x0A0,'DFLT':0x00008000,'RW':'RW','FIELDS':{ #0x8000
'refresh_timer1_start_value_x32': {'r':(12,23),'d':0x8,'c':'reserved'},
'refresh_timer0_start_value_x32': {'r':( 0,11),'d':0,'c':'reserved'}}},
'che_t_zq': {'OFFS': 0x0A4,'DFLT':0x10300802,'RW':'RW','FIELDS':{ # 0x10200802
'reg_ddrc_t_zq_short_nop': {'r':(22,31),'d':0x40,'c':'DDR3 and LPDDR2 only: number of NOP after ZQCS (ZQ calibration short)'},
'reg_ddrc_t_zq_long_nop': {'r':(12,21),'d':0x300,'c':'DDR3 and LPDDR2 only: number of NOP after ZQCL (ZQ calibration long)'},
'reg_ddrc_t_zq_long_nop': {'r':(12,21),'d':0x300,'c':'DDR3 and LPDDR2 only: number of NOP after ZQCL (ZQ calibration long)'}, # 0x200
'reg_ddrc_t_mod': {'r':( 2,11),'d':0x200,'c':'Mode register set command update delay >=0x80'},
'reg_ddrc_ddr3': {'r':( 1, 1),'d':0x1,'c':'0 - DDR2, 1 - DDR3'},
'reg_ddrc_dis_auto_zq ': {'r':( 0, 0),'d':0,'c':'DDR3 and LPDDR2 only: 1 - disable auto generation of ZQCS, 0 - enable'}}},
't_zq_short_interval_reg': {'OFFS': 0x0A8,'DFLT':0x0020003A,'RW':'RW','FIELDS':{
'dram_rstn_x1024': {'r':(20,27),'d':0x2,'c':'DDR3 only: Number of cycles to assert reset during init sequence (in 1024 cycles)'},
't_zq_short_interval_x1024': {'r':( 0,19),'d':0x3a,'c':'DDR3 and LPDDR2 only: AVerage interval between automatic ZQCS in 1024 clock cycles'}}},
'che_t_zq_short_interval_reg': {'OFFS': 0x0A8,'DFLT':0x0020003A,'RW':'RW','FIELDS':{ # 0x690cb73
'dram_rstn_x1024': {'r':(20,27),'d':0x2,'c':'DDR3 only: Number of cycles to assert reset during init sequence (in 1024 cycles)'}, #0x69
't_zq_short_interval_x1024': {'r':( 0,19),'d':0x3a,'c':'DDR3 and LPDDR2 only: AVerage interval between automatic ZQCS in 1024 clock cycles'}}}, #0xcb73
#
' deep_pwrdwn_reg':{'OFFS': 0x0AC,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # in code it was called 'status_data_sl_dll_01_reg'
'deeppowerdown_to_x1024': {'r':( 1, 8),'d':0,'c':'LPDDR2 only: minimal deep power down time in 1024 clk (specs - 500usec)'},
' deep_pwrdwn_reg':{'OFFS': 0x0AC,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 1fe in code it was called 'status_data_sl_dll_01_reg'
'deeppowerdown_to_x1024': {'r':( 1, 8),'d':0,'c':'LPDDR2 only: minimal deep power down time in 1024 clk (specs - 500usec)'}, # 0xff
'deeppowerdown_en': {'r':( 0, 0),'d':0,'c':'LPDDR2 only: 0 - normal, 1 - go to deep power down when transaction store is empty'}}},
'reg_2c': {'OFFS': 0x0B0,'DFLT':0x00000000,'RW':'M','FIELDS':{ # in code it was called 'status_data_sl_dll_23_reg'
'reg_2c': {'OFFS': 0x0B0,'DFLT':0x00000000,'RW':'M','FIELDS':{ # 0xffffff in code it was called 'status_data_sl_dll_23_reg'
'reg_ddrc_dfi_rd_data_eye_train': {'r':(28,28),'d':0,'c':'DDR3 and LPDDR2 only: 1 - read data eye training (part of init sequence)'},
'reg_ddrc_dfi_rd_dqs_gate_level': {'r':(27,27),'d':0,'c':'1 - Read DQS gate leveling mode (DDR3 DFI only)'},
'reg_ddrc_dfi_wr_level_en': {'r':(26,26),'d':0,'c':'1 - Write leveling mode (DDR3 DFI only)'},
'ddrc_reg_trdlvl_max_error': {'r':(25,25),'d':0,'m':'R','c':'DDR3 and LPDDR2 only: leveling/gate training timeout (clear on write)'},
'ddrc_reg_twrlvl_max_error': {'r':(24,24),'d':0,'m':'R','c':'DDR3 only: write leveling timeout (clear on write)'},
'dfi_rdlvl_max_x1024': {'r':(12,23),'d':0,'c':'Read leveling maximal time in 1024 clk. Typical value 0xFFF'},
'dfi_wrlvl_max_x1024': {'r':( 0,11),'d':0,'c':'Write leveling maximal time in 1024 clk. Typical value 0xFFF'}}},
'reg_2d': {'OFFS': 0x0B4,'DFLT':0x00000200,'RW':'RW','FIELDS':{ # in code it was called 'status_dqs_sl_dll_01_reg'
'dfi_rdlvl_max_x1024': {'r':(12,23),'d':0,'c':'Read leveling maximal time in 1024 clk. Typical value 0xFFF'}, # 0xfff
'dfi_wrlvl_max_x1024': {'r':( 0,11),'d':0,'c':'Write leveling maximal time in 1024 clk. Typical value 0xFFF'}}},# 0xfff
'reg_2d': {'OFFS': 0x0B4,'DFLT':0x00000200,'RW':'RW','FIELDS':{ # 200 in code it was called 'status_dqs_sl_dll_01_reg'
'reserved1': {'r':(10,10),'d':0,'c':'reserved'},
'reg_ddrc_skip_ocd': {'r':( 9, 9),'d':0x1,'c':'should be 1, 0 is not supported. 1 - skip OCD adjustment step during DDR2 init, use OCD_Default and OCD_exit'},
'reserved2': {'r':( 0, 8),'d':0,'c':'reserved'}}},
'dfi_timimg': {'OFFS': 0x0B8,'DFLT':0x00200067,'RW':'RW','FIELDS':{ # in code it was called 'status_dqs_sl_dll_23_reg'
'dfi_timimg': {'OFFS': 0x0B8,'DFLT':0x00200067,'RW':'RW','FIELDS':{ # 0x200066 in code it was called 'status_dqs_sl_dll_23_reg'
'reg_ddrc_dfi_t_ctrlup_max': {'r':(15,24),'d':0x40,'c':'Maximal number of clocks ddrc_dfi_ctrlupd_req can assert'},
'reg_ddrc_dfi_t_ctrlup_min': {'r':( 5,14),'d':0x3,'c':'Minimal number of clocks ddrc_dfi_ctrlupd_req must be asserted'},
'reg_ddrc_dfi_t_rddata_en': {'r':( 0, 4),'d':0x7,'c':'LPDDR2 - RL, DDR2 and DDR3 - RL-1'}}},
'reg_ddrc_dfi_t_rddata_en': {'r':( 0, 4),'d':0x7,'c':'LPDDR2 - RL, DDR2 and DDR3 - RL-1'}}}, # 0x6
# u32 reserved1[0x2];
'che_ecc_control_reg_offset':{'OFFS': 0x0C4,'DFLT':0x0,'RW':'RW', 'FIELDS':{
'che_ecc_control_reg_offset':{'OFFS': 0x0C4,'DFLT':0x0,'RW':'RW', 'FIELDS':{ # 0x0
'clear_correctable_dram_ecc_error': {'r':(1, 1),'d':0,'c':'1 - clear correctable log (valid+counters)'},
'clear_uncorrectable_dram_ecc_error':{'r':(0, 0),'d':0,'c':'1 - clear uncorrectable log (valid+counters)'}}},
'che_corr_ecc_log_reg_offset':{'OFFS': 0x0C8,'DFLT':0x0,'RW':'M', 'FIELDS':{
'che_corr_ecc_log_reg_offset':{'OFFS': 0x0C8,'DFLT':0x0,'RW':'M', 'FIELDS':{ # 0x0
'ecc_corrected_bit_num': {'r':( 1, 7),'d':0,'m':'CW','c':'encoded error bits for up to 72-bit data'},
'corr_ecc_log_valid': {'r':( 0, 0),'d':0,'m':'R','c':'set to 1 when correctable error is captured'}}},
'che_corr_ecc_addr_reg_offset':{'OFFS': 0x0CC,'DFLT':0x0,'RW':'R', 'FIELDS':{
......@@ -304,7 +305,7 @@ DDRC_DEFS={ #not all fields are defined currently
'corr_ecc_dat_63_32': {'r':( 0,31),'d':0,'m':'R','c':'bits[32:63] of the word with correctable ECC error. actually all are 0'}}},
'che_corr_ecc_data_71_64_reg_offset':{'OFFS': 0x0D8,'DFLT':0x0,'RW':'R', 'FIELDS':{
'corr_ecc_dat_71_64': {'r':( 0,31),'d':0,'m':'R','c':'bits[64:71] of the word with correctable ECC error. only lower 5 bits have data, the rest are 0'}}},
'che_uncorr_ecc_log_reg_offset':{'OFFS': 0x0DC,'DFLT':0x0,'RW':'R', 'FIELDS':{
'che_uncorr_ecc_log_reg_offset':{'OFFS': 0x0DC,'DFLT':0x0,'RW':'R', 'FIELDS':{ # 0x0
'uncorr_ecc_log_valid': {'r':( 0, 0),'d':0,'m':'R','c':'Set to 1 when uncorrectable error is capture (no more captured until cleared), cleared by che_ecc_control_reg_offset'}}},
'che_uncorr_ecc_addr_reg_offset':{'OFFS': 0x0E0,'DFLT':0x0,'RW':'R', 'FIELDS':{
'uncorr_ecc_log_bank': {'r':(28,30),'d':0,'m':'R','c':'bank [0:2]'},
......@@ -316,10 +317,10 @@ DDRC_DEFS={ #not all fields are defined currently
'uncorr_ecc_dat_63_32': {'r':( 0,31),'d':0,'m':'R','c':'bits[32:63] of the word with uncorrectable ECC error. actually all are 0'}}},
'che_uncorr_ecc_data_71_64_reg_offset':{'OFFS': 0x0EC,'DFLT':0x0,'RW':'R', 'FIELDS':{
'uncorr_ecc_dat_71_64': {'r':( 0,31),'d':0,'m':'R','c':'bits[64:71] of the word with uncorrectable ECC error. only lower 5 bits have data, the rest are 0'}}},
'che_ecc_stats_reg_offset':{'OFFS': 0x0F0,'DFLT':0x00000000,'RW':'CW', 'FIELDS':{
'che_ecc_stats_reg_offset':{'OFFS': 0x0F0,'DFLT':0x00000000,'RW':'CW', 'FIELDS':{ # 0x0
'stat_num_corr_err': {'r':( 8,15),'d':0,'m':'R','c':'Number of correctable ECC errors since 1 written to bit 1 of che_ecc_control_reg_offset (0xC4)'},
'stat_num_uncorr_err': {'r':( 0, 7),'d':0,'m':'R','c':'Number of uncorrectable ECC errors since 1 written to bit 0 of che_ecc_control_reg_offset (0xC4)'}}},
'ecc_scrub': {'OFFS': 0x0F4,'DFLT':0x00000008,'RW':'RW', 'FIELDS':{
'ecc_scrub': {'OFFS': 0x0F4,'DFLT':0x00000008,'RW':'RW', 'FIELDS':{ # 0x8
'reg_ddrc_dis_scrub': {'r':( 3, 3),'d':1,'c':'1 - disable ECC scrubs, 0 - enable ECC scrubs'},
'reg_ddrc_ecc_mode': {'r':( 0, 2),'d':0,'c':'DRAM ECC mode. Valid only 0(no ECC) and 0x4 - "SEC/DED over 1-beat'}}},
'che_ecc_corr_bit_mask_31_0_reg_offset':{'OFFS': 0x0F8,'DFLT':0x0,'RW':'R', 'FIELDS':{
......@@ -327,157 +328,157 @@ DDRC_DEFS={ #not all fields are defined currently
'che_ecc_corr_bit_mask_63_32_reg_offset':{'OFFS': 0x0FC,'DFLT':0x0,'RW':'R', 'FIELDS':{
'ddrc_reg_ecc_corr_bit_mask': {'r':( 0,31),'d':0,'m':'R','c':'bits[32:63] of the mask of the corrected data (1 - corrected, 0 - uncorrected). all bits are 0'}}},
# u32 reserved2[0x14];
'phy_rcvr_enable': {'OFFS': 0x114,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_rcvr_enable': {'OFFS': 0x114,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_dif_off': {'r':( 4, 7),'d':0,'c':'"Off" value of the drive of the receiver-enabled pins'},
'reg_phy_dif_on': {'r':( 0, 3),'d':0,'c':'"On" value of the drive of the receiver-enabled pins'}}},
'phy_config0': {'OFFS': 0x118,'DFLT':0x40000001,'RW':'RW','FIELDS':{
'phy_config0': {'OFFS': 0x118,'DFLT':0x40000001,'RW':'RW','FIELDS':{ # 0x40000001
'reg_phy_dq_offset': {'r':(24,30),'d':0x40,'c':'Offset value of DQS to DQ during write leveling of data slice 0. Default is 0x40 for 90-degree shift'},
'reserved1': {'r':(15,23),'d':0,'c':'reserved'},
'reserved2': {'r':( 6,14),'d':0,'c':'reserved'},
'reserved3': {'r':( 5, 5),'d':0,'c':'reserved'},
'reserved4': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_bist_err_clr': {'r':(15,23),'d':0,'c':'reserved'},
'reg_phy_bist_shift_dq': {'r':( 6,14),'d':0,'c':'reserved'},
'reg_phy_board_lpbk_rx': {'r':( 5, 5),'d':0,'c':'reserved'},
'reg_phy_board_lpbk_tx': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_wrlvl_inc_mode': {'r':( 3, 3),'d':0,'c':'reserved'},
'reg_phy_gatelvl_inc_mode': {'r':( 2, 2),'d':0,'c':'reserved'},
'reg_phy_rdlvl_inc_mode': {'r':( 1, 1),'d':0,'c':'reserved'},
'reg_phy_data_slice_in_use': {'r':( 0, 0),'d':1,'c':'Data bus width for read FIFO generation. 0 - read data responses are ignored, 1 - data slice 0 is valid (always 1)'}}},
'phy_config1': {'OFFS': 0x11C,'DFLT':0x40000001,'RW':'RW','FIELDS':{
'phy_config1': {'OFFS': 0x11C,'DFLT':0x40000001,'RW':'RW','FIELDS':{ # 0x40000001
'reg_phy_dq_offset': {'r':(24,30),'d':0x40,'c':'Offset value of DQS to DQ during write leveling of data slice 1. Default is 0x40 for 90-degree shift'},
'reserved1': {'r':(15,23),'d':0,'c':'reserved'},
'reserved2': {'r':( 6,14),'d':0,'c':'reserved'},
'reserved3': {'r':( 5, 5),'d':0,'c':'reserved'},
'reserved4': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_bist_err_clr': {'r':(15,23),'d':0,'c':'reserved'},
'reg_phy_bist_shift_dq': {'r':( 6,14),'d':0,'c':'reserved'},
'reg_phy_board_lpbk_rx': {'r':( 5, 5),'d':0,'c':'reserved'},
'reg_phy_board_lpbk_tx': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_wrlvl_inc_mode': {'r':( 3, 3),'d':0,'c':'reserved'},
'reg_phy_gatelvl_inc_mode': {'r':( 2, 2),'d':0,'c':'reserved'},
'reg_phy_rdlvl_inc_mode': {'r':( 1, 1),'d':0,'c':'reserved'},
'reg_phy_data_slice_in_use': {'r':( 0, 0),'d':1,'c':'Data bus width for read FIFO generation. 0 - read data responses are ignored, 1 - data slice 1 is valid'}}},
'phy_config2': {'OFFS': 0x120,'DFLT':0x40000001,'RW':'RW','FIELDS':{
'phy_config2': {'OFFS': 0x120,'DFLT':0x40000001,'RW':'RW','FIELDS':{ # 0x40000001
'reg_phy_dq_offset': {'r':(24,30),'d':0x40,'c':'Offset value of DQS to DQ during write leveling of data slice 2. Default is 0x40 for 90-degree shift'},
'reserved1': {'r':(15,23),'d':0,'c':'reserved'},
'reserved2': {'r':( 6,14),'d':0,'c':'reserved'},
'reserved3': {'r':( 5, 5),'d':0,'c':'reserved'},
'reserved4': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_bist_err_clr': {'r':(15,23),'d':0,'c':'reserved'},
'reg_phy_bist_shift_dq': {'r':( 6,14),'d':0,'c':'reserved'},
'reg_phy_board_lpbk_rx': {'r':( 5, 5),'d':0,'c':'reserved'},
'reg_phy_board_lpbk_tx': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_wrlvl_inc_mode': {'r':( 3, 3),'d':0,'c':'reserved'},
'reg_phy_gatelvl_inc_mode': {'r':( 2, 2),'d':0,'c':'reserved'},
'reg_phy_rdlvl_inc_mode': {'r':( 1, 1),'d':0,'c':'reserved'},
'reg_phy_data_slice_in_use': {'r':( 0, 0),'d':1,'c':'Data bus width for read FIFO generation. 0 - read data responses are ignored, 1 - data slice 2 is valid'}}},
'phy_config3': {'OFFS': 0x124,'DFLT':0x40000001,'RW':'RW','FIELDS':{
'phy_config3': {'OFFS': 0x124,'DFLT':0x40000001,'RW':'RW','FIELDS':{ # 0x40000001
'reg_phy_dq_offset': {'r':(24,30),'d':0x40,'c':'Offset value of DQS to DQ during write leveling of data slice 3. Default is 0x40 for 90-degree shift'},
'reserved1': {'r':(15,23),'d':0,'c':'reserved'},
'reserved2': {'r':( 6,14),'d':0,'c':'reserved'},
'reserved3': {'r':( 5, 5),'d':0,'c':'reserved'},
'reserved4': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_bist_err_clr': {'r':(15,23),'d':0,'c':'reserved'},
'reg_phy_bist_shift_dq': {'r':( 6,14),'d':0,'c':'reserved'},
'reg_phy_board_lpbk_rx': {'r':( 5, 5),'d':0,'c':'reserved'},
'reg_phy_board_lpbk_tx': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_wrlvl_inc_mode': {'r':( 3, 3),'d':0,'c':'reserved'},
'reg_phy_gatelvl_inc_mode': {'r':( 2, 2),'d':0,'c':'reserved'},
'reg_phy_rdlvl_inc_mode': {'r':( 1, 1),'d':0,'c':'reserved'},
'reg_phy_data_slice_in_use': {'r':( 0, 0),'d':1,'c':'Data bus width for read FIFO generation. 0 - read data responses are ignored, 1 - data slice 3 is valid'}}},
# u32 reserved3[1]; /* 0x128*/,
'phy_init_ratio0': {'OFFS': 0x12C,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_init_ratio0': {'OFFS': 0x12C,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_gatelvl_init_ratio': {'r':(10,19),'d':0,'c':'User-programmable init ratio used by Gate Leveling FSM, data slice 0'},
'reg_phy_wrlvl_init_ratio': {'r':( 0, 9),'d':0,'c':'User-programmable init ratio used by Write Leveling FSM, data slice 0'}}},
'phy_init_ratio1': {'OFFS': 0x130,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_init_ratio1': {'OFFS': 0x130,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_gatelvl_init_ratio': {'r':(10,19),'d':0,'c':'User-programmable init ratio used by Gate Leveling FSM, data slice 1'},
'reg_phy_wrlvl_init_ratio': {'r':( 0, 9),'d':0,'c':'User-programmable init ratio used by Write Leveling FSM, data slice 1'}}},
'phy_init_ratio2': {'OFFS': 0x134,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_init_ratio2': {'OFFS': 0x134,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_gatelvl_init_ratio': {'r':(10,19),'d':0,'c':'User-programmable init ratio used by Gate Leveling FSM, data slice 2'},
'reg_phy_wrlvl_init_ratio': {'r':( 0, 9),'d':0,'c':'User-programmable init ratio used by Write Leveling FSM, data slice 2'}}},
'phy_init_ratio3': {'OFFS': 0x138,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_init_ratio3': {'OFFS': 0x138,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_gatelvl_init_ratio': {'r':(10,19),'d':0,'c':'User-programmable init ratio used by Gate Leveling FSM, data slice 3'},
'reg_phy_wrlvl_init_ratio': {'r':( 0, 9),'d':0,'c':'User-programmable init ratio used by Write Leveling FSM, data slice 3'}}},
#
'phy_rd_dqs_cfg0': {'OFFS': 0x140,'DFLT':0x00000040,'RW':'RW','FIELDS':{
'phy_rd_dqs_cfg0': {'OFFS': 0x140,'DFLT':0x00000040,'RW':'RW','FIELDS':{ # 0x35
'reg_phy_rd_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_rd_dqs_slave_force is 1, use this tap/delay value for read DQS slave DLL, data slice 0'},
'reg_phy_rd_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_rd_dqs_slave_ratio for the read DQS slave DLL, 1 - use provided in reg_phy_rd_dqs_slave_delay, data slice 0'},
'reg_phy_rd_dqs_slave_ratio': {'r':( 0, 9),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 0'}}},
'phy_rd_dqs_cfg1': {'OFFS': 0x144,'DFLT':0x00000040,'RW':'RW','FIELDS':{
'reg_phy_rd_dqs_slave_ratio': {'r':( 0, 9),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 0'}}}, # 0x35
'phy_rd_dqs_cfg1': {'OFFS': 0x144,'DFLT':0x00000040,'RW':'RW','FIELDS':{ # 0x35
'reg_phy_rd_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_rd_dqs_slave_force is 1, use this tap/delay value for read DQS slave DLL, data slice 1'},
'reg_phy_rd_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_rd_dqs_slave_ratio for the read DQS slave DLL, 1 - use provided in reg_phy_rd_dqs_slave_delay, data slice 1'},
'reg_phy_rd_dqs_slave_ratio': {'r':( 0, 9),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 1'}}},
'phy_rd_dqs_cfg2': {'OFFS': 0x148,'DFLT':0x00000040,'RW':'RW','FIELDS':{
'reg_phy_rd_dqs_slave_ratio': {'r':( 0, 9),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 1'}}}, # 0x35
'phy_rd_dqs_cfg2': {'OFFS': 0x148,'DFLT':0x00000040,'RW':'RW','FIELDS':{ # 0x35
'reg_phy_rd_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_rd_dqs_slave_force is 1, use this tap/delay value for read DQS slave DLL, data slice 2'},
'reg_phy_rd_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_rd_dqs_slave_ratio for the read DQS slave DLL, 1 - use provided in reg_phy_rd_dqs_slave_delay, data slice 2'},
'reg_phy_rd_dqs_slave_ratio': {'r':( 0, 9),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 2'}}},
'phy_rd_dqs_cfg3': {'OFFS': 0x14C,'DFLT':0x00000040,'RW':'RW','FIELDS':{
'reg_phy_rd_dqs_slave_ratio': {'r':( 0, 9),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 2'}}}, # 0x35
'phy_rd_dqs_cfg3': {'OFFS': 0x14C,'DFLT':0x00000040,'RW':'RW','FIELDS':{ # 0x35
'reg_phy_rd_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_rd_dqs_slave_force is 1, use this tap/delay value for read DQS slave DLL, data slice 3'},
'reg_phy_rd_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_rd_dqs_slave_ratio for the read DQS slave DLL, 1 - use provided in reg_phy_rd_dqs_slave_delay, data slice 3'},
'reg_phy_rd_dqs_slave_ratio': {'r':( 0, 9),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 3'}}},
'reg_phy_rd_dqs_slave_ratio': {'r':( 0, 9),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 3'}}}, # 0x35
# u32 reserved4[1]; /* 0x150 */
'phy_wr_dqs_cfg0': {'OFFS': 0x154,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_wr_dqs_cfg0': {'OFFS': 0x154,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_wr_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 0'},
'reg_phy_wr_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 0'},
'reg_phy_wr_dqs_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 0. Program manual training ratio'}}},
'phy_wr_dqs_cfg1': {'OFFS': 0x158,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_wr_dqs_cfg1': {'OFFS': 0x158,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_wr_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 1'},
'reg_phy_wr_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 1'},
'reg_phy_wr_dqs_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 1. Program manual training ratio'}}},
'phy_wr_dqs_cfg2': {'OFFS': 0x15C,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_wr_dqs_cfg2': {'OFFS': 0x15C,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_wr_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 2'},
'reg_phy_wr_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 2'},
'reg_phy_wr_dqs_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 2. Program manual training ratio'}}},
'phy_wr_dqs_cfg3': {'OFFS': 0x160,'DFLT':0x00000000,'RW':'RW','FIELDS':{
'phy_wr_dqs_cfg3': {'OFFS': 0x160,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
'reg_phy_wr_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 3'},
'reg_phy_wr_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 3'},
'reg_phy_wr_dqs_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 3. Program manual training ratio'}}},
# u32 reserved5[1]; /* 0x164 */
'phy_we_cfg0': {'OFFS': 0x168,'DFLT':0x00000040,'RW':'RW','FIELDS':{
'phy_we_cfg0': {'OFFS': 0x168,'DFLT':0x00000040,'RW':'RW','FIELDS':{ # 0x35
'reg_phy_fifo_we_in_delay': {'r':(12,20),'d':0,'c':'If reg_phy_fifo_we_in_force is 1, use this tap/delay value for fifo_we_0 slave DLL, data slice 0'},
'reg_phy_fifo_we_in_force': {'r':(11,11),'d':0,'c':'0 - use reg_phy_fifo_we_slave_ratio for fifo_we_0 slave DLL, 1 - use provided in reg_phy_fifo_we_in_delay, data slice 0'},
'reg_phy_fifo_we_slave_ratio': {'r':( 0,10),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 0. Program manual training ratio'}}},
'phy_we_cfg1': {'OFFS': 0x16C,'DFLT':0x00000040,'RW':'RW','FIELDS':{
'reg_phy_fifo_we_slave_ratio': {'r':( 0,10),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 0. Program manual training ratio'}}}, # 0x35
'phy_we_cfg1': {'OFFS': 0x16C,'DFLT':0x00000040,'RW':'RW','FIELDS':{ # 0x35
'reg_phy_fifo_we_in_delay': {'r':(12,20),'d':0,'c':'If reg_phy_fifo_we_in_force is 1, use this tap/delay value for fifo_we_1 slave DLL, data slice 1'},
'reg_phy_fifo_we_in_force': {'r':(11,11),'d':0,'c':'0 - use reg_phy_fifo_we_slave_ratio for fifo_we_1 slave DLL, 1 - use provided in reg_phy_fifo_we_in_delay, data slice 1'},
'reg_phy_fifo_we_slave_ratio': {'r':( 0,10),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 1. Program manual training ratio'}}},
'phy_we_cfg2': {'OFFS': 0x170,'DFLT':0x00000040,'RW':'RW','FIELDS':{
'reg_phy_fifo_we_slave_ratio': {'r':( 0,10),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 1. Program manual training ratio'}}}, # 0x35
'phy_we_cfg2': {'OFFS': 0x170,'DFLT':0x00000040,'RW':'RW','FIELDS':{ # 0x35
'reg_phy_fifo_we_in_delay': {'r':(12,20),'d':0,'c':'If reg_phy_fifo_we_in_force is 1, use this tap/delay value for fifo_we_2 slave DLL, data slice 2'},
'reg_phy_fifo_we_in_force': {'r':(11,11),'d':0,'c':'0 - use reg_phy_fifo_we_slave_ratio for fifo_we_2 slave DLL, 1 - use provided in reg_phy_fifo_we_in_delay, data slice 2'},
'reg_phy_fifo_we_slave_ratio': {'r':( 0,10),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 2. Program manual training ratio'}}},
'phy_we_cfg3': {'OFFS': 0x174,'DFLT':0x00000040,'RW':'RW','FIELDS':{
'reg_phy_fifo_we_slave_ratio': {'r':( 0,10),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 2. Program manual training ratio'}}}, # 0x35
'phy_we_cfg3': {'OFFS': 0x174,'DFLT':0x00000040,'RW':'RW','FIELDS':{ # 0x35
'reg_phy_fifo_we_in_delay': {'r':(12,20),'d':0,'c':'If reg_phy_fifo_we_in_force is 1, use this tap/delay value for fifo_we_3 slave DLL, data slice 3'},
'reg_phy_fifo_we_in_force': {'r':(11,11),'d':0,'c':'0 - use reg_phy_fifo_we_slave_ratio for fifo_we_3 slave DLL, 1 - use provided in reg_phy_fifo_we_in_delay, data slice 3'},
'reg_phy_fifo_we_slave_ratio': {'r':( 0,10),'d':0x40,'c':'Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 3. Program manual training ratio'}}},
# u32 reserved6[1]; /* 0x178 */
'wr_data_slv0': {'OFFS': 0x17C,'DFLT':0x00000080,'RW':'RW','FIELDS':{
'wr_data_slv0': {'OFFS': 0x17C,'DFLT':0x00000080,'RW':'RW','FIELDS':{ # 0x40
'reg_phy_wr_data_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write data slave DLL, data slice 0'},
'reg_phy_wr_data_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write data slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 0'},
'reg_phy_wr_data_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 0. Program manual training ratio'}}},
'wr_data_slv1': {'OFFS': 0x180,'DFLT':0x00000080,'RW':'RW','FIELDS':{
'reg_phy_wr_data_slave_ratio': {'r':( 0, 9),'d':0x80,'c':'Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 0. Program manual training ratio'}}}, # 0x40
'wr_data_slv1': {'OFFS': 0x180,'DFLT':0x00000080,'RW':'RW','FIELDS':{ # 0x40
'reg_phy_wr_data_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write data slave DLL, data slice 1'},
'reg_phy_wr_data_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write data slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 1'},
'reg_phy_wr_data_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 1. Program manual training ratio'}}},
'wr_data_slv2': {'OFFS': 0x184,'DFLT':0x00000080,'RW':'RW','FIELDS':{
'reg_phy_wr_data_slave_ratio': {'r':( 0, 9),'d':0x80,'c':'Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 1. Program manual training ratio'}}}, # 0x40
'wr_data_slv2': {'OFFS': 0x184,'DFLT':0x00000080,'RW':'RW','FIELDS':{ # 0x40
'reg_phy_wr_data_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write data slave DLL, data slice 2'},
'reg_phy_wr_data_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write data slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 2'},
'reg_phy_wr_data_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 2. Program manual training ratio'}}},
'wr_data_slv3': {'OFFS': 0x188,'DFLT':0x00000080,'RW':'RW','FIELDS':{
'reg_phy_wr_data_slave_ratio': {'r':( 0, 9),'d':0x80,'c':'Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 2. Program manual training ratio'}}}, # 0x40
'wr_data_slv3': {'OFFS': 0x188,'DFLT':0x00000080,'RW':'RW','FIELDS':{ # 0x40
'reg_phy_wr_data_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write data slave DLL, data slice 3'},
'reg_phy_wr_data_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write data slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 3'},
'reg_phy_wr_data_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 3. Program manual training ratio'}}},
'reg_phy_wr_data_slave_ratio': {'r':( 0, 9),'d':0x80,'c':'Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 3. Program manual training ratio'}}}, # 0x40
# u32 reserved7[1]; /* 0x18C*/
'reg_64': {'OFFS': 0x190,'DFLT':0x10020000,'RW':'RW','COMMENTS':'Training control 2','FIELDS':{
'reserved1': {'r':(31,31),'d':0, 'c':'reserved'},
'reg_64': {'OFFS': 0x190,'DFLT':0x10020000,'RW':'RW','COMMENTS':'Training control 2','FIELDS':{ #10020000
'reg_phy_int_lpbk': {'r':(31,31),'d':0, 'c':'reserved'},
'reg_phy_cmd_latency': {'r':(30,30),'d':0, 'c':'1: Delay command to PHY by a FF'},
'reg_phy_lpddr': {'r':(29,29),'d':0, 'c':'0: DDR2/DDR3, 1 - LPDDR2'},
'reserved2': {'r':(28,28),'d':1,' c':'reserved'},
'reg_phy_use_rank0_delays': {'r':(28,28),'d':1,' c':'reserved'},
'reg_phy_ctrl_slave_delay': {'r':(21,27),'d':0,' c':'when reg_phy_rd_dqs_slave_force==1 this value (combined with bits 18:19 of reg_65) set address/command slave DLL'},
'reg_phy_ctrl_slave_force': {'r':(20,20),'d':0,' c':'0:use reg_phy_ctrl_slave_ratio for addr/cmd slave DLL, 1 - overwrite with reg_phy_ctrl_slave_delay'},
'reg_phy_ctrl_slave_ratio': {'r':(10,19),'d':0x80,'c':'address/command delay in clock/256'},
'reg_phy_sel_logic': {'r':( 9, 9),'d':0,'c':'Read leveling algorithm select - 0:algorithm 1, 1: algorithm 2'},
'reserved3': {'r':( 8, 8),'d':0,'c':'reserved'},
'reg_phy_all_dq_mpr_rd_resp': {'r':( 8, 8),'d':0,'c':'reserved'},
'reg_phy_invert_clkout': {'r':( 7, 7),'d':0,'c':'1 - invert clock polarity to DRAM'},
'reserved4': {'r':( 5, 6),'d':0,'c':'reserved'},
'reserved5': {'r':( 4, 4),'d':0,'c':'reserved'},
'reserved6': {'r':( 3, 3),'d':0,'c':'reserved'},
'reserved7': {'r':( 2, 2),'d':0,'c':'reserved'},
'reg_phy_bist_mode': {'r':( 5, 6),'d':0,'c':'reserved'},
'reg_phy_bist_force_err': {'r':( 4, 4),'d':0,'c':'reserved'},
'reg_phy_bist_enable': {'r':( 3, 3),'d':0,'c':'reserved'},
'reg_phy_at_spd_atpg': {'r':( 2, 2),'d':0,'c':'reserved'},
'reg_phy_bl2': {'r':( 1, 1),'d':0,'c':'reserved'},
'reserved8': {'r':( 0, 0),'d':0,'c':'reserved'}}},
'reg_65': {'OFFS': 0x194,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Training control 3','FIELDS':{
'reg_phy_loopback': {'r':( 0, 0),'d':0,'c':'reserved'}}},
'reg_65': {'OFFS': 0x194,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Training control 3','FIELDS':{ # 0x3c82
'reg_phy_ctrl_slave_delay': {'r':(18,19),'d':0,'c':'when reg_phy_rd_dqs_slave_force==1 this value (combined with bits 21:27 of reg_64) set address/command slave DLL'},
'reg_phy_dis_calib_rst': {'r':(17,17),'d':0,'c':'disable dll_claib from resetting Read Capture FIFO'},
'reg_phy_use_rd_data_eye_level': {'r':(16,16),'d':0,'c':'Read Data Eye training control - 0 use fixed register data, 1 use data eye leveling data'},
'reg_phy_use_rd_dqs_gate_level': {'r':(15,15),'d':0,'c':'Read DQS Gate training control: 0 - used fixed data, 1 - use calculated data'},
'reg_phy_use_wr_level': {'r':(14,14),'d':0,'c':'Write leveling control: 0 - used programmed register data, 1 - use calculated data'},
'reg_phy_dll_lock_diff': {'r':(10,13),'d':0,'c':'Maximal number of DLL taps before DLL deasserts lock'},
'reg_phy_rd_rl_delay': {'r':( 5, 9),'d':0,'c':''},
'reg_phy_wr_rl_delay': {'r':( 0, 4),'d':0,'c':''}}},
'reg_phy_dll_lock_diff': {'r':(10,13),'d':0,'c':'Maximal number of DLL taps before DLL deasserts lock'}, # 0xf
'reg_phy_rd_rl_delay': {'r':( 5, 9),'d':0,'c':''}, # 0x4
'reg_phy_wr_rl_delay': {'r':( 0, 4),'d':0,'c':''}}}, # 0x2
# u32 reserved7[3]; /* 0x198 */
# The fifo_we_slave ratios for each slice(0 through 3) must be interpreted by software in the following way:
# Slice 0: fifo_we_ratio_slice_0[10:0] = {Reg_6A[9],Reg_69[18:9]}
......@@ -560,58 +561,58 @@ DDRC_DEFS={ #not all fields are defined currently
'reg_arb_rev_num': {'r':(20,25),'d':0x01, 'm':'R','c':'Revision number'},
'reg_arb_prov_num': {'r':(12,19),'d':0x53, 'm':'R','c':'Provision number'},
'reg_arb_part_num': {'r':( 0,11),'d':0x42, 'm':'R','c':'Part number'}}},
'page_mask': {'OFFS': 0x204,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Arbiter Page Mask','FIELDS':{
'page_mask': {'OFFS': 0x204,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Arbiter Page Mask','FIELDS':{ # 0x0
'reg_arb_page_addr_mask': {'r':( 0,31),'d':0x0,'c':'Arbiter page hit/miss: 0 - column address, 1 - row/bank address (applies to 64-bit address, not byte addr) '}}},
'axi_priority_wr_port0': {'OFFS': 0x208,'DFLT':0x000803FF,'RW':'M','COMMENTS':'AXI priority control for write port 0','FIELDS':{
'axi_priority_wr_port0': {'OFFS': 0x208,'DFLT':0x000803FF,'RW':'M','COMMENTS':'AXI priority control for write port 0','FIELDS':{ #0x803ff
'reserved1': {'r':(19,19),'d':0x1, 'c':'reserved'},
'reg_arb_dis_page_match_wr_portn': {'r':(18,18),'d':0, 'c':'Disable page match feature'},
'reg_arb_disable_urgent_wr_portn': {'r':(17,17),'d':0, 'c':'Disable urgent for this Write Port'},
'reg_arb_disable_aging_wr_portn': {'r':(16,16),'d':0, 'c':'Disable aging for this Write Port'},
'reserved2': {'r':(10,15),'d':0, 'm':'R','c':'reserved'},
'reg_arb_pri_wr_portn': {'r':( 0, 9),'d':0x3FF, 'c':'Priority for this write port, >=4, lower value - higher priority'}}},
'axi_priority_wr_port1': {'OFFS': 0x20C,'DFLT':0x000803FF,'RW':'M','COMMENTS':'AXI priority control for write port 1','FIELDS':{
'axi_priority_wr_port1': {'OFFS': 0x20C,'DFLT':0x000803FF,'RW':'M','COMMENTS':'AXI priority control for write port 1','FIELDS':{ #0x803ff
'reserved1': {'r':(19,19),'d':0x1, 'c':'reserved'},
'reg_arb_dis_page_match_wr_portn': {'r':(18,18),'d':0, 'c':'Disable page match feature'},
'reg_arb_disable_urgent_wr_portn': {'r':(17,17),'d':0, 'c':'Disable urgent for this Write Port'},
'reg_arb_disable_aging_wr_portn': {'r':(16,16),'d':0, 'c':'Disable aging for this Write Port'},
'reserved2': {'r':(10,15),'d':0, 'm':'R','c':'reserved'},
'reg_arb_pri_wr_portn': {'r':( 0, 9),'d':0x3FF, 'c':'Priority for this write port, >=4, lower value - higher priority'}}},
'axi_priority_wr_port2': {'OFFS': 0x210,'DFLT':0x000803FF,'RW':'M','COMMENTS':'AXI priority control for write port 2','FIELDS':{
'axi_priority_wr_port2': {'OFFS': 0x210,'DFLT':0x000803FF,'RW':'M','COMMENTS':'AXI priority control for write port 2','FIELDS':{ #0x803ff
'reserved1': {'r':(19,19),'d':0x1, 'c':'reserved'},
'reg_arb_dis_page_match_wr_portn': {'r':(18,18),'d':0, 'c':'Disable page match feature'},
'reg_arb_disable_urgent_wr_portn': {'r':(17,17),'d':0, 'c':'Disable urgent for this Write Port'},
'reg_arb_disable_aging_wr_portn': {'r':(16,16),'d':0, 'c':'Disable aging for this Write Port'},
'reserved2': {'r':(10,15),'d':0, 'm':'R','c':'reserved'},
'reg_arb_pri_wr_portn': {'r':( 0, 9),'d':0x3FF, 'c':'Priority for this write port, >=4, lower value - higher priority'}}},
'axi_priority_wr_port3': {'OFFS': 0x214,'DFLT':0x000803FF,'RW':'M','COMMENTS':'AXI priority control for write port 3','FIELDS':{
'axi_priority_wr_port3': {'OFFS': 0x214,'DFLT':0x000803FF,'RW':'M','COMMENTS':'AXI priority control for write port 3','FIELDS':{ #0x803ff
'reserved1': {'r':(19,19),'d':0x1, 'c':'reserved'},
'reg_arb_dis_page_match_wr_portn': {'r':(18,18),'d':0, 'c':'Disable page match feature'},
'reg_arb_disable_urgent_wr_portn': {'r':(17,17),'d':0, 'c':'Disable urgent for this Write Port'},
'reg_arb_disable_aging_wr_portn': {'r':(16,16),'d':0, 'c':'Disable aging for this Write Port'},
'reserved2': {'r':(10,15),'d':0, 'm':'R','c':'reserved'},
'reg_arb_pri_wr_portn': {'r':( 0, 9),'d':0x3FF, 'c':'Priority for this write port, >=4, lower value - higher priority'}}},
'axi_priority_rd_port0': {'OFFS': 0x218,'DFLT':0x000003FF,'RW':'M','COMMENTS':'AXI priority control for read port 0','FIELDS':{
'axi_priority_rd_port0': {'OFFS': 0x218,'DFLT':0x000003FF,'RW':'M','COMMENTS':'AXI priority control for read port 0','FIELDS':{ #0x3ff
'reg_arb_set_hpr_rd_portn': {'r':(19,19),'d':0x1, 'c':'Enable reads to be HPR for this port'},
'reg_arb_dis_page_match_rd_portn': {'r':(18,18),'d':0, 'c':'Disable page match feature'},
'reg_arb_disable_urgent_rd_portn': {'r':(17,17),'d':0, 'c':'Disable urgent for this Read Port'},
'reg_arb_disable_aging_rd_portn': {'r':(16,16),'d':0, 'c':'Disable aging for this Read Port'},
'reserved1': {'r':(10,15),'d':0, 'm':'R','c':'reserved'},
'reg_arb_pri_rd_portn': {'r':( 0, 9),'d':0x3FF, 'c':'Priority for this Read port, lower value - higher priority'}}},
'axi_priority_rd_port1': {'OFFS': 0x21C,'DFLT':0x000003FF,'RW':'M','COMMENTS':'AXI priority control for read port 1','FIELDS':{
'axi_priority_rd_port1': {'OFFS': 0x21C,'DFLT':0x000003FF,'RW':'M','COMMENTS':'AXI priority control for read port 1','FIELDS':{ #0x3ff
'reg_arb_set_hpr_rd_portn': {'r':(19,19),'d':0x1, 'c':'Enable reads to be HPR for this port'},
'reg_arb_dis_page_match_rd_portn': {'r':(18,18),'d':0, 'c':'Disable page match feature'},
'reg_arb_disable_urgent_rd_portn': {'r':(17,17),'d':0, 'c':'Disable urgent for this Read Port'},
'reg_arb_disable_aging_rd_portn': {'r':(16,16),'d':0, 'c':'Disable aging for this Read Port'},
'reserved1': {'r':(10,15),'d':0, 'm':'R','c':'reserved'},
'reg_arb_pri_rd_portn': {'r':( 0, 9),'d':0x3FF, 'c':'Priority for this Read port, lower value - higher priority'}}},
'axi_priority_rd_port2': {'OFFS': 0x220,'DFLT':0x000003FF,'RW':'M','COMMENTS':'AXI priority control for read port 2','FIELDS':{
'axi_priority_rd_port2': {'OFFS': 0x220,'DFLT':0x000003FF,'RW':'M','COMMENTS':'AXI priority control for read port 2','FIELDS':{ #0x3ff
'reg_arb_set_hpr_rd_portn': {'r':(19,19),'d':0x1, 'c':'Enable reads to be HPR for this port'},
'reg_arb_dis_page_match_rd_portn': {'r':(18,18),'d':0, 'c':'Disable page match feature'},
'reg_arb_disable_urgent_rd_portn': {'r':(17,17),'d':0, 'c':'Disable urgent for this Read Port'},
'reg_arb_disable_aging_rd_portn': {'r':(16,16),'d':0, 'c':'Disable aging for this Read Port'},
'reserved1': {'r':(10,15),'d':0, 'm':'R','c':'reserved'},
'reg_arb_pri_rd_portn': {'r':( 0, 9),'d':0x3FF, 'c':'Priority for this Read port, lower value - higher priority'}}},
'axi_priority_rd_port3': {'OFFS': 0x224,'DFLT':0x000003FF,'RW':'M','COMMENTS':'AXI priority control for read port 3','FIELDS':{
'axi_priority_rd_port3': {'OFFS': 0x224,'DFLT':0x000003FF,'RW':'M','COMMENTS':'AXI priority control for read port 3','FIELDS':{ #0x3ff
'reg_arb_set_hpr_rd_portn': {'r':(19,19),'d':0x1, 'c':'Enable reads to be HPR for this port'},
'reg_arb_dis_page_match_rd_portn': {'r':(18,18),'d':0, 'c':'Disable page match feature'},
'reg_arb_disable_urgent_rd_portn': {'r':(17,17),'d':0, 'c':'Disable urgent for this Read Port'},
......@@ -635,19 +636,19 @@ DDRC_DEFS={ #not all fields are defined currently
'reg_excl_acc_id0_port': {'r':( 0, 8),'d':0, 'c':'reserved'}}},
'mode_reg_read': {'OFFS': 0x2A4,'DFLT':0x00000000,'RW':'R','COMMENTS':'Mode register read data','FIELDS':{
'ddrc_reg_rd_mrr_data': {'r':( 0,31),'d':0x0, 'M':'R','c':'LPDDR2 only: Mode register read data, valid when ddrc_co_rd_mrr_data_valid is set'}}},
'lpddr_ctrl0': {'OFFS': 0x2A8,'DFLT':0x00000000,'RW':'RW','COMMENTS':'LPDDR2 control register 0','FIELDS':{
'lpddr_ctrl0': {'OFFS': 0x2A8,'DFLT':0x00000000,'RW':'RW','COMMENTS':'LPDDR2 control register 0','FIELDS':{ # 0x0
'reg_ddrc_mr4_margin': {'r':( 4,11),'d':0, 'c':'unused'},
'reserved1': {'r':( 3, 3),'d':0, 'c':'reserved'},
'reg_ddrc_derate_enable': {'r':( 2, 2),'d':0, 'c':'Timing parameter derating ENABLED using MR4 read data'},
'reserved2': {'r':( 1, 1),'d':0, 'c':'reserved'},
'reg_ddrc_lpddr2': {'r':( 0, 0),'d':0, 'c':'0 - DDR2/DDR3 in use, 1 - LPDDR2 in use'}}},
'lpddr_ctrl1': {'OFFS': 0x2AC,'DFLT':0x00000000,'RW':'RW','COMMENTS':'LPDDR2 control register 1','FIELDS':{
'lpddr_ctrl1': {'OFFS': 0x2AC,'DFLT':0x00000000,'RW':'RW','COMMENTS':'LPDDR2 control register 1','FIELDS':{ # 0x0
'reg_ddrc_mr4_read_int erval': {'r':(31, 0),'d':0, 'c':'Interval between two MR4 reads (for derating timing)'}}},
'lpddr_ctrl2': {'OFFS': 0x2B0,'DFLT':0x003C0015,'RW':'RW','COMMENTS':'LPDDR2 control register 2','FIELDS':{
'reg_ddrc_t_mrw': {'r':(12,21),'d':0x3C0,'c':'Wait for MR writes, typically required 5???'},
'reg_ddrc_idle_after_reset_x32': {'r':( 4,11),'d':0x1, 'c':'Idle time after reset command, tINIT4 (in clockx32)'},
'reg_ddrc_min_stable_clock_x1': {'r':( 0, 3),'d':0x5, 'c':'time to wait after first CKE high, tINIT2 in clock cycles. Typically required 5 (tCK)'}}},
'lpddr_ctrl3': {'OFFS': 0x2B4,'DFLT':0x00000601,'RW':'RW','COMMENTS':'LPDDR2 control register 3','FIELDS':{
'reg_ddrc_dev_zqinit_x32': {'r':( 8,17),'d':0x1, 'c':'tZQINIT - ZQ initial calibration (in clockx32). LPDDR@ typically require 1 microsecond'},
'reg_ddrc_max_auto_init_x1024': {'r':( 0, 7),'d':0x1, 'c':'tINIT5 - maximal duration of autoinitialization (in clockx1024). Typical 10 microseconds'}}}
'lpddr_ctrl2': {'OFFS': 0x2B0,'DFLT':0x003C0015,'RW':'RW','COMMENTS':'LPDDR2 control register 2','FIELDS':{ # 0x5125
'reg_ddrc_t_mrw': {'r':(12,21),'d':0x3C0,'c':'Wait for MR writes, typically required 5???'}, #0x5
'reg_ddrc_idle_after_reset_x32': {'r':( 4,11),'d':0x1, 'c':'Idle time after reset command, tINIT4 (in clockx32)'}, #0x12
'reg_ddrc_min_stable_clock_x1': {'r':( 0, 3),'d':0x5, 'c':'time to wait after first CKE high, tINIT2 in clock cycles. Typically required 5 (tCK)'}}}, # 0x5
'lpddr_ctrl3': {'OFFS': 0x2B4,'DFLT':0x00000601,'RW':'RW','COMMENTS':'LPDDR2 control register 3','FIELDS':{ # 0x12a8
'reg_ddrc_dev_zqinit_x32': {'r':( 8,17),'d':0x1, 'c':'tZQINIT - ZQ initial calibration (in clockx32). LPDDR@ typically require 1 microsecond'}, #0x1200
'reg_ddrc_max_auto_init_x1024': {'r':( 0, 7),'d':0x1, 'c':'tINIT5 - maximal duration of autoinitialization (in clockx1024). Typical 10 microseconds'}}} # #0xa8
}
#!/usr/bin/env python
# Copyright (C) 2013, Elphel.inc.
# Definitions of configuration parameters for DDR memory
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2013, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
#Use 'TYPE':'I' for decimal output, 'H' - for hex. On input both are accepted
DDR_CFG_DEFS=[
{'NAME':'ENABLE', 'CONF_NAME':'CONFIG_EZYNQ_DDR_ENABLE','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':True,
'DESCRIPTION':'Enable DDR memory'},
{'NAME':'MEMORY_TYPE', 'CONF_NAME':'CONFIG_EZYNQ_DDR_MEMORY_TYPE','TYPE':('DDR3','DDR3L','DDR2','LPDDR2'),'MANDATORY':True,'DERIVED':False,'DEFAULT':'DDR3',
'DESCRIPTION':'DDR memory type'},
{'NAME':'TARGET_FREQ_MHZ', 'CONF_NAME':'CONFIG_EZYNQ_DDR_TARGET_FREQ_MHZ','TYPE':'F','MANDATORY':True,'DERIVED':True,'DEFAULT':533.333333,
'DESCRIPTION':'Target DDR clock frequency in MHz (actual frequency will depend on the clock/clock muxes)'},
{'NAME':'FREQ_MHZ', 'CONF_NAME':'CONFIG_EZYNQ_DDR_FREQ_MHZ','TYPE':'F','MANDATORY':True,'DERIVED':True,'DEFAULT':533.333333,
'DESCRIPTION':'Actual DDR clock frequency in MHz, may be derived form CONFIG_EZYNQ_DDR_TARGET_FREQ_MHZ and clock multiplexer settings'},
{'NAME':'CL', 'CONF_NAME':'CONFIG_EZYNQ_DDR_CL','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':7,
'DESCRIPTION':'CAS read latency (in tCK)'},
{'NAME':'AL', 'CONF_NAME':'CONFIG_EZYNQ_DDR_AL','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':0,
'DESCRIPTION':'Posted CAS additive latency (in tCK)'},
{'NAME':'CWL', 'CONF_NAME':'CONFIG_EZYNQ_DDR_CWL','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':6,
'DESCRIPTION':'CAS write latency (in tCK)'},
{'NAME':'RCD', 'CONF_NAME':'CONFIG_EZYNQ_DDR_RCD','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':7,
'DESCRIPTION':'RAS to CAS delay (in tCK)'},
{'NAME':'RP', 'CONF_NAME':'CONFIG_EZYNQ_DDR_RP','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':7,
'DESCRIPTION':'Row Precharge time (in tCK)'},
{'NAME':'T_RC', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_RC','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':48.75,
'DESCRIPTION':'Activate to Activate or Refresh command period (ns)'},
{'NAME':'T_RAS_MIN', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_RAS_MIN','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':35.0,
'DESCRIPTION':'Minimal Row Active time (ns)'},
{'NAME':'T_FAW', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_FAW','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':40.0,
'DESCRIPTION':'Minimal running window for 4 page activates (ns)'},
{'NAME':'T_RFC', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_RFC','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':350.0,
'DESCRIPTION':'Minimal Refresh-to-Activate or Refresh command period (ns)'},
{'NAME':'T_WR', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_WR','TYPE':'F','MANDATORY':True,'DERIVED':False,'DEFAULT':15.0,
'DESCRIPTION':'Write recovery time (ns)'},
{'NAME':'BANK_ADDR_COUNT', 'CONF_NAME':'CONFIG_EZYNQ_DDR_BANK_ADDR_COUNT','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':3,
'DESCRIPTION':'Number of DDR banks'},
{'NAME':'ROW_ADDR_COUNT', 'CONF_NAME':'CONFIG_EZYNQ_DDR_ROW_ADDR_COUNT','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':15,
'DESCRIPTION':'Number of DDR banks'},
{'NAME':'COL_ADDR_COUNT', 'CONF_NAME':'CONFIG_EZYNQ_DDR_COL_ADDR_COUNT','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':10,
'DESCRIPTION':'Number of DDR banks'},
{'NAME':'ECC', 'CONF_NAME':'CONFIG_EZYNQ_DDR_ECC','TYPE':'B','MANDATORY':False,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Enable ECC for the DDR memory'},
{'NAME':'BUS_WIDTH', 'CONF_NAME':'CONFIG_EZYNQ_DDR_BUS_WIDTH','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':32,
'DESCRIPTION':'SoC DDR bus width'},
{'NAME':'BL', 'CONF_NAME':'CONFIG_EZYNQ_DDR_BL','TYPE':(8,4),'MANDATORY':True,'DERIVED':False,'DEFAULT':8, # DDR2 may have different lengths?
'DESCRIPTION':'Burst length'},
{'NAME':'HIGH_TEMP', 'CONF_NAME':'CONFIG_EZYNQ_DDR_HIGH_TEMP','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'High temperature (influences refresh)'},
{'NAME':'T_REFI_US', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_REFI_US','TYPE':'F','MANDATORY':False,'DERIVED':False,'DEFAULT':7.8,
'DESCRIPTION':'Maximal average periodic refresh, microseconds. Will be automatically reduced if high temperature option is selected'},
{'NAME':'PARTNO', 'CONF_NAME':'CONFIG_EZYNQ_DDR_PARTNO','TYPE':'T','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Memory part number (currently not used - derive some parameters later)'},
{'NAME':'DRAM_WIDTH', 'CONF_NAME':'CONFIG_EZYNQ_DDR_DRAM_WIDTH','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':16,
'DESCRIPTION':'Memory chip bus width'},
{'NAME':'SPEED_BIN', 'CONF_NAME':'CONFIG_EZYNQ_DDR_SPEED_BIN','TYPE':'T','MANDATORY':True,'DERIVED':False,'DEFAULT':'DDR3_1066F',
'DESCRIPTION':'Memory speed bin (currently not used - derive timing later)'},
{'NAME':'TRAIN_WRITE_LEVEL','CONF_NAME':'CONFIG_EZYNQ_DDR_TRAIN_WRITE_LEVEL','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Automatically train write leveling during initialization'},
{'NAME':'TRAIN_READ_GATE', 'CONF_NAME':'CONFIG_EZYNQ_DDR_TRAIN_READ_GATE','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Automatically train read gate timing during initialization'},
{'NAME':'TRAIN_DATA_EYE', 'CONF_NAME':'CONFIG_EZYNQ_DDR_TRAIN_DATA_EYE','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Automatically train data eye during initialization'},
{'NAME':'CLOCK_STOP_EN', 'CONF_NAME':'CONFIG_EZYNQ_DDR_CLOCK_STOP_EN','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Enable clock stop'},
{'NAME':'INTERNAL_VREF', 'CONF_NAME':'CONFIG_EZYNQ_DDR_USE_INTERNAL_VREF','TYPE':'B','MANDATORY':True,'DERIVED':False,'DEFAULT':False,
'DESCRIPTION':'Use internal Vref'},
{'NAME':'OUT_SLEW_NEG', 'CONF_NAME':'CONFIG_EZYNQ_DDR_OUT_SLEW_NEG','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':26,
'DESCRIPTION':'Slew rate negative for DDR address/clock outputs'},
{'NAME':'OUT_SLEW_POS', 'CONF_NAME':'CONFIG_EZYNQ_DDR_OUT_SLEW_POS','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':26,
'DESCRIPTION':'Slew rate positive for DDR address/clock outputs'},
{'NAME':'OUT_DRIVE_NEG', 'CONF_NAME':'CONFIG_EZYNQ_DDR_OUT_DRIVE_NEG','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':12,
'DESCRIPTION':'Drive strength negative for DDR address/clock outputs'},
{'NAME':'OUT_DRIVE_POS', 'CONF_NAME':'CONFIG_EZYNQ_DDR_OUT_DRIVE_POS','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':28,
'DESCRIPTION':'Drive strength positive for DDR address/clock outputs'},
{'NAME':'BIDIR_SLEW_NEG', 'CONF_NAME':'CONFIG_EZYNQ_DDR_BIDIR_SLEW_NEG','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':31,
'DESCRIPTION':'Slew rate negative for driving DDR DQ/DQS signals'},
{'NAME':'BIDIR_SLEW_POS', 'CONF_NAME':'CONFIG_EZYNQ_DDR_BIDIR_SLEW_POS','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':6,
'DESCRIPTION':'Drive strength positive for driving DDR DQ/DQS signals'},
{'NAME':'BIDIR_DRIVE_NEG', 'CONF_NAME':'CONFIG_EZYNQ_DDR_BIDIR_DRIVE_NEG','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':12,
'DESCRIPTION':'Drive strength negative for driving DDR DQ/DQS signals'},
{'NAME':'BIDIR_DRIVE_POS', 'CONF_NAME':'CONFIG_EZYNQ_DDR_BIDIR_DRIVE_POS','TYPE':'I','MANDATORY':True,'DERIVED':False,'DEFAULT':28,
'DESCRIPTION':'Slew rate positive for driving DDR DQ/DQS signals'},
{'NAME':'RTP', 'CONF_NAME':'CONFIG_EZYNQ_DDR_RTP','TYPE':'I','MANDATORY':False,'DERIVED':False,'DEFAULT':4,
'DESCRIPTION':'Minimal Read-to-Precharge time (in tCK). Will use max of this and CONFIG_EZYNQ_DDR_T_RTP/CONFIG_EZYNQ_DDR_T_CK'},
{'NAME':'T_RTP', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_RTP','TYPE':'F','MANDATORY':False,'DERIVED':False,'DEFAULT':7.5,
'DESCRIPTION':'Minimal Read-to-Precharge time (ns). Will use max of this divided by CONFIG_EZYNQ_DDR_T_CK and CONFIG_EZYNQ_DDR_RTP'},
{'NAME':'WTR', 'CONF_NAME':'CONFIG_EZYNQ_DDR_WTR','TYPE':'I','MANDATORY':False,'DERIVED':False,'DEFAULT':4,
'DESCRIPTION':'Minimal Write-to-Read time (in tCK). Will use max of this and CONFIG_EZYNQ_DDR_T_WTR/CONFIG_EZYNQ_DDR_T_CK'},
{'NAME':'T_WTR', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_WTR','TYPE':'F','MANDATORY':False,'DERIVED':False,'DEFAULT':7.5,
'DESCRIPTION':'Minimal Write-to-Read time (ns). Will use max of this divided by CONFIG_EZYNQ_DDR_T_CK and CONFIG_EZYNQ_DDR_WTR'},
{'NAME':'XP', 'CONF_NAME':'CONFIG_EZYNQ_DDR_XP','TYPE':'I','MANDATORY':False,'DERIVED':False,'DEFAULT':4,
'DESCRIPTION':'Minimal Minimal time from power down (DLL on) to any operation (in tCK)'},
{'NAME':'T_DQSCK_MAX', 'CONF_NAME':'CONFIG_EZYNQ_DDR_T_DQSCK_MAX','TYPE':'F','MANDATORY':False,'DERIVED':False,'DEFAULT':7.5,
'DESCRIPTION':'DQS output access time from CK (ns). Used for LPDDR2 '},
# CONFIG_EZYNQ_DDR_RTP = 4
# CONFIG_EZYNQ_DDR_T_RTP = 7.5
# CONFIG_EZYNQ_DDR_WTR = 4
# CONFIG_EZYNQ_DDR_T_WTR = 7.5
# CONFIG_EZYNQ_DDR_XP = 4 # power down (DLL on) to any operation, cycles
# CONFIG_EZYNQ_DDR_T_DQSCK_MAX = 5.5 # (LPDDR2 only)
]
#TODO make some of (possibly) derived, leave '_T_' for ns only!
# CONFIG_EZYNQ_DDR_FREQ_MHZ = 533.333333 *
# CONFIG_EZYNQ_DDR_CL = 7 *
# CONFIG_EZYNQ_DDR_CWL = 6 *
# CONFIG_EZYNQ_DDR_RCD = 7 (was CONFIG_EZYNQ_DDR_T_RCD = 7) *
# CONFIG_EZYNQ_DDR_RP = 7 (was CONFIG_EZYNQ_DDR_T_RP = 7) *
# CONFIG_EZYNQ_DDR_T_RC = 48.75 *
# CONFIG_EZYNQ_DDR_T_RAS_MIN = 35.0 *
# CONFIG_EZYNQ_DDR_T_FAW = 40.0 *
# CONFIG_EZYNQ_DDR_T_RFC = 350.0
# CONFIG_EZYNQ_DDR_T_WR = 15.0
# CONFIG_EZYNQ_DDR_RTP = 4
# CONFIG_EZYNQ_DDR_tRTP = 7.5
# CONFIG_EZYNQ_DDR_WTR = 4
# CONFIG_EZYNQ_DDR_tWTR = 7.5
# CONFIG_EZYNQ_DDR_AL = 0 *
# CONFIG_EZYNQ_DDR_BANK_ADDR_COUNT = 3 *
# CONFIG_EZYNQ_DDR_ROW_ADDR_COUNT = 15 *
# CONFIG_EZYNQ_DDR_COL_ADDR_COUNT = 10 *
# CONFIG_EZYNQ_DDR_ENABLE = 1 *
# CONFIG_EZYNQ_DDR_MEMORY_TYPE = DDR3 *
# CONFIG_EZYNQ_DDR_ECC = Disabled *
# CONFIG_EZYNQ_DDR_BUS_WIDTH = 32 *
# CONFIG_EZYNQ_DDR_BL = 8 *
# CONFIG_EZYNQ_DDR_T_REFI_US = 7.8 *
# CONFIG_EZYNQ_DDR_HIGH_TEMP = Normal *
# CONFIG_EZYNQ_DDR_PARTNO = MT41K256M16RE-125 *
# CONFIG_EZYNQ_DDR_DRAM_WIDTH = 16 *
# CONFIG_EZYNQ_DDR_SPEED_BIN = DDR3_1066F *
# CONFIG_EZYNQ_DDR_TRAIN_WRITE_LEVEL = 0
# CONFIG_EZYNQ_DDR_TRAIN_READ_GATE = 0
# CONFIG_EZYNQ_DDR_TRAIN_DATA_EYE = 0
# CONFIG_EZYNQ_DDR_CLOCK_STOP_EN = 0
# CONFIG_EZYNQ_DDR_USE_INTERNAL_VREF = 0
#CONFIG_EZYNQ_DDR_DEVICE_CAPACITY_MBITS = 4096 - can be calculated
#!/usr/bin/env python
# Copyright (C) 2013, Elphel.inc.
# Definitions of Zynq DDRIOB registers
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2013, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
# DDRIOB Registers
DDRIOB_DEFS={ #not all fields are defined currently
'BASE_ADDR':(0xF8000000,), # SLCR
'MODULE_NAME':('slcr',),
'ddriob_addr0': {'OFFS': 0xb40,'DFLT':0x00000800,'RW':'RW', #0x600
'COMMENTS':'DDR IOB config for A[0:14], CKE and DRST_B',
'FIELDS':{
'reserved1': {'r':(12,31),'d':0, 'c':'Reserved'},
'pullup_en': {'r':(11,11),'d':0x1,'c':'Pullup on outputs 1- enabled, 0 - disabled'}, #0
'output_en': {'r':( 9,10),'d':0, 'c':'Output enable tied to 0 - ibuf, 3 - obuf, 1,2 - reserved'}, #3
'term_disable_mode': {'r':( 8, 8),'d':0, 'c':'0 - termination always enabled (should be during init/training), 1 - use dynamic on/off'},
'ibuf_disable_mode': {'r':( 7, 7),'d':0, 'c':'0 - ibuf enabled (should be during init/training), 1 - dynamic'},
'dci_type': {'r':( 5, 6),'d':0, 'c':'0 - DCI disabled (DDR2/3L ADDR, CLK), 1 DCI DRIVE LPDDR2, 2 - reserved, 3 - DCI term (DDR2/3/3L DQ, DQS'},
'term_en': {'r':( 4, 4),'d':0, 'c':'1 - tri-state termination enabled, 0 - disabled'},
'dci_update_b': {'r':( 3, 3),'d':0, 'c':'1 - DCI update enabled, 0 - disabled'},
'inp_type': {'r':( 1, 2),'d':0, 'c':'Input buffer control: 0 - off, 1 - Vref based (sstl, hstl), 2 - diff rcv, 3 - LVCMOS rcv'},
'inp_power': {'r':( 0, 0),'d':0, 'c':'Reserved'}}},
'ddriob_addr1': {'OFFS': 0xb44,'DFLT':0x00000800,'RW':'RW', #0x600
'COMMENTS':'DDR IOB config for BA[0:2], ODT, CS, WE, RAS, CAS',
'FIELDS':{
'reserved1': {'r':(12,31),'d':0, 'c':'Reserved'},
'pullup_en': {'r':(11,11),'d':0x1,'c':'Pullup on outputs 1- enabled, 0 - disabled'}, #0
'output_en': {'r':( 9,10),'d':0, 'c':'Output enable tied to 0 - ibuf, 3 - obuf, 1,2 - reserved'}, #3
'term_disable_mode': {'r':( 8, 8),'d':0, 'c':'0 - termination always enabled (should be during init/training), 1 - use dynamic on/off'},
'ibuf_disable_mode': {'r':( 7, 7),'d':0, 'c':'0 - ibuf enabled (should be during init/training), 1 - dynamic'},
'dci_type': {'r':( 5, 6),'d':0, 'c':'0 - DCI disabled (DDR2/3L ADDR, CLK), 1 DCI DRIVE LPDDR2, 2 - reserved, 3 - DCI term (DDR2/3/3L DQ, DQS'},
'term_en': {'r':( 4, 4),'d':0, 'c':'1 - tri-state termination enabled, 0 - disabled'},
'dci_update_b': {'r':( 3, 3),'d':0, 'c':'1 - DCI update enabled, 0 - disabled'},
'inp_type': {'r':( 1, 2),'d':0, 'c':'Input buffer control: 0 - off, 1 - Vref based (sstl, hstl), 2 - diff rcv, 3 - LVCMOS rcv'},
'inp_power': {'r':( 0, 0),'d':0, 'c':'Reserved'}}},
'ddriob_data0': {'OFFS': 0xb48,'DFLT':0x00000800,'RW':'RW', #0x672
'COMMENTS':'DDR IOB config for data[0:15]',
'FIELDS':{
'reserved1': {'r':(12,31),'d':0, 'c':'Reserved'},
'pullup_en': {'r':(11,11),'d':0x1,'c':'Pullup on outputs 1- enabled, 0 - disabled'}, #0
'output_en': {'r':( 9,10),'d':0, 'c':'Output enable tied to 0 - ibuf, 3 - obuf, 1,2 - reserved'}, #3
'term_disable_mode': {'r':( 8, 8),'d':0, 'c':'0 - termination always enabled (should be during init/training), 1 - use dynamic on/off'},
'ibuf_disable_mode': {'r':( 7, 7),'d':0, 'c':'0 - ibuf enabled (should be during init/training), 1 - dynamic'},
'dci_type': {'r':( 5, 6),'d':0, 'c':'0 - DCI disabled (DDR2/3L ADDR, CLK), 1 DCI DRIVE LPDDR2, 2 - reserved, 3 - DCI term (DDR2/3/3L DQ, DQS'}, #3
'term_en': {'r':( 4, 4),'d':0, 'c':'1 - tri-state termination enabled, 0 - disabled'}, #1
'dci_update_b': {'r':( 3, 3),'d':0, 'c':'1 - DCI update enabled, 0 - disabled'},
'inp_type': {'r':( 1, 2),'d':0, 'c':'Input buffer control: 0 - off, 1 - Vref based (sstl, hstl), 2 - diff rcv, 3 - LVCMOS rcv'},#1
'inp_power': {'r':( 0, 0),'d':0, 'c':'Reserved'}}},
'ddriob_data1': {'OFFS': 0xb4C,'DFLT':0x00000800,'RW':'RW', #0x672
'COMMENTS':'DDR IOB config for data[16:31]',
'FIELDS':{
'reserved1': {'r':(12,31),'d':0, 'c':'Reserved'},
'pullup_en': {'r':(11,11),'d':0x1,'c':'Pullup on outputs 1- enabled, 0 - disabled'}, #0
'output_en': {'r':( 9,10),'d':0, 'c':'Output enable tied to 0 - ibuf, 3 - obuf, 1,2 - reserved'}, #3
'term_disable_mode': {'r':( 8, 8),'d':0, 'c':'0 - termination always enabled (should be during init/training), 1 - use dynamic on/off'},
'ibuf_disable_mode': {'r':( 7, 7),'d':0, 'c':'0 - ibuf enabled (should be during init/training), 1 - dynamic'},
'dci_type': {'r':( 5, 6),'d':0, 'c':'0 - DCI disabled (DDR2/3L ADDR, CLK), 1 DCI DRIVE LPDDR2, 2 - reserved, 3 - DCI term (DDR2/3/3L DQ, DQS'}, #3
'term_en': {'r':( 4, 4),'d':0, 'c':'1 - tri-state termination enabled, 0 - disabled'}, #1
'dci_update_b': {'r':( 3, 3),'d':0, 'c':'1 - DCI update enabled, 0 - disabled'},
'inp_type': {'r':( 1, 2),'d':0, 'c':'Input buffer control: 0 - off, 1 - Vref based (sstl, hstl), 2 - diff rcv, 3 - LVCMOS rcv'}, #1
'inp_power': {'r':( 0, 0),'d':0, 'c':'Reserved'}}},
'ddriob_diff0': {'OFFS': 0xb50,'DFLT':0x00000800,'RW':'RW', #0x674
'COMMENTS':'DDR IOB config for DQS[0:1]',
'FIELDS':{
'reserved1': {'r':(12,31),'d':0, 'c':'Reserved'},
'pullup_en': {'r':(11,11),'d':0x1,'c':'Pullup on outputs 1- enabled, 0 - disabled'}, #0
'output_en': {'r':( 9,10),'d':0, 'c':'Output enable tied to 0 - ibuf, 3 - obuf, 1,2 - reserved'}, #3
'term_disable_mode': {'r':( 8, 8),'d':0, 'c':'0 - termination always enabled (should be during init/training), 1 - use dynamic on/off'},
'ibuf_disable_mode': {'r':( 7, 7),'d':0, 'c':'0 - ibuf enabled (should be during init/training), 1 - dynamic'},
'dci_type': {'r':( 5, 6),'d':0, 'c':'0 - DCI disabled (DDR2/3L ADDR, CLK), 1 DCI DRIVE LPDDR2, 2 - reserved, 3 - DCI term (DDR2/3/3L DQ, DQS'}, #3
'term_en': {'r':( 4, 4),'d':0, 'c':'1 - tri-state termination enabled, 0 - disabled'}, #1
'dci_update_b': {'r':( 3, 3),'d':0, 'c':'1 - DCI update enabled, 0 - disabled'},
'inp_type': {'r':( 1, 2),'d':0, 'c':'Input buffer control: 0 - off, 1 - Vref based (sstl, hstl), 2 - diff rcv, 3 - LVCMOS rcv'}, #2
'inp_power': {'r':( 0, 0),'d':0, 'c':'Reserved'}}},
'ddriob_diff1': {'OFFS': 0xb54,'DFLT':0x00000800,'RW':'RW', #0x674
'COMMENTS':'DDR IOB config for DQS[2:3]',
'FIELDS':{
'reserved1': {'r':(12,31),'d':0, 'c':'Reserved'},
'pullup_en': {'r':(11,11),'d':0x1,'c':'Pullup on outputs 1- enabled, 0 - disabled'}, #0
'output_en': {'r':( 9,10),'d':0, 'c':'Output enable tied to 0 - ibuf, 3 - obuf, 1,2 - reserved'}, #3
'term_disable_mode': {'r':( 8, 8),'d':0, 'c':'0 - termination always enabled (should be during init/training), 1 - use dynamic on/off'},
'ibuf_disable_mode': {'r':( 7, 7),'d':0, 'c':'0 - ibuf enabled (should be during init/training), 1 - dynamic'},
'dci_type': {'r':( 5, 6),'d':0, 'c':'0 - DCI disabled (DDR2/3L ADDR, CLK), 1 DCI DRIVE LPDDR2, 2 - reserved, 3 - DCI term (DDR2/3/3L DQ, DQS'}, #3
'term_en': {'r':( 4, 4),'d':0, 'c':'1 - tri-state termination enabled, 0 - disabled'}, #1
'dci_update_b': {'r':( 3, 3),'d':0, 'c':'1 - DCI update enabled, 0 - disabled'},
'inp_type': {'r':( 1, 2),'d':0, 'c':'Input buffer control: 0 - off, 1 - Vref based (sstl, hstl), 2 - diff rcv, 3 - LVCMOS rcv'}, #2
'inp_power': {'r':( 0, 0),'d':0, 'c':'Reserved'}}},
'ddriob_clock': {'OFFS': 0xb58,'DFLT':0x00000800,'RW':'RW', #use 0x600
'COMMENTS':'DDR IOB config for clock output',
'FIELDS':{
'reserved1': {'r':(12,31),'d':0, 'c':'Reserved'},
'pullup_en': {'r':(11,11),'d':0x1,'c':'Pullup on outputs 1- enabled, 0 - disabled '}, # 0
'output_en': {'r':( 9,10),'d':0, 'c':'Output enable tied to 0 - ibuf, 3 - obuf, 1,2 - reserved'}, #3
'term_disable_mode': {'r':( 8, 8),'d':0, 'c':'0 - termination always enabled (should be during init/training), 1 - use dynamic on/off'},
'ibuf_disable_mode': {'r':( 7, 7),'d':0, 'c':'0 - ibuf enabled (should be during init/training), 1 - dynamic'},
'dci_type': {'r':( 5, 6),'d':0, 'c':'0 - DCI disabled (DDR2/3L ADDR, CLK), 1 DCI DRIVE LPDDR2, 2 - reserved, 3 - DCI term (DDR2/3/3L DQ, DQS'},
'term_en': {'r':( 4, 4),'d':0, 'c':'1 - tri-state termination enabled, 0 - disabled'},
'dci_update_b': {'r':( 3, 3),'d':0, 'c':'1 - DCI update enabled, 0 - disabled'},
'inp_type': {'r':( 1, 2),'d':0, 'c':'Input buffer control: 0 - off, 1 - Vref based (sstl, hstl), 2 - diff rcv, 3 - LVCMOS rcv'},
'inp_power': {'r':( 0, 0),'d':0, 'c':'Reserved'}}},
'ddriob_drive_slew_addr': {'OFFS': 0xb5c,'DFLT':0,'RW':'RW', #0xd6861c
'COMMENTS':'Drive/slew control for address and command pins, computed by a undisclosed Xilinx algorithm using silicon version and DDR standard, should be taken from TCL code',
'FIELDS':{
'rterm': {'r':(27,31),'d':0, 'c':'Reserved'},
'gtl': {'r':(24,26),'d':0, 'c':'Reserved'},
'slew_n': {'r':(19,23),'d':0x1a,'c':'Reserved'},
'slew_p': {'r':(14,18),'d':0x1a,'c':'Reserved'},
'drive_n': {'r':( 7,13),'d':0xc, 'c':'Reserved'},
'drive_p': {'r':( 0, 6),'d':0x1c,'c':'Reserved'}}},
'ddriob_drive_slew_data': {'OFFS': 0xb60,'DFLT':0,'RW':'RW', #0xf9861c
'COMMENTS':'Drive/slew control for data pins, computed by a undisclosed Xilinx algorithm using silicon version and DDR standard, should be taken from TCL code',
'FIELDS':{
'rterm': {'r':(27,31),'d':0, 'c':'Reserved'},
'gtl': {'r':(24,26),'d':0, 'c':'Reserved'},
'slew_n': {'r':(19,23),'d':0x1f,'c':'Reserved'},
'slew_p': {'r':(14,18),'d':0x6, 'c':'Reserved'},
'drive_n': {'r':( 7,13),'d':0xc, 'c':'Reserved'},
'drive_p': {'r':( 0, 6),'d':0x1c,'c':'Reserved'}}},
'ddriob_drive_slew_diff': {'OFFS': 0xb64,'DFLT':0,'RW':'RW', #0xf9861c
'COMMENTS':'Drive/slew control for differential DQS pins, computed by a undisclosed Xilinx algorithm using silicon version and DDR standard, should be taken from TCL code',
'FIELDS':{
'rterm': {'r':(27,31),'d':0, 'c':'Reserved'},
'gtl': {'r':(24,26),'d':0, 'c':'Reserved'},
'slew_n': {'r':(19,23),'d':0x1f,'c':'Reserved'},
'slew_p': {'r':(14,18),'d':0x6, 'c':'Reserved'},
'drive_n': {'r':( 7,13),'d':0xc, 'c':'Reserved'},
'drive_p': {'r':( 0, 6),'d':0x1c,'c':'Reserved'}}},
'ddriob_drive_slew_clock': {'OFFS': 0xb68,'DFLT':0,'RW':'RW', #0xd6861c
'COMMENTS':'Drive/slew control for differential DQS pins, computed by a undisclosed Xilinx algorithm using silicon version and DDR standard, should be taken from TCL code',
'FIELDS':{
'rterm': {'r':(27,31),'d':0, 'c':'Reserved'},
'gtl': {'r':(24,26),'d':0, 'c':'Reserved'},
'slew_n': {'r':(19,23),'d':0x1a,'c':'Reserved'},
'slew_p': {'r':(14,18),'d':0x1a,'c':'Reserved'},
'drive_n': {'r':( 7,13),'d':0xc, 'c':'Reserved'},
'drive_p': {'r':( 0, 6),'d':0x1c,'c':'Reserved'}}},
'ddriob_ddr_ctrl': {'OFFS': 0xb6C,'DFLT':0x0,'RW':'RW', #0xe60
'COMMENTS':'DDR IOB buffer control',
'FIELDS':{
'reserved1': {'r':(15,31),'d':0, 'c':'Reserved'},
'cke_pullup_en': {'r':(14,14),'d':0, 'c':'Reserved'},
'drst_b_pullup_en': {'r':(13,13),'d':0, 'c':'Reserved'},
'refio_pullup_en': {'r':(12,12),'d':0, 'c':'Reserved'},
'refio_test': {'r':(10,11),'d':0, 'c':'Reserved'}, #3/0 - changing
'refio_en': {'r':( 9, 9),'d':0, 'c':'1 - use VRP/VRN, 0 - ignore'}, #1
'vref_pullup_en': {'r':( 7, 8),'d':0, 'c':'Reserved'},
'vref_ext_en': {'r':( 5, 6),'d':0, 'c':'+1 - enable external Vref for dq[0:15], +2 - en Vref for dq[16:31]'}, #3
'vref_sel': {'r':( 1, 4),'d':0, 'c':'Vref: 0 -off, 1 - 1.2/2V (LPDDR2), 2 - 1.35/2V (DDR3L), 4 - 1.5/2(DDR3), 8 - 1.8/2V(DDR2)'},
'vref_int_en': {'r':( 0, 0),'d':0, 'c':'1 - enable internal Vref'}}},
'ddriob_dci_ctrl': {'OFFS': 0xb70,'DFLT':0x20,'RW':'RW', #0x823
'COMMENTS':'DDR IOB DCI Config',
'FIELDS':{
'reserved1': {'r':(27,31),'d':0, 'c':'Reserved'},
'int_dci_en': {'r':(26,26),'d':0, 'c':'Reserved'},
'tst_rst': {'r':(25,25),'d':0, 'c':'Reserved'},
'tst_hlp': {'r':(24,24),'d':0, 'c':'Reserved'},
'tst_hln': {'r':(23,23),'d':0, 'c':'Reserved'},
'tst_clk': {'r':(22,22),'d':0, 'c':'Reserved'},
'init_complete': {'r':(21,21),'d':0, 'c':'Reserved'},
'update_control': {'r':(20,20),'d':0, 'c':'DCI update mode - use values in the Calibration Table'},
'pref_opt2': {'r':(17,19),'d':0, 'c':'DCI Calibration mode - use values in the Calibration Table'},
'pref_opt1': {'r':(14,16),'d':0, 'c':'14:15 - DCI Calibration mode - use values in the Calibration Table'},
'nref_opt4': {'r':(11,13),'d':0, 'c':'DCI Calibration mode - use values in the Calibration Table'}, #1
'nref_opt2': {'r':( 8,10),'d':0, 'c':'DCI Calibration mode - use values in the Calibration Table'},
'nref_opt1': {'r':( 6, 7),'d':0, 'c':'DCI Calibration mode - use values in the Calibration Table'},
'vrn_out': {'r':( 5, 5),'d':1, 'c':'Reserved'}, #1
'vrp_out': {'r':( 4, 4),'d':0, 'c':'Reserved'},
'vrn_tri': {'r':( 3, 3),'d':0, 'c':'Reserved'},
'vrp_tri': {'r':( 2, 2),'d':0, 'c':'Reserved'},
'enable': {'r':( 1, 1),'d':0, 'c':'DCI System enable. Silicon v2+ require set to 1'}, #1
'reset': {'r':( 0, 0),'d':0, 'c':'Toggle once to initialize FF-s in DCI system.'}}}, #1
'ddriob_dci_status': {'OFFS': 0xb74,'DFLT':0x0,'RW':'RW', #0x823
'COMMENTS':'DDR IOB buffer control',
'FIELDS':{
'reserved1': {'r':(14,31),'d':0,'m':'R', 'c':'Reserved'},
'done': {'r':(13,13),'d':0, 'c':'DCI done'},
'reserved2': {'r':(12,12),'d':0, 'c':'Reserved'},
'reserved3': {'r':(11,11),'d':0, 'c':'Reserved'},
'reserved4': {'r':(10,10),'d':0,'m':'R', 'c':'Reserved'},
'reserved5': {'r':( 9, 9),'d':0,'m':'R', 'c':'Reserved'},
'reserved6': {'r':( 8, 8),'d':0,'m':'R', 'c':'Reserved'},
'reserved7': {'r':( 7, 7),'d':0,'m':'R', 'c':'Reserved'},
'reserved8': {'r':( 6, 6),'d':0,'m':'R', 'c':'Reserved'},
'reserved9': {'r':( 5, 5),'d':0,'m':'R', 'c':'Reserved'},
'reserved10': {'r':( 3, 4),'d':0,'m':'R', 'c':'Reserved'},
'reserved11': {'r':( 2, 2),'d':0,'m':'R', 'c':'Reserved'},
'reserved12': {'r':( 1, 1),'d':0,'m':'R', 'c':'Reserved'},
'lock': {'r':( 0, 0),'d':0,'m':'R', 'c':'DCI status input'}}},
}
#!/usr/bin/env python
# Copyright (C) 2013, Elphel.inc.
# process configuration of features
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2013, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
class EzynqFeatures:
#Modify for this class
ERRORS={
'ERR_NOT_A_VARIANT': 'Specified value is not a valid variant',
'ERR_NOT_AN_INTEGER': 'Value is not an integer',
'ERR_NOT_A_FLOAT': 'Value is not a float',
'ERR_NOT_A_BOOLEAN': 'Value is not a boolean'
}
BOOLEANS=(('0','FALSE','DISABLE','DISABLED','N'),
('1','TRUE', 'ENABLE','ENABLED','Y'))
# defines - a list, order determines HTML output order
# Each element has fields:
# 'NAME' - unique name to access this parameter
# 'CONF_NAME' - how it appears in configuration file, '@' may be replaced by str(channel)
# 'TYPE' - either "I" for integer, F - float, T - text, B- boolean (may be false/true, 0/1 or enable{d}/disable{d} or tuple with valid options for value
# 'MANDATORY' - boolean: this parameter is mandatory (either directly specified or derived from some others)
# 'DERIVED' - TBD later
# 'DEFAULT' - default value (to be suggested on error? Use if not mandatory parameter?
# 'DESCRIPTION' - Parameter description - use in error message?
def _choice_val(self,t,value):
if isinstance(t,tuple) :
for c in t:
if isinstance(c,int):
try:
if (c==int(value,0)):
return c
except:
pass
elif isinstance(c,float):
try:
if (c==float(value)):
return c
except:
pass
elif isinstance(c, bool):
if value in self.BOOLEANS[1]:
return True
elif value in self.BOOLEANS[0]:
return False
elif isinstance(c, str):
return value
else:
return None
def __init__(self,defines,channel=0):
self.defs={}
for i,feature in enumerate(defines):
self.defs[feature['NAME']]=feature
self.defs[feature['NAME']]['INDEX']=i
self.channel=channel
self.pars={}
self.config_names={}
self.defined=[]
for name in self.defs:
cn=self.defs[name];
self.config_names[cn['CONF_NAME'].replace('@',str(channel))]=name
def parse_features(self,raw_configs):
for line in raw_configs:
conf_name = line['KEY']
value = line['VALUE']
value=str(value).upper()
try:
name=self.config_names[conf_name]
except:
continue
feature= self.defs[name]
if (value=='HELP'):
try:
print conf_name+': '+feature['DESCRIPTION']
except:
print conf_name+': description is not available'
continue
if isinstance(feature['TYPE'], tuple):
val=self._choice_val(feature['TYPE'],value)
if val==None:
raise Exception(self.BOOLEANS['ERR_NOT_A_VARIANT']+': '+line['VALUE'] +' is not a valid variant for parameter '+
conf_name+'. Valid are:'+str(feature['TYPE']))
else:
value=val
elif (feature['TYPE']=='I') or (feature['TYPE']=='H'):
try:
value= int(value,0)
except:
raise Exception(self.ERRORS['ERR_NOT_AN_INTEGER']+': '+line['VALUE'] +' is not a valid INTEGER value for parameter '+ conf_name)
elif (feature['TYPE']=='F'):
try:
value= float(value)
except:
raise Exception(self.ERRORS['ERR_NOT_A_FLOAT']+': '+line['VALUE'] +' is not a valid FLOAT value for parameter '+ conf_name)
elif (feature['TYPE']=='B'):
if value in self.BOOLEANS[1]:
value=True
elif value in self.BOOLEANS[0]:
value=False
else:
# print line['VALUE'],type(line['VALUE'])
# print line['VALUE'] in self.BOOLEANS[1]
raise Exception(self.ERRORS['ERR_NOT_A_BOOLEAN']+': '+line['VALUE'] +' is not a valid boolean value for parameter '+ conf_name+
'. Valid for "True" are:'+str(self.BOOLEANS[1])+', for "False" - '+str(self.BOOLEANS[0]))
elif (feature['TYPE']=='T'):
pass #keep string value
self.pars[name]=value
self.defined.append(name)
#check after calculating derivative parameters
def check_missing_features(self):
all_set=True
for name in self.defs:
if (not name in self.pars):
if self.defs[name]['MANDATORY']:
all_set=False
print "Configuration file is missing mandatory parameter "+self.defs[name]['CONF_NAME']+': '+self.defs[name]['DESCRIPTION']
else:
# use default parameter
# print 'Adding default : ',name,'=', self.defs[name]['DEFAULT']
self.pars[name]=self.defs[name]['DEFAULT']
return all_set
def get_par_names(self):
# name_offs=sorted([(name,self.registers[name]['OFFS']) for name in self.registers], key = lambda l: l[1])
# print '---self.registers=',self.registers
# unsorted_name_offs=[(name,self.defs[name]['OFFS']) for name in self.registers]
# print '---unsorted_name_offs=',unsorted_name_offs
# name_offs=sorted(unsorted_name_offs, key = lambda l: l[1])
# print '---name_offs=',name_offs
# return [n for n in name_offs]
# sort register names in the order of addresses
# name_index=sorted([(name,self.defs[name]['INDEX']) for name in self.pars], key = lambda l: l[1])
# return [n for n in sorted([(name,self.defs[name]['OFFS']) for name in self.registers], key = lambda l: l[1])]
return [n[0] for n in sorted([(name,self.defs[name]['INDEX']) for name in self.pars], key = lambda l: l[1])]
#TODO: Use SELECT for options?
def get_par_value(self,name):
try:
return self.pars[name]
except:
print 'name=',name
print self.pars
raise Exception (name+' not found in self.pars')
def html_list_features(self,html_file):
html_file.write('<table border="1">\n')
html_file.write('<tr><th>Configuration name</th><th>Value</th><th>Type/<br/>Choices</th><th>Mandatory</th><th>Derived</th><th>Default</th><th>Description</th></tr>\n')
# print self.get_par_names()
# for name in self.pars:
for name in self.get_par_names():
# name= self.config_names[conf_name]
feature= self.defs[name]
value= self.get_par_value(name)
if isinstance(value,int):
if (feature['TYPE']=='H'):
value=hex(value)
else:
value=str(value)
derived= not name in self.defined
if isinstance (feature['TYPE'],tuple):
par_type='<select>\n'
for t in feature['TYPE']:
par_type+=' <option>'+str(t)+'</option>\n'
# par_type+=('','<br/>')[i>0]+str(t)
par_type+='</select>\n'
else:
par_type={'H':'Integer','I':'Integer','F':'Float','B':'Boolean','T':'Text'}[feature['TYPE']]
html_file.write('<tr><th>'+feature['CONF_NAME']+'</th><td>'+str(value)+'</td><td>'+par_type+
'</td><td>'+('-','Y')[feature['MANDATORY']]+'</td><td>'+('-','Y')[derived]+'</td><td>'+str(feature['DEFAULT'])+'</td><td>'+feature['DESCRIPTION']+'</td></tr>\n')
html_file.write('</table>\n')
\ No newline at end of file
......@@ -21,6 +21,95 @@ __version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
# new_sets.append((addr,data,mask,self.module_name,register_name,self.registers[register_name]))
def print_html_reg_header(html_file, title='',show_bit_fields=True, show_comments=True,filter_fields=True):
if title:
html_file.write('<h2>'+title+'</h2>\n')
html_file.write('<table border="1">\n')
if show_bit_fields:
html_file.write('<tr><th>Address/<br/>bit field</th><th>Register name/<br>Bit field name</th><th>R/W</th><th>Value</th><th>Previous<br/>Value</th><th>Default</th>\n')
else:
html_file.write('<tr><th>Address</th><th>Register name</th><th>R/W</th><th>Value</th><th>Default</th>\n')
if show_comments:
html_file.write('<th>Comments</th>')
html_file.write('</tr>')
def print_html_reg_footer(html_file):
html_file.write('</table>\n')
def print_html_registers(html_file, reg_sets, show_bit_fields=True, show_comments=True,filter_fields=True):
# new_sets.append((addr,data,mask,self.module_name,register_name,self.registers[register_name]))
current_reg_state={} #address: (data,mask)
for addr, data, mask, module_name, register_name, r_def in reg_sets:
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]
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
html_file.write('<tr>\n')
try:
comments=r_def['COMMENTS']
except:
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 show_comments:
html_file.write('<th>'+comments+'</th>')
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:
f_rw=('R','RW')[field['m']!='R']
except:
f_rw='RW'
f_mask=0
r=(min(field['r'][0],field['r'][1]),max(field['r'][0],field['r'][1]))
for i in range(r[0],r[1]+1):
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 show_comments:
try:
f_comments=field['c']
except:
f_comments=''
html_file.write('<td>'+f_comments+'</td>')
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 show_comments:
html_file.write('<td>'+comments+'</td>')
html_file.write('\n</tr>\n')
current_reg_state[addr]=(new_data,new_mask)
class EzynqRegisters:
ERRORS={
'ERR_REG': 'Register name is not defined',
......@@ -35,19 +124,91 @@ class EzynqRegisters:
mask |= 1<<i
return mask
def _data(self,bits,data,warn=False):
mask=self._mask(bits)>>min(bits)
if (data & ~mask)!=0 :
mask=self._mask(bits)
smask=mask>>min(bits)
if (data & ~smask)!=0 :
msg ='Data '+hex(data)+' does not fit info the bit field '+bits
if warn:
print 'WARNING: '+msg
else:
raise Exception (self.ERRORS['ERR_BITS']+' '+msg)
return (data & mask) << min(bits)
return ((data & smask) << min(bits),mask)
def _final_data_mask(self,register_name):
if not register_name in self.defs:
raise Exception (self.ERRORS['ERR_REG']+' '+register_name)
addr=self.base_addr+self.defs[register_name]['OFFS']
try:
data,mask=self.registers[register_name] # already in the list of registers?
except:
raise Exception (self.ERRORS['ERR_REG']+' '+register_name+" is not set in this series")
try:
old_data,old_mask=self.initial_state[addr]
except:
old_data=data
old_mask=0
data = ((old_data ^ data) & mask) ^old_data
mask |= old_mask
return (data,mask)
def __init__(self,defines,channel=0,permit_undefined_bits=False):
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 get_reg_names(self):
# name_offs=sorted([(name,self.registers[name]['OFFS']) for name in self.registers], key = lambda l: l[1])
# print '---self.registers=',self.registers
# unsorted_name_offs=[(name,self.defs[name]['OFFS']) for name in self.registers]
# print '---unsorted_name_offs=',unsorted_name_offs
# name_offs=sorted(unsorted_name_offs, key = lambda l: l[1])
# print '---name_offs=',name_offs
# return [n for n in name_offs]
# sort register names in the order of addresses
# return [n for n in sorted([(name,self.defs[name]['OFFS']) for name in self.registers], key = lambda l: l[1])]
return [n[0] for n in sorted([(name,self.defs[name]['OFFS']) for name in self.registers], key = lambda l: l[1])]
#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
def get_register_sets(self, sort_addr=True,apply_new=True):
new_sets=[]
# for register_name in self.registers:
# print self.get_reg_names()
for register_name in self.get_reg_names(): # sorted by increasing offsets
addr=self.base_addr+self.defs[register_name]['OFFS']
_,mask=self.registers[register_name] # added (new only) mask, new data
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]))
if apply_new:
self.set_initial_state(new_sets, False)
self.registers={} # delete the applied registers
return self.previous_reg_sets # all register sets - previous with new attached
else:
return new_sets # only new register sets, does not change state
def __init__(self,defines,channel=0,current_reg_sets=[],permit_undefined_bits=False):
self.set_initial_state(current_reg_sets,True) # 'replay' previous register settings to the initial register state (et
self.defs=defines
self.base_addr=self.defs['BASE_ADDR'][channel]
self.registers={}
self.module_name=self.defs['MODULE_NAME'][channel]
self.registers={} # now for name it will hold (address, data, mask) tuples
# calculate R/W masks
self.ro_masks={}
for reg_name in self.defs:
......@@ -63,8 +224,6 @@ class EzynqRegisters:
# some bits are writable, some - readonly
ro_mask=0
wr_mask=0
# print '==== reg_name=',reg_name
# print '==== reg=',reg
try:
fields=reg['FIELDS']
except:
......@@ -84,19 +243,27 @@ class EzynqRegisters:
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
try:
d=self.defs[register_name]['DFLT']
old_data=self.defs[register_name]['DFLT']
except:
d=0 # DFLT not defined
# d=int (d,0)
diff = (data ^ d) & self.ro_masks[register_name]
old_data=0 # DFLT not defined
diff = (data ^ old_data) & self.ro_masks[register_name]
if diff:
msg= register_name+" readonly mask="+hex(self.ro_masks[register_name])+" default data="+hex(d)+" new data = "+data+" force="+force
msg= register_name+" readonly mask="+hex(self.ro_masks[register_name])+" previous data="+hex(old_data)+" new data = "+data+" force="+force
if force:
print 'WARNING: '+msg
else:
raise Exception (self.ERRORS['ERR_RO'] + " " + msg)
self.registers[register_name]=data
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 unset_word(self,register):
if not register in self.defs:
......@@ -110,23 +277,28 @@ class EzynqRegisters:
def set_bitfield(self,register_name,field_name,data,force=False,warn=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']
try:
old_data=self.registers[register_name] # already in the list of registers?
except:
old_data,old_mask=self.registers[register_name] # already in the list of registers?
except:
try:
old_data=self.defs[register_name]['DFLT'] # default provided?
except:
old_data=0 # DFLT not defined, use 0
old_data=old_data
#new data and mask
old_mask=0
try:
field=self.defs[register_name]['FIELDS'][field_name]
except:
print self.defs[register_name]
raise Exception (self.ERRORS['ERR_FIELD']+': '+register_name+'.'+field_name)
mask= self._mask(field['r'])
new_data=self._data(field['r'],data,warn)
combined_data= ((new_data ^ old_data) & mask) ^ old_data # new data applied to old data
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
......@@ -134,13 +306,23 @@ class EzynqRegisters:
print 'WARNING: '+msg
else:
raise Exception (self.ERRORS['ERR_RO'] + " " + msg)
self.registers[register_name]=combined_data
self.registers[register_name]=(combined_data,combined_mask)
def set_bitfields(self,register_name,field_data,force=False,warn=False):
if (len(field_data)==2) and not isinstance(field_data[1],tuple):
field_data=(field_data,)
# print field_data
for field_name,data in field_data:
self.set_bitfield(register_name,field_name,data,force,warn)
def unset_bitfield(self,register_name,field_name):
if not register_name in self.defs:
raise Exception (self.ERRORS['ERR_REG']+' '+register_name)
try:
old_data=self.registers[register_name] # already in the list of registers?
old_data,old_mask=self.registers[register_name] # already in the list of registers?
except:
return # register is not set
try:
......@@ -154,20 +336,11 @@ class EzynqRegisters:
raise Exception (self.ERRORS['ERR_FIELD']+': '+register_name+'.'+field_name)
mask= self._mask(field['r'])
combined_data= ((dflt_data ^ old_data) & mask) ^ old_data # new data applied to old data
self.registers[register_name]=combined_data # no need to verify readonly - restoring defaults
combined_mask=old_mask & (~mask)
self.registers[register_name]=(combined_data,combined_mask) # no need to verify readonly - restoring defaults
def get_reg_names(self):
# name_offs=sorted([(name,self.registers[name]['OFFS']) for name in self.registers], key = lambda l: l[1])
# print '---self.registers=',self.registers
# unsorted_name_offs=[(name,self.defs[name]['OFFS']) for name in self.registers]
# print '---unsorted_name_offs=',unsorted_name_offs
# name_offs=sorted(unsorted_name_offs, key = lambda l: l[1])
# print '---name_offs=',name_offs
# return [n for n in name_offs]
# sort register names in the order of addresses
return [n for n in sorted([(name,self.defs[name]['OFFS']) for name in self.registers], key = lambda l: l[1])]
def _get_register_address_data_default(self,register_name,from_defines=False):
def _get_register_address_data_mask_default_previous(self,register_name,from_defines=False):
if not register_name in self.defs:
raise Exception (self.ERRORS['ERR_REG']+' '+register_name)
def_reg= self.defs[register_name]
......@@ -177,19 +350,28 @@ class EzynqRegisters:
except:
dflt_data=0 #default is not defined for the register
data=dflt_data
mask=(self.ro_masks[register_name] ^ 0xffffffff) & 0xffffffff # write enabled bits in the register
try:
prev_data,_=self.initial_state[address]
except:
prev_data=-1 # never set before
#self.initial_state[addr]=(data,mask)
if not from_defines:
try:
data=self.registers[register_name]
_,mask=self.registers[register_name] # keep only this mask fro the register
data,_=self._final_data_mask(register_name) # return final data, combining mew settings with the previous
except:
raise Exception (self.ERRORS['ERR_NOTSET'] + " " + register_name)
return (address,data,dflt_data)
return (address,data,mask,dflt_data,prev_data)
def get_address_data_pairs_list(self):
return[{'ADDRESS':self.base_addr+self.defs[name]['OFFS']} for name in self.get_reg_names()]
def get_register_details(self,register_name,from_defines=False):
def get_register_details(self,register_name,from_defines=False,filter_fields=True):
# print '===register_name=',register_name
address, data, dflt_data = self._get_register_address_data_default(register_name,from_defines)
address, data, mask, dflt_data, prev_data = self._get_register_address_data_mask_default_previous(register_name,from_defines)
details={'NAME':register_name,'ADDRESS':address,'DATA':data}
def_reg= self.defs[register_name]
for key in def_reg:
......@@ -205,26 +387,33 @@ class EzynqRegisters:
details['RW']='RW'
if not 'COMMENTS' in details:
details['COMMENTS']=''
details['PREVIOUS']=prev_data #negative - not previously set
field_details=[]
for field_name in def_reg['FIELDS']:
# print '+++++ field_name=',field_name
# print ' details=',details
field_details.append(self.get_bitfield_details(register_name,field_name,from_defines))
# print '+++++ field_details=',field_details
field=self.get_bitfield_details(register_name,field_name,from_defines)
field_mask=self._mask(field['r'])
if (not filter_fields) or (field_mask & mask):
field_details.append(field)
# print '+++++ field_details=',field_details
details['FIELDS']=sorted(field_details, key = lambda rr: -rr['r'][0]) # from MSB to LSB
return details
def get_bitfield_details(self,register_name,field_name,from_defines=False):
_, data, dflt_data = self._get_register_address_data_default(register_name,from_defines)
# _, data, dflt_data = self._get_register_address_data_default(register_name,from_defines)
# address, data, mask, dflt_data, prev_data = self._get_register_address_data_mask_default_previous(register_name,from_defines)
_, data, _, dflt_data, prev_data = self._get_register_address_data_mask_default_previous(register_name,from_defines)
if not field_name in self.defs[register_name]['FIELDS']:
raise Exception (self.ERRORS['ERR_FIELD']+' '+register_name+'.'+field_name)
bit_field=self.defs[register_name]['FIELDS'][field_name]
mask=self._mask(bit_field['r'])
field_data=(data & mask) >> min(bit_field['r'])
field_dflt=(dflt_data & mask) >> min(bit_field['r'])
field_details={'NAME':field_name,'DATA':field_data}
field_prev=((prev_data & mask) >> min(bit_field['r']) & mask) >> min(bit_field['r'])
field_details={'NAME':field_name,'DATA':field_data,'PREV':field_prev}
for key in bit_field:
field_details[key]=bit_field[key]
field_details['d']=field_dflt
......@@ -236,30 +425,33 @@ class EzynqRegisters:
field_details['c']=''
return field_details
def print_html_register(self, register_name, html_file, show_bit_fields=True, show_comments=True):
r=self.get_register_details(register_name,False)
def print_html_register(self, register_name, html_file, show_bit_fields=True, show_comments=True,filter_fields=True):
r=self.get_register_details(register_name,False,filter_fields)
html_file.write('<tr>\n')
prev_data_exists=r['PREVIOUS']>=0
prev_data = ('-', hex(r['PREVIOUS']))[prev_data_exists]
if show_bit_fields:
html_file.write(' <th>'+hex(r['ADDRESS'])+'</th><th>'+r['NAME']+'</th><th>'+r['RW']+'</th><th>'+hex(r['DATA'])+'</th><th>'+hex(r['DFLT'])+'</th>')
html_file.write(' <th>'+hex(r['ADDRESS'])+'</th><th>'+r['NAME']+'</th><th>'+r['RW']+'</th><th>'+hex(r['DATA'])+'</th><th>'+prev_data+'</th><th>'+hex(r['DFLT'])+'</th>')
if show_comments:
html_file.write('<th>'+(r['COMMENTS'])+'</th>')
html_file.write('\n</tr>\n')
for field in r['FIELDS']:
field_prev=('-', hex(field['PREV']))[prev_data_exists]
html_file.write(' <tr><td>'+str(field['r'][0])+":"+str(field['r'][1])+'</td><td>'+field['NAME']+'</td><td>'+field['m']+'</td>')
html_file.write('<td>'+hex(field['DATA'])+'</td><td>'+hex(field['d'])+'</td>')
html_file.write('<td>'+hex(field['DATA'])+'</td><td>'+field_prev+'</td><td>'+hex(field['d'])+'</td>')
if show_comments:
html_file.write('<td>'+(field['c'])+'</td>')
html_file.write('\n</tr>\n')
else:
html_file.write(' <th>'+hex(r['ADDRESS'])+'</th><td>'+r['NAME']+'</td><td>'+r['RW']+'</td><td><b>'+hex(r['DATA'])+'</b></td><td>'+hex(r['DFLT'])+'</td>')
html_file.write(' <th>'+hex(r['ADDRESS'])+'</th><td>'+r['NAME']+'</td><td>'+r['RW']+'</td><td><b>'+hex(r['DATA'])+'</th><th>'+prev_data+'</b></td><td>'+hex(r['DFLT'])+'</td>')
if show_comments:
html_file.write('<td>'+r['COMMENTS']+'</td>')
html_file.write('\n</tr>\n')
def print_html_registers(self, html_file, show_bit_fields=True, show_comments=True):
def print_html_registers(self, html_file, show_bit_fields=True, show_comments=True,filter_fields=True):
html_file.write('<table border="1">\n')
if show_bit_fields:
html_file.write('<tr><th>Address/<br/>bit field</th><th>Register name/<br>Bit field name</th><th>R/W</th><th>Value</th><th>Default</th>\n')
html_file.write('<tr><th>Address/<br/>bit field</th><th>Register name/<br>Bit field name</th><th>R/W</th><th>Value</th><th>Previous<br/>Value</th><th>Default</th>\n')
if show_comments:
html_file.write('<th>Comments</th>')
html_file.write('</tr>')
......@@ -270,7 +462,7 @@ class EzynqRegisters:
html_file.write('</tr>')
for register in self.get_reg_names():
self.print_html_register(register[0], html_file, show_bit_fields, show_comments)
self.print_html_register(register[0], html_file, show_bit_fields, show_comments,filter_fields)
html_file.write('</table>\n')
......
......@@ -23,6 +23,7 @@ __email__ = "andrey@elphel.com"
__status__ = "Development"
import struct
import ezynq_ddr
import ezynq_registers
# http://docs.python.org/2/howto/argparse.html
import argparse
......@@ -943,9 +944,11 @@ raw_configs=read_config(args.configs)
permit_undefined_bits=False
force=True #False
warn_notfit=True # False
ddr=ezynq_ddr.EzynqDDR(permit_undefined_bits, force, warn_notfit)
ddr.parse_raw_register_set(raw_configs,QUALIFIER_CHAR,force,warn_notfit)
regs_masked=[]
ddr=ezynq_ddr.EzynqDDR(regs_masked,permit_undefined_bits, force, warn_notfit)
ddr.parse_parameters(raw_configs)
##ddr.parse_ddriob_raw_register_set(raw_configs,QUALIFIER_CHAR,force,warn_notfit)
##ddr.parse_ddrc_raw_register_set(raw_configs,QUALIFIER_CHAR,force,warn_notfit)
#ddr.print_html_registers(html_file, show_bit_fields=True, show_comments=True)
#class EzynqDDR:
# def __init__(self,permit_undefined_bits=False,force=False,warn=False):
......@@ -999,7 +1002,26 @@ else:
#output_slcr_lock(registers,f,False,MIO_HTML_MASK) #prohibited by RBL
output_mio(registers,f,mio,MIO_HTML_MASK)
ddr.print_html_registers(f, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200)
ddr.check_missing_features()
ddr.html_list_features(f)
#ddr.ddr_init_memory(current_reg_sets,force=False,warn=False): # will program to sequence 'MAIN'
ddr.ddr_init_memory([],False,False) # will program to sequence 'MAIN'
reg_sets=ddr.get_new_register_sets()
#ezynq_registers.print_html_reg_header(f, title, show_bit_fields=True, show_comments=True,filter_fields=True)
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, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400)
#print_html_registers(html_file, reg_sets, show_bit_fields=True, show_comments=True,filter_fields=True):
ezynq_registers.print_html_reg_footer(f)
#ddr.print_html_registers(f, MIO_HTML_MASK & 0x100, MIO_HTML_MASK & 0x200, not MIO_HTML_MASK & 0x400) #filter_fields=True
#output_gpio_out(registers,f,MIO_HTML_MASK) #prohibited by RBL
......
......@@ -81,7 +81,154 @@ CONFIG_EZYNQ_BOOT_OCM_IMAGE_LENGTH= 0#0x30000 # number of bytes to load to the
CONFIG_EZYNQ_START_EXEC= 0x00 # start of execution address
CONFIG_EZYNQ_DDR_PERIPHERAL_CLKSRC = DDR PLL
CONFIG_EZYNQ_DDR_RAM_BASEADDR = 0x00100000
CONFIG_EZYNQ_DDR_RAM_HIGHADDR = 0x3FFFFFFF
CONFIG_EZYNQ_DDR_TARGET_FREQ_MHZ = 533.3333 # New added
CONFIG_EZYNQ_DDR_FREQ_MHZ = 533.333374 # Taking available CLK and divisors into account?
CONFIG_EZYNQ_DCI_PERIPHERAL_FREQMHZ = 10.158731 # Taking available CLK and divisors into account?
CONFIG_EZYNQ_DDR_ENABLE = 1
CONFIG_EZYNQ_DDR_MEMORY_TYPE = DDR3
CONFIG_EZYNQ_DDR_ECC = Disabled
CONFIG_EZYNQ_DDR_BUS_WIDTH = 32
CONFIG_EZYNQ_DDR_BL = 8
CONFIG_EZYNQ_DDR_HIGH_TEMP = False # Normal
CONFIG_EZYNQ_DDR_T_REFI_US = 7.8
CONFIG_EZYNQ_DDR_T_RFC = 300 # 350.0
CONFIG_EZYNQ_DDR_T_WR = 15.0 # Write recovery time
CONFIG_EZYNQ_DDR_RTP = 4
CONFIG_EZYNQ_DDR_T_RTP = 7.5
CONFIG_EZYNQ_DDR_WTR = 4
CONFIG_EZYNQ_DDR_T_WTR = 7.5
CONFIG_EZYNQ_DDR_XP = 4 # power down (DLL on) to any operation, cycles
CONFIG_EZYNQ_DDR_T_DQSCK_MAX = 5.5 # (LPDDR2 only)
CONFIG_EZYNQ_DDR_PARTNO = MT41K256M16RE-125
CONFIG_EZYNQ_DDR_DRAM_WIDTH = 16
#CONFIG_EZYNQ_DDR_DEVICE_CAPACITY_MBITS = 4096 - can be calculated
CONFIG_EZYNQ_DDR_SPEED_BIN = DDR3_1066F
CONFIG_EZYNQ_DDR_TRAIN_WRITE_LEVEL = 0
CONFIG_EZYNQ_DDR_TRAIN_READ_GATE = 0
CONFIG_EZYNQ_DDR_TRAIN_DATA_EYE = 0
CONFIG_EZYNQ_DDR_CLOCK_STOP_EN = 0
CONFIG_EZYNQ_DDR_USE_INTERNAL_VREF = 0
# undisclosed algorithm, get values from ps7*
CONFIG_EZYNQ_DDR_OUT_SLEW_NEG = 26
CONFIG_EZYNQ_DDR_OUT_SLEW_POS = 26
CONFIG_EZYNQ_DDR_OUT_DRIVE_NEG = 12
CONFIG_EZYNQ_DDR_OUT_DRIVE_POS = 28
CONFIG_EZYNQ_DDR_BIDIR_SLEW_NEG = 31
CONFIG_EZYNQ_DDR_BIDIR_SLEW_POS = 6
CONFIG_EZYNQ_DDR_BIDIR_DRIVE_NEG = 12
CONFIG_EZYNQ_DDR_BIDIR_DRIVE_POS = 28
CONFIG_EZYNQ_DDR_FREQ_MHZ = 533.333333
CONFIG_EZYNQ_DDR_BANK_ADDR_COUNT = 3
CONFIG_EZYNQ_DDR_ROW_ADDR_COUNT = 15
CONFIG_EZYNQ_DDR_COL_ADDR_COUNT = 10
CONFIG_EZYNQ_DDR_CL = 7
CONFIG_EZYNQ_DDR_CWL = 6
#CONFIG_EZYNQ_DDR_T_RCD = 7
#CONFIG_EZYNQ_DDR_T_RP = 7
CONFIG_EZYNQ_DDR_RCD = 7
CONFIG_EZYNQ_DDR_RP = 7
CONFIG_EZYNQ_DDR_T_RC = 48.75
CONFIG_EZYNQ_DDR_T_RAS_MIN = 35.0
CONFIG_EZYNQ_DDR_T_FAW = 40.0
CONFIG_EZYNQ_DDR_AL = 0
CONFIG_EZYNQ_DDR_DQS_TO_CLK_DELAY_0 = 0.0
CONFIG_EZYNQ_DDR_DQS_TO_CLK_DELAY_1 = 0.0
CONFIG_EZYNQ_DDR_DQS_TO_CLK_DELAY_2 = 0.0
CONFIG_EZYNQ_DDR_DQS_TO_CLK_DELAY_3 = 0.0
CONFIG_EZYNQ_DDR_BOARD_DELAY0 = 0.0
CONFIG_EZYNQ_DDR_BOARD_DELAY1 = 0.0
CONFIG_EZYNQ_DDR_BOARD_DELAY2 = 0.0
CONFIG_EZYNQ_DDR_BOARD_DELAY3 = 0.0
CONFIG_EZYNQ_DDR_DQS_0_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_DQS_1_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_DQS_2_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_DQS_3_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_DQ_0_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_DQ_1_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_DQ_2_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_DQ_3_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_CLOCK_0_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_CLOCK_1_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_CLOCK_2_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_CLOCK_3_LENGTH_MM = 0
CONFIG_EZYNQ_DDR_DQS_0_PACKAGE_LENGTH = 504
CONFIG_EZYNQ_DDR_DQS_1_PACKAGE_LENGTH = 495
CONFIG_EZYNQ_DDR_DQS_2_PACKAGE_LENGTH = 520
CONFIG_EZYNQ_DDR_DQS_3_PACKAGE_LENGTH = 835
CONFIG_EZYNQ_DDR_DQ_0_PACKAGE_LENGTH = 465
CONFIG_EZYNQ_DDR_DQ_1_PACKAGE_LENGTH = 480
CONFIG_EZYNQ_DDR_DQ_2_PACKAGE_LENGTH = 550
CONFIG_EZYNQ_DDR_DQ_3_PACKAGE_LENGTH = 780
CONFIG_EZYNQ_DDR_CLOCK_0_PACKAGE_LENGTH = 470.0
CONFIG_EZYNQ_DDR_CLOCK_1_PACKAGE_LENGTH = 470.0
CONFIG_EZYNQ_DDR_CLOCK_2_PACKAGE_LENGTH = 470.0
CONFIG_EZYNQ_DDR_CLOCK_3_PACKAGE_LENGTH = 470.0
CONFIG_EZYNQ_DDR_DQS_0_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_DQS_1_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_DQS_2_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_DQS_3_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_DQ_0_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_DQ_1_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_DQ_2_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_DQ_3_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_CLOCK_0_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_CLOCK_1_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_CLOCK_2_PROPOGATION_DELAY = 160
CONFIG_EZYNQ_DDR_CLOCK_3_PROPOGATION_DELAY = 160
# PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_0 = -0.005
# PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_1 = -0.004
# PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_2 = -0.008
# PCW_PACKAGE_DDR_DQS_TO_CLK_DELAY_3 = -0.058
# PCW_PACKAGE_DDR_BOARD_DELAY0 = 0.075
# PCW_PACKAGE_DDR_BOARD_DELAY1 = 0.076
# PCW_PACKAGE_DDR_BOARD_DELAY2 = 0.082
# PCW_PACKAGE_DDR_BOARD_DELAY3 = 0.100
#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
# 'reg_ddrc_selfref_en': {'r':(12,12),'d':0,'c':'Dynamic - 1 - go to Self Refresh when transaction store is empty'},
# 'reserved1': {'r':(11,11),'d':0,'m':'R','c':'reserved'},
# 'reg_ddrc_dis_collision_page_opt': {'r':(10,10),'d':0,'c':'Disable autoprecharge for collisions (write+write or read+write to the same address) when reg_ddrc_dis_wc==1'},
# 'reg_ddrc_dis_wc': {'r':( 9, 9),'d':0,'c':'1 - disable write combine, 0 - enable'},
# 'reg_ddrc_refresh_update_level': {'r':( 8, 8),'d':0,'c':'Dynamic: toggle to indicate refressh register(s) update'},
# 'reg_ddrc_auto_pre_en': {'r':( 7, 7),'d':0,'c':'1 - most R/W will be with autoprecharge'},
# 'reg_ddrc_lpr_num_entries': {'r':( 1, 6),'d':0x1F,'c':'(bit 6 ignored) (Size of low priority transaction store+1). HPR - 32 - this value'},
# 'reg_ddrc_pageclose': {'r':( 0, 0),'d':0,'c':'1 - close bank if no transactions in the store for it, 0 - keep open until not needed by other'}}},
# 'phy_wr_dqs_cfg0': {'OFFS': 0x154,'DFLT':0x00000000,'RW':'RW','FIELDS':{
# 'reg_phy_wr_dqs_slave_delay': {'r':(11,19),'d':0,'c':'If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 0'},
# 'reg_phy_wr_dqs_slave_force': {'r':(10,10),'d':0,'c':'0 - use reg_phy_wr_dqs_slave_ratio for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 0'},
# 'reg_phy_wr_dqs_slave_ratio': {'r':( 0, 9),'d':0,'c':'Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 0. Program manual training ratio'}}},
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