Commit 6ae98d30 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

Merge branch 'master' of ssh://git.code.sf.net/p/elphel/ezynq

parents 189514d6 ef0b31fc
Development of the ROM boot loader header generator for Xilinx Zynq based boards Ezynq project is started to create a bootloader for systems based on the Xilinx Zynq SoC without
The included sample zed_ezynq.h provides defines for Microzed board, it is to be included in includes/configs/<boardname>.h the inconvenience of the non-free tools and/or files.
After running The goal is not just to "free" the code, but to provide users with the higher degree of flexibi-
make <boardname>_congig lity in fine-tuning of the configuration parameters.
and then
make
the include/autoconf.mk will be generated and you can run
./ezynqcfg.py -c include/autoconf.mk [-o boot_head.bin] [--html u-boot.html [--html-mask 255]] [-v]
This command will generate boot_head.bin and u-boot.html Initial release includes configuration for the MicroZed board we used for this software develop-
When there will be u-boot running from OCM, it will be possible to make a bootable immage with ment, we plan to add support for more boards, including Elphel NC393 camera - the reason we
cat boot_head.bin u-boot.bin > boot.bin started this project.
Ezynq partially duplicates functionality of Xilinx proprietary tools - bootgen and fsbl (first
stage boot loader). It does not support secure boot functionality (that we have no interest in)
and loading the FPGA (PL) part with the bitstream - we plan to do that under control of the
operating system as we did in our earlier products, if needed this feature can be implemented
using U-boot.
This software consists of Python program that processes data from U-boot configuration files
(configuration parameters start with CONFIG_EZYNQ_ prefix) that are collected in
include/autoconf.mk (it is generated by "make include/autoconf.mk") and generates several output
files:
1 - the header file (default name boot_head.bin) formatted for the Zynq ROM Boot Loader (RBL)
according to section 6.3.2 of Xilinx UG585 -"Zynq-7000 AP SoC Technical Reference Manual". This
file uses RBL register initialization feature to set registers (MIO, DDR) that can be written
before system clocks and DDR memory are initialized - that requires polling status information
and waiting for particular states are reached.
2 - ezynq.c file to be compiled and linked with other U-boot files. All ezynq-specific code is
called by a modified version of the arch_cpu_init() function - the only difference from the
U-boot version for Xilinx Zynq designed to be used with the proprietary FSBL program. This code
finishes register initialization (contrary to RBL it can wait for certain states are reached)
and performs relocation of the code from the on-chip memory (OCM) to the main system memory,
U-boot takes over from there. Optionally the debug code is generated that controls the LED state
at different stages of the boot process and outputs register states to the serial port.
3 - html output file (default name u-boot.html) that lists the configuration parameters used
(specified and calculated from others), used PLLs and clocks, configured interfaces and their
usage of the MIO pins. It then lists all the registers written by RBL and written/tested during
execution of the arch_cpu_init(). Most of the registers are listed in the same sequence as they
are set in hardware, the very last ones show registers that may be set/tested multiple times (as
related to UART debug data output). The software keeps track of the register data writes and
uses the default values provided in UG585, so when only some bit fields of the whole register
need to be modified, software relies on the calculated previous value and does not perform read
operations on the actual registers before writing the modified data back.
The U-boot version designed to be used with FSBL relied on it to initialize registers, clocks
and DRAM memory, load U-boot image to DRAM at address 0x4000000 and pass control there. FSBL
itself was loaded by RBL into on-chip memory (OCM) at address 0, having 192K of the total 256K
mapped to 0x0..0x2ffff and the remaining 64K - to the upper 0xffff0000..0xffffffff, the same
mapping is passed to U-boot that uses the high OCM memory for stack initially and later remaps
all of the OCM to 0xfffc0000.0xffffffff. Starting from 0x4000000 U-boot relocates itself to
address zero and runs there.
When using Ezynq the size of the U-boot image is limited to 192K - it is all what Zynq RBL can
load by itself. It is quite a lot (192K is just for code, data uses DRAM and is not limited by
the OCM) so U-boot can be loaded in a simple one-stage process without the need of the SPL when
first a mini-version of U-boot is loaded, and that version later loads the full U-boot to DRAM.
Generated arch_cpu_init() starts running in OCM, initializes DRAM, copies itself (first 192K
OCM) to DRAM to 0x4000000.0x402ffff (using just C, not assembly code) and than adds 0x4000000 to
the program counter. In this state it is possible to map DRAM to the 0x0.0x2ffff instead of the
OCM and copy 0x4000000.0x402ffff back to 0x0.0x2ffff and so return from the function
arch_cpu_init() gets the execution to the same low address where it started, but now it is in
the DRAM, not in the OCM. U-boot relocation functionality nicely skips actual relocation (as
the source and destination addresses are the same) and the data memory is initialized when 192K
OCM limit is not in effect anymore.
INSTALLATION (see below for testing without U-boot installation)
When Ezynq repository is cloned, there is install_uboot.sh script in the top directory. Running
this script clones u-boot-xlnx and then adds links to the files in Ezynq sub-directory
u-boot-tree from the corresponding directories of the u-boot-xlnx, that allows to update Ezynq
project files by "git pull".
These links created by install_uboot.sh add new configuration files and replace 3 files in the
u-boot-xlnx:
* boards.cfg - adding zynq-microzed there
* arch/arm/cpu/armv7/zynq/cpu.c - disabling arch_cpu_init() there if configuration was made for
Ezynq
* arch/arm/cpu/armv7/zynq/Makefile - to add autogenerated (not in the repository)
arch/arm/cpu/armv7/zynq/ezynq.c
New files include:
* include/configs/zynq_microzed.h configuration parameters for U-boot features, described in
U-boot README file
* include/configs/ezynq/ezynq_MT41K256M16RE125.h - Ezynq configuration parameters containing
Micron DDR3 memory datasheet for the memory used by MicroZed board
* include/configs/ezynq/ezynq_XC7Z010_1CLG400.h - Ezynq configuration parameters containing
Xilinx Zynq datasheet data for the SoC used by MicroZed board
* include/configs/ezynq/ezynq_XC7Z010_1CLG400.h - Ezynq configuration parameters containing
Xilinx Zynq datasheet data for the SoC used by MicroZed board
* include/configs/ezynq/zed_ezynq.h - rest of the Ezynq configuration parameters (it has the
include lines for the 2 datasheet files listed above)
* makeuboot - script that configures U-boot for the microzed board, creates include/autoconf.mk,
runs ezynqcfg.py to create Ezynq code (RBL header and ezynq.c), builds and links U-boot
generating u-boot.bin, reruns ezynqcfg.py to include the length of the u-boot.bin into
boot_head.bin and then combines boot_head.bin and u-boot.bin into boot.bin with a simple
'cat' command.
TESTING WITHOUT U-BOOT AND CROSS-COMPILER TOOLCHAIN
It is possible to try just the ezynqcfg.py script without building u-boot, no ARM toolchain
is required
./ezynqcfg.py -c test.mk --html test.html --html-mask 0x3ff --lowlevel ezynq.c
This command uses a demo test.mk that mimics include/autoconf.mk and generates test.html and
ezynq.c files
For testing the program it is possible to make a shortcut and substitute the autoconf.mk with a manually edited file,
such as test.mk - it has some examples of other valid defines to fine-tune the hardware configuration
Temporary testing is performed with (only html file output):
./ezynqcfg.py -c test.mk --html test.html --html-mask 0x3ff
...@@ -563,6 +563,88 @@ class EzynqClk: ...@@ -563,6 +563,88 @@ class EzynqClk:
clk_register_set.set_bitfields('arm_pll_ctrl',(('pll_bypass_force', 0), clk_register_set.set_bitfields('arm_pll_ctrl',(('pll_bypass_force', 0),
('pll_bypass_qual', 0)),force,warn) ('pll_bypass_qual', 0)),force,warn)
return self.get_new_register_sets() return self.get_new_register_sets()
# reset instantiated peripherals
def reset_peripherals(self,current_reg_sets,force=False,warn=False):
# print ezynq_slcr_clk_def.RESETS
extra_interfaces=[{'NAME':'DMA'}]
used_interfaces=self.used_mio_interfaces+extra_interfaces
def set_resets(reset_on):
for iface in used_interfaces:
name=iface['NAME']
if name in ezynq_slcr_clk_def.RESETS:
rst=ezynq_slcr_clk_def.RESETS[name]
if len(rst)>1:
rst=rst[iface['CHANNEL']]
else:
rst=rst[0]
fields=[]
for fld in rst['FIELDS']:
# print name, fld
fields.append((fld['FIELD_NAME'],fld[('OFF','RST')[reset_on]]))
rst_register_set.set_bitfields(rst['REG'],tuple(fields),force,warn)
rst_register_set=self.clk_register_set
rst_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
set_resets(True)
rst_register_set.flush()
set_resets(False)
return rst_register_set.get_register_sets(True,True)
#
# self.used_mio_interfaces
# uart_register_set=self.uart_register_set
# slcr_register_set=self.slcr_register_set
# slcr_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
# slcr_register_set.set_bitfields('uart_rst_ctrl',( # dflt=0
# ('uart1_ref_rst', self.channel==1), # UART 1 reference clock domain reset: 0 - normal, 1 - reset
# ('uart0_ref_rst', self.channel==0), # UART 0 reference clock domain reset: 0 - normal, 1 - reset
# ('uart1_cpu1x_rst', self.channel==1), # UART 1 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
# ('uart0_cpu1x_rst', self.channel==0)),force,warn) #UART 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
# slcr_register_set.flush()
# slcr_register_set.set_bitfields('uart_rst_ctrl',( # dflt=0
# ('uart1_ref_rst', 0), # UART 1 reference clock domain reset: 0 - normal, 1 - reset
# ('uart0_ref_rst', 0), # UART 0 reference clock domain reset: 0 - normal, 1 - reset
# ('uart1_cpu1x_rst', 0), # UART 1 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
# ('uart0_cpu1x_rst', 0)),force,warn) #UART 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
# reg_sets=slcr_register_set.get_register_sets(sort_addr=True,apply_new=True)
# RESETS= {'DMA': ({'REG':'dmac_rst_ctrl','FIELDS':({'FIELD_NAME':'dmac_rst', 'RST':1,'OFF':0})}),
# 'USB': ({'REG':'usb_rst_ctrl', 'FIELDS':({'FIELD_NAME':'usb0_cpu1x_rst', 'RST':1,'OFF':0})},
# {'REG':'usb_rst_ctrl', 'FIELDS':({'FIELD_NAME':'usb1_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'ETH': ({'REG':'gem_rst_ctrl', 'FIELDS':({'FIELD_NAME':'gem0_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'gem0_rx_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'gem0_cpu1x_rst', 'RST':1,'OFF':0})},
# {'REG':'gem_rst_ctrl', 'FIELDS':({'FIELD_NAME':'gem1_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'gem1_rx_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'gem1_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'SDIO':({'REG':'sdio_rst_ctrl','FIELDS':({'FIELD_NAME':'sdio0_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'sdio0_cpu1x_rst', 'RST':1,'OFF':0})},
# {'REG':'sdio_rst_ctrl','FIELDS':({'FIELD_NAME':'sdio1_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'sdio1_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'SPI': ({'REG':'spi_rst_ctrl', 'FIELDS':({'FIELD_NAME':'spi0_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'spi0_cpu1x_rst', 'RST':1,'OFF':0})},
# {'REG':'spi_rst_ctrl', 'FIELDS':({'FIELD_NAME':'spi1_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'spi1_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'CAN': ({'REG':'can_rst_ctrl', 'FIELDS':({'FIELD_NAME':'can0_cpu1x_rst', 'RST':1,'OFF':0})},
# {'REG':'can_rst_ctrl', 'FIELDS':({'FIELD_NAME':'can1_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'I2C': ({'REG':'i2c_rst_ctrl', 'FIELDS':({'FIELD_NAME':'i2c0_cpu1x_rst', 'RST':1,'OFF':0})},
# {'REG':'i2c_rst_ctrl', 'FIELDS':({'FIELD_NAME':'i2c1_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'UART':({'REG':'uart_rst_ctrl','FIELDS':({'FIELD_NAME':'uart0_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'uart0_cpu1x_rst', 'RST':1,'OFF':0})},
# {'REG':'uart_rst_ctrl','FIELDS':({'FIELD_NAME':'uart1_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'uart1_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'GPIO':({'REG':'gpio_rst_ctrl','FIELDS':({'FIELD_NAME':'gpio_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'QSPI':({'REG':'qspi_rst_ctrl','FIELDS':({'FIELD_NAME':'qspi_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'qspi_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'NAND':({'REG':'smc_rst_ctrl', 'FIELDS':({'FIELD_NAME':'smc_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'smc_cpu1x_rst', 'RST':1,'OFF':0})}),
# 'NOR': ({'REG':'smc_rst_ctrl', 'FIELDS':({'FIELD_NAME':'smc_ref_rst', 'RST':1,'OFF':0},
# {'FIELD_NAME':'smc_cpu1x_rst', 'RST':1,'OFF':0})}),
# }
#clocks setup #clocks setup
......
...@@ -503,13 +503,13 @@ SLCR_CLK_DEFS={ #not all fields are defined currently ...@@ -503,13 +503,13 @@ SLCR_CLK_DEFS={ #not all fields are defined currently
'COMMENTS':'Central interconnect software reset control', 'COMMENTS':'Central interconnect software reset control',
'FIELDS':{ 'FIELDS':{
'reserved': {'r':( 1,31),'d':0, 'c':'reserved'}, 'reserved': {'r':( 1,31),'d':0, 'c':'reserved'},
'ddr_rst': {'r':( 0, 0),'d':0, 'c':'Central interconnect reset: 0 - normal, 1 - reset. Make sure AXI does not have outstanding transactions and the bus is idle'}}}, 'topsw_rst': {'r':( 0, 0),'d':0, 'c':'Central interconnect reset: 0 - normal, 1 - reset. Make sure AXI does not have outstanding transactions and the bus is idle'}}},
'dmac_rst_ctrl': {'OFFS': 0x20c,'DFLT':0,'RW':'RW', # Never set 'dmac_rst_ctrl': {'OFFS': 0x20c,'DFLT':0,'RW':'RW', # Never set
'COMMENTS':'DMA controller software reset control', 'COMMENTS':'DMA controller software reset control',
'FIELDS':{ 'FIELDS':{
'reserved': {'r':( 1,31),'d':0, 'c':'reserved'}, 'reserved': {'r':( 1,31),'d':0, 'c':'reserved'},
'ddr_rst': {'r':( 0, 0),'d':0, 'c':'DMA controller reset: 0 - normal, 1 - reset (and write enable DMAC trust zone register)'}}}, 'dmac_rst': {'r':( 0, 0),'d':0, 'c':'DMA controller reset: 0 - normal, 1 - reset (and write enable DMAC trust zone register)'}}},
'usb_rst_ctrl': {'OFFS': 0x210,'DFLT':0,'RW':'RW', # Never set 'usb_rst_ctrl': {'OFFS': 0x210,'DFLT':0,'RW':'RW', # Never set
'COMMENTS':'USB software reset control', 'COMMENTS':'USB software reset control',
...@@ -549,7 +549,7 @@ SLCR_CLK_DEFS={ #not all fields are defined currently ...@@ -549,7 +549,7 @@ SLCR_CLK_DEFS={ #not all fields are defined currently
'spi1_cpu1x_rst': {'r':( 1, 1),'d':0, 'c':'SPI 1 CPU_1x clock domain reset: 0 - normal, 1 - reset'}, 'spi1_cpu1x_rst': {'r':( 1, 1),'d':0, 'c':'SPI 1 CPU_1x clock domain reset: 0 - normal, 1 - reset'},
'spi0_cpu1x_rst': {'r':( 0, 0),'d':0, 'c':'SPI 0 CPU_1x clock domain reset: 0 - normal, 1 - reset'}}}, 'spi0_cpu1x_rst': {'r':( 0, 0),'d':0, 'c':'SPI 0 CPU_1x clock domain reset: 0 - normal, 1 - reset'}}},
'cam_rst_ctrl': {'OFFS': 0x220,'DFLT':0,'RW':'RW', # Never set 'can_rst_ctrl': {'OFFS': 0x220,'DFLT':0,'RW':'RW', # Never set
'COMMENTS':'CAN software reset control', 'COMMENTS':'CAN software reset control',
'FIELDS':{ 'FIELDS':{
'reserved1': {'r':( 4,31),'d':0, 'c':'reserved'}, 'reserved1': {'r':( 4,31),'d':0, 'c':'reserved'},
...@@ -580,15 +580,15 @@ SLCR_CLK_DEFS={ #not all fields are defined currently ...@@ -580,15 +580,15 @@ SLCR_CLK_DEFS={ #not all fields are defined currently
'reserved': {'r':( 1,31),'d':0, 'c':'reserved'}, 'reserved': {'r':( 1,31),'d':0, 'c':'reserved'},
'gpio_cpu1x_rst': {'r':( 0, 0),'d':0, 'c':'GPIO 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset'}}}, 'gpio_cpu1x_rst': {'r':( 0, 0),'d':0, 'c':'GPIO 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset'}}},
'lqspi_rst_ctrl': {'OFFS': 0x230,'DFLT':0,'RW':'RW', # Never set 'qspi_rst_ctrl': {'OFFS': 0x230,'DFLT':0,'RW':'RW', # Never set
'COMMENTS':'Quad SPI software reset control for reference clock and CPU_1x (AMBA) clock domains', 'COMMENTS':'Quad SPI software reset control for reference clock and CPU_1x (AMBA) clock domains',
'FIELDS':{ 'FIELDS':{
'reserved': {'r':( 2,31),'d':0, 'c':'reserved'}, 'reserved': {'r':( 2,31),'d':0, 'c':'reserved'},
'qspi_ref_rst': {'r':( 1, 1),'d':0, 'c':'QSPI reference clock domain reset: 0 - normal, 1 - reset'}, 'qspi_ref_rst': {'r':( 1, 1),'d':0, 'c':'QSPI reference clock domain reset: 0 - normal, 1 - reset'},
'lqspi_cpu1x_rst': {'r':( 0, 0),'d':0, 'c':'QSPI CPU_1x clock domain reset: 0 - normal, 1 - reset'}}}, 'qspi_cpu1x_rst': {'r':( 0, 0),'d':0, 'c':'QSPI CPU_1x clock domain reset: 0 - normal, 1 - reset'}}},
'smc_rst_ctrl': {'OFFS': 0x234,'DFLT':0,'RW':'RW', # Never set 'smc_rst_ctrl': {'OFFS': 0x234,'DFLT':0,'RW':'RW', # Never set
'COMMENTS':'Quad SPI software reset control for reference clock and CPU_1x (AMBA) clock domains', 'COMMENTS':'SMS software reset control for reference clock and CPU_1x (AMBA) clock domains',
'FIELDS':{ 'FIELDS':{
'reserved': {'r':( 2,31),'d':0, 'c':'reserved'}, 'reserved': {'r':( 2,31),'d':0, 'c':'reserved'},
'smc_ref_rst': {'r':( 1, 1),'d':0, 'c':'SMC reference clock domain reset: 0 - normal, 1 - reset'}, 'smc_ref_rst': {'r':( 1, 1),'d':0, 'c':'SMC reference clock domain reset: 0 - normal, 1 - reset'},
...@@ -780,3 +780,38 @@ PLL_PARS=(( 13, 2,6,750), ...@@ -780,3 +780,38 @@ PLL_PARS=(( 13, 2,6,750),
((37,40),2,12,250), ((37,40),2,12,250),
((41,47),3,12,250), ((41,47),3,12,250),
((48,66),3,12,250)) ((48,66),3,12,250))
RESETS= {'DMA': ({'REG':'dmac_rst_ctrl','FIELDS':({'FIELD_NAME':'dmac_rst', 'RST':1,'OFF':0},)},),
'USB': ({'REG':'usb_rst_ctrl', 'FIELDS':({'FIELD_NAME':'usb0_cpu1x_rst', 'RST':1,'OFF':0},)},
{'REG':'usb_rst_ctrl', 'FIELDS':({'FIELD_NAME':'usb1_cpu1x_rst', 'RST':1,'OFF':0},)} ),
'ETH': ({'REG':'gem_rst_ctrl', 'FIELDS':({'FIELD_NAME':'gem0_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'gem0_rx_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'gem0_cpu1x_rst', 'RST':1,'OFF':0} )},
{'REG':'gem_rst_ctrl', 'FIELDS':({'FIELD_NAME':'gem1_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'gem1_rx_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'gem1_cpu1x_rst', 'RST':1,'OFF':0})}),
'SDIO':({'REG':'sdio_rst_ctrl','FIELDS':({'FIELD_NAME':'sdio0_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'sdio0_cpu1x_rst', 'RST':1,'OFF':0} )},
{'REG':'sdio_rst_ctrl','FIELDS':({'FIELD_NAME':'sdio1_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'sdio1_cpu1x_rst', 'RST':1,'OFF':0} )} ),
'SPI': ({'REG':'spi_rst_ctrl', 'FIELDS':({'FIELD_NAME':'spi0_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'spi0_cpu1x_rst', 'RST':1,'OFF':0} )},
{'REG':'spi_rst_ctrl', 'FIELDS':({'FIELD_NAME':'spi1_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'spi1_cpu1x_rst', 'RST':1,'OFF':0} )} ),
'CAN': ({'REG':'can_rst_ctrl', 'FIELDS':({'FIELD_NAME':'can0_cpu1x_rst', 'RST':1,'OFF':0},)},
{'REG':'can_rst_ctrl', 'FIELDS':({'FIELD_NAME':'can1_cpu1x_rst', 'RST':1,'OFF':0},)} ),
'I2C': ({'REG':'i2c_rst_ctrl', 'FIELDS':({'FIELD_NAME':'i2c0_cpu1x_rst', 'RST':1,'OFF':0},)},
{'REG':'i2c_rst_ctrl', 'FIELDS':({'FIELD_NAME':'i2c1_cpu1x_rst', 'RST':1,'OFF':0},)} ),
'UART':({'REG':'uart_rst_ctrl','FIELDS':({'FIELD_NAME':'uart0_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'uart0_cpu1x_rst', 'RST':1,'OFF':0} )},
{'REG':'uart_rst_ctrl','FIELDS':({'FIELD_NAME':'uart1_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'uart1_cpu1x_rst', 'RST':1,'OFF':0} )} ),
'GPIO':({'REG':'gpio_rst_ctrl','FIELDS':({'FIELD_NAME':'gpio_cpu1x_rst', 'RST':1,'OFF':0},)},),
'QSPI':({'REG':'qspi_rst_ctrl','FIELDS':({'FIELD_NAME':'qspi_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'qspi_cpu1x_rst', 'RST':1,'OFF':0} )},),
'NAND':({'REG':'smc_rst_ctrl', 'FIELDS':({'FIELD_NAME':'smc_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'smc_cpu1x_rst', 'RST':1,'OFF':0} )},),
'NOR': ({'REG':'smc_rst_ctrl', 'FIELDS':({'FIELD_NAME':'smc_ref_rst', 'RST':1,'OFF':0},
{'FIELD_NAME':'smc_cpu1x_rst', 'RST':1,'OFF':0} )},),
}
...@@ -119,22 +119,23 @@ class EzynqUART: ...@@ -119,22 +119,23 @@ class EzynqUART:
def setup_uart(self,current_reg_sets,force=False,warn=False): def setup_uart(self,current_reg_sets,force=False,warn=False):
uart_register_set=self.uart_register_set uart_register_set=self.uart_register_set
slcr_register_set=self.slcr_register_set
slcr_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
slcr_register_set.set_bitfields('uart_rst_ctrl',( # dflt=0
('uart1_ref_rst', self.channel==1), # UART 1 reference clock domain reset: 0 - normal, 1 - reset
('uart0_ref_rst', self.channel==0), # UART 0 reference clock domain reset: 0 - normal, 1 - reset
('uart1_cpu1x_rst', self.channel==1), # UART 1 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
('uart0_cpu1x_rst', self.channel==0)),force,warn) #UART 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
slcr_register_set.flush()
slcr_register_set.set_bitfields('uart_rst_ctrl',( # dflt=0
('uart1_ref_rst', 0), # UART 1 reference clock domain reset: 0 - normal, 1 - reset
('uart0_ref_rst', 0), # UART 0 reference clock domain reset: 0 - normal, 1 - reset
('uart1_cpu1x_rst', 0), # UART 1 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
('uart0_cpu1x_rst', 0)),force,warn) #UART 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
reg_sets=slcr_register_set.get_register_sets(sort_addr=True,apply_new=True)
uart_register_set.set_initial_state(reg_sets, True)# start from the current registers state # slcr_register_set=self.slcr_register_set
# slcr_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
# slcr_register_set.set_bitfields('uart_rst_ctrl',( # dflt=0
# ('uart1_ref_rst', self.channel==1), # UART 1 reference clock domain reset: 0 - normal, 1 - reset
# ('uart0_ref_rst', self.channel==0), # UART 0 reference clock domain reset: 0 - normal, 1 - reset
# ('uart1_cpu1x_rst', self.channel==1), # UART 1 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
# ('uart0_cpu1x_rst', self.channel==0)),force,warn) #UART 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
# slcr_register_set.flush()
# slcr_register_set.set_bitfields('uart_rst_ctrl',( # dflt=0
# ('uart1_ref_rst', 0), # UART 1 reference clock domain reset: 0 - normal, 1 - reset
# ('uart0_ref_rst', 0), # UART 0 reference clock domain reset: 0 - normal, 1 - reset
# ('uart1_cpu1x_rst', 0), # UART 1 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
# ('uart0_cpu1x_rst', 0)),force,warn) #UART 0 CPU_1x clock domain (AMBA) reset: 0 - normal, 1 - reset
# reg_sets=slcr_register_set.get_register_sets(sort_addr=True,apply_new=True)
uart_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
uart_register_set.set_bitfields('mode',( # dflt=4 uart_register_set.set_bitfields('mode',( # dflt=4
('chmode', 0), # Channel Mode: 0 - normal, 1 - auto echo, 2 - local loopback, 3 - remote loopback ('chmode', 0), # Channel Mode: 0 - normal, 1 - auto echo, 2 - local loopback, 3 - remote loopback
('nbstop', 0), # Number of stop bits: 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits, 3 - reserved ('nbstop', 0), # Number of stop bits: 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits, 3 - reserved
......
...@@ -205,12 +205,21 @@ inline void register_setup(void) ...@@ -205,12 +205,21 @@ inline void register_setup(void)
self._add_reg_writes(reg_sets) self._add_reg_writes(reg_sets)
self.cfile+='}\n\n' self.cfile+='}\n\n'
def pll_setup (self, reg_sets,clk): #clk is an instance of ezynq_clk.EzynqClk def pll_setup (self, reg_sets):
self.sections.append('pll_setup') self.sections.append('pll_setup')
self.cfile+='''/* Wait for PLLs locked:*/ self.cfile+='''/* Wait for PLLs locked */
inline void pll_setup(void) inline void pll_setup(void)
{ {
\t/* Wait for all used PLLs locked, then release PLL bypass on each PLL */ \t/* Wait for all used PLLs locked, then release PLL bypass on each PLL */
'''
self._add_reg_writes(reg_sets)
self.cfile+='}\n\n'
def make_resets (self, reg_sets):
self.sections.append('resets')
self.cfile+='''/* Reset defined peripherals */
inline void reset_peripherals(void)
{
''' '''
self._add_reg_writes(reg_sets) self._add_reg_writes(reg_sets)
self.cfile+='}\n\n' self.cfile+='}\n\n'
...@@ -407,53 +416,32 @@ int arch_cpu_init(void) ...@@ -407,53 +416,32 @@ int arch_cpu_init(void)
''' '''
self._cp_led('LED_CHECKPOINT_3') # After setting clock registers self._cp_led('LED_CHECKPOINT_3') # After setting clock registers
self.cfile+='''/* self.cfile+='\tpll_setup(); /* Wait PLLs locked and turn off bypass - all clocks should have specified values now */ \n'
Wait PLLs locked and turn off bypass - all clocks should have specified values now self.cfile+='\treset_peripherals(); /* Reset defined peripherals */\n'
*/
\tpll_setup();
'''
self._cp_led('LED_CHECKPOINT_4') # After PLL bypass is OFF self._cp_led('LED_CHECKPOINT_4') # After PLL bypass is OFF
if 'uart_init' in self.sections: if 'uart_init' in self.sections:
self.cfile+='''/* Initialize UART for debug information output */ self.cfile+='\tuart_init(); /* Initialize UART for debug information output */\n'
\tuart_init();
'''
self._cp_led('LED_CHECKPOINT_5') # After UART is programmed self._cp_led('LED_CHECKPOINT_5') # After UART is programmed
if self.features.get_par_value_or_none('DUMP_SLCR_EARLY'): if self.features.get_par_value_or_none('DUMP_SLCR_EARLY'):
self.cfile+='\tuart_puts("SLCR registers before DCI/DDR initialization\\r\\n");\n' self.cfile+='\tuart_puts("SLCR registers before DCI/DDR initialization\\r\\n");\n'
self.cfile+='\tdump_slcr_regs(); /*Dump all SLCR registers before DCI/DDR initialization */\n' self.cfile+='\tdump_slcr_regs(); /* Dump all SLCR registers before DCI/DDR initialization */\n'
if self.features.get_par_value_or_none('DUMP_DDRC_EARLY'): if self.features.get_par_value_or_none('DUMP_DDRC_EARLY'):
self.cfile+='\tuart_puts("DDRC registers before DCI/DDR initialization\\r\\n");\n' self.cfile+='\tuart_puts("DDRC registers before DCI/DDR initialization\\r\\n");\n'
self.cfile+='\tdump_ddrc_regs(); /*Dump all DDRC registers before DCI/DDR initialization */\n' self.cfile+='\tdump_ddrc_regs(); /* Dump all DDRC registers before DCI/DDR initialization */\n'
self.cfile+='''/* self.cfile+='\tdci_calibration(); /* Calibrate DDR DCI impedance and wait for completion */\n'
Calibrate DDR DCI impedance and wait for completion
*/
\tdci_calibration();
'''
self._cp_led('LED_CHECKPOINT_6') # After DCI is calibrated self._cp_led('LED_CHECKPOINT_6') # After DCI is calibrated
self.cfile+='''/* self.cfile+='\tddr_start(); /* Remove soft reset from DDR controller - this will start initialization. Wait for completion */\n'
Remove soft reset from DDR controller - that starts initialization. Wait for completion
*/
\tddr_start();
'''
self._cp_led('LED_CHECKPOINT_7') # After DDR is initialized self._cp_led('LED_CHECKPOINT_7') # After DDR is initialized
if self.features.get_par_value_or_none('DUMP_SLCR_LATE'): if self.features.get_par_value_or_none('DUMP_SLCR_LATE'):
self.cfile+='\tuart_puts("SLCR registers after DCI/DDR initialization\\r\\n");\n' self.cfile+='\tuart_puts("SLCR registers after DCI/DDR initialization\\r\\n");\n'
self.cfile+='\tdump_slcr_regs(); /*Dump all SLCR registers after DCI/DDR initialization */\n' self.cfile+='\tdump_slcr_regs(); /* Dump all SLCR registers after DCI/DDR initialization */\n'
if self.features.get_par_value_or_none('DUMP_DDRC_LATE'): if self.features.get_par_value_or_none('DUMP_DDRC_LATE'):
self.cfile+='\tuart_puts("DDRC registers after DCI/DDR initialization\\r\\n");\n' self.cfile+='\tuart_puts("DDRC registers after DCI/DDR initialization\\r\\n");\n'
self.cfile+='\tdump_ddrc_regs(); /*Dump all DDRC registers after DCI/DDR initialization */\n' self.cfile+='\tdump_ddrc_regs(); /* Dump all DDRC registers after DCI/DDR initialization */\n'
self.cfile+='''/* self.cfile+='''/* Copy 3 pages of OCM from 0x00000.0x2ffff to DDR 0x4000000.0x402ffff*/
Copy 3 pages of OCM from 0x00000.0x2ffff to DDR 0x4000000.0x402ffff
*/
\tint * s= (int *) 0; \tint * s= (int *) 0;
\tint * d= (int *) 0x4000000; \tint * d= (int *) 0x4000000;
\twhile (s< ((int *)0x30000)) *d++=*s++; \twhile (s< ((int *)0x30000)) *d++=*s++;
''' '''
self.cfile+='\tddrc_wait_queue_empty(); /* Wait no commands are pending in DDRC queue */\n' self.cfile+='\tddrc_wait_queue_empty(); /* Wait no commands are pending in DDRC queue */\n'
...@@ -469,13 +457,8 @@ int arch_cpu_init(void) ...@@ -469,13 +457,8 @@ int arch_cpu_init(void)
# seems some delay is needed before remapping DDR memory # seems some delay is needed before remapping DDR memory
self.cfile+='\tddrc_wait_queue_empty(); /* seems some delay is needed here before remapping DDR memory */\n' self.cfile+='\tddrc_wait_queue_empty(); /* seems some delay is needed here before remapping DDR memory */\n'
self._cp_led('LED_CHECKPOINT_9') # After relocation to DDR (to 0x4000000+ ) self._cp_led('LED_CHECKPOINT_9') # After relocation to DDR (to 0x4000000+ )
self.cfile+='''/* self.cfile+='\twritel(0, &scu_base->filter_start); /* Remap DDR to zero, FILTERSTART */\n'
Remap DDR to zero, FILTERSTART self.cfile+='''/* Device config APB, unlock the PCAP */
*/
\twritel(0, &scu_base->filter_start);
/*
Device config APB, unlock the PCAP
*/
\twritel(0x757BDF0D, &devcfg_base->unlock); \twritel(0x757BDF0D, &devcfg_base->unlock);
\twritel(0xFFFFFFFF, &devcfg_base->rom_shadow); \twritel(0xFFFFFFFF, &devcfg_base->rom_shadow);
''' '''
......
...@@ -361,6 +361,10 @@ segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'CLK','TITLE':'Clock regi ...@@ -361,6 +361,10 @@ segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'CLK','TITLE':'Clock regi
#print 'Debug mode: CLK/PLL configuration by u-boot' #print 'Debug mode: CLK/PLL configuration by u-boot'
reg_sets=clk.clocks_pll_bypass_off(reg_sets,force) reg_sets=clk.clocks_pll_bypass_off(reg_sets,force)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'PLL','TITLE':'Registers to switch to PLL'}) segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'PLL','TITLE':'Registers to switch to PLL'})
reg_sets=clk.reset_peripherals(reg_sets,force)
segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'RESETS','TITLE':'Resetting defined peripherals after clocks changed'})
if u_boot.features.get_par_value_or_none('BOOT_DEBUG'): if u_boot.features.get_par_value_or_none('BOOT_DEBUG'):
uart=ezynq_uart.EzynqUART() uart=ezynq_uart.EzynqUART()
uart.parse_parameters(raw_configs,used_mio_interfaces,False) uart.parse_parameters(raw_configs,used_mio_interfaces,False)
...@@ -490,15 +494,6 @@ if args.outfile: ...@@ -490,15 +494,6 @@ if args.outfile:
print 'Generating binary output ',os.path.abspath(args.outfile) print 'Generating binary output ',os.path.abspath(args.outfile)
write_image(image,args.outfile) write_image(image,args.outfile)
if (args.lowlevel): if (args.lowlevel):
# segments.append({'TO':len(reg_sets),'RBL':True,'NAME':'MIO','TITLE':'MIO registers configuration'})
# segments.append({'TO':len(reg_sets),'RBL':True,'NAME':'DDR0','TITLE':'DDR registers configuration'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'CLK','TITLE':'Clock registers configuration'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'PLL','TITLE':'Registers to switch to PLL'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'UART_INIT','TITLE':'Registers to initialize UART'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DCI','TITLE':'DDR DCI Calibration'})
# segments.append({'TO':len(reg_sets),'RBL':False,'NAME':'DDR_START','TITLE':'DDR initialization start'})
#CONFIG_EZYNQ_UART_DEBUG_USE_LED
if 'SLCR_LOCK_UNLOCK' in segment_dict: if 'SLCR_LOCK_UNLOCK' in segment_dict:
u_boot.make_slcr_lock_unlock (reg_sets[segment_dict['SLCR_LOCK_UNLOCK']['FROM']:segment_dict['SLCR_LOCK_UNLOCK']['TO']]) u_boot.make_slcr_lock_unlock (reg_sets[segment_dict['SLCR_LOCK_UNLOCK']['FROM']:segment_dict['SLCR_LOCK_UNLOCK']['TO']])
if 'LED' in segment_dict: if 'LED' in segment_dict:
...@@ -507,7 +502,10 @@ if (args.lowlevel): ...@@ -507,7 +502,10 @@ if (args.lowlevel):
if 'CLK' in segment_dict: if 'CLK' in segment_dict:
u_boot.registers_setup (reg_sets[segment_dict['CLK']['FROM']:segment_dict['CLK']['TO']],clk,num_rbl_regs) u_boot.registers_setup (reg_sets[segment_dict['CLK']['FROM']:segment_dict['CLK']['TO']],clk,num_rbl_regs)
if 'PLL' in segment_dict: if 'PLL' in segment_dict:
u_boot.pll_setup (reg_sets[segment_dict['PLL']['FROM']:segment_dict['PLL']['TO']],clk) u_boot.pll_setup (reg_sets[segment_dict['PLL']['FROM']:segment_dict['PLL']['TO']])
if 'RESETS' in segment_dict:
u_boot.make_resets (reg_sets[segment_dict['RESETS']['FROM']:segment_dict['RESETS']['TO']])
if 'UART_INIT' in segment_dict: if 'UART_INIT' in segment_dict:
u_boot.uart_init (reg_sets[segment_dict['UART_INIT']['FROM']:segment_dict['UART_INIT']['TO']]) u_boot.uart_init (reg_sets[segment_dict['UART_INIT']['FROM']:segment_dict['UART_INIT']['TO']])
if 'UART_XMIT' in segment_dict: if 'UART_XMIT' in segment_dict:
......
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