Skip to content

Porting Binary Header

vladabr edited this page Feb 10, 2016 · 17 revisions

Porting Binary Header

General Information

The binary header is the first hardware initialization routine. It is executed by the Boot ROM before loading and running U-Boot. The execution flow of the binary header is shown below:

  1. General Initialization

  2. SERDES Initialization

  3. DDR3 Initialization

  4. DDR3 Silicon Initialization

  5. DDR3 Driver

  6. Suspend Wake Up

The binary header source code is included in the U-Boot source package in the tools/marvell/bin_hdr directory, but is compiled separately. Using the doimage tool, the binary header and U-Boot are combined into one image. The table below lists the binary header components and respective locations.

Table: Binary Header Components/Locations

Component Location

Initial general initialization

src_init/a38x/

SERDES configuration and initialization

src_phy/a38x

DDR3 Initialization

src_ddr/

DDR3 Silicon Initialization

src_ddr/ddr3libv2/src/Silicon/

DDR3 Driver

src_ddr/ddr3libv2/src/Driver/ddr3/

Common included files

inc/common/, inc/ddr3_soc/a38x/

Common utilities (such as UART, TWSI, and TIMER)

platform/utils/, platform/sysEnv/a38x/, platform/drivers/

System environment

platform/sysEnv/a38x

The binary header initialization steps are described below.

General Initialization

The general initialization component is used for tasks that must be performed prior to DDR and SERDES configurations, for example the UART initialization sequence.

Configuring ARMADA® 38x Low Cost Flavor

In contrast to all other flavors, 6W21(A383) and 6W23(A384) flavors are controlled in the software, and all the hardware limitations are enforced via U-Boot software. All other flavors have a Device ID field in the S@R register (values 0-6), The 6W21 flavors must be configured differently, as explained below, because wrong configuration might cause a problem with the interface numbers problem. To enable 6W21(A383), remove the comment characters from the relevant REDUCED_FLAVOR section, defined in the generalInit.h file, For example, to configure 6W21(A383), the relevant section in generalInit.h looks like the following:

#define REDUCED_FLAVOR 0x383 /* 0x383: A383 - 6W22 */
//#define REDUCED_FLAVOR 0x384 /* 0x384: A384 - 6W23 */

NOTE: The above comment in the code mentions the device 6W22 but it refers to 6W21. Since the code is frozen for 2015_T1, this comment remains as is in order to be aligned with the code.

SERDES Initialization

The following section elaborates how to select the configuration for SERDES initialization.

Lane Mode Selection

The SERDES lane configuration setup is defined in: mvHighSpeedTopologySpec-38x.c under tools/marvell/bin_hdr/src_phy/a38x/ with SERDES_MAP struct for each lane. The following example demonstrates a full configuration selection for customer board #0, the following struct is the only struct that must be changed for customer implementation.

For the A38x:

SERDES_MAP CustomerBoardTopologyConfig[][MAX_SERDES_LANES] =
{
	/* Customer Board #0 Topology - reference from Marvell DB-BP board */
	/* serdesType,	serdesSpeed,	serdesMode,	      swapTx,	 swapRx */
	{ SATA0,	__3Gbps,	SERDES_DEFAULT_MODE,  MV_FALSE,  MV_FALSE },
	{ PEX0,		__5Gbps,	PEX_ROOT_COMPLEX_x1,  MV_FALSE,  MV_FALSE },
	{ PEX1,		__5Gbps,	PEX_ROOT_COMPLEX_x1,  MV_FALSE,  MV_FALSE },
	{ SATA3,	__3Gbps,	SERDES_DEFAULT_MODE,  MV_FALSE,  MV_FALSE },
	{ USB3_HOST0,	__5Gbps,	SERDES_DEFAULT_MODE,  MV_FALSE,  MV_FALSE },
	{ USB3_HOST1,	__5Gbps,	SERDES_DEFAULT_MODE,  MV_FALSE,  MV_FALSE }
}

The above configuration entries may be modified according to customer’s board needs. If a certain lane is not in use, it must be set to DEFAULT_SERDES mode.

SERDES_MAP struct definition:

typedef struct {
    SERDES_TYPE serdesType;
    SERDES_SPEED serdesSpeed;
    SERDES_MODE serdesMode;
    MV_BOOL swapRx;
    MV_BOOL swapTx;
} SERDES_MAP;

If a specific lane’s Tx/Rx polarity is swapped (on board assembly), it must be indicated accordingly in the Boolean swapTx/swapRx fields as MV_TRUE.

A specific SERDES mode must be set only for the PCIe lane type. Other SERDES types must use SERDES_DEFAULT mode.

See the hardware specification for optional lane selection options for different flavors.

Table: ARMADA 38x Valid SERDES Type/Mode per Lane

Lane Options

Lane 0

DEFAULT_SERDES, PEX0(X1), PEX0(X4), SATA0, SGMII0

Lane 1

DEFAULT_SERDES, PEX0(X1), PEX1(X4), SATA0, SGMII0, SGMII1, USB3_HOST0, QSGMII

Lane 2

DEFAULT_SERDES, PEX1(X1), PEX2(X4), SATA1, SGMII1

Lane 3

DEFAULT_SERDES, PEX3(X1), PEX3(X4), SATA3, SGMII2, USB3_HOST1, USB3_DEVICE

Lane 4

DEFAULT_SERDES, PEX1, SGMII1,USB3_HOST0, USB3_DEVICE, SATA2

Lane 5

DEFAULT_SERDES, PEX2, SATA2, SGMII2,USB3_HOST1, USB3_DEVICE

Table: ARMADA 38x Valid SERDES Speed per Type

Lane Type Valid Speed Settings

PEX

2.5 Gbps (GEN1), 5 Gbps (GEN2)

SATA

1.5 Gbps (GEN1), 3 Gbps (GEN2), 6Gbps (GEN3)

SGMII

1.25 Gbps (SGMII), 3.125 Gbps (SGMII2.5)

QSGMII

5 Gbps

USB3_HOST0

5 Gbps

USB3_DEVICE

5 Gbps

Board Specification Structure for SERDES Configuration

NOTE: Board specification does not require any changes when porting to a single customer board.

The array loadTopologyFuncArr (defined at bin_hdr/src_phy/a38x/mvHighSpeedTopologySpec-38x.c) includes pointers to the load topology routines per board. Board ID index is used as the index of the array derived by mvBoardIdIndexGet().

In the following example, two customer boards are supported, with the same SERDES configuration routine for both (loadTopologyCustomer). Configuration entries can be modified according to customer’s board needs.

loadTopologyFuncPtr loadTopologyFuncArr[] =
{
    loadTopologyCustomer,         /* Customer Board 0 */
    loadTopologyCustomer,         /* Customer Board 1*/
};

DDR3 Initialization

DRAM initialization is performed by the DDR3 training sequence. The DDR3 training sequence binary header is executed by the Boot ROM. The training sequence object library is included in the U-Boot source package.

Table below lists the DRAM initialization header files that must be modified for DRAM Initialization. These files are located in tools/marvell/bin_hdr/inc/ddr3_soc/a38x.

Table: DRAM Initialization Header Files

Component Component File

DRAM static modes, DLB configuration

ddr3_a38x_vars.h and ddr3_a39x_vars.h

Static Initialization of Memory Controller Registers

ddr3_a38x_static.h and ddr3_a39x_static.h

DDR3 Topology configuration

ddr3_a38x_topolgy.h and ddr3_a39x_topolgy.h

Binary Header Configuration

DDR topology is the main configuration structure configured outside of the DDR3 training algorithm. The topology defines DRAM device parameters and other board-related information (DQS/Ck swap, mirroring, etc). The 3 tables below list the parameters that must be set in the /tools/marvell/bin_hdr/inc/ddr3_soc/a38x/ddr3_a38x_topology.h file to configure the binary header behavior. The configuration is done by the entry in the topology map matched to the board’s board ID. The main topology entry type is MV_HWS_TOPOLOGY_MAP, defined in tools/marvell/bin_hdr/inc/common, with existing definitions for two customer boards. Customer board configuration entries can be changed according to customer’s board requirements.

Table: MV_HWS_TOPOLOGY_MAP

Parameter Name Parameter Description Possible Values

interfaceActiveMask

Mask of active DDR3 interfaces

Static integer bitmask per SoC (should not be modified)

interfaceParams

Array of parameters for each enabled interface (for each enabled interface and within an interface for each 8-bit memory device interface), adapted interfaceParams entry must be configured - respectively)

For details see Table Interface Parameters below.

activeBusMask

Mask of active 8-bit memory device bus interfaces, i.e. 0xF (32BIT) is 4-busses, 32-bit configuration, 0x13(16BIT_ECC) is 16-bit configuration with ECC on bus4

BUS_WIDTH_16BIT BUS_WIDTH_32BIT

Table: Interface Parameters

Parameter Name Parameter Description Possible Values

asBusParams

Per bus parameters explained below

See Table BusParams Fields below

speedBinIndex

Index of speed bin table will be used

Speed bin list in mvDdr3TopologyDef.h

busWidth

Width of the memory device bus, 8 or 16 bits

BUS_WIDTH_8, BUS_WIDTH_16 (any value other than 16 will set bus width of 8BIT)

memorySize

Total size of the DRAM

Sizes list in mvDdr3TopologyDef.h

memoryFreq

Frequency of the DRAM (may be overwritten by sample at reset values)

List of frequencies in mvDdr3TopologyDef.h

casWL, casL

If set to 0, will be computed at runtime using speed bin parameters, if different – overwrites speed bin parameters

Integer

interfaceTemp

The interface temperature impacts the value of the refresh rate. The refresh rate depends on the frequency and temperature: a high temperature refresh rate is double the low temperature refresh rate

Temperature list in mvDdr3TopologyDef.h

NOTE: There might be more than one bus per interface and each memory device bus interface has its own quad parameters group. Therefore, per active memory device bus interface, configure the 4 parameters shown in the Table BusParams Fields below.

Table: BusParams Fields

Parameter Name Parameter Description Possible Values

csBitmask

Chip Select bitmask

0x1 for single CS0, 0x3 for Dual CS

mirrorEnableBitmask

Mirror configuration of the bus

0 = Not Mirrored 1 = Mirrored

isDqsSwap

Are DQS signals swapped

0 = Not Swapped 1 = Swapped

isCkSwap

Are CK signals swapped

0 = Not Swapped 1 = Swapped

The following topology example describes customer board #0, with single DRAM interface, single CS, speed grade of 1866L, device bus width of 8 bits, density is 4 Gb, target frequency 800 MHz and CAS calculated by speed bin, with low refresh rate. The number of octet buses supported is 5, but only 4 are used, meaning a 32-bit mode without EEC2 are used, meaning a 16-bit mode without ECC.

NOTE: All BusParams parameters must be identical for all buses.

interfaceActiveMask=0x1,
interfaceParams:
	asBusParams:
		csBitmask = 0x1
		mirrorEnableBitmask = 0
		isDqsSwap = 0
isCkSwap = 0
	speedBinIndex = SPEED_BIN_DDR_1866L
	busWidth = BUS_WIDTH_8
	memorySize = MEM_4G
	memoryFreq = DDR_FREQ_800
	casWL = casL = 0
	interfaceTemp = MV_HWS_TEMP_LOW
activeBusMask = INTERFACE_BUS_MASK_32BIT
MV_HWS_TOPOLOGY_MAP TopologyMap[] =
{
    /* 1st customer board */
    {
      0x1, /* active interfaces */
    /*cs_mask, mirror, dqs_swap, ck_swap x PUPs  speed_bin, memory_width  mem_size, frequency, casL casWL      temperature */
	{{{{0x1,0,0,0}, {0x1,0,0,0}, {0x1,0,0,0}, {0x1,0,0,0}, {0x1,0,0,0}}, SPEED_BIN_DDR_1866L, BUS_WIDTH_8, MEM_4G, DDR_FREQ_800, 0 ,   0 , MV_HWS_TEMP_LOW}},
  INTERFACE_BUS_MASK_32BIT,  /* Bus mask */
  INTERFACE_BUS_MASK_16BIT,  /* Bus mask */
}

The following topology example describes customer board #0, with single DRAM interface, single CS, speed grade of 1866L, device bus width of 8 bits, density of 4-Gbit, target frequency of 800 MHz and CAS calculated by speed bin, with low refresh rate. The number of octet buses supported is 5, but 2 are used, meaning a 16-bit mode without ECC.

interfaceActiveMask=0x1,
interfaceParams:
asBusParams:
csBitmask = 0x1
mirrorEnableBitmask = 0
isDqsSwap = 0
isCkSwap = 0
speedBinIndex = SPEED_BIN_DDR_1866L
busWidth = BUS_WIDTH_8
memorySize = MEM_4G
memoryFreq = DDR_FREQ_800
casWL = casL = 0
interfaceTemp = MV_HWS_TEMP_LOW
activeBusMask = INTERFACE_BUS_MASK_16BIT
MV_HWS_TOPOLOGY_MAP TopologyMap[] =
{
/* 1st customer board */
{
0x1, /* active interfaces */
/*cs_mask, mirror, dqs_swap, ck_swap x PUPs speed_bin, memory_width mem_size, frequency,
casL casWL temperature */
{{{{0x1,0,0,0}, {0x1,0,0,0}, {0x0,0,0,0}, {0x0,0,0,0}, {0x0,0,0,0}}, SPEED_BIN_DDR_1866L,
BUS_WIDTH_8, MEM_4G, DDR_FREQ_800, 0 , 0 , MV_HWS_TEMP_LOW}},
INTERFACE_BUS_MASK_16BIT, /* Buses mask */
}

Device DRAM Modes

DRAM modes structures contains the STATIC Dunit configuration per board per frequency. If the compilation flag SUPPORT_STATIC_DUNIT_CONFIG is defined, and the parameter genericInitController is set to 0, the DDR initialization flow executes the static configuration of DDR (rather than the dynamic algorithm). The genericInitController variable is a global variable, defined under tools/marvell/bin_hdr/src_ddr/ddr3_init_tipv2.c. DRAM mode configuration is defined in the ddr3_a38x_vars.h file, with existing definitions for 2 customer boards. The table entry is selected according to the board ID index, which is selected before compilation and returned by the mvBoardIdIndexGet() routine.

The MCregs register table pointer contains register-value pairs for static initialization of the memory controller (ddr3_a38x_mc_static.h). This register table must end with register-value pair of 0,0 that marks the end of the table.

In the following example, 800 represents the target DRAM frequency:

MV_DRAM_MODES ddr_modes[] =
{
/* Conf name              CPUFreq      FabFreq Chip ID  Chip/Board                       MC regs*/
  {"a38x_customer_0_800", DDR_FREQ_800, 0,     0x0,     ARMADA_38x_CUSTOMER_BOARD_ID0,  ddr3_customer_800},
  {"a38x_customer_1_800", DDR_FREQ_800, 0,     0x0,     ARMADA_38x_CUSTOMER_BOARD_ID1,  ddr3_customer_800},
};

DDR3 Training Lib Internal Parameters Configuration

The ddr3HwsTuneTrainingParams() function sets the number of training global parameters and passes the configuration to the training library.

NOTE: Marvell recommends using dynamic DDR configuration.

The function is implemented in ddr3_init_tipv2.c and is used per SoC as shown below:

#define MV_TUNE_TRAINING_PARAMS_CK_DELAY           160
#define MV_TUNE_TRAINING_PARAMS_PHYREG3VAL         0xA

#define MV_TUNE_TRAINING_PARAMS_PRI_DATA           123
#define MV_TUNE_TRAINING_PARAMS_NRI_DATA           123
#define MV_TUNE_TRAINING_PARAMS_PRI_CTRL           74
#define MV_TUNE_TRAINING_PARAMS_NRI_CTRL           74

#define MV_TUNE_TRAINING_PARAMS_P_ODT_DATA         45
#define MV_TUNE_TRAINING_PARAMS_N_ODT_DATA	   45
#define MV_TUNE_TRAINING_PARAMS_P_ODT_CTRL         45
#define MV_TUNE_TRAINING_PARAMS_N_ODT_CTRL	   45

#define MV_TUNE_TRAINING_PARAMS_DIC           	   0x2
#define MV_TUNE_TRAINING_PARAMS_ODT_CONFIG         0x120012
#define MV_TUNE_TRAINING_PARAMS_RTT_NOM		   0x44

Table: DDR3 Training Lib Internal Parameters Configuration

Parameter Name Description

CK_DELAY

The delay between command and clock signals by 8-memory devices

CK_DELAY_16

The delay between a command and clock signals by 16-memory devices

PRI_DATA

P-finger configuration for data driver strength

NRI_DATA

N-finger configuration for data driver strength

PRI_CTRL

P-finger configuration for control driver strength

NRI_CTRL

N-finger configuration for control driver strength

P_ODT_DATA

P-finger configuration for data ODT (On-die termination)

P_ODT_CTRL

Reserved, but not in use

N_ODT_CTRL

Reserved, but not in use

DIC

SDRAM Output Driver Impedance Control

ODT_CONFIG

Marvell ODT (On-die termination) control

RTT_NOM

SDRAM Input Nominal ODT (On-die termination)

RTT_WR

SDRAM Input Dynamic ODT (On-die termination)

NOTE: The default defines is configured according to the Marvell recommendation (Marvell recommends using dynamic DDR configuration). Each define may be changed to a different value according to Marvell field engineer recommendations.

DDR3 Logging

The DDR3 logging level can be modified by calling ddr3HwsSetLogLevel() function with blocks and levels defined in tools/marvell/bin_hdr/inc/common/mvDdr3LoggingDef.h.

Table Log Levels describes the log levels that can be selected. Contact your Marvell field application engineer with these logs if there is a problem.

Table: Log Levels

Debug Block Log Level Description

First stage

MV_DEBUG_BLOCK_TRAINING_MAIN

High-level information and status of each stage (run/passed/failed)

Second stage (various stages of training)

MV_DEBUG_BLOCK_STATIC

Static configuration stages, not run in default

MV_DEBUG_BLOCK_LEVELING

Read/write leveling stages

MV_DEBUG_BLOCK_CENTRALIZATION

Centralization stages

MV_DEBUG_BLOCK_PBS

PBS stages

Last stage

MV_DEBUG_BLOCK_IP

IP engine low-level function dumps

MV_DEBUG_STAGES_REG_DUMP

Register dumps in significant training stages

MV_DEBUG_BLOCK_ACCESS

Read/write trace for all registers

Other

MV_DEBUG_BLOCK_BIST

Not relevant for SoC

MV_DEBUG_BLOCK_ALG

VREF stage, not supported yet

MV_DEBUG_BLOCK_DEVICE

SoC-specific configurations

MV_DEBUG_BLOCK_ALL

All excluding IP and REG_DUMP, that must be enabled separately

By default, all logs are configured to the error log level by the following call: ddr3HwsSetLogLevel(MV_DEBUG_BLOCK_ALL, DEBUG_LEVEL_ERROR); under tools/marvell/bin_hdr/src_ddr/ddr3_init_tipv2.c

For example, to enable memory dumps in significant algorithms, call ddr3HwsSetLogLevel() again, after exiting the previous call, as shown below:

ddr3HwsSetLogLevel(MV_DEBUG_STAGES_REG_DUMP, DEBUG_LEVEL_TRACE);
ddr3HwsSetLogLevel(MV_DEBUG_BLOCK_TRAINING_MAIN, DEBUG_LEVEL_TRACE);

DDR4 Porting

DDR4 porting is the same as DDR3 porting. To compile the U-Boot image, add the "-m 4" option to invocation of the build.pl. The following is an example of this:

/build.pl -f spi -v 15t1 -i spi -b armada_38x_customer0 –c -m4

Also update in the relevant topology entry, the speedBinIndex field. The list of DDR4 speed bins supported is placed in inc/common/mvDdr3TopolgyDef.h under the #else of the DDR3 speed bins, listed under #ifdef CONFIG_DDR3.

The speedBinIndex field and busWidth definitions for DDR4 speed bins supported are placed in ddr3_a38x_topology.h under the #else of the DDR3 definitions under #ifdef CONFIG_DDR3.

DDR3 Training

By default, the DDR3 training is compiled, and the resulting library file ddr3_training_a38x.lib is placed under tools\marvell\bin_hdr\src_ddr\ddr3libv2.

NOTE: Generally, the DDR3 sources should not be modified. To modify the DDR3 training, contact your Marvell application engineer.

Common Utilities

This component configures common utilities, such as UART, TWSI, Timers, etc.

Modify Default UART Interface

UART0 is the default UART interface, and is defined in mv_uart.c under tools/marvell/bin_hdr/platform/drivers:

MV_U32 uartOffset = UART0_REG_OFFSET;

To set UART1 as the default UART interface instead of UART0:

  1. Update the uartOffset definition to UART1_REG_OFFSET.

  2. Update the UART MPP configuration in the correct MPP register (by default only UART0 MPP values are defined).

The example below shows how to set UART1 MPP values for the ARMADA 38x SoC:

  • UART1 MPP configuration for A38x: MPP19 =0x6, and MPP20 = 0x6

  • MPP19 and MPP20 are defined in the 3rd MPP register (each MPP register consists of 8 MPP values)

MV_U32 regData = MV_REG_READ(MPP_CONTROL_REG(2));
regData |= 0x00066000;
MV_REG_WRITE(MPP_CONTROL_REG(2), regData);

Adding or Updating Binary Header Components

This section describes how to add or update an existing binary header component.

Component Name and Main Function

The structure MV_BINARY_HEADER_COMPONENTS defined in tools/marvell/bin_hdr/in_common/mvBinHdrComponents.h defines a component’s name and its main function.

CAUTION: Do not use the Marvell proprietary board names. Instead, create new names. The Marvell naming may imply a specific implementation of the Marvell board that may not be relevant to a customer board.

The main function of a component must be defined in the following format:

MV_STATUS (*ComponentFunc) (void);

For example, the general initialization sequence is stated by:

MV_STATUS mvGeneralInit(void);

The main dispatcher calls the component’s main function in the BIN_HEADER_COMPONENT_TABLE. This table must end with a NULL entry.

typedef struct _binaryHeaderComponent {
   char *ComponentName; /* component name */
   MV_STATUS (*ComponentFunc) (void); /* main function */
} MV_BINARY_HEADER_COMPONENTS;

The component’s main function must return MV_OK for U-Boot execution to continue.

Compilation

Each component is compiled twice: the first time for normal operation and the second time for booting from UART.

NOTE: Printing output via UART is disabled for the second image created for booting from UART.

Adding a New Component to the Binary Header

To add a new component to the binary header:

  1. Create a new directory in tools/marvell/bin_hdr.

    • For example, tools/marvell/bin_hdr/src_<component_name>.

  2. Place the component source code and makefile in the new component directory.

  3. Edit the makefile:

    • Add the component directory to the COMPONENT_SUBDIRS.

    • Add the component library name to the HDR_COMPONENT.

    • Add the UART component library name to HDR_COMPONENT_UART.

  4. Open and edit mvBinHdrComponents.h that is placed in the directory tools/marvell/bin_hdr/inc/common:

    • Add the new entry to table BIN_HEADER_COMPONENT_TABLE.

    • Add the main component subroutine definition.

  5. Recompile U-Boot.