aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/fdt_fixup.c32
-rw-r--r--docs/about/maintainers.rst839
-rw-r--r--drivers/allwinner/axp/common.c19
-rw-r--r--drivers/brcm/i2c/i2c.c886
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/cot.c284
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/csf_hdr.h155
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk64
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c365
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/input_bl2_ch289
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/input_bl2_ch365
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_265
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/input_blx_ch230
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/input_blx_ch337
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/input_pbi_ch343
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_243
-rw-r--r--drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c180
-rw-r--r--drivers/nxp/auth/tbbr/tbbr_cot.c820
-rw-r--r--drivers/nxp/console/16550_console.S319
-rw-r--r--drivers/nxp/console/console.mk46
-rw-r--r--drivers/nxp/console/console_16550.c33
-rw-r--r--drivers/nxp/console/console_pl011.c35
-rw-r--r--drivers/nxp/console/plat_console.h38
-rw-r--r--drivers/nxp/crypto/caam/caam.mk28
-rw-r--r--drivers/nxp/crypto/caam/include/caam.h53
-rw-r--r--drivers/nxp/crypto/caam/include/caam_io.h56
-rw-r--r--drivers/nxp/crypto/caam/include/hash.h85
-rw-r--r--drivers/nxp/crypto/caam/include/jobdesc.h56
-rw-r--r--drivers/nxp/crypto/caam/include/jr_driver_config.h205
-rw-r--r--drivers/nxp/crypto/caam/include/rsa.h40
-rw-r--r--drivers/nxp/crypto/caam/include/sec_hw_specific.h506
-rw-r--r--drivers/nxp/crypto/caam/include/sec_jr_driver.h178
-rw-r--r--drivers/nxp/crypto/caam/src/auth/auth.mk12
-rw-r--r--drivers/nxp/crypto/caam/src/auth/hash.c155
-rw-r--r--drivers/nxp/crypto/caam/src/auth/nxp_crypto.c123
-rw-r--r--drivers/nxp/crypto/caam/src/auth/rsa.c179
-rw-r--r--drivers/nxp/crypto/caam/src/caam.c339
-rw-r--r--drivers/nxp/crypto/caam/src/hw_key_blob.c81
-rw-r--r--drivers/nxp/crypto/caam/src/jobdesc.c236
-rw-r--r--drivers/nxp/crypto/caam/src/rng.c251
-rw-r--r--drivers/nxp/crypto/caam/src/sec_hw_specific.c635
-rw-r--r--drivers/nxp/crypto/caam/src/sec_jr_driver.c241
-rw-r--r--drivers/nxp/csu/csu.c34
-rw-r--r--drivers/nxp/csu/csu.h40
-rw-r--r--drivers/nxp/csu/csu.mk28
-rw-r--r--drivers/nxp/dcfg/dcfg.c167
-rw-r--r--drivers/nxp/dcfg/dcfg.h85
-rw-r--r--drivers/nxp/dcfg/dcfg.mk28
-rw-r--r--drivers/nxp/dcfg/dcfg_lsch2.h79
-rw-r--r--drivers/nxp/dcfg/dcfg_lsch3.h77
-rw-r--r--drivers/nxp/dcfg/scfg.h59
-rw-r--r--drivers/nxp/ddr/fsl-mmdc/ddr.mk19
-rw-r--r--drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c176
-rw-r--r--drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h173
-rw-r--r--drivers/nxp/ddr/include/ddr.h151
-rw-r--r--drivers/nxp/ddr/include/ddr_io.h38
-rw-r--r--drivers/nxp/ddr/include/dimm.h330
-rw-r--r--drivers/nxp/ddr/include/immap.h125
-rw-r--r--drivers/nxp/ddr/include/opts.h119
-rw-r--r--drivers/nxp/ddr/include/regs.h109
-rw-r--r--drivers/nxp/ddr/include/utility.h24
-rw-r--r--drivers/nxp/ddr/nxp-ddr/README.odt31
-rw-r--r--drivers/nxp/ddr/nxp-ddr/ddr.c930
-rw-r--r--drivers/nxp/ddr/nxp-ddr/ddr.mk79
-rw-r--r--drivers/nxp/ddr/nxp-ddr/ddrc.c594
-rw-r--r--drivers/nxp/ddr/nxp-ddr/dimm.c399
-rw-r--r--drivers/nxp/ddr/nxp-ddr/regs.c1394
-rw-r--r--drivers/nxp/ddr/nxp-ddr/utility.c275
-rw-r--r--drivers/nxp/ddr/phy-gen1/phy.c97
-rw-r--r--drivers/nxp/ddr/phy-gen2/csr.h151
-rw-r--r--drivers/nxp/ddr/phy-gen2/ddr4fw.h2897
-rw-r--r--drivers/nxp/ddr/phy-gen2/ddrphy.mk20
-rw-r--r--drivers/nxp/ddr/phy-gen2/input.h106
-rw-r--r--drivers/nxp/ddr/phy-gen2/messages.h2909
-rw-r--r--drivers/nxp/ddr/phy-gen2/phy.c2669
-rw-r--r--drivers/nxp/ddr/phy-gen2/phy.h334
-rw-r--r--drivers/nxp/ddr/phy-gen2/pie.h632
-rw-r--r--drivers/nxp/drivers.mk90
-rw-r--r--drivers/nxp/flexspi/nor/flexspi_nor.c25
-rw-r--r--drivers/nxp/flexspi/nor/flexspi_nor.h15
-rw-r--r--drivers/nxp/flexspi/nor/flexspi_nor.mk35
-rw-r--r--drivers/nxp/flexspi/nor/fspi.c853
-rw-r--r--drivers/nxp/flexspi/nor/fspi.h385
-rw-r--r--drivers/nxp/flexspi/nor/test_fspi.c91
-rw-r--r--drivers/nxp/gic/gic.mk46
-rw-r--r--drivers/nxp/gic/include/gicv2/plat_gic.h72
-rw-r--r--drivers/nxp/gic/include/gicv3/plat_gic.h114
-rw-r--r--drivers/nxp/gic/ls_gicv2.c76
-rw-r--r--drivers/nxp/gic/ls_gicv3.c78
-rw-r--r--drivers/nxp/gpio/gpio.mk30
-rw-r--r--drivers/nxp/gpio/nxp_gpio.c144
-rw-r--r--drivers/nxp/gpio/nxp_gpio.h53
-rw-r--r--drivers/nxp/i2c/i2c.c257
-rw-r--r--drivers/nxp/i2c/i2c.h52
-rw-r--r--drivers/nxp/i2c/i2c.mk25
-rw-r--r--drivers/nxp/interconnect/interconnect.mk44
-rw-r--r--drivers/nxp/interconnect/ls_cci.c38
-rw-r--r--drivers/nxp/interconnect/ls_ccn.c31
-rw-r--r--drivers/nxp/interconnect/ls_interconnect.h19
-rw-r--r--drivers/nxp/pmu/pmu.c45
-rw-r--r--drivers/nxp/pmu/pmu.h75
-rw-r--r--drivers/nxp/pmu/pmu.mk28
-rw-r--r--drivers/nxp/qspi/qspi.c29
-rw-r--r--drivers/nxp/qspi/qspi.h30
-rw-r--r--drivers/nxp/qspi/qspi.mk28
-rw-r--r--drivers/nxp/sd/sd_mmc.c1496
-rw-r--r--drivers/nxp/sd/sd_mmc.h337
-rw-r--r--drivers/nxp/sd/sd_mmc.mk28
-rw-r--r--drivers/nxp/sec_mon/sec_mon.mk27
-rw-r--r--drivers/nxp/sec_mon/snvs.c186
-rw-r--r--drivers/nxp/sec_mon/snvs.h86
-rw-r--r--drivers/nxp/sfp/fuse_prov.c462
-rw-r--r--drivers/nxp/sfp/fuse_prov.h83
-rw-r--r--drivers/nxp/sfp/sfp.c167
-rw-r--r--drivers/nxp/sfp/sfp.h100
-rw-r--r--drivers/nxp/sfp/sfp.mk35
-rw-r--r--drivers/nxp/sfp/sfp_error_codes.h40
-rw-r--r--drivers/nxp/timer/nxp_timer.c143
-rw-r--r--drivers/nxp/timer/nxp_timer.h35
-rw-r--r--drivers/nxp/timer/timer.mk27
-rw-r--r--drivers/nxp/tzc/plat_tzc400.c187
-rw-r--r--drivers/nxp/tzc/plat_tzc400.h55
-rw-r--r--drivers/nxp/tzc/tzc.mk35
-rw-r--r--include/common/tbbr/cot_def.h4
-rw-r--r--include/common/tbbr/tbbr_img_def.h14
-rw-r--r--include/drivers/brcm/i2c/i2c.h161
-rw-r--r--include/drivers/brcm/i2c/i2c_regs.h271
-rw-r--r--include/drivers/nxp/flexspi/flash_info.h61
-rw-r--r--include/drivers/nxp/flexspi/fspi_api.h122
-rw-r--r--include/drivers/nxp/flexspi/xspi_error_codes.h28
-rw-r--r--include/drivers/nxp/smmu/nxp_smmu.h30
-rw-r--r--include/lib/utils_def.h5
-rw-r--r--include/tools_share/firmware_image_package.h6
-rw-r--r--include/tools_share/tbbr_oid.h3
-rw-r--r--make_helpers/tbbr/tbbr_tools.mk4
-rw-r--r--plat/allwinner/common/sunxi_cpu_ops.c14
-rw-r--r--plat/allwinner/sun50i_a64/platform.mk3
-rw-r--r--plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h7
-rw-r--r--plat/brcm/board/common/board_common.mk12
-rw-r--r--plat/nxp/common/aarch64/bl31_data.S558
-rw-r--r--plat/nxp/common/aarch64/ls_helpers.S194
-rw-r--r--plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h51
-rw-r--r--plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h53
-rw-r--r--plat/nxp/common/fip_handler/common/platform_oid.h16
-rw-r--r--plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk38
-rw-r--r--plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c232
-rw-r--r--plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h26
-rw-r--r--plat/nxp/common/fip_handler/fuse_fip/fuse.mk100
-rw-r--r--plat/nxp/common/fip_handler/fuse_fip/fuse_io.h27
-rw-r--r--plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c223
-rw-r--r--plat/nxp/common/img_loadr/img_loadr.mk21
-rw-r--r--plat/nxp/common/img_loadr/load_img.c79
-rw-r--r--plat/nxp/common/img_loadr/load_img.h14
-rw-r--r--plat/nxp/common/include/default/ch_2/soc_default_base_addr.h69
-rw-r--r--plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h61
-rw-r--r--plat/nxp/common/include/default/ch_3/soc_default_base_addr.h64
-rw-r--r--plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h84
-rw-r--r--plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h78
-rw-r--r--plat/nxp/common/include/default/plat_default_def.h164
-rw-r--r--plat/nxp/common/nv_storage/nv_storage.mk29
-rw-r--r--plat/nxp/common/nv_storage/plat_nv_storage.c120
-rw-r--r--plat/nxp/common/nv_storage/plat_nv_storage.h40
-rw-r--r--plat/nxp/common/psci/aarch64/psci_utils.S1155
-rw-r--r--plat/nxp/common/psci/include/plat_psci.h107
-rw-r--r--plat/nxp/common/psci/plat_psci.c475
-rw-r--r--plat/nxp/common/psci/psci.mk35
-rw-r--r--plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c103
-rw-r--r--plat/nxp/common/setup/common.mk105
-rw-r--r--plat/nxp/common/setup/core.mk20
-rw-r--r--plat/nxp/common/setup/include/bl31_data.h61
-rw-r--r--plat/nxp/common/setup/include/ls_interrupt_mgmt.h23
-rw-r--r--plat/nxp/common/setup/include/mmu_def.h34
-rw-r--r--plat/nxp/common/setup/include/plat_common.h147
-rw-r--r--plat/nxp/common/setup/include/plat_macros.S22
-rw-r--r--plat/nxp/common/setup/ls_bl2_el3_setup.c300
-rw-r--r--plat/nxp/common/setup/ls_bl31_setup.c210
-rw-r--r--plat/nxp/common/setup/ls_common.c240
-rw-r--r--plat/nxp/common/setup/ls_err.c55
-rw-r--r--plat/nxp/common/setup/ls_image_load.c33
-rw-r--r--plat/nxp/common/setup/ls_interrupt_mgmt.c66
-rw-r--r--plat/nxp/common/setup/ls_io_storage.c519
-rw-r--r--plat/nxp/common/setup/ls_stack_protector.c22
-rw-r--r--plat/nxp/common/sip_svc/aarch64/sipsvc.S152
-rw-r--r--plat/nxp/common/sip_svc/include/sipsvc.h80
-rw-r--r--plat/nxp/common/sip_svc/sip_svc.c194
-rw-r--r--plat/nxp/common/sip_svc/sipsvc.mk35
-rw-r--r--plat/nxp/common/tbbr/csf_tbbr.c81
-rw-r--r--plat/nxp/common/tbbr/nxp_rotpk.S21
-rw-r--r--plat/nxp/common/tbbr/tbbr.mk155
-rw-r--r--plat/nxp/common/tbbr/x509_tbbr.c105
-rw-r--r--plat/nxp/common/warm_reset/plat_warm_reset.c121
-rw-r--r--plat/nxp/common/warm_reset/plat_warm_rst.h28
-rw-r--r--plat/nxp/common/warm_reset/warm_reset.mk20
-rw-r--r--plat/nxp/soc-lx2160a/aarch64/lx2160a.S1824
-rw-r--r--plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S77
-rw-r--r--plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S229
-rw-r--r--plat/nxp/soc-lx2160a/ddr_fip.mk97
-rw-r--r--plat/nxp/soc-lx2160a/ddr_sb.mk43
-rw-r--r--plat/nxp/soc-lx2160a/ddr_tbbr.mk95
-rw-r--r--plat/nxp/soc-lx2160a/erratas_soc.c418
-rw-r--r--plat/nxp/soc-lx2160a/erratas_soc.mk21
-rw-r--r--plat/nxp/soc-lx2160a/include/errata.h14
-rw-r--r--plat/nxp/soc-lx2160a/include/soc.h142
-rw-r--r--plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c355
-rw-r--r--plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h105
-rw-r--r--plat/nxp/soc-lx2160a/lx2160aqds/platform.c29
-rw-r--r--plat/nxp/soc-lx2160a/lx2160aqds/platform.mk91
-rw-r--r--plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h14
-rw-r--r--plat/nxp/soc-lx2160a/lx2160aqds/policy.h38
-rw-r--r--plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c212
-rw-r--r--plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h105
-rw-r--r--plat/nxp/soc-lx2160a/lx2160ardb/platform.c29
-rw-r--r--plat/nxp/soc-lx2160a/lx2160ardb/platform.mk91
-rw-r--r--plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h14
-rw-r--r--plat/nxp/soc-lx2160a/lx2160ardb/policy.h38
-rw-r--r--plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c354
-rw-r--r--plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h105
-rw-r--r--plat/nxp/soc-lx2160a/lx2162aqds/platform.c29
-rw-r--r--plat/nxp/soc-lx2160a/lx2162aqds/platform.mk92
-rw-r--r--plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h14
-rw-r--r--plat/nxp/soc-lx2160a/lx2162aqds/policy.h38
-rw-r--r--plat/nxp/soc-lx2160a/soc.c528
-rw-r--r--plat/nxp/soc-lx2160a/soc.def201
-rw-r--r--plat/nxp/soc-lx2160a/soc.mk173
-rw-r--r--plat/rpi/rpi4/platform.mk8
-rw-r--r--services/std_svc/spmd/spmd_main.c18
-rw-r--r--tools/cert_create/Makefile14
-rw-r--r--tools/cert_create/include/cert.h19
-rw-r--r--tools/cert_create/include/ext.h19
-rw-r--r--tools/cert_create/include/key.h19
-rw-r--r--tools/cert_create/src/cert.c27
-rw-r--r--tools/cert_create/src/ext.c26
-rw-r--r--tools/cert_create/src/key.c27
-rw-r--r--tools/fiptool/Makefile20
-rw-r--r--tools/fiptool/fiptool.c36
-rw-r--r--tools/fiptool/tbbr_config.h4
-rw-r--r--tools/nxp/cert_create_helper/cert_create_tbbr.mk31
-rw-r--r--tools/nxp/cert_create_helper/include/pdef_tbb_cert.h21
-rw-r--r--tools/nxp/cert_create_helper/include/pdef_tbb_ext.h25
-rw-r--r--tools/nxp/cert_create_helper/include/pdef_tbb_key.h18
-rw-r--r--tools/nxp/cert_create_helper/src/pdef_tbb_cert.c62
-rw-r--r--tools/nxp/cert_create_helper/src/pdef_tbb_ext.c108
-rw-r--r--tools/nxp/cert_create_helper/src/pdef_tbb_key.c18
-rw-r--r--tools/nxp/create_pbl/Makefile61
-rw-r--r--tools/nxp/create_pbl/README65
-rw-r--r--tools/nxp/create_pbl/byte_swap.c113
-rw-r--r--tools/nxp/create_pbl/create_pbl.c996
-rw-r--r--tools/nxp/create_pbl/create_pbl.mk52
-rw-r--r--tools/nxp/create_pbl/pbl_ch2.mk60
-rw-r--r--tools/nxp/create_pbl/pbl_ch3.mk71
-rw-r--r--tools/nxp/plat_fiptool/plat_def_uuid_config.c90
-rw-r--r--tools/nxp/plat_fiptool/plat_fiptool.mk33
251 files changed, 44701 insertions, 446 deletions
diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c
index e88a550080..46606fb6e2 100644
--- a/common/fdt_fixup.c
+++ b/common/fdt_fixup.c
@@ -188,6 +188,8 @@ int dt_add_psci_cpu_enable_methods(void *fdt)
*
* See reserved-memory/reserved-memory.txt in the (Linux kernel) DT binding
* documentation for details.
+ * According to this binding, the address-cells and size-cells must match
+ * those of the root node.
*
* Return: 0 on success, a negative error value otherwise.
******************************************************************************/
@@ -195,23 +197,37 @@ int fdt_add_reserved_memory(void *dtb, const char *node_name,
uintptr_t base, size_t size)
{
int offs = fdt_path_offset(dtb, "/reserved-memory");
- uint32_t addresses[3];
+ uint32_t addresses[4];
+ int ac, sc;
+ unsigned int idx = 0;
+ ac = fdt_address_cells(dtb, 0);
+ sc = fdt_size_cells(dtb, 0);
if (offs < 0) { /* create if not existing yet */
offs = fdt_add_subnode(dtb, 0, "reserved-memory");
- if (offs < 0)
+ if (offs < 0) {
return offs;
- fdt_setprop_u32(dtb, offs, "#address-cells", 2);
- fdt_setprop_u32(dtb, offs, "#size-cells", 1);
+ }
+ fdt_setprop_u32(dtb, offs, "#address-cells", ac);
+ fdt_setprop_u32(dtb, offs, "#size-cells", sc);
fdt_setprop(dtb, offs, "ranges", NULL, 0);
}
- addresses[0] = cpu_to_fdt32(HIGH_BITS(base));
- addresses[1] = cpu_to_fdt32(base & 0xffffffff);
- addresses[2] = cpu_to_fdt32(size & 0xffffffff);
+ if (ac > 1) {
+ addresses[idx] = cpu_to_fdt32(HIGH_BITS(base));
+ idx++;
+ }
+ addresses[idx] = cpu_to_fdt32(base & 0xffffffff);
+ idx++;
+ if (sc > 1) {
+ addresses[idx] = cpu_to_fdt32(HIGH_BITS(size));
+ idx++;
+ }
+ addresses[idx] = cpu_to_fdt32(size & 0xffffffff);
+ idx++;
offs = fdt_add_subnode(dtb, offs, node_name);
fdt_setprop(dtb, offs, "no-map", NULL, 0);
- fdt_setprop(dtb, offs, "reg", addresses, 12);
+ fdt_setprop(dtb, offs, "reg", addresses, idx * sizeof(uint32_t));
return 0;
}
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 14a3b45e39..0b3f782c51 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -9,42 +9,45 @@ maintainers merge a contribution.
More details may be found in the `Project Maintenance Process`_ document.
+.. |M| replace:: **Mail**
+.. |G| replace:: **GitHub ID**
+.. |F| replace:: **Files**
.. _maintainers:
Maintainers
-----------
-:M: Dan Handley <dan.handley@arm.com>
-:G: `danh-arm`_
-:M: Soby Mathew <soby.mathew@arm.com>
-:G: `soby-mathew`_
-:M: Sandrine Bailleux <sandrine.bailleux@arm.com>
-:G: `sandrine-bailleux-arm`_
-:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
-:G: `AlexeiFedorov`_
-:M: Manish Pandey <manish.pandey2@arm.com>
-:G: `manish-pandey-arm`_
-:M: Mark Dykes <mark.dykes@arm.com>
-:G: `mardyk01`_
-:M: Olivier Deprez <olivier.deprez@arm.com>
-:G: `odeprez`_
-:M: Bipin Ravi <bipin.ravi@arm.com>
-:G: `bipinravi-arm`_
-:M: Joanna Farley <joanna.farley@arm.com>
-:G: `joannafarley-arm`_
-:M: Julius Werner <jwerner@chromium.org>
-:G: `jwerner-chromium`_
-:M: Varun Wadekar <vwadekar@nvidia.com>
-:G: `vwadekar`_
-:M: Andre Przywara <andre.przywara@arm.com>
-:G: `Andre-ARM`_
-:M: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
-:G: `laurenw-arm`_
-:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
-:G: `madhukar-Arm`_
-:M: Raghu Krishnamurthy <raghu.ncstate@icloud.com>
-:G: `raghuncstate`_
+:|M|: Dan Handley <dan.handley@arm.com>
+:|G|: `danh-arm`_
+:|M|: Soby Mathew <soby.mathew@arm.com>
+:|G|: `soby-mathew`_
+:|M|: Sandrine Bailleux <sandrine.bailleux@arm.com>
+:|G|: `sandrine-bailleux-arm`_
+:|M|: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:|G|: `AlexeiFedorov`_
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|M|: Mark Dykes <mark.dykes@arm.com>
+:|G|: `mardyk01`_
+:|M|: Olivier Deprez <olivier.deprez@arm.com>
+:|G|: `odeprez`_
+:|M|: Bipin Ravi <bipin.ravi@arm.com>
+:|G|: `bipinravi-arm`_
+:|M|: Joanna Farley <joanna.farley@arm.com>
+:|G|: `joannafarley-arm`_
+:|M|: Julius Werner <jwerner@chromium.org>
+:|G|: `jwerner-chromium`_
+:|M|: Varun Wadekar <vwadekar@nvidia.com>
+:|G|: `vwadekar`_
+:|M|: Andre Przywara <andre.przywara@arm.com>
+:|G|: `Andre-ARM`_
+:|M|: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
+:|G|: `laurenw-arm`_
+:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:|G|: `madhukar-Arm`_
+:|M|: Raghu Krishnamurthy <raghu.ncstate@icloud.com>
+:|G|: `raghuncstate`_
.. _code owners:
@@ -52,59 +55,59 @@ Maintainers
Code owners
-----------
-Core Code
-~~~~~~~~~
+Common Code
+~~~~~~~~~~~
Armv7-A architecture port
^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Etienne Carriere <etienne.carriere@linaro.org>
-:G: `etienne-lms`_
+:|M|: Etienne Carriere <etienne.carriere@linaro.org>
+:|G|: `etienne-lms`_
Build Definitions for CMake Build System
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
-:G: `javieralso-arm`_
-:M: Chris Kay <chris.kay@arm.com>
-:G: `CJkay`_
-:F: /
+:|M|: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:|G|: `javieralso-arm`_
+:|M|: Chris Kay <chris.kay@arm.com>
+:|G|: `CJKay`_
+:|F|: /
Software Delegated Exception Interface (SDEI)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Mark Dykes <mark.dykes@arm.com>
-:G: `mardyk01`_
-:M: John Powell <John.Powell@arm.com>
-:G: `john-powell-arm`_
-:F: services/std_svc/sdei/
+:|M|: Mark Dykes <mark.dykes@arm.com>
+:|G|: `mardyk01`_
+:|M|: John Powell <John.Powell@arm.com>
+:|G|: `john-powell-arm`_
+:|F|: services/std_svc/sdei/
Trusted Boot
^^^^^^^^^^^^
-:M: Sandrine Bailleux <sandrine.bailleux@arm.com>
-:G: `sandrine-bailleux-arm`_
-:M: Manish Pandey <manish.pandey2@arm.com>
-:G: `manish-pandey-arm`_
-:M: Manish Badarkhe <manish.badarkhe@arm.com>
-:G: `ManishVB-Arm`_
-:F: drivers/auth/
+:|M|: Sandrine Bailleux <sandrine.bailleux@arm.com>
+:|G|: `sandrine-bailleux-arm`_
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|M|: Manish Badarkhe <manish.badarkhe@arm.com>
+:|G|: `ManishVB-Arm`_
+:|F|: drivers/auth/
Secure Partition Manager (SPM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Olivier Deprez <olivier.deprez@arm.com>
-:G: `odeprez`_
-:M: Manish Pandey <manish.pandey2@arm.com>
-:G: `manish-pandey-arm`_
-:M: Maksims Svecovs <maksims.svecovs@arm.com>
-:G: `max-shvetsov`_
-:M: Joao Alves <Joao.Alves@arm.com>
-:G: `J-Alves`_
-:F: services/std_svc/spm\*
+:|M|: Olivier Deprez <olivier.deprez@arm.com>
+:|G|: `odeprez`_
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|M|: Maksims Svecovs <maksims.svecovs@arm.com>
+:|G|: `max-shvetsov`_
+:|M|: Joao Alves <Joao.Alves@arm.com>
+:|G|: `J-Alves`_
+:|F|: services/std_svc/spm\*
Exception Handling Framework (EHF)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Manish Badarkhe <manish.badarkhe@arm.com>
-:G: `ManishVB-Arm`_
-:M: John Powell <John.Powell@arm.com>
-:G: `john-powell-arm`_
-:F: bl31/ehf.c
+:|M|: Manish Badarkhe <manish.badarkhe@arm.com>
+:|G|: `ManishVB-Arm`_
+:|M|: John Powell <John.Powell@arm.com>
+:|G|: `john-powell-arm`_
+:|F|: bl31/ehf.c
Drivers, Libraries and Framework Code
@@ -112,455 +115,500 @@ Drivers, Libraries and Framework Code
Console API framework
^^^^^^^^^^^^^^^^^^^^^
-:M: Julius Werner <jwerner@chromium.org>
-:G: `jwerner-chromium`_
-:F: drivers/console/
-:F: include/drivers/console.h
-:F: plat/common/aarch64/crash_console_helpers.S
+:|M|: Julius Werner <jwerner@chromium.org>
+:|G|: `jwerner-chromium`_
+:|F|: drivers/console/
+:|F|: include/drivers/console.h
+:|F|: plat/common/aarch64/crash_console_helpers.S
coreboot support libraries
^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Julius Werner <jwerner@chromium.org>
-:G: `jwerner-chromium`_
-:F: drivers/coreboot/
-:F: include/drivers/coreboot/
-:F: include/lib/coreboot.h
-:F: lib/coreboot/
+:|M|: Julius Werner <jwerner@chromium.org>
+:|G|: `jwerner-chromium`_
+:|F|: drivers/coreboot/
+:|F|: include/drivers/coreboot/
+:|F|: include/lib/coreboot.h
+:|F|: lib/coreboot/
eMMC/UFS drivers
^^^^^^^^^^^^^^^^
-:M: Haojian Zhuang <haojian.zhuang@linaro.org>
-:G: `hzhuang1`_
-:F: drivers/partition/
-:F: drivers/synopsys/emmc/
-:F: drivers/synopsys/ufs/
-:F: drivers/ufs/
-:F: include/drivers/dw_ufs.h
-:F: include/drivers/ufs.h
-:F: include/drivers/synopsys/dw_mmc.h
+:|M|: Haojian Zhuang <haojian.zhuang@linaro.org>
+:|G|: `hzhuang1`_
+:|F|: drivers/partition/
+:|F|: drivers/synopsys/emmc/
+:|F|: drivers/synopsys/ufs/
+:|F|: drivers/ufs/
+:|F|: include/drivers/dw_ufs.h
+:|F|: include/drivers/ufs.h
+:|F|: include/drivers/synopsys/dw_mmc.h
Power State Coordination Interface (PSCI)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
-:G: `javieralso-arm`_
-:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
-:G: `madhukar-Arm`_
-:M: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
-:G: `laurenw-arm`_
-:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
-:G: `zelalem-aweke`_
-:F: lib/psci/
+:|M|: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:|G|: `javieralso-arm`_
+:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:|G|: `madhukar-Arm`_
+:|M|: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
+:|G|: `laurenw-arm`_
+:|M|: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:|G|: `zelalem-aweke`_
+:|F|: lib/psci/
DebugFS
^^^^^^^
-:M: Olivier Deprez <olivier.deprez@arm.com>
-:G: `odeprez`_
-:F: lib/debugfs/
+:|M|: Olivier Deprez <olivier.deprez@arm.com>
+:|G|: `odeprez`_
+:|F|: lib/debugfs/
Firmware Configuration Framework (FCONF)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
-:G: `madhukar-Arm`_
-:M: Manish Badarkhe <manish.badarkhe@arm.com>
-:G: `ManishVB-Arm`_
-:M: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
-:G: `laurenw-arm`_
-:F: lib/fconf/
+:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:|G|: `madhukar-Arm`_
+:|M|: Manish Badarkhe <manish.badarkhe@arm.com>
+:|G|: `ManishVB-Arm`_
+:|M|: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
+:|G|: `laurenw-arm`_
+:|F|: lib/fconf/
Performance Measurement Framework (PMF)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Joao Alves <Joao.Alves@arm.com>
-:G: `J-Alves`_
-:M: Jimmy Brisson <Jimmy.Brisson@arm.com>
-:G: `theotherjimmy`_
-:F: lib/pmf/
+:|M|: Joao Alves <Joao.Alves@arm.com>
+:|G|: `J-Alves`_
+:|M|: Jimmy Brisson <Jimmy.Brisson@arm.com>
+:|G|: `theotherjimmy`_
+:|F|: lib/pmf/
Arm CPU libraries
^^^^^^^^^^^^^^^^^
-:M: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
-:G: `laurenw-arm`_
-:M: John Powell <John.Powell@arm.com>
-:G: `john-powell-arm`_
-:F: lib/cpus/
+:|M|: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
+:|G|: `laurenw-arm`_
+:|M|: John Powell <John.Powell@arm.com>
+:|G|: `john-powell-arm`_
+:|F|: lib/cpus/
Reliability Availability Serviceabilty (RAS) framework
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Olivier Deprez <olivier.deprez@arm.com>
-:G: `odeprez`_
-:M: Manish Pandey <manish.pandey2@arm.com>
-:G: `manish-pandey-arm`_
-:F: lib/extensions/ras/
+:|M|: Olivier Deprez <olivier.deprez@arm.com>
+:|G|: `odeprez`_
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|F|: lib/extensions/ras/
Activity Monitors Unit (AMU) extensions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
-:G: `AlexeiFedorov`_
-:F: lib/extensions/amu/
+:|M|: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:|G|: `AlexeiFedorov`_
+:|F|: lib/extensions/amu/
Memory Partitioning And Monitoring (MPAM) extensions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
-:G: `zelalem-aweke`_
-:M: Jimmy Brisson <Jimmy.Brisson@arm.com>
-:G: `theotherjimmy`_
-:F: lib/extensions/mpam/
+:|M|: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:|G|: `zelalem-aweke`_
+:|M|: Jimmy Brisson <Jimmy.Brisson@arm.com>
+:|G|: `theotherjimmy`_
+:|F|: lib/extensions/mpam/
Pointer Authentication (PAuth) and Branch Target Identification (BTI) extensions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
-:G: `AlexeiFedorov`_
-:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
-:G: `zelalem-aweke`_
-:F: lib/extensions/pauth/
+:|M|: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:|G|: `AlexeiFedorov`_
+:|M|: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:|G|: `zelalem-aweke`_
+:|F|: lib/extensions/pauth/
Statistical Profiling Extension (SPE)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
-:G: `zelalem-aweke`_
-:M: Jimmy Brisson <Jimmy.Brisson@arm.com>
-:G: `theotherjimmy`_
-:F: lib/extensions/spe/
+:|M|: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:|G|: `zelalem-aweke`_
+:|M|: Jimmy Brisson <Jimmy.Brisson@arm.com>
+:|G|: `theotherjimmy`_
+:|F|: lib/extensions/spe/
Scalable Vector Extension (SVE)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Jimmy Brisson <Jimmy.Brisson@arm.com>
-:G: `theotherjimmy`_
-:F: lib/extensions/sve/
+:|M|: Jimmy Brisson <Jimmy.Brisson@arm.com>
+:|G|: `theotherjimmy`_
+:|F|: lib/extensions/sve/
Standard C library
^^^^^^^^^^^^^^^^^^
-:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
-:G: `AlexeiFedorov`_
-:M: John Powell <John.Powell@arm.com>
-:G: `john-powell-arm`_
-:F: lib/libc/
+:|M|: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:|G|: `AlexeiFedorov`_
+:|M|: John Powell <John.Powell@arm.com>
+:|G|: `john-powell-arm`_
+:|F|: lib/libc/
Library At ROM (ROMlib)
^^^^^^^^^^^^^^^^^^^^^^^
-:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
-:G: `madhukar-Arm`_
-:F: lib/romlib/
+:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:|G|: `madhukar-Arm`_
+:|F|: lib/romlib/
Translation tables (``xlat_tables``) library
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
-:G: `javieralso-arm`_
-:M: Joao Alves <Joao.Alves@arm.com>
-:G: `J-Alves`_
-:F: lib/xlat\_tables_\*/
+:|M|: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:|G|: `javieralso-arm`_
+:|M|: Joao Alves <Joao.Alves@arm.com>
+:|G|: `J-Alves`_
+:|F|: lib/xlat\_tables_\*/
IO abstraction layer
^^^^^^^^^^^^^^^^^^^^
-:M: Manish Pandey <manish.pandey2@arm.com>
-:G: `manish-pandey-arm`_
-:M: Olivier Deprez <olivier.deprez@arm.com>
-:G: `odeprez`_
-:F: drivers/io/
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|M|: Olivier Deprez <olivier.deprez@arm.com>
+:|G|: `odeprez`_
+:|F|: drivers/io/
GIC driver
^^^^^^^^^^
-:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
-:G: `AlexeiFedorov`_
-:M: Manish Pandey <manish.pandey2@arm.com>
-:G: `manish-pandey-arm`_
-:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
-:G: `madhukar-Arm`_
-:M: Olivier Deprez <olivier.deprez@arm.com>
-:G: `odeprez`_
-:F: drivers/arm/gic/
+:|M|: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:|G|: `AlexeiFedorov`_
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:|G|: `madhukar-Arm`_
+:|M|: Olivier Deprez <olivier.deprez@arm.com>
+:|G|: `odeprez`_
+:|F|: drivers/arm/gic/
Libfdt wrappers
^^^^^^^^^^^^^^^
-:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
-:G: `madhukar-Arm`_
-:M: Manish Badarkhe <manish.badarkhe@arm.com>
-:G: `ManishVB-Arm`_
-:F: common/fdt_wrappers.c
+:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:|G|: `madhukar-Arm`_
+:|M|: Manish Badarkhe <manish.badarkhe@arm.com>
+:|G|: `ManishVB-Arm`_
+:|F|: common/fdt_wrappers.c
Firmware Encryption Framework
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Sumit Garg <sumit.garg@linaro.org>
-:G: `b49020`_
-:F: drivers/io/io_encrypted.c
-:F: include/drivers/io/io_encrypted.h
-:F: include/tools_share/firmware_encrypted.h
+:|M|: Sumit Garg <sumit.garg@linaro.org>
+:|G|: `b49020`_
+:|F|: drivers/io/io_encrypted.c
+:|F|: include/drivers/io/io_encrypted.h
+:|F|: include/tools_share/firmware_encrypted.h
Measured Boot
^^^^^^^^^^^^^
-:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
-:G: `AlexeiFedorov`_
-:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
-:G: `javieralso-arm`_
-:F: drivers/measured_boot
-:F: include/drivers/measured_boot
-:F: plat/arm/board/fvp/fvp_measured_boot.c
+:|M|: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:|G|: `AlexeiFedorov`_
+:|M|: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:|G|: `javieralso-arm`_
+:|F|: drivers/measured_boot
+:|F|: include/drivers/measured_boot
+:|F|: plat/arm/board/fvp/fvp_measured_boot.c
System Control and Management Interface (SCMI) Server
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Etienne Carriere <etienne.carriere@st.com>
-:G: `etienne-lms`_
-:M: Peng Fan <peng.fan@nxp.com>
-:G: `MrVan`_
-:F: drivers/scmi-msg
-:F: include/drivers/scmi\*
+:|M|: Etienne Carriere <etienne.carriere@st.com>
+:|G|: `etienne-lms`_
+:|M|: Peng Fan <peng.fan@nxp.com>
+:|G|: `MrVan`_
+:|F|: drivers/scmi-msg
+:|F|: include/drivers/scmi\*
Platform Ports
~~~~~~~~~~~~~~
Allwinner ARMv8 platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Andre Przywara <andre.przywara@arm.com>
-:G: `Andre-ARM`_
-:M: Samuel Holland <samuel@sholland.org>
-:G: `smaeul`_
-:F: docs/plat/allwinner.rst
-:F: plat/allwinner/
-:F: drivers/allwinner/
+:|M|: Andre Przywara <andre.przywara@arm.com>
+:|G|: `Andre-ARM`_
+:|M|: Samuel Holland <samuel@sholland.org>
+:|G|: `smaeul`_
+:|F|: docs/plat/allwinner.rst
+:|F|: plat/allwinner/
+:|F|: drivers/allwinner/
Amlogic Meson S905 (GXBB) platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Andre Przywara <andre.przywara@arm.com>
-:G: `Andre-ARM`_
-:F: docs/plat/meson-gxbb.rst
-:F: drivers/amlogic/
-:F: plat/amlogic/gxbb/
+:|M|: Andre Przywara <andre.przywara@arm.com>
+:|G|: `Andre-ARM`_
+:|F|: docs/plat/meson-gxbb.rst
+:|F|: drivers/amlogic/
+:|F|: plat/amlogic/gxbb/
Amlogic Meson S905x (GXL) platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Remi Pommarel <repk@triplefau.lt>
-:G: `remi-triplefault`_
-:F: docs/plat/meson-gxl.rst
-:F: plat/amlogic/gxl/
+:|M|: Remi Pommarel <repk@triplefau.lt>
+:|G|: `remi-triplefault`_
+:|F|: docs/plat/meson-gxl.rst
+:|F|: plat/amlogic/gxl/
Amlogic Meson S905X2 (G12A) platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Carlo Caione <ccaione@baylibre.com>
-:G: `carlocaione`_
-:F: docs/plat/meson-g12a.rst
-:F: plat/amlogic/g12a/
+:|M|: Carlo Caione <ccaione@baylibre.com>
+:|G|: `carlocaione`_
+:|F|: docs/plat/meson-g12a.rst
+:|F|: plat/amlogic/g12a/
Amlogic Meson A113D (AXG) platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Carlo Caione <ccaione@baylibre.com>
-:G: `carlocaione`_
-:F: docs/plat/meson-axg.rst
-:F: plat/amlogic/axg/
+:|M|: Carlo Caione <ccaione@baylibre.com>
+:|G|: `carlocaione`_
+:|F|: docs/plat/meson-axg.rst
+:|F|: plat/amlogic/axg/
Arm FPGA platform port
^^^^^^^^^^^^^^^^^^^^^^
-:M: Andre Przywara <andre.przywara@arm.com>
-:G: `Andre-ARM`_
-:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
-:G: `javieralso-arm`_
-:F: plat/arm/board/arm_fpga
-
-Arm System Guidance for Infrastructure / Mobile FVP platforms
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Nariman Poushin <nariman.poushin@linaro.org>
-:G: `npoushin`_
-:M: Thomas Abraham <thomas.abraham@arm.com>
-:G: `thomas-arm`_
-:F: plat/arm/css/sgi/
-:F: plat/arm/css/sgm/
-:F: plat/arm/board/sgi575/
-:F: plat/arm/board/sgm775/
+:|M|: Andre Przywara <andre.przywara@arm.com>
+:|G|: `Andre-ARM`_
+:|M|: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:|G|: `javieralso-arm`_
+:|F|: plat/arm/board/arm_fpga
+
+Arm FVP Platform port
+^^^^^^^^^^^^^^^^^^^^^
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:|G|: `madhukar-Arm`_
+:|F|: plat/arm/board/fvp
+
+Arm Juno Platform port
+^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|M|: Chris Kay <chris.kay@arm.com>
+:|G|: `CJKay`_
+:|F|: plat/arm/board/juno
+
+Arm Morello and N1SDP Platform ports
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Manoj Kumar <manoj.kumar3@arm.com>
+:|G|: `manojkumar-arm`_
+:|M|: Chandni Cherukuri <chandni.cherukuri@arm.com>
+:|G|: `chandnich`_
+:|F|: plat/arm/board/morello
+:|F|: plat/arm/board/n1sdp
+
+Arm Rich IoT Platform ports
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+:|G|: `abdellatif-elkhlifi`_
+:|M|: Vishnu Banavath <vishnu.banavath@arm.com>
+:|G|: `vishnu-banavath`_
+:|F|: plat/arm/board/corstone700
+:|F|: plat/arm/board/a5ds
+
+Arm Reference Design platform ports
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Thomas Abraham <thomas.abraham@arm.com>
+:|G|: `thomas-arm`_
+:|M|: Vijayenthiran Subramaniam <vijayenthiran.subramaniam@arm.com>
+:|G|: `vijayenthiran-arm`_
+:|F|: plat/arm/css/sgi/
+:|F|: plat/arm/board/rde1edge/
+:|F|: plat/arm/board/rdn1edge/
+:|F|: plat/arm/board/rdn2/
+:|F|: plat/arm/board/rdv1/
+:|F|: plat/arm/board/rdv1mc/
+:|F|: plat/arm/board/sgi575/
+
+Arm Total Compute(tc0) platform port
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+:|G|: `arugan02`_
+:|M|: Usama Arif <usama.arif@arm.com>
+:|G|: `uarif1`_
+:|F|: plat/arm/board/tc0
HiSilicon HiKey and HiKey960 platform ports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Haojian Zhuang <haojian.zhuang@linaro.org>
-:G: `hzhuang1`_
-:F: docs/plat/hikey.rst
-:F: docs/plat/hikey960.rst
-:F: plat/hisilicon/hikey/
-:F: plat/hisilicon/hikey960/
+:|M|: Haojian Zhuang <haojian.zhuang@linaro.org>
+:|G|: `hzhuang1`_
+:|F|: docs/plat/hikey.rst
+:|F|: docs/plat/hikey960.rst
+:|F|: plat/hisilicon/hikey/
+:|F|: plat/hisilicon/hikey960/
HiSilicon Poplar platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Shawn Guo <shawn.guo@linaro.org>
-:G: `shawnguo2`_
-:F: docs/plat/poplar.rst
-:F: plat/hisilicon/poplar/
+:|M|: Shawn Guo <shawn.guo@linaro.org>
+:|G|: `shawnguo2`_
+:|F|: docs/plat/poplar.rst
+:|F|: plat/hisilicon/poplar/
Intel SocFPGA platform ports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Tien Hock Loh <tien.hock.loh@intel.com>
-:G: `thloh85-intel`_
-:M: Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com>
-:G: mabdulha
-:F: plat/intel/soc
-:F: drivers/intel/soc/
+:|M|: Tien Hock Loh <tien.hock.loh@intel.com>
+:|G|: `thloh85-intel`_
+:|M|: Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com>
+:|G|: mabdulha
+:|F|: plat/intel/soc
+:|F|: drivers/intel/soc/
MediaTek platform ports
^^^^^^^^^^^^^^^^^^^^^^^
-:M: Yidi Lin (林以廸) <yidi.lin@mediatek.com>
-:G: `mtk09422`_
-:F: plat/mediatek/
+:|M|: Yidi Lin (林以廸) <yidi.lin@mediatek.com>
+:|G|: `mtk09422`_
+:|F|: plat/mediatek/
Marvell platform ports and SoC drivers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Konstantin Porotchkin <kostap@marvell.com>
-:G: `kostapr`_
-:F: docs/plat/marvell/
-:F: plat/marvell/
-:F: drivers/marvell/
-:F: tools/marvell/
+:|M|: Konstantin Porotchkin <kostap@marvell.com>
+:|G|: `kostapr`_
+:|F|: docs/plat/marvell/
+:|F|: plat/marvell/
+:|F|: drivers/marvell/
+:|F|: tools/marvell/
NVidia platform ports
^^^^^^^^^^^^^^^^^^^^^
-:M: Varun Wadekar <vwadekar@nvidia.com>
-:G: `vwadekar`_
-:F: docs/plat/nvidia-tegra.rst
-:F: include/lib/cpus/aarch64/denver.h
-:F: lib/cpus/aarch64/denver.S
-:F: plat/nvidia/
+:|M|: Varun Wadekar <vwadekar@nvidia.com>
+:|G|: `vwadekar`_
+:|F|: docs/plat/nvidia-tegra.rst
+:|F|: include/lib/cpus/aarch64/denver.h
+:|F|: lib/cpus/aarch64/denver.S
+:|F|: plat/nvidia/
NXP QorIQ Layerscape platform ports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Jiafei Pan <jiafei.pan@nxp.com>
-:G: `qoriq-open-source`_
-:F: docs/plat/ls1043a.rst
-:F: plat/layerscape/
+:|M|: Jiafei Pan <jiafei.pan@nxp.com>
+:|G|: `qoriq-open-source`_
+:|F|: docs/plat/ls1043a.rst
+:|F|: plat/layerscape/
NXP i.MX 7 WaRP7 platform port and SoC drivers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
-:G: `bryanodonoghue`_
-:M: Jun Nie <jun.nie@linaro.org>
-:G: `niej`_
-:F: docs/plat/warp7.rst
-:F: plat/imx/common/
-:F: plat/imx/imx7/
-:F: drivers/imx/timer/
-:F: drivers/imx/uart/
-:F: drivers/imx/usdhc/
+:|M|: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+:|G|: `bryanodonoghue`_
+:|M|: Jun Nie <jun.nie@linaro.org>
+:|G|: `niej`_
+:|F|: docs/plat/warp7.rst
+:|F|: plat/imx/common/
+:|F|: plat/imx/imx7/
+:|F|: drivers/imx/timer/
+:|F|: drivers/imx/uart/
+:|F|: drivers/imx/usdhc/
NXP i.MX 8 platform port
^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Anson Huang <Anson.Huang@nxp.com>
-:G: `Anson-Huang`_
-:F: docs/plat/imx8.rst
-:F: plat/imx/
+:|M|: Anson Huang <Anson.Huang@nxp.com>
+:|G|: `Anson-Huang`_
+:|F|: docs/plat/imx8.rst
+:|F|: plat/imx/
NXP i.MX8M platform port
^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Jacky Bai <ping.bai@nxp.com>
-:G: `JackyBai`_
-:F: docs/plat/imx8m.rst
-:F: plat/imx/imx8m/
+:|M|: Jacky Bai <ping.bai@nxp.com>
+:|G|: `JackyBai`_
+:|F|: docs/plat/imx8m.rst
+:|F|: plat/imx/imx8m/
QEMU platform port
^^^^^^^^^^^^^^^^^^
-:M: Jens Wiklander <jens.wiklander@linaro.org>
-:G: `jenswi-linaro`_
-:F: docs/plat/qemu.rst
-:F: plat/qemu/
+:|M|: Jens Wiklander <jens.wiklander@linaro.org>
+:|G|: `jenswi-linaro`_
+:|F|: docs/plat/qemu.rst
+:|F|: plat/qemu/
QTI platform port
^^^^^^^^^^^^^^^^^
-:M: Saurabh Gorecha <sgorecha@codeaurora.org>
-:G: `sgorecha`_
-:M: Debasish Mandal <dmandal@codeaurora.org>
-:M: QTI TF Maintainers <qti.trustedfirmware.maintainers@codeaurora.org>
-:F: docs/plat/qti.rst
-:F: plat/qti/
+:|M|: Saurabh Gorecha <sgorecha@codeaurora.org>
+:|G|: `sgorecha`_
+:|M|: Debasish Mandal <dmandal@codeaurora.org>
+:|M|: QTI TF Maintainers <qti.trustedfirmware.maintainers@codeaurora.org>
+:|F|: docs/plat/qti.rst
+:|F|: plat/qti/
Raspberry Pi 3 platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
-:G: `grandpaul`_
-:F: docs/plat/rpi3.rst
-:F: plat/rpi/rpi3/
-:F: plat/rpi/common/
-:F: drivers/rpi3/
-:F: include/drivers/rpi3/
+:|M|: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+:|G|: `grandpaul`_
+:|F|: docs/plat/rpi3.rst
+:|F|: plat/rpi/rpi3/
+:|F|: plat/rpi/common/
+:|F|: drivers/rpi3/
+:|F|: include/drivers/rpi3/
Raspberry Pi 4 platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Andre Przywara <andre.przywara@arm.com>
-:G: `Andre-ARM`_
-:F: docs/plat/rpi4.rst
-:F: plat/rpi/rpi4/
-:F: plat/rpi/common/
-:F: drivers/rpi3/
-:F: include/drivers/rpi3/
+:|M|: Andre Przywara <andre.przywara@arm.com>
+:|G|: `Andre-ARM`_
+:|F|: docs/plat/rpi4.rst
+:|F|: plat/rpi/rpi4/
+:|F|: plat/rpi/common/
+:|F|: drivers/rpi3/
+:|F|: include/drivers/rpi3/
Renesas rcar-gen3 platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Jorge Ramirez-Ortiz <jramirez@baylibre.com>
-:G: `ldts`_
-:M: Marek Vasut <marek.vasut@gmail.com>
-:G: `marex`_
-:F: docs/plat/rcar-gen3.rst
-:F: plat/renesas/common
-:F: plat/renesas/rcar
-:F: drivers/renesas/common
-:F: drivers/renesas/rcar
-:F: tools/renesas/rcar_layout_create
+:|M|: Jorge Ramirez-Ortiz <jramirez@baylibre.com>
+:|G|: `ldts`_
+:|M|: Marek Vasut <marek.vasut@gmail.com>
+:|G|: `marex`_
+:|F|: docs/plat/rcar-gen3.rst
+:|F|: plat/renesas/common
+:|F|: plat/renesas/rcar
+:|F|: drivers/renesas/common
+:|F|: drivers/renesas/rcar
+:|F|: tools/renesas/rcar_layout_create
Renesas RZ/G2 platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Biju Das <biju.das.jz@bp.renesas.com>
-:G: `bijucdas`_
-:M: Marek Vasut <marek.vasut@gmail.com>
-:G: `marex`_
-:M: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
-:G: `prabhakarlad`_
-:F: docs/plat/rz-g2.rst
-:F: plat/renesas/common
-:F: plat/renesas/rzg
-:F: drivers/renesas/common
-:F: drivers/renesas/rzg
-:F: tools/renesas/rzg_layout_create
+:|M|: Biju Das <biju.das.jz@bp.renesas.com>
+:|G|: `bijucdas`_
+:|M|: Marek Vasut <marek.vasut@gmail.com>
+:|G|: `marex`_
+:|M|: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+:|G|: `prabhakarlad`_
+:|F|: docs/plat/rz-g2.rst
+:|F|: plat/renesas/common
+:|F|: plat/renesas/rzg
+:|F|: drivers/renesas/common
+:|F|: drivers/renesas/rzg
+:|F|: tools/renesas/rzg_layout_create
RockChip platform port
^^^^^^^^^^^^^^^^^^^^^^
-:M: Tony Xie <tony.xie@rock-chips.com>
-:G: `TonyXie06`_
-:G: `rockchip-linux`_
-:M: Heiko Stuebner <heiko@sntech.de>
-:G: `mmind`_
-:F: plat/rockchip/
+:|M|: Tony Xie <tony.xie@rock-chips.com>
+:|G|: `TonyXie06`_
+:|G|: `rockchip-linux`_
+:|M|: Heiko Stuebner <heiko@sntech.de>
+:|G|: `mmind`_
+:|F|: plat/rockchip/
STM32MP1 platform port
^^^^^^^^^^^^^^^^^^^^^^
-:M: Yann Gautier <yann.gautier@st.com>
-:G: `Yann-lms`_
-:F: docs/plat/stm32mp1.rst
-:F: drivers/st/
-:F: fdts/stm32\*
-:F: include/drivers/st/
-:F: include/dt-bindings/\*/stm32\*
-:F: plat/st/
-:F: tools/stm32image/
+:|M|: Yann Gautier <yann.gautier@st.com>
+:|G|: `Yann-lms`_
+:|F|: docs/plat/stm32mp1.rst
+:|F|: drivers/st/
+:|F|: fdts/stm32\*
+:|F|: include/drivers/st/
+:|F|: include/dt-bindings/\*/stm32\*
+:|F|: plat/st/
+:|F|: tools/stm32image/
Synquacer platform port
^^^^^^^^^^^^^^^^^^^^^^^
-:M: Sumit Garg <sumit.garg@linaro.org>
-:G: `b49020`_
-:F: docs/plat/synquacer.rst
-:F: plat/socionext/synquacer/
+:|M|: Sumit Garg <sumit.garg@linaro.org>
+:|G|: `b49020`_
+:|F|: docs/plat/synquacer.rst
+:|F|: plat/socionext/synquacer/
Texas Instruments platform port
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Nishanth Menon <nm@ti.com>
-:G: `nmenon`_
-:F: docs/plat/ti-k3.rst
-:F: plat/ti/
+:|M|: Nishanth Menon <nm@ti.com>
+:|G|: `nmenon`_
+:|F|: docs/plat/ti-k3.rst
+:|F|: plat/ti/
UniPhier platform port
^^^^^^^^^^^^^^^^^^^^^^
-:M: Orphan
-:F: docs/plat/socionext-uniphier.rst
-:F: plat/socionext/uniphier/
+:|M|: Orphan
+:|F|: docs/plat/socionext-uniphier.rst
+:|F|: plat/socionext/uniphier/
Xilinx platform port
^^^^^^^^^^^^^^^^^^^^
-:M: Michal Simek <michal.simek@xilinx.com>
-:G: `michalsimek`_
-:M: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@xilinx.com>
-:G: `venkatesh`_
-:F: docs/plat/xilinx-zynqmp.rst
-:F: plat/xilinx/
+:|M|: Michal Simek <michal.simek@xilinx.com>
+:|G|: `michalsimek`_
+:|M|: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@xilinx.com>
+:|G|: `venkatesh`_
+:|F|: docs/plat/xilinx-zynqmp.rst
+:|F|: plat/xilinx/
Secure Payloads and Dispatchers
@@ -568,61 +616,61 @@ Secure Payloads and Dispatchers
OP-TEE dispatcher
^^^^^^^^^^^^^^^^^
-:M: Jens Wiklander <jens.wiklander@linaro.org>
-:G: `jenswi-linaro`_
-:F: docs/components/spd/optee-dispatcher.rst
-:F: services/spd/opteed/
+:|M|: Jens Wiklander <jens.wiklander@linaro.org>
+:|G|: `jenswi-linaro`_
+:|F|: docs/components/spd/optee-dispatcher.rst
+:|F|: services/spd/opteed/
TLK/Trusty secure payloads
^^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Varun Wadekar <vwadekar@nvidia.com>
-:G: `vwadekar`_
-:F: docs/components/spd/tlk-dispatcher.rst
-:F: docs/components/spd/trusty-dispatcher.rst
-:F: include/bl32/payloads/tlk.h
-:F: services/spd/tlkd/
-:F: services/spd/trusty/
+:|M|: Varun Wadekar <vwadekar@nvidia.com>
+:|G|: `vwadekar`_
+:|F|: docs/components/spd/tlk-dispatcher.rst
+:|F|: docs/components/spd/trusty-dispatcher.rst
+:|F|: include/bl32/payloads/tlk.h
+:|F|: services/spd/tlkd/
+:|F|: services/spd/trusty/
Test Secure Payload (TSP)
^^^^^^^^^^^^^^^^^^^^^^^^^
-:M: Manish Badarkhe <manish.badarkhe@arm.com>
-:G: `ManishVB-Arm`_
-:F: bl32/tsp/
-:F: services/spd/tspd/
+:|M|: Manish Badarkhe <manish.badarkhe@arm.com>
+:|G|: `ManishVB-Arm`_
+:|F|: bl32/tsp/
+:|F|: services/spd/tspd/
Tools
~~~~~
Fiptool
^^^^^^^
-:M: Joao Alves <Joao.Alves@arm.com>
-:G: `J-Alves`_
-:F: tools/fiptool/
+:|M|: Joao Alves <Joao.Alves@arm.com>
+:|G|: `J-Alves`_
+:|F|: tools/fiptool/
Cert_create tool
^^^^^^^^^^^^^^^^
-:M: Sandrine Bailleux <sandrine.bailleux@arm.com>
-:G: `sandrine-bailleux-arm`_
-:F: tools/cert_create/
+:|M|: Sandrine Bailleux <sandrine.bailleux@arm.com>
+:|G|: `sandrine-bailleux-arm`_
+:|F|: tools/cert_create/
Encrypt_fw tool
^^^^^^^^^^^^^^^
-:M: Sumit Garg <sumit.garg@linaro.org>
-:G: `b49020`_
-:F: tools/encrypt_fw/
+:|M|: Sumit Garg <sumit.garg@linaro.org>
+:|G|: `b49020`_
+:|F|: tools/encrypt_fw/
Sptool
^^^^^^
-:M: Manish Pandey <manish.pandey2@arm.com>
-:G: `manish-pandey-arm`_
-:F: tools/sptool/
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|F|: tools/sptool/
Build system
^^^^^^^^^^^^
-:M: Manish Pandey <manish.pandey2@arm.com>
-:G: `manish-pandey-arm`_
-:F: Makefile
-:F: make_helpers/
+:|M|: Manish Pandey <manish.pandey2@arm.com>
+:|G|: `manish-pandey-arm`_
+:|F|: Makefile
+:|F|: make_helpers/
.. _AlexeiFedorov: https://github.com/AlexeiFedorov
.. _Andre-ARM: https://github.com/Andre-ARM
@@ -681,5 +729,12 @@ Build system
.. _raghuncstate: https://github.com/raghuncstate
.. _CJKay: https://github.com/cjkay
.. _nmenon: https://github.com/nmenon
+.. _manojkumar-arm: https://github.com/manojkumar-arm
+.. _chandnich: https://github.com/chandnich
+.. _abdellatif-elkhlifi: https://github.com/abdellatif-elkhlifi
+.. _vishnu-banavath: https://github.com/vishnu-banavath
+.. _vijayenthiran-arm: https://github.com/vijayenthiran-arm
+.. _arugan02: https://github.com/arugan02
+.. _uarif1: https://github.com/uarif1
.. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/
diff --git a/drivers/allwinner/axp/common.c b/drivers/allwinner/axp/common.c
index e98b16fdb2..143fb0f2d2 100644
--- a/drivers/allwinner/axp/common.c
+++ b/drivers/allwinner/axp/common.c
@@ -96,12 +96,27 @@ static int setup_regulator(const void *fdt, int node,
return 0;
}
+static bool is_node_disabled(const void *fdt, int node)
+{
+ const char *cell;
+ cell = fdt_getprop(fdt, node, "status", NULL);
+ if (cell == NULL) {
+ return false;
+ }
+ return strcmp(cell, "okay") != 0;
+}
+
static bool should_enable_regulator(const void *fdt, int node)
{
- if (fdt_getprop(fdt, node, "phandle", NULL) != NULL)
+ if (is_node_disabled(fdt, node)) {
+ return false;
+ }
+ if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) {
return true;
- if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL)
+ }
+ if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) {
return true;
+ }
return false;
}
diff --git a/drivers/brcm/i2c/i2c.c b/drivers/brcm/i2c/i2c.c
new file mode 100644
index 0000000000..2096a82595
--- /dev/null
+++ b/drivers/brcm/i2c/i2c.c
@@ -0,0 +1,886 @@
+/*
+ * Copyright (c) 2016 - 2021, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <i2c.h>
+#include <i2c_regs.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+/* Max instances */
+#define MAX_I2C 2U
+
+/* Transaction error codes defined in Master command register (0x30) */
+#define MSTR_STS_XACT_SUCCESS 0U
+#define MSTR_STS_LOST_ARB 1U
+#define MSTR_STS_NACK_FIRST_BYTE 2U
+ /* NACK on a byte other than the first byte */
+#define MSTR_STS_NACK_NON_FIRST_BYTE 3U
+
+#define MSTR_STS_TTIMEOUT_EXCEEDED 4U
+#define MSTR_STS_TX_TLOW_MEXT_EXCEEDED 5U
+#define MSTR_STS_RX_TLOW_MEXT_EXCEEDED 6U
+
+/* SMBUS protocol values defined in register 0x30 */
+#define SMBUS_PROT_QUICK_CMD 0U
+#define SMBUS_PROT_SEND_BYTE 1U
+#define SMBUS_PROT_RECV_BYTE 2U
+#define SMBUS_PROT_WR_BYTE 3U
+#define SMBUS_PROT_RD_BYTE 4U
+#define SMBUS_PROT_WR_WORD 5U
+#define SMBUS_PROT_RD_WORD 6U
+#define SMBUS_PROT_BLK_WR 7U
+#define SMBUS_PROT_BLK_RD 8U
+#define SMBUS_PROT_PROC_CALL 9U
+#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10U
+
+/* Number can be changed later */
+#define BUS_BUSY_COUNT 100000U
+
+#define IPROC_I2C_INVALID_ADDR 0xFFU
+
+#define I2C_SMBUS_BLOCK_MAX 32U
+
+/*
+ * Enum to specify clock speed. The user will provide it during initialization.
+ * If needed, it can be changed dynamically
+ */
+typedef enum iproc_smb_clk_freq {
+ IPROC_SMB_SPEED_100KHz = 0,
+ IPROC_SMB_SPEED_400KHz = 1,
+ IPROC_SMB_SPEED_INVALID = 255
+} smb_clk_freq_t;
+
+/* Structure used to pass information to read/write functions. */
+struct iproc_xact_info {
+ /* Bus Identifier */
+ uint32_t bus_id;
+ /* Device Address */
+ uint8_t devaddr;
+ /* Passed by caller to send SMBus command cod e*/
+ uint8_t command;
+ /* actual data passed by the caller */
+ uint8_t *data;
+ /* Size of data buffer passed */
+ uint32_t size;
+ /* Sent by caller specifying PEC, 10-bit addresses */
+ uint16_t flags;
+ /* SMBus protocol to use to perform transaction */
+ uint8_t smb_proto;
+ /* true if command field below is valid. Otherwise, false */
+ uint32_t cmd_valid;
+};
+
+static const uintptr_t smbus_base_reg_addr[MAX_I2C] = {
+ SMBUS0_REGS_BASE,
+ SMBUS1_REGS_BASE
+};
+
+/* Function to read a value from specified register. */
+static uint32_t iproc_i2c_reg_read(uint32_t bus_id, unsigned long reg_addr)
+{
+ uint32_t val;
+ uintptr_t smbus;
+
+ smbus = smbus_base_reg_addr[bus_id];
+
+ val = mmio_read_32(smbus + reg_addr);
+ VERBOSE("i2c %u: reg %p read 0x%x\n", bus_id,
+ (void *)(smbus + reg_addr), val);
+ return val;
+}
+
+/* Function to write a value ('val') in to a specified register. */
+static void iproc_i2c_reg_write(uint32_t bus_id,
+ unsigned long reg_addr,
+ uint32_t val)
+{
+ uintptr_t smbus;
+
+ smbus = smbus_base_reg_addr[bus_id];
+
+ mmio_write_32((smbus + reg_addr), val);
+ VERBOSE("i2c %u: reg %p wrote 0x%x\n", bus_id,
+ (void *)(smbus + reg_addr), val);
+}
+
+/* Function to clear and set bits in a specified register. */
+static void iproc_i2c_reg_clearset(uint32_t bus_id,
+ unsigned long reg_addr,
+ uint32_t clear,
+ uint32_t set)
+{
+ uintptr_t smbus;
+
+ smbus = smbus_base_reg_addr[bus_id];
+
+ mmio_clrsetbits_32((smbus + reg_addr), clear, set);
+ VERBOSE("i2c %u: reg %p clear 0x%x, set 0x%x\n", bus_id,
+ (void *)(smbus + reg_addr), clear, set);
+}
+
+/* Function to dump all SMBUS register */
+#ifdef BCM_I2C_DEBUG
+static int iproc_dump_i2c_regs(uint32_t bus_id)
+{
+ uint32_t regval;
+
+ if (bus_id > MAX_I2C) {
+ return -1;
+ }
+
+ INFO("----------------------------------------------\n");
+ INFO("%s: Dumping SMBus %u registers...\n", __func__, bus_id);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
+ INFO("SMB_CFG_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG);
+ INFO("SMB_TIMGCFG_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_ADDR_REG);
+ INFO("SMB_ADDR_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_MSTRFIFOCTL_REG);
+ INFO("SMB_MSTRFIFOCTL_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_SLVFIFOCTL_REG);
+ INFO("SMB_SLVFIFOCTL_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_BITBANGCTL_REG);
+ INFO("SMB_BITBANGCTL_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
+ INFO("SMB_MSTRCMD_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_SLVCMD_REG);
+ INFO("SMB_SLVCMD_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_EVTEN_REG);
+ INFO("SMB_EVTEN_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG);
+ INFO("SMB_EVTSTS_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATAWR_REG);
+ INFO("SMB_MSTRDATAWR_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATARD_REG);
+ INFO("SMB_MSTRDATARD_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATAWR_REG);
+ INFO("SMB_SLVDATAWR_REG=0x%x\n", regval);
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATARD_REG);
+ INFO("SMB_SLVDATARD_REG=0x%x\n", regval);
+
+ INFO("----------------------------------------------\n");
+ return 0;
+}
+#endif
+
+/*
+ * Function to ensure that the previous transaction was completed before
+ * initiating a new transaction. It can also be used in polling mode to
+ * check status of completion of a command
+ */
+static int iproc_i2c_startbusy_wait(uint32_t bus_id)
+{
+ uint32_t regval;
+ uint32_t retry = 0U;
+
+ /*
+ * Check if an operation is in progress. During probe it won't be.
+ * Want to make sure that the transaction in progress is completed.
+ */
+ do {
+ udelay(1U);
+ regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
+ regval &= SMB_MSTRSTARTBUSYCMD_MASK;
+ if (retry++ > BUS_BUSY_COUNT) {
+ ERROR("%s: START_BUSY bit didn't clear, exiting\n",
+ __func__);
+ return -1;
+ }
+
+ } while (regval != 0U);
+
+ return 0;
+}
+
+/*
+ * This function copies data to SMBus's Tx FIFO. Valid for write transactions
+ * info: Data to copy in to Tx FIFO. For read commands, the size should be
+ * set to zero by the caller
+ */
+static void iproc_i2c_write_trans_data(struct iproc_xact_info *info)
+{
+ uint32_t regval;
+ uint8_t devaddr;
+ uint32_t i;
+ uint32_t num_data_bytes = 0U;
+
+#ifdef BCM_I2C_DEBUG
+ INFO("%s:dev_addr=0x%x,cmd_valid=%d, cmd=0x%x, size=%u proto=%d\n",
+ __func__, info->devaddr, info->cmd_valid, info->command,
+ info->size, info->smb_proto);
+#endif
+ /* Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n */
+ devaddr = (info->devaddr << 1);
+
+ /*
+ * Depending on the SMBus protocol, we need to write additional
+ * transaction data in to Tx FIFO. Refer to section 5.5 of SMBus spec
+ * for sequence for a transaction
+ */
+ switch (info->smb_proto) {
+ case SMBUS_PROT_RECV_BYTE:
+ /* No additional data to be written */
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ devaddr | 0x1U | SMB_MSTRWRSTS_MASK);
+ break;
+ case SMBUS_PROT_SEND_BYTE:
+ num_data_bytes = info->size;
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ devaddr);
+ break;
+ case SMBUS_PROT_RD_BYTE:
+ case SMBUS_PROT_RD_WORD:
+ case SMBUS_PROT_BLK_RD:
+ /* Write slave address with R/W~ set (bit #0) */
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ devaddr | 0x1U);
+ break;
+ case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL:
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ devaddr | 0x1U | SMB_MSTRWRSTS_MASK);
+ break;
+ case SMBUS_PROT_WR_BYTE:
+ case SMBUS_PROT_WR_WORD:
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ devaddr);
+ /*
+ * No additional bytes to be written. Data portion is written
+ * in the 'for' loop below
+ */
+ num_data_bytes = info->size;
+ break;
+ case SMBUS_PROT_BLK_WR:
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ devaddr);
+ /* 3rd byte is byte count */
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ info->size);
+ num_data_bytes = info->size;
+ break;
+ default:
+ return;
+ }
+
+ /* If the protocol needs command code, copy it */
+ if (info->cmd_valid) {
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ info->command);
+ }
+
+ /*
+ * Copy actual data from caller. In general, for reads,
+ * no data is copied.
+ */
+ for (i = 0U; num_data_bytes; --num_data_bytes, i++) {
+ /* For the last byte, set MASTER_WR_STATUS bit */
+ regval = (num_data_bytes == 1U) ?
+ info->data[i] | SMB_MSTRWRSTS_MASK : info->data[i];
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
+ regval);
+ }
+}
+
+/*
+ * This function writes to the master command register and
+ * then polls for completion
+ */
+static int iproc_i2c_write_master_command(uint32_t mastercmd,
+ struct iproc_xact_info *info)
+{
+ uint32_t retry = 0U;
+ uint32_t regval;
+
+ iproc_i2c_reg_write(info->bus_id, SMB_MSTRCMD_REG, mastercmd);
+
+ /* Check for Master Busy status */
+ regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG);
+ while ((regval & SMB_MSTRSTARTBUSYCMD_MASK) != 0U) {
+ udelay(1U);
+ if (retry++ > BUS_BUSY_COUNT) {
+ ERROR("%s: START_BUSY bit didn't clear, exiting\n",
+ __func__);
+ return -1;
+ }
+ regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG);
+ }
+
+ /* If start_busy bit cleared, check if there are any errors */
+ if (!(regval & SMB_MSTRSTARTBUSYCMD_MASK)) {
+ /* start_busy bit cleared, check master_status field now */
+ regval &= SMB_MSTRSTS_MASK;
+ regval >>= SMB_MSTRSTS_SHIFT;
+ if (regval != MSTR_STS_XACT_SUCCESS) {
+ /* Error We can flush Tx FIFO here */
+ ERROR("%s: ERROR: %u exiting\n", __func__, regval);
+ return -1;
+ }
+ }
+ return 0;
+
+}
+/* Function to initiate data send and verify completion status */
+static int iproc_i2c_data_send(struct iproc_xact_info *info)
+{
+ int rc;
+ uint32_t mastercmd;
+
+ /* Make sure the previous transaction completed */
+ rc = iproc_i2c_startbusy_wait(info->bus_id);
+
+ if (rc < 0) {
+ WARN("%s: Send: bus is busy, exiting\n", __func__);
+ return rc;
+ }
+ /* Write transaction bytes to Tx FIFO */
+ iproc_i2c_write_trans_data(info);
+
+ /*
+ * Program master command register (0x30) with protocol type and set
+ * start_busy_command bit to initiate the write transaction
+ */
+ mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) |
+ SMB_MSTRSTARTBUSYCMD_MASK;
+
+ if (iproc_i2c_write_master_command(mastercmd, info)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Function to initiate data receive, verify completion status,
+ * and read from SMBUS Read FIFO
+ */
+static int iproc_i2c_data_recv(struct iproc_xact_info *info,
+ uint32_t *num_bytes_read)
+{
+ int rc;
+ uint32_t mastercmd;
+ uint32_t regval;
+
+ /* Make sure the previous transaction completed */
+ rc = iproc_i2c_startbusy_wait(info->bus_id);
+
+ if (rc < 0) {
+ WARN("%s: Receive: Bus is busy, exiting\n", __func__);
+ return rc;
+ }
+
+ /* Program all transaction bytes into master Tx FIFO */
+ iproc_i2c_write_trans_data(info);
+
+ /*
+ * Program master command register (0x30) with protocol type and set
+ * start_busy_command bit to initiate the write transaction
+ */
+ mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) |
+ SMB_MSTRSTARTBUSYCMD_MASK | info->size;
+
+ if (iproc_i2c_write_master_command(mastercmd, info)) {
+ return -1;
+ }
+
+ /* Read received byte(s), after TX out address etc */
+ regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRDATARD_REG);
+
+ /* For block read, protocol (hw) returns byte count,as the first byte */
+ if (info->smb_proto == SMBUS_PROT_BLK_RD) {
+ uint32_t i;
+
+ *num_bytes_read = regval & SMB_MSTRRDDATA_MASK;
+ /*
+ * Limit to reading a max of 32 bytes only; just a safeguard.
+ * If # bytes read is a number > 32, check transaction set up,
+ * and contact hw engg.
+ * Assumption: PEC is disabled
+ */
+ for (i = 0U; (i < *num_bytes_read) &&
+ (i < I2C_SMBUS_BLOCK_MAX); i++) {
+ /* Read Rx FIFO for data bytes */
+ regval = iproc_i2c_reg_read(info->bus_id,
+ SMB_MSTRDATARD_REG);
+ info->data[i] = regval & SMB_MSTRRDDATA_MASK;
+ }
+ } else {
+ /* 1 Byte data */
+ *info->data = regval & SMB_MSTRRDDATA_MASK;
+ *num_bytes_read = 1U;
+ }
+
+ return 0;
+}
+
+/*
+ * This function set clock frequency for SMBus block. As per hardware
+ * engineering, the clock frequency can be changed dynamically.
+ */
+static int iproc_i2c_set_clk_freq(uint32_t bus_id, smb_clk_freq_t freq)
+{
+ uint32_t val;
+
+ switch (freq) {
+ case IPROC_SMB_SPEED_100KHz:
+ val = 0U;
+ break;
+ case IPROC_SMB_SPEED_400KHz:
+ val = 1U;
+ break;
+ default:
+ return -1;
+ }
+
+ iproc_i2c_reg_clearset(bus_id, SMB_TIMGCFG_REG,
+ SMB_TIMGCFG_MODE400_MASK,
+ val << SMB_TIMGCFG_MODE400_SHIFT);
+
+ return 0;
+}
+
+/* Helper function to fill the iproc_xact_info structure */
+static void iproc_i2c_fill_info(struct iproc_xact_info *info, uint32_t bus_id,
+ uint8_t devaddr, uint8_t cmd, uint8_t *value,
+ uint8_t smb_proto, uint32_t cmd_valid)
+{
+ info->bus_id = bus_id;
+ info->devaddr = devaddr;
+ info->command = (uint8_t)cmd;
+ info->smb_proto = smb_proto;
+ info->data = value;
+ info->size = 1U;
+ info->flags = 0U;
+ info->cmd_valid = cmd_valid;
+}
+
+/* This function initializes the SMBUS */
+static void iproc_i2c_init(uint32_t bus_id, int speed)
+{
+ uint32_t regval;
+
+#ifdef BCM_I2C_DEBUG
+ INFO("%s: Enter Init\n", __func__);
+#endif
+
+ /* Put controller in reset */
+ regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
+ regval |= BIT(SMB_CFG_RST_SHIFT);
+ regval &= ~(BIT(SMB_CFG_SMBEN_SHIFT));
+ iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
+
+ /* Wait 100 usec per spec */
+ udelay(100U);
+
+ /* Bring controller out of reset */
+ regval &= ~(BIT(SMB_CFG_RST_SHIFT));
+ iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
+
+ /*
+ * Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0.
+ * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts
+ */
+ regval = SMB_MSTRRXFIFOFLSH_MASK | SMB_MSTRTXFIFOFLSH_MASK;
+ iproc_i2c_reg_write(bus_id, SMB_MSTRFIFOCTL_REG, regval);
+
+ /*
+ * Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero
+ * since there will be only one master
+ */
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
+ regval |= SMB_CFG_SMBEN_MASK;
+ iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
+ /* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */
+ mdelay(10U);
+
+ /* If error then set default speed */
+ if (i2c_set_bus_speed(bus_id, speed)) {
+ i2c_set_bus_speed(bus_id, I2C_SPEED_DEFAULT);
+ }
+
+ /* Disable intrs */
+ regval = 0x0U;
+ iproc_i2c_reg_write(bus_id, SMB_EVTEN_REG, regval);
+
+ /* Clear intrs (W1TC) */
+ regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG);
+ iproc_i2c_reg_write(bus_id, SMB_EVTSTS_REG, regval);
+
+#ifdef BCM_I2C_DEBUG
+ iproc_dump_i2c_regs(bus_id);
+
+ INFO("%s: Exit Init Successfully\n", __func__);
+#endif
+}
+
+/*
+ * Function Name: i2c_init
+ *
+ * Description:
+ * This function initializes the SMBUS.
+ *
+ * Parameters:
+ * bus_id - I2C bus ID
+ * speed - I2C bus speed in Hz
+ *
+ * Return:
+ * 0 on success, or -1 on failure.
+ */
+int i2c_init(uint32_t bus_id, int speed)
+{
+ if (bus_id > MAX_I2C) {
+ WARN("%s: Invalid Bus %u\n", __func__, bus_id);
+ return -1;
+ }
+
+ iproc_i2c_init(bus_id, speed);
+ return 0U;
+}
+
+/*
+ * Function Name: i2c_probe
+ *
+ * Description:
+ * This function probes the I2C bus for the existence of the specified
+ * device.
+ *
+ * Parameters:
+ * bus_id - I2C bus ID
+ * devaddr - Device Address
+ *
+ * Return:
+ * 0 on success, or -1 on failure.
+ */
+int i2c_probe(uint32_t bus_id, uint8_t devaddr)
+{
+ uint32_t regval;
+ int rc;
+
+ /*
+ * i2c_init() Initializes internal regs, disable intrs (and then clear intrs),
+ * set fifo thresholds, etc.
+ * Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n
+ */
+ regval = (devaddr << 1U);
+ iproc_i2c_reg_write(bus_id, SMB_MSTRDATAWR_REG, regval);
+
+ regval = ((SMBUS_PROT_QUICK_CMD << SMB_MSTRSMBUSPROTO_SHIFT) |
+ SMB_MSTRSTARTBUSYCMD_MASK);
+ iproc_i2c_reg_write(bus_id, SMB_MSTRCMD_REG, regval);
+
+ rc = iproc_i2c_startbusy_wait(bus_id);
+
+ if (rc < 0) {
+ WARN("%s: Probe: bus is busy, exiting\n", __func__);
+ return rc;
+ }
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
+ if (((regval & SMB_MSTRSTS_MASK) >> SMB_MSTRSTS_SHIFT) == 0)
+ VERBOSE("i2c device address: 0x%x\n", devaddr);
+ else
+ return -1;
+
+#ifdef BCM_I2C_DEBUG
+ iproc_dump_i2c_regs(bus_id);
+#endif
+ return 0;
+}
+
+/*
+ * Function Name: i2c_recv_byte
+ *
+ * Description:
+ * This function reads I2C data from a device without specifying
+ * a command regsiter.
+ *
+ * Parameters:
+ * bus_id - I2C bus ID
+ * devaddr - Device Address
+ * value - Data Read
+ *
+ * Return:
+ * 0 on success, or -1 on failure.
+ */
+int i2c_recv_byte(uint32_t bus_id, uint8_t devaddr, uint8_t *value)
+{
+ int rc;
+ struct iproc_xact_info info;
+ uint32_t num_bytes_read = 0;
+
+ iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, value,
+ SMBUS_PROT_RECV_BYTE, 0U);
+
+ /* Refer to i2c_smbus_read_byte for params passed. */
+ rc = iproc_i2c_data_recv(&info, &num_bytes_read);
+
+ if (rc < 0) {
+ printf("%s: %s error accessing device 0x%x\n",
+ __func__, "Read", devaddr);
+ }
+
+ return rc;
+}
+
+/*
+ * Function Name: i2c_send_byte
+ *
+ * Description:
+ * This function send I2C data to a device without specifying
+ * a command regsiter.
+ *
+ * Parameters:
+ * bus_id - I2C bus ID
+ * devaddr - Device Address
+ * value - Data Send
+ *
+ * Return:
+ * 0 on success, or -1 on failure.
+ */
+int i2c_send_byte(uint32_t bus_id, uint8_t devaddr, uint8_t value)
+{
+ int rc;
+ struct iproc_xact_info info;
+
+ iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, &value,
+ SMBUS_PROT_SEND_BYTE, 0U);
+
+ /* Refer to i2c_smbus_write_byte params passed. */
+ rc = iproc_i2c_data_send(&info);
+
+ if (rc < 0) {
+ ERROR("%s: %s error accessing device 0x%x\n",
+ __func__, "Write", devaddr);
+ }
+
+ return rc;
+}
+
+/* Helper function to read a single byte */
+static int i2c_read_byte(uint32_t bus_id,
+ uint8_t devaddr,
+ uint8_t regoffset,
+ uint8_t *value)
+{
+ int rc;
+ struct iproc_xact_info info;
+ uint32_t num_bytes_read = 0U;
+
+ iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, value,
+ SMBUS_PROT_RD_BYTE, 1U);
+
+ /* Refer to i2c_smbus_read_byte for params passed. */
+ rc = iproc_i2c_data_recv(&info, &num_bytes_read);
+
+ if (rc < 0) {
+ ERROR("%s: %s error accessing device 0x%x\n",
+ __func__, "Read", devaddr);
+ }
+ return rc;
+}
+
+/*
+ * Function Name: i2c_read
+ *
+ * Description:
+ * This function reads I2C data from a device with a designated
+ * command register
+ *
+ * Parameters:
+ * bus_id - I2C bus ID
+ * devaddr - Device Address
+ * addr - Register Offset
+ * alen - Address Length, 1 for byte, 2 for word (not supported)
+ * buffer - Data Buffer
+ * len - Data Length in bytes
+ *
+ * Return:
+ * 0 on success, or -1 on failure.
+ */
+int i2c_read(uint32_t bus_id,
+ uint8_t devaddr,
+ uint32_t addr,
+ int alen,
+ uint8_t *buffer,
+ int len)
+{
+ uint32_t i;
+
+ if (alen > 1) {
+ WARN("I2C read: addr len %d not supported\n", alen);
+ return -1;
+ }
+
+ if (addr + len > 256) {
+ WARN("I2C read: address out of range\n");
+ return -1;
+ }
+
+ for (i = 0U; i < len; i++) {
+ if (i2c_read_byte(bus_id, devaddr, addr + i, &buffer[i])) {
+ ERROR("I2C read: I/O error\n");
+ iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* Helper function to write a single byte */
+static int i2c_write_byte(uint32_t bus_id,
+ uint8_t devaddr,
+ uint8_t regoffset,
+ uint8_t value)
+{
+ int rc;
+ struct iproc_xact_info info;
+
+ iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, &value,
+ SMBUS_PROT_WR_BYTE, 1U);
+
+ /* Refer to i2c_smbus_write_byte params passed. */
+ rc = iproc_i2c_data_send(&info);
+
+ if (rc < 0) {
+ ERROR("%s: %s error accessing device 0x%x\n",
+ __func__, "Write", devaddr);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Function Name: i2c_write
+ *
+ * Description:
+ * This function write I2C data to a device with a designated
+ * command register
+ *
+ * Parameters:
+ * bus_id - I2C bus ID
+ * devaddr - Device Address
+ * addr - Register Offset
+ * alen - Address Length, 1 for byte, 2 for word (not supported)
+ * buffer - Data Buffer
+ * len - Data Length in bytes
+ *
+ * Return:
+ * 0 on success, or -1 on failure.
+ */
+int i2c_write(uint32_t bus_id,
+ uint8_t devaddr,
+ uint32_t addr,
+ int alen,
+ uint8_t *buffer,
+ int len)
+{
+ uint32_t i;
+
+ if (alen > 1) {
+ WARN("I2C write: addr len %d not supported\n", alen);
+ return -1;
+ }
+
+ if (addr + len > 256U) {
+ WARN("I2C write: address out of range\n");
+ return -1;
+ }
+
+ for (i = 0U; i < len; i++) {
+ if (i2c_write_byte(bus_id, devaddr, addr + i, buffer[i])) {
+ ERROR("I2C write: I/O error\n");
+ iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Function Name: i2c_set_bus_speed
+ *
+ * Description:
+ * This function configures the SMBUS speed
+ *
+ * Parameters:
+ * bus_id - I2C bus ID
+ * speed - I2C bus speed in Hz
+ *
+ * Return:
+ * 0 on success, or -1 on failure.
+ */
+int i2c_set_bus_speed(uint32_t bus_id, uint32_t speed)
+{
+ switch (speed) {
+ case I2C_SPEED_100KHz:
+ iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_100KHz);
+ break;
+
+ case I2C_SPEED_400KHz:
+ iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_400KHz);
+ break;
+
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Function Name: i2c_get_bus_speed
+ *
+ * Description:
+ * This function returns the SMBUS speed.
+ *
+ * Parameters:
+ * bus_id - I2C bus ID
+ *
+ * Return:
+ * Bus speed in Hz, 0 on failure
+ */
+uint32_t i2c_get_bus_speed(uint32_t bus_id)
+{
+ uint32_t regval;
+ uint32_t retval = 0U;
+
+ regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG);
+ regval &= SMB_TIMGCFG_MODE400_MASK;
+ regval >>= SMB_TIMGCFG_MODE400_SHIFT;
+
+ switch (regval) {
+ case IPROC_SMB_SPEED_100KHz:
+ retval = I2C_SPEED_100KHz;
+ break;
+
+ case IPROC_SMB_SPEED_400KHz:
+ retval = I2C_SPEED_400KHz;
+ break;
+
+ default:
+ break;
+ }
+ return retval;
+}
+
diff --git a/drivers/nxp/auth/csf_hdr_parser/cot.c b/drivers/nxp/auth/csf_hdr_parser/cot.c
new file mode 100644
index 0000000000..4502ed690d
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/cot.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <drivers/auth/auth_mod.h>
+
+#if USE_TBBR_DEFS
+#include <tools_share/tbbr_oid.h>
+#else
+#include <platform_oid.h>
+#endif
+
+
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t sig_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, 0);
+
+static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID);
+
+/*
+ * TBBR Chain of trust definition
+ */
+static const auth_img_desc_t bl31_image = {
+ .img_id = BL31_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t scp_bl2_image = {
+ .img_id = SCP_BL2_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t bl32_image = {
+ .img_id = BL32_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t bl33_image = {
+ .img_id = BL33_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+#ifdef POLICY_FUSE_PROVISION
+static const auth_img_desc_t fuse_prov_img = {
+ .img_id = FUSE_PROV_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t fuse_upgrade_img = {
+ .img_id = FUSE_UP_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+#endif
+#ifdef CONFIG_DDR_FIP_IMAGE
+static const auth_img_desc_t ddr_imem_udimm_1d_img = {
+ .img_id = DDR_IMEM_UDIMM_1D_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_imem_udimm_2d_img = {
+ .img_id = DDR_IMEM_UDIMM_2D_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_dmem_udimm_1d_img = {
+ .img_id = DDR_DMEM_UDIMM_1D_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_dmem_udimm_2d_img = {
+ .img_id = DDR_DMEM_UDIMM_2D_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_imem_rdimm_1d_img = {
+ .img_id = DDR_IMEM_RDIMM_1D_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_imem_rdimm_2d_img = {
+ .img_id = DDR_IMEM_RDIMM_2D_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_dmem_rdimm_1d_img = {
+ .img_id = DDR_DMEM_RDIMM_1D_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_dmem_rdimm_2d_img = {
+ .img_id = DDR_DMEM_RDIMM_2D_IMAGE_ID,
+ .img_type = IMG_PLAT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &sig_hash
+ }
+ }
+ }
+};
+#endif
+
+static const auth_img_desc_t * const cot_desc[] = {
+ [BL31_IMAGE_ID] = &bl31_image,
+ [SCP_BL2_IMAGE_ID] = &scp_bl2_image,
+ [BL32_IMAGE_ID] = &bl32_image,
+ [BL33_IMAGE_ID] = &bl33_image,
+#ifdef POLICY_FUSE_PROVISION
+ [FUSE_PROV_IMAGE_ID] = &fuse_prov_img,
+ [FUSE_UP_IMAGE_ID] = &fuse_upgrade_img,
+#endif
+#ifdef CONFIG_DDR_FIP_IMAGE
+ [DDR_IMEM_UDIMM_1D_IMAGE_ID] = &ddr_imem_udimm_1d_img,
+ [DDR_IMEM_UDIMM_2D_IMAGE_ID] = &ddr_imem_udimm_2d_img,
+ [DDR_DMEM_UDIMM_1D_IMAGE_ID] = &ddr_dmem_udimm_1d_img,
+ [DDR_DMEM_UDIMM_2D_IMAGE_ID] = &ddr_dmem_udimm_2d_img,
+ [DDR_IMEM_RDIMM_1D_IMAGE_ID] = &ddr_imem_rdimm_1d_img,
+ [DDR_IMEM_RDIMM_2D_IMAGE_ID] = &ddr_imem_rdimm_2d_img,
+ [DDR_DMEM_RDIMM_1D_IMAGE_ID] = &ddr_dmem_rdimm_1d_img,
+ [DDR_DMEM_RDIMM_2D_IMAGE_ID] = &ddr_dmem_rdimm_2d_img,
+#endif
+};
+
+/* Register the CoT in the authentication module */
+REGISTER_COT(cot_desc);
diff --git a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h b/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
new file mode 100644
index 0000000000..eaead7614e
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CSF_HDR_H
+#define CSF_HDR_H
+
+#include "caam.h"
+#include "hash.h"
+#include "rsa.h"
+
+/* Barker code size in bytes */
+#define CSF_BARKER_LEN 4 /* barker code length in ESBC uboot client */
+ /* header */
+
+#ifdef CSF_HDR_CH3
+struct csf_hdr {
+ uint8_t barker[CSF_BARKER_LEN]; /* 0x00 Barker code */
+ uint32_t srk_tbl_off; /* 0x04 SRK Table Offset */
+
+ struct {
+ uint8_t num_srk; /* 0x08 No. of keys */
+ uint8_t srk_sel; /* Key no. to be used */
+ uint8_t reserve; /* 0x0a rseerved */
+ } len_kr;
+ uint8_t ie_flag;
+
+ uint32_t uid_flag;
+
+ uint32_t psign; /* 0x10 signature offset */
+ uint32_t sign_len; /* 0x14 length of signature */
+
+ union {
+ struct {
+ uint32_t sg_table_offset; /* 0x18 SG Table Offset */
+ uint32_t sg_entries; /* 0x1c no of entries in SG */
+ } sg_isbc;
+ uint64_t img_addr; /* 64 bit pointer to ESBC Image */
+ };
+
+ union {
+ struct {
+ uint32_t img_size; /* ESBC client img size in bytes */
+ uint32_t ie_key_sel;
+ } img;
+ uint64_t entry_point; /* 0x20-0x24 ESBC entry point */
+ };
+
+ uint32_t fsl_uid_0; /* 0x28 Freescale unique id 0 */
+ uint32_t fsl_uid_1; /* 0x2c Freescale unique id 1 */
+ uint32_t oem_uid_0; /* 0x30 OEM unique id 0 */
+ uint32_t oem_uid_1; /* 0x34 OEM unique id 1 */
+ uint32_t oem_uid_2; /* 0x38 OEM unique id 2 */
+ uint32_t oem_uid_3; /* 0x3c OEM unique id 3 */
+ uint32_t oem_uid_4; /* 0x40 OEM unique id 4 */
+
+ uint32_t reserved[3]; /* 0x44 - 0x4f */
+};
+
+/* Srk table and key revocation check */
+#define UNREVOCABLE_KEY 8
+#define REVOC_KEY_ALIGN 7
+#define MAX_KEY_ENTRIES 8
+
+#else
+
+/* CSF header for Chassis 2 */
+struct csf_hdr {
+ uint8_t barker[CSF_BARKER_LEN]; /* barker code */
+ union {
+ uint32_t pkey; /* public key offset */
+ uint32_t srk_tbl_off;
+ };
+
+ union {
+ uint32_t key_len; /* pub key length in bytes */
+ struct {
+ uint32_t srk_table_flag:8;
+ uint32_t srk_sel:8;
+ uint32_t num_srk:16;
+ } len_kr;
+ };
+
+ uint32_t psign; /* signature offset */
+ uint32_t sign_len; /* length of the signature in bytes */
+
+ /* SG Table used by ISBC header */
+ union {
+ struct {
+ uint32_t sg_table_offset; /* 0x14 SG Table Offset */
+ uint32_t sg_entries; /* no of entries in SG table */
+ } sg_isbc;
+ struct {
+ uint32_t reserved1; /* Reserved field */
+ uint32_t img_size; /* ESBC img size in bytes */
+ } img;
+ };
+
+ uint32_t entry_point; /* ESBC client entry point */
+ uint32_t reserved2; /* Scatter gather flag */
+ uint32_t uid_flag;
+ uint32_t fsl_uid_0;
+ uint32_t oem_uid_0;
+ uint32_t reserved3[2];
+ uint32_t fsl_uid_1;
+ uint32_t oem_uid_1;
+
+ /* The entries below aren't present in ISBC header */
+ uint64_t img_addr; /* 64 bit pointer to ESBC Image */
+ uint32_t ie_flag;
+ uint32_t ie_key_sel;
+};
+
+/* Srk table and key revocation check */
+#define UNREVOCABLE_KEY 4
+#define REVOC_KEY_ALIGN 3
+#define MAX_KEY_ENTRIES 4
+
+#endif
+
+struct srk_table {
+ uint32_t key_len;
+ uint8_t pkey[2 * RSA_4K_KEY_SZ_BYTES];
+};
+
+/*
+ * This struct contains the following fields
+ * length of the segment
+ * Destination Target ID
+ * source address
+ * destination address
+ */
+struct sg_table {
+ uint32_t len; /* Length of Image */
+ uint32_t res1;
+ union {
+ uint64_t src_addr; /* SRC Address of Image */
+ struct {
+ uint32_t src_addr;
+ uint32_t dst_addr;
+ } img;
+ };
+};
+
+int validate_esbc_header(void *img_hdr, void **img_key, uint32_t *key_len,
+ void **img_sign, uint32_t *sign_len,
+ enum sig_alg *algo);
+
+int calc_img_hash(struct csf_hdr *hdr, void *img_addr, uint32_t img_size,
+ uint8_t *img_hash, uint32_t *hash_len);
+
+#endif
diff --git a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk b/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk
new file mode 100644
index 0000000000..d518dbba9d
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk
@@ -0,0 +1,64 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+CSF_HDR_SOURCES := $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/csf_hdr_parser.c
+
+CSF_HDR_SOURCES += $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/plat_img_parser.c
+
+PLAT_INCLUDES += -I$(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/
+
+$(eval $(call add_define, CSF_HEADER_PREPENDED))
+
+
+# Path to CST directory is required to generate the CSF header
+# and prepend it to image before fip image gets generated
+ifeq (${CST_DIR},)
+ $(error Error: CST_DIR not set)
+endif
+
+# Rules are created for generating and appending CSF header to images before
+# FIT image generation
+
+# CST_BL31
+define CST_BL31_RULE
+$(1): $(2)
+ @echo " Generating CSF Header for $$@ $$<"
+ $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \
+ --app $(2) ${BL31_INPUT_FILE}
+endef
+
+CST_BL31_SUFFIX := .cst
+
+# CST_BL32
+define CST_BL32_RULE
+$(1): $(2)
+ @echo " Generating CSF Header for $$@ $$<"
+ $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \
+ --app $(2) ${BL32_INPUT_FILE}
+endef
+
+CST_BL32_SUFFIX := .cst
+
+# CST_BL33
+define CST_BL33_RULE
+$(1): $(2)
+ @echo " Generating CSF Header for $$@ $$<"
+ $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \
+ --app $(2) ${BL33_INPUT_FILE}
+endef
+
+CST_BL33_SUFFIX := .cst
+
+# CST_SCP_BL2
+define CST_SCP_BL2_RULE
+$(1): $(2)
+ @echo " Generating CSF Header for $$@ $$<"
+ $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \
+ --app $(2) ${FUSE_INPUT_FILE}
+endef
+
+CST_SCP_BL2_SUFFIX := .cst
diff --git a/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c b/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c
new file mode 100644
index 0000000000..b878082aee
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2014-2016, Freescale Semiconductor, Inc.
+ * Copyright 2017-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <cassert.h>
+#include <common/debug.h>
+#include <csf_hdr.h>
+#include <dcfg.h>
+#include <drivers/auth/crypto_mod.h>
+#include <lib/utils.h>
+#include <sfp.h>
+
+/* Maximum OID string length ("a.b.c.d.e.f ...") */
+#define MAX_OID_STR_LEN 64
+
+#define LIB_NAME "NXP CSFv2"
+
+#ifdef CSF_HDR_CH3
+/* Barker Code for LS Ch3 ESBC Header */
+static const uint8_t barker_code[CSF_BARKER_LEN] = { 0x12, 0x19, 0x20, 0x01 };
+#else
+static const uint8_t barker_code[CSF_BARKER_LEN] = { 0x68, 0x39, 0x27, 0x81 };
+#endif
+
+#define CHECK_KEY_LEN(key_len) (((key_len) == 2 * RSA_1K_KEY_SZ_BYTES) || \
+ ((key_len) == 2 * RSA_2K_KEY_SZ_BYTES) || \
+ ((key_len) == 2 * RSA_4K_KEY_SZ_BYTES))
+
+/* Flag to indicate if values are there in rotpk_hash_table */
+bool rotpk_not_dpld = true;
+uint8_t rotpk_hash_table[MAX_KEY_ENTRIES][SHA256_BYTES];
+uint32_t num_rotpk_hash_entries;
+
+/*
+ * This function deploys the hashes of the various platform keys in
+ * rotpk_hash_table. This is done in case of secure boot after comparison
+ * of table's hash with the hash in SFP fuses. This installation is done
+ * only in the first header parsing.
+ */
+static int deploy_rotpk_hash_table(void *srk_buffer, uint16_t num_srk)
+{
+ void *ctx;
+ int ret = 0;
+ int i, j = 0;
+ unsigned int digest_size = SHA256_BYTES;
+ enum hash_algo algo = SHA256;
+ uint8_t hash[SHA256_BYTES];
+ uint32_t srk_hash[SHA256_BYTES/4] __aligned(CACHE_WRITEBACK_GRANULE);
+ struct srk_table *srktbl = (void *)srk_buffer;
+ struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(get_sfp_addr()
+ + SFP_FUSE_REGS_OFFSET);
+
+
+ if (num_srk > MAX_KEY_ENTRIES) {
+ return -1;
+ }
+
+ ret = hash_init(algo, &ctx);
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Update hash with that of SRK table */
+ ret = hash_update(algo, ctx, (uint8_t *)((uint8_t *)srk_buffer),
+ num_srk * sizeof(struct srk_table));
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Copy hash at destination buffer */
+ ret = hash_final(algo, ctx, hash, digest_size);
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Add comparison of hash with SFP hash here */
+ for (i = 0; i < SHA256_BYTES/4; i++) {
+ srk_hash[i] =
+ mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]);
+ }
+
+ VERBOSE("SRK table HASH\n");
+ for (i = 0; i < 8; i++) {
+ VERBOSE("%x\n", *((uint32_t *)hash + i));
+ }
+
+ if (memcmp(hash, srk_hash, SHA256_BYTES) != 0) {
+ ERROR("Error in installing ROTPK table\n");
+ ERROR("SRK hash doesn't match the fuse hash\n");
+ return -1;
+ }
+
+ /* Hash table already deployed */
+ if (rotpk_not_dpld == false) {
+ return 0;
+ }
+
+ for (i = 0; i < num_srk; i++) {
+ ret = hash_init(algo, &ctx);
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Update hash with that of SRK table */
+ ret = hash_update(algo, ctx, srktbl[i].pkey, srktbl[i].key_len);
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Copy hash at destination buffer */
+ ret = hash_final(algo, ctx, rotpk_hash_table[i], digest_size);
+ if (ret != 0) {
+ return -1;
+ }
+ VERBOSE("Table key %d HASH\n", i);
+ for (j = 0; j < 8; j++) {
+ VERBOSE("%x\n", *((uint32_t *)rotpk_hash_table[i] + j));
+ }
+ }
+ rotpk_not_dpld = false;
+ num_rotpk_hash_entries = num_srk;
+
+ return 0;
+}
+
+/*
+ * Calculate hash of ESBC hdr and ESBC. This function calculates the
+ * single hash of ESBC header and ESBC image
+ */
+int calc_img_hash(struct csf_hdr *hdr,
+ void *img_addr, uint32_t img_size,
+ uint8_t *img_hash, uint32_t *hash_len)
+{
+ void *ctx;
+ int ret = 0;
+ unsigned int digest_size = SHA256_BYTES;
+ enum hash_algo algo = SHA256;
+
+ ret = hash_init(algo, &ctx);
+ /* Copy hash at destination buffer */
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Update hash for CSF Header */
+ ret = hash_update(algo, ctx, (uint8_t *)hdr, sizeof(struct csf_hdr));
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Update hash with that of SRK table */
+ ret = hash_update(algo, ctx,
+ (uint8_t *)((uint8_t *)hdr + hdr->srk_tbl_off),
+ hdr->len_kr.num_srk * sizeof(struct srk_table));
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Update hash for actual Image */
+ ret = hash_update(algo, ctx, (uint8_t *)(img_addr), img_size);
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* Copy hash at destination buffer */
+ ret = hash_final(algo, ctx, img_hash, digest_size);
+ if (ret != 0) {
+ return -1;
+ }
+
+ *hash_len = digest_size;
+
+ VERBOSE("IMG encoded HASH\n");
+ for (int i = 0; i < 8; i++) {
+ VERBOSE("%x\n", *((uint32_t *)img_hash + i));
+ }
+
+ return 0;
+}
+
+/* This function checks if selected key is revoked or not.*/
+static uint32_t is_key_revoked(uint32_t keynum, uint32_t rev_flag)
+{
+ if (keynum == UNREVOCABLE_KEY) {
+ return 0;
+ }
+
+ if (((uint32_t)(1 << (REVOC_KEY_ALIGN - keynum)) & rev_flag) != 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Parse the header to extract the type of key,
+ * Check if key is not revoked
+ * and return the key , key length and key_type
+ */
+static int32_t get_key(struct csf_hdr *hdr, uint8_t **key, uint32_t *len,
+ enum sig_alg *key_type)
+{
+ int i = 0;
+ uint32_t ret = 0U;
+ uint32_t key_num, key_revoc_flag;
+ void *esbc = hdr;
+ struct srk_table *srktbl = (void *)((uint8_t *)esbc + hdr->srk_tbl_off);
+ bool sb;
+ uint32_t mode;
+
+ /* We currently support only RSA keys and signature */
+ *key_type = RSA;
+
+ /* Check for number of SRK entries */
+ if ((hdr->len_kr.num_srk == 0) ||
+ (hdr->len_kr.num_srk > MAX_KEY_ENTRIES)) {
+ ERROR("Error in NUM entries in SRK Table\n");
+ return -1;
+ }
+
+ /*
+ * Check the key number field. It should be not greater than
+ * number of entries in SRK table.
+ */
+ key_num = hdr->len_kr.srk_sel;
+ if ((key_num == 0) || (key_num > hdr->len_kr.num_srk)) {
+ ERROR("Invalid Key number\n");
+ return -1;
+ }
+
+ /* Get revoc key from sfp */
+ key_revoc_flag = get_key_revoc();
+
+ /* Check if selected key has been revoked */
+ ret = is_key_revoked(key_num, key_revoc_flag);
+ if (ret != 0) {
+ ERROR("Selected key has been revoked\n");
+ return -1;
+ }
+
+ /* Check for valid key length - allowed key sized 1k, 2k and 4K */
+ for (i = 0; i < hdr->len_kr.num_srk; i++) {
+ if (CHECK_KEY_LEN(srktbl[i].key_len) == 0) {
+ ERROR("Invalid key length\n");
+ return -1;
+ }
+ }
+
+ /* We don't return error from here. While parsing we just try to
+ * install the srk table. Failure needs to be taken care of in
+ * case of secure boot. This failure will be handled at the time
+ * of rotpk comparison in plat_get_rotpk_info function
+ */
+ sb = check_boot_mode_secure(&mode);
+ if (sb) {
+ ret = deploy_rotpk_hash_table(srktbl, hdr->len_kr.num_srk);
+ if (ret != 0) {
+ ERROR("ROTPK FAILURE\n");
+ /* For ITS =1 , return failure */
+ if (mode != 0) {
+ return -1;
+ }
+ ERROR("SECURE BOOT DEV-ENV MODE:\n");
+ ERROR("\tCHECK ROTPK !\n");
+ ERROR("\tCONTINUING ON FAILURE...\n");
+ }
+ }
+
+ /* Return the length of the selected key */
+ *len = srktbl[key_num - 1].key_len;
+
+ /* Point key to the selected key */
+ *key = (uint8_t *)&(srktbl[key_num - 1].pkey);
+
+ return 0;
+}
+
+/*
+ * This function would parse the CSF header and do the following:
+ * 1. Basic integrity checks
+ * 2. Key checks and extract the key from SRK/IE Table
+ * 3. Key hash comparison with SRKH in fuses in case of SRK Table
+ * 4. OEM/UID checks - To be added
+ * 5. Hash calculation for various components used in signature
+ * 6. Signature integrity checks
+ * return -> 0 on success, -1 on failure
+ */
+int validate_esbc_header(void *img_hdr, void **img_key, uint32_t *key_len,
+ void **img_sign, uint32_t *sign_len,
+ enum sig_alg *algo)
+{
+ struct csf_hdr *hdr = img_hdr;
+ uint8_t *s;
+ int32_t ret = 0;
+ void *esbc = (uint8_t *)img_hdr;
+ uint8_t *key;
+ uint32_t klen;
+
+ /* check barker code */
+ if (memcmp(hdr->barker, barker_code, CSF_BARKER_LEN) != 0) {
+ ERROR("Wrong barker code in header\n");
+ return -1;
+ }
+
+ ret = get_key(hdr, &key, &klen, algo);
+ if (ret != 0) {
+ return -1;
+ }
+
+ /* check signaure */
+ if (klen == (2 * hdr->sign_len)) {
+ /* check signature length */
+ if (((hdr->sign_len == RSA_1K_KEY_SZ_BYTES) ||
+ (hdr->sign_len == RSA_2K_KEY_SZ_BYTES) ||
+ (hdr->sign_len == RSA_4K_KEY_SZ_BYTES)) == 0) {
+ ERROR("Wrong Signature length in header\n");
+ return -1;
+ }
+ } else {
+ ERROR("RSA key length not twice the signature length\n");
+ return -1;
+ }
+
+ /* modulus most significant bit should be set */
+
+ if ((key[0] & 0x80) == 0U) {
+ ERROR("RSA Public key MSB not set\n");
+ return -1;
+ }
+
+ /* modulus value should be odd */
+ if ((key[klen / 2 - 1] & 0x1) == 0U) {
+ ERROR("Public key Modulus in header not odd\n");
+ return -1;
+ }
+
+ /* Check signature value < modulus value */
+ s = (uint8_t *)(esbc + hdr->psign);
+
+ if (!(memcmp(s, key, hdr->sign_len) < 0)) {
+ ERROR("Signature not less than modulus");
+ return -1;
+ }
+
+ /* Populate the return addresses */
+ *img_sign = (void *)(s);
+
+ /* Save the length of signature */
+ *sign_len = hdr->sign_len;
+
+ *img_key = (uint8_t *)key;
+
+ *key_len = klen;
+
+ return ret;
+}
diff --git a/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 b/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2
new file mode 100644
index 0000000000..bf8934bc91
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014-2016, Freescale Semiconductor, Inc.
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+---------------------------------------------------
+# Specify the platform. [Mandatory]
+# Choose Platform - 1010/1040/2041/3041/4080/5020/5040/9131/9132/9164/4240/C290/LS1
+PLATFORM=LS1043
+# ESBC Flag. Specify ESBC=0 to sign u-boot and ESBC=1 to sign ESBC images.(default is 0)
+ESBC=0
+---------------------------------------------------
+# Entry Point/Image start address field in the header.[Mandatory]
+# (default=ADDRESS of first file specified in images)
+ENTRY_POINT=10000000
+---------------------------------------------------
+# Specify the file name of the keys separated by comma.
+# The number of files and key select should lie between 1 and 4 for 1040 and C290.
+# For rest of the platforms only one key is required and key select should not be provided.
+
+# USAGE (for 4080/5020/5040/3041/2041/1010/913x): PRI_KEY = <key1.pri>
+# USAGE (for 1040/C290/9164/4240/LS1): PRI_KEY = <key1.pri>, <key2.pri>, <key3.pri>, <key4.pri>
+
+# PRI_KEY (Default private key :srk.pri) - [Optional]
+PRI_KEY=srk.pri
+# PUB_KEY (Default public key :srk.pub) - [Optional]
+PUB_KEY=srk.pub
+# Please provide KEY_SELECT(between 1 to 4) (Required for 1040/C290/9164/4240/LS1 only) - [Optional]
+KEY_SELECT=
+---------------------------------------------------
+# Specify SG table address, only for (2041/3041/4080/5020/5040) with ESBC=0 - [Optional]
+SG_TABLE_ADDR=
+---------------------------------------------------
+# Specify the target where image will be loaded. (Default is NOR_16B) - [Optional]
+# Only required for Non-PBL Devices (1010/1040/9131/9132i/C290)
+# Select from - NOR_8B/NOR_16B/NAND_8B_512/NAND_8B_2K/NAND_8B_4K/NAND_16B_512/NAND_16B_2K/NAND_16B_4K/SD/MMC/SPI
+IMAGE_TARGET=
+---------------------------------------------------
+# Specify IMAGE, Max 8 images are possible. DST_ADDR is required only for Non-PBL Platform. [Mandatory]
+# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR}
+IMAGE_1={bl2.bin,10000000,ffffffff}
+IMAGE_2={,,}
+IMAGE_3={,,}
+IMAGE_4={,,}
+IMAGE_5={,,}
+IMAGE_6={,,}
+IMAGE_7={,,}
+IMAGE_8={,,}
+---------------------------------------------------
+# Specify OEM AND FSL ID to be populated in header. [Optional]
+# e.g FSL_UID=11111111
+FSL_UID_0=
+FSL_UID_1=
+OEM_UID_0=
+OEM_UID_1=
+---------------------------------------------------
+# Specify the file names of csf header and sg table. (Default :hdr.out) [Optional]
+OUTPUT_HDR_FILENAME=hdr_bl2.out
+
+# Specify the file names of hash file and sign file.
+HASH_FILENAME=img_hash.out
+INPUT_SIGN_FILENAME=sign.out
+
+# Specify the signature size.It is mandatory when neither public key nor private key is specified.
+# Signature size would be [0x80 for 1k key, 0x100 for 2k key, and 0x200 for 4k key].
+SIGN_SIZE=
+---------------------------------------------------
+# Specify the output file name of sg table. (Default :sg_table.out). [Optional]
+# Please note that OUTPUT SG BIN is only required for 2041/3041/4080/5020/5040 when ESBC flag is not set.
+OUTPUT_SG_BIN=
+---------------------------------------------------
+# Following fields are Required for 4240/9164/1040/C290 only
+
+# Specify House keeping Area
+# Required for 4240/9164/1040/C290 only when ESBC flag is not set. [Mandatory]
+HK_AREA_POINTER=
+HK_AREA_SIZE=
+---------------------------------------------------
+# Following field Required for 4240/9164/1040/C290 only
+# Specify Secondary Image Flag. (0 or 1) - [Optional]
+# (Default is 0)
+SEC_IMAGE=0
+# Specify Manufacturing Protection Flag. (0 or 1) - [Optional]
+# Required only for LS1(Default is 0)
+MP_FLAG=1
+---------------------------------------------------
diff --git a/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 b/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3
new file mode 100644
index 0000000000..5fdad9c6eb
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+---------------------------------------------------
+# Specify the platform. [Mandatory]
+# Choose Platform -
+# TRUST 3.2: LX2160
+PLATFORM=LS2088
+---------------------------------------------------
+# Entry Point/Image start address field in the header.[Mandatory]
+# (default=ADDRESS of first file specified in images)
+# Address can be 64 bit
+ENTRY_POINT=1800A000
+---------------------------------------------------
+# Specify the Key Information.
+# PUB_KEY [Mandatory] Comma Separated List
+# Usage: <srk1.pub> <srk2.pub> .....
+PUB_KEY=srk.pub
+# KEY_SELECT [Mandatory]
+# USAGE (for TRUST 3.x): (between 1 to 8)
+KEY_SELECT=1
+# PRI_KEY [Mandatory] Single Key Used for Signing
+# USAGE: <srk.pri>
+PRI_KEY=srk.pri
+---------------------------------------------------
+# Specify IMAGE, Max 8 images are possible.
+# DST_ADDR is required only for Non-PBL Platform. [Mandatory]
+# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR}
+# Address can be 64 bit
+IMAGE_1={bl2.bin,1800A000,ffffffff}
+IMAGE_2={,,}
+IMAGE_3={,,}
+IMAGE_4={,,}
+IMAGE_5={,,}
+IMAGE_6={,,}
+IMAGE_7={,,}
+IMAGE_8={,,}
+---------------------------------------------------
+# Specify OEM AND FSL ID to be populated in header. [Optional]
+# e.g FSL_UID_0=11111111
+FSL_UID_0=
+FSL_UID_1=
+OEM_UID_0=
+OEM_UID_1=
+OEM_UID_2=
+OEM_UID_3=
+OEM_UID_4=
+---------------------------------------------------
+# Specify the output file names [Optional].
+# Default Values chosen in Tool
+OUTPUT_HDR_FILENAME=hdr_bl2.out
+IMAGE_HASH_FILENAME=
+RSA_SIGN_FILENAME=
+---------------------------------------------------
+# Specify The Flags. (0 or 1) - [Optional]
+MP_FLAG=0
+ISS_FLAG=1
+LW_FLAG=0
+---------------------------------------------------
+# Specify VERBOSE as 1, if you want to Display Header Information [Optional]
+VERBOSE=1
diff --git a/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 b/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2
new file mode 100644
index 0000000000..cc7c07c2ea
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+---------------------------------------------------
+# Specify the platform. [Mandatory]
+# Choose Platform -
+# TRUST 3.2: LX2160
+PLATFORM=LX2160
+---------------------------------------------------
+# Entry Point/Image start address field in the header.[Mandatory]
+# (default=ADDRESS of first file specified in images)
+# Address can be 64 bit
+ENTRY_POINT=1800D000
+---------------------------------------------------
+# Specify the Key Information.
+# PUB_KEY [Mandatory] Comma Separated List
+# Usage: <srk1.pub> <srk2.pub> .....
+PUB_KEY=srk.pub
+# KEY_SELECT [Mandatory]
+# USAGE (for TRUST 3.x): (between 1 to 8)
+KEY_SELECT=1
+# PRI_KEY [Mandatory] Single Key Used for Signing
+# USAGE: <srk.pri>
+PRI_KEY=srk.pri
+---------------------------------------------------
+# Specify IMAGE, Max 8 images are possible.
+# DST_ADDR is required only for Non-PBL Platform. [Mandatory]
+# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR}
+# Address can be 64 bit
+IMAGE_1={bl2.bin,1800D000,ffffffff}
+IMAGE_2={,,}
+IMAGE_3={,,}
+IMAGE_4={,,}
+IMAGE_5={,,}
+IMAGE_6={,,}
+IMAGE_7={,,}
+IMAGE_8={,,}
+---------------------------------------------------
+# Specify OEM AND FSL ID to be populated in header. [Optional]
+# e.g FSL_UID_0=11111111
+FSL_UID_0=
+FSL_UID_1=
+OEM_UID_0=
+OEM_UID_1=
+OEM_UID_2=
+OEM_UID_3=
+OEM_UID_4=
+---------------------------------------------------
+# Specify the output file names [Optional].
+# Default Values chosen in Tool
+OUTPUT_HDR_FILENAME=hdr_bl2.out
+IMAGE_HASH_FILENAME=
+RSA_SIGN_FILENAME=
+---------------------------------------------------
+# Specify The Flags. (0 or 1) - [Optional]
+MP_FLAG=0
+ISS_FLAG=1
+LW_FLAG=0
+---------------------------------------------------
+# Specify VERBOSE as 1, if you want to Display Header Information [Optional]
+VERBOSE=1
diff --git a/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 b/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2
new file mode 100644
index 0000000000..93b020be02
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+---------------------------------------------------
+# Specify the platform. [Mandatory]
+# Choose Platform - 1010/1040/2041/3041/4080/5020/5040/9131/9132/9164/4240/C290/LS1
+PLATFORM=LS1043
+# ESBC Flag. Specify ESBC=0 to sign u-boot and ESBC=1 to sign ESBC images.(default is 0)
+ESBC=1
+---------------------------------------------------
+# Specify the file name of the keys separated by comma.
+
+# PRI_KEY (Default private key :srk.pri) - [Optional]
+PRI_KEY=srk.pri
+# PUB_KEY (Default public key :srk.pub) - [Optional]
+PUB_KEY=srk.pub
+# Please provide KEY_SELECT(between 1 to 4) (Required for 1040/C290/9164/4240 only) - [Optional]
+KEY_SELECT=1
+---------------------------------------------------
+# Specify OEM AND FSL ID to be populated in header. [Optional]
+# e.g FSL_UID=11111111
+FSL_UID_0=
+FSL_UID_1=
+OEM_UID_0=
+OEM_UID_1=
+---------------------------------------------------
diff --git a/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 b/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3
new file mode 100644
index 0000000000..18e8e3b73d
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+ESBC=1
+---------------------------------------------------
+# Specify the platform. [Mandatory]
+# Choose Platform -
+# TRUST 3.0: LS2085
+# TRUST 3.1: LS2088, LS1088
+PLATFORM=LS2088
+---------------------------------------------------
+# Specify the Key Information.
+# PUB_KEY [Mandatory] Comma Separated List
+# Usage: <srk1.pub> <srk2.pub> .....
+PUB_KEY=srk.pub
+# KEY_SELECT [Mandatory]
+# USAGE (for TRUST 3.x): (between 1 to 8)
+KEY_SELECT=1
+# PRI_KEY [Mandatory] Single Key Used for Signing
+# USAGE: <srk.pri>
+PRI_KEY=srk.pri
+
+---------------------------------------------------
+# Specify OEM AND FSL ID to be populated in header. [Optional]
+# e.g FSL_UID_0=11111111
+FSL_UID_0=
+FSL_UID_1=
+OEM_UID_0=
+OEM_UID_1=
+OEM_UID_2=
+OEM_UID_3=
+OEM_UID_4=
+---------------------------------------------------
diff --git a/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 b/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3
new file mode 100644
index 0000000000..9111a2a290
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+---------------------------------------------------
+# Specify the platform. [Mandatory]
+# Choose Platform -
+# TRUST 3.0: LS2085
+# TRUST 3.1: LS2088, LS1088
+PLATFORM=LS2088
+---------------------------------------------------
+# Specify the Key Information.
+# PUB_KEY [Mandatory] Comma Separated List
+# Usage: <srk1.pub> <srk2.pub> .....
+PUB_KEY=srk.pub
+# KEY_SELECT [Mandatory]
+# USAGE (for TRUST 3.x): (between 1 to 8)
+KEY_SELECT=1
+# PRI_KEY [Mandatory] Single Key Used for Signing
+# USAGE: <srk.pri>
+PRI_KEY=srk.pri
+---------------------------------------------------
+# Specify OEM AND FSL ID to be populated in header. [Optional]
+# e.g FSL_UID_0=11111111
+FSL_UID_0=
+FSL_UID_1=
+OEM_UID_0=
+OEM_UID_1=
+OEM_UID_2=
+OEM_UID_3=
+OEM_UID_4=
+---------------------------------------------------
+# Specify The Flags. (0 or 1) - [Optional]
+MP_FLAG=0
+ISS_FLAG=1
+LW_FLAG=0
+---------------------------------------------------
+# Specify VERBOSE as 1, if you want to Display Header Information [Optional]
+VERBOSE=1
+---------------------------------------------------
diff --git a/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 b/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2
new file mode 100644
index 0000000000..c2d7ce43ef
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+---------------------------------------------------
+# Specify the platform. [Mandatory]
+# Choose Platform -
+# TRUST 3.0: LS2085
+# TRUST 3.1: LS2088, LS1088
+PLATFORM=LX2160
+---------------------------------------------------
+# Specify the Key Information.
+# PUB_KEY [Mandatory] Comma Separated List
+# Usage: <srk1.pub> <srk2.pub> .....
+PUB_KEY=srk.pub
+# KEY_SELECT [Mandatory]
+# USAGE (for TRUST 3.x): (between 1 to 8)
+KEY_SELECT=1
+# PRI_KEY [Mandatory] Single Key Used for Signing
+# USAGE: <srk.pri>
+PRI_KEY=srk.pri
+---------------------------------------------------
+# Specify OEM AND FSL ID to be populated in header. [Optional]
+# e.g FSL_UID_0=11111111
+FSL_UID_0=
+FSL_UID_1=
+OEM_UID_0=
+OEM_UID_1=
+OEM_UID_2=
+OEM_UID_3=
+OEM_UID_4=
+---------------------------------------------------
+# Specify The Flags. (0 or 1) - [Optional]
+MP_FLAG=0
+ISS_FLAG=1
+LW_FLAG=0
+---------------------------------------------------
+# Specify VERBOSE as 1, if you want to Display Header Information [Optional]
+VERBOSE=1
+---------------------------------------------------
diff --git a/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c b/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c
new file mode 100644
index 0000000000..43b78e549a
--- /dev/null
+++ b/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2014-2016, Freescale Semiconductor, Inc.
+ * Copyright 2017-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <csf_hdr.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/auth/img_parser_mod.h>
+#include <lib/utils.h>
+#include <sfp.h>
+
+/* Temporary variables to speed up the authentication parameters search. These
+ * variables are assigned once during the integrity check and used any time an
+ * authentication parameter is requested, so we do not have to parse the image
+ * again.
+ */
+
+/* Hash of Image + CSF Header + SRK table */
+uint8_t img_hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE);
+uint32_t hash_len;
+
+/* Key being used for authentication
+ * Points to the key in CSF header copied in DDR
+ * ESBC client key
+ */
+void *img_key;
+uint32_t key_len;
+
+/* ESBC client signature */
+void *img_sign;
+uint32_t sign_len;
+enum sig_alg alg;
+
+/* Maximum OID string length ("a.b.c.d.e.f ...") */
+#define MAX_OID_STR_LEN 64
+
+#define LIB_NAME "NXP CSFv2"
+
+/*
+ * Clear all static temporary variables.
+ */
+static void clear_temp_vars(void)
+{
+#define ZERO_AND_CLEAN(x) \
+ do { \
+ zeromem(&x, sizeof(x)); \
+ clean_dcache_range((uintptr_t)&x, sizeof(x)); \
+ } while (0)
+
+ ZERO_AND_CLEAN(img_key);
+ ZERO_AND_CLEAN(img_sign);
+ ZERO_AND_CLEAN(img_hash);
+ ZERO_AND_CLEAN(key_len);
+ ZERO_AND_CLEAN(hash_len);
+ ZERO_AND_CLEAN(sign_len);
+
+#undef ZERO_AND_CLEAN
+}
+
+/* Exported functions */
+
+static void init(void)
+{
+ clear_temp_vars();
+}
+
+/*
+ * This function would check the integrity of the CSF header
+ */
+static int check_integrity(void *img, unsigned int img_len)
+{
+ int ret;
+
+ /*
+ * The image file has been successfully loaded till here.
+ *
+ * Flush the image to main memory so that it can be authenticated
+ * by CAAM, a HW accelerator regardless of cache and MMU state.
+ */
+ flush_dcache_range((uintptr_t) img, img_len);
+
+ /*
+ * Image is appended at an offset of 16K (IMG_OFFSET) to the header.
+ * So the size in header should be equal to img_len - IMG_OFFSET
+ */
+ VERBOSE("Barker code is %x\n", *(unsigned int *)img);
+ ret = validate_esbc_header(img, &img_key, &key_len, &img_sign,
+ &sign_len, &alg);
+ if (ret < 0) {
+ ERROR("Header authentication failed\n");
+ clear_temp_vars();
+ return IMG_PARSER_ERR;
+ }
+ /* Calculate the hash of various components from the image */
+ ret = calc_img_hash(img, (uint8_t *)img + CSF_HDR_SZ,
+ img_len - CSF_HDR_SZ, img_hash, &hash_len);
+ if (ret != 0) {
+ ERROR("Issue in hash calculation %d\n", ret);
+ clear_temp_vars();
+ return IMG_PARSER_ERR;
+ }
+
+ return IMG_PARSER_OK;
+}
+
+/*
+ * Extract an authentication parameter from CSF header
+ *
+ * CSF header has already been parsed and the required information like
+ * hash of data, signature, length stored in global variables has been
+ * extracted in chek_integrity function. This data
+ * is returned back to the caller.
+ */
+static int get_auth_param(const auth_param_type_desc_t *type_desc,
+ void *img, unsigned int img_len,
+ void **param, unsigned int *param_len)
+{
+ int rc = IMG_PARSER_OK;
+
+ /* We do not use img because the check_integrity function has already
+ * extracted the relevant data ( pk, sig_alg, etc)
+ */
+
+ switch (type_desc->type) {
+
+ /* Hash will be returned for comparison with signature */
+ case AUTH_PARAM_HASH:
+ *param = (void *)img_hash;
+ *param_len = (unsigned int)SHA256_BYTES;
+ break;
+
+ /* Return the public key used for signature extracted from the SRK table
+ * after checks with key revocation
+ */
+ case AUTH_PARAM_PUB_KEY:
+ /* Get the subject public key */
+ /* For a 1K key - the length would be 2k/8 = 0x100 bytes
+ * 2K RSA key - 0x200 , 4K RSA - 0x400
+ */
+ *param = img_key;
+ *param_len = (unsigned int)key_len;
+ break;
+
+ /* Call a function to tell if signature is RSA or ECDSA. ECDSA to be
+ * supported in later platforms like LX2 etc
+ */
+ case AUTH_PARAM_SIG_ALG:
+ /* Algo will be signature - RSA or ECDSA on hash */
+ *param = (void *)&alg;
+ *param_len = 4U;
+ break;
+
+ /* Return the signature */
+ case AUTH_PARAM_SIG:
+ *param = img_sign;
+ *param_len = (unsigned int)sign_len;
+ break;
+
+ case AUTH_PARAM_NV_CTR:
+
+ default:
+ rc = IMG_PARSER_ERR_NOT_FOUND;
+ break;
+ }
+
+ return rc;
+}
+
+REGISTER_IMG_PARSER_LIB(IMG_PLAT, LIB_NAME, init,
+ check_integrity, get_auth_param);
diff --git a/drivers/nxp/auth/tbbr/tbbr_cot.c b/drivers/nxp/auth/tbbr/tbbr_cot.c
new file mode 100644
index 0000000000..bb21fa04cb
--- /dev/null
+++ b/drivers/nxp/auth/tbbr/tbbr_cot.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <drivers/auth/auth_mod.h>
+
+#if USE_TBBR_DEFS
+#include <tools_share/tbbr_oid.h>
+#else
+#include <platform_oid.h>
+#endif
+
+
+#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256
+#define HASH_DER_LEN 51
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384
+#define HASH_DER_LEN 67
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512
+#define HASH_DER_LEN 83
+#else
+#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID"
+#endif
+
+/*
+ * The platform must allocate buffers to store the authentication parameters
+ * extracted from the certificates. In this case, because of the way the CoT is
+ * established, we can reuse some of the buffers on different stages
+ */
+
+static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
+
+static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN];
+static unsigned char trusted_world_pk_buf[PK_DER_LEN];
+static unsigned char non_trusted_world_pk_buf[PK_DER_LEN];
+static unsigned char content_pk_buf[PK_DER_LEN];
+static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
+
+#ifdef CONFIG_DDR_FIP_IMAGE
+static unsigned char ddr_fw_content_pk_buf[PK_DER_LEN];
+static unsigned char ddr_imem_udimm_1d_hash_buf[HASH_DER_LEN];
+static unsigned char ddr_imem_udimm_2d_hash_buf[HASH_DER_LEN];
+static unsigned char ddr_dmem_udimm_1d_hash_buf[HASH_DER_LEN];
+static unsigned char ddr_dmem_udimm_2d_hash_buf[HASH_DER_LEN];
+
+static unsigned char ddr_imem_rdimm_1d_hash_buf[HASH_DER_LEN];
+static unsigned char ddr_imem_rdimm_2d_hash_buf[HASH_DER_LEN];
+static unsigned char ddr_dmem_rdimm_1d_hash_buf[HASH_DER_LEN];
+static unsigned char ddr_dmem_rdimm_2d_hash_buf[HASH_DER_LEN];
+#endif
+
+/*
+ * Parameter type descriptors
+ */
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+
+static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_RAW_DATA, 0);
+
+
+static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
+static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID);
+static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
+static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
+static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID);
+static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID);
+static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
+static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
+
+#ifdef CONFIG_DDR_FIP_IMAGE
+static auth_param_type_desc_t ddr_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, DDR_FW_CONTENT_CERT_PK_OID);
+
+static auth_param_type_desc_t ddr_imem_udimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, DDR_IMEM_UDIMM_1D_HASH_OID);
+static auth_param_type_desc_t ddr_imem_udimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, DDR_IMEM_UDIMM_2D_HASH_OID);
+static auth_param_type_desc_t ddr_dmem_udimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, DDR_DMEM_UDIMM_1D_HASH_OID);
+static auth_param_type_desc_t ddr_dmem_udimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, DDR_DMEM_UDIMM_2D_HASH_OID);
+
+static auth_param_type_desc_t ddr_imem_rdimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, DDR_IMEM_RDIMM_1D_HASH_OID);
+static auth_param_type_desc_t ddr_imem_rdimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, DDR_IMEM_RDIMM_2D_HASH_OID);
+static auth_param_type_desc_t ddr_dmem_rdimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, DDR_DMEM_RDIMM_1D_HASH_OID);
+static auth_param_type_desc_t ddr_dmem_rdimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, DDR_DMEM_RDIMM_2D_HASH_OID);
+#endif
+
+
+/*
+ * Trusted key certificate
+ */
+static const auth_img_desc_t trusted_key_cert = {
+ .img_id = TRUSTED_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &trusted_world_pk,
+ .data = {
+ .ptr = (void *)trusted_world_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &non_trusted_world_pk,
+ .data = {
+ .ptr = (void *)non_trusted_world_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+};
+
+/*
+ * SoC Firmware
+ */
+static const auth_img_desc_t soc_fw_key_cert = {
+ .img_id = SOC_FW_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &soc_fw_content_pk,
+ .data = {
+ .ptr = (void *)content_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+};
+static const auth_img_desc_t soc_fw_content_cert = {
+ .img_id = SOC_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &soc_fw_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &soc_fw_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &soc_fw_hash,
+ .data = {
+ .ptr = (void *)soc_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &soc_fw_config_hash,
+ .data = {
+ .ptr = (void *)soc_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+static const auth_img_desc_t bl31_image = {
+ .img_id = BL31_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &soc_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &soc_fw_hash
+ }
+ }
+ }
+};
+/* SOC FW Config */
+static const auth_img_desc_t soc_fw_config = {
+ .img_id = SOC_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &soc_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &soc_fw_config_hash
+ }
+ }
+ }
+};
+/*
+ * Trusted OS Firmware
+ */
+static const auth_img_desc_t trusted_os_fw_key_cert = {
+ .img_id = TRUSTED_OS_FW_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tos_fw_content_pk,
+ .data = {
+ .ptr = (void *)content_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+};
+static const auth_img_desc_t trusted_os_fw_content_cert = {
+ .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_os_fw_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &tos_fw_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tos_fw_hash,
+ .data = {
+ .ptr = (void *)tos_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &tos_fw_extra1_hash,
+ .data = {
+ .ptr = (void *)tos_fw_extra1_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &tos_fw_extra2_hash,
+ .data = {
+ .ptr = (void *)tos_fw_extra2_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [3] = {
+ .type_desc = &tos_fw_config_hash,
+ .data = {
+ .ptr = (void *)tos_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+static const auth_img_desc_t bl32_image = {
+ .img_id = BL32_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_os_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tos_fw_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t bl32_extra1_image = {
+ .img_id = BL32_EXTRA1_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_os_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tos_fw_extra1_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t bl32_extra2_image = {
+ .img_id = BL32_EXTRA2_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_os_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tos_fw_extra2_hash
+ }
+ }
+ }
+};
+/* TOS FW Config */
+static const auth_img_desc_t tos_fw_config = {
+ .img_id = TOS_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_os_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tos_fw_config_hash
+ }
+ }
+ }
+};
+/*
+ * Non-Trusted Firmware
+ */
+static const auth_img_desc_t non_trusted_fw_key_cert = {
+ .img_id = NON_TRUSTED_FW_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &non_trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &non_trusted_nv_ctr,
+ .plat_nv_ctr = &non_trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &nt_fw_content_pk,
+ .data = {
+ .ptr = (void *)content_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+};
+static const auth_img_desc_t non_trusted_fw_content_cert = {
+ .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &non_trusted_fw_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &nt_fw_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &non_trusted_nv_ctr,
+ .plat_nv_ctr = &non_trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &nt_world_bl_hash,
+ .data = {
+ .ptr = (void *)nt_world_bl_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &nt_fw_config_hash,
+ .data = {
+ .ptr = (void *)nt_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+static const auth_img_desc_t bl33_image = {
+ .img_id = BL33_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &non_trusted_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &nt_world_bl_hash
+ }
+ }
+ }
+};
+/* NT FW Config */
+static const auth_img_desc_t nt_fw_config = {
+ .img_id = NT_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &non_trusted_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &nt_fw_config_hash
+ }
+ }
+ }
+};
+#ifdef CONFIG_DDR_FIP_IMAGE
+/*
+ * DDR Firmware
+ */
+static const auth_img_desc_t ddr_fw_key_cert = {
+ .img_id = DDR_FW_KEY_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &trusted_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &trusted_world_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &ddr_fw_content_pk,
+ .data = {
+ .ptr = (void *)ddr_fw_content_pk_buf,
+ .len = (unsigned int)PK_DER_LEN
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_udimm_fw_content_cert = {
+ .img_id = DDR_UDIMM_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &ddr_fw_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &ddr_fw_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &ddr_imem_udimm_1d_fw_hash,
+ .data = {
+ .ptr = (void *)ddr_imem_udimm_1d_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &ddr_imem_udimm_2d_fw_hash,
+ .data = {
+ .ptr = (void *)ddr_imem_udimm_2d_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &ddr_dmem_udimm_1d_fw_hash,
+ .data = {
+ .ptr = (void *)ddr_dmem_udimm_1d_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [3] = {
+ .type_desc = &ddr_dmem_udimm_2d_fw_hash,
+ .data = {
+ .ptr = (void *)ddr_dmem_udimm_2d_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ }
+};
+
+static const auth_img_desc_t ddr_imem_udimm_1d_img = {
+ .img_id = DDR_IMEM_UDIMM_1D_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &ddr_udimm_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ddr_imem_udimm_1d_fw_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_imem_udimm_2d_img = {
+ .img_id = DDR_IMEM_UDIMM_2D_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &ddr_udimm_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ddr_imem_udimm_2d_fw_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_dmem_udimm_1d_img = {
+ .img_id = DDR_DMEM_UDIMM_1D_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &ddr_udimm_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ddr_dmem_udimm_1d_fw_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_dmem_udimm_2d_img = {
+ .img_id = DDR_DMEM_UDIMM_2D_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &ddr_udimm_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ddr_dmem_udimm_2d_fw_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t ddr_rdimm_fw_content_cert = {
+ .img_id = DDR_RDIMM_FW_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = &ddr_fw_key_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &ddr_fw_content_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &ddr_imem_rdimm_1d_fw_hash,
+ .data = {
+ .ptr = (void *)ddr_imem_rdimm_1d_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &ddr_imem_rdimm_2d_fw_hash,
+ .data = {
+ .ptr = (void *)ddr_imem_rdimm_2d_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &ddr_dmem_rdimm_1d_fw_hash,
+ .data = {
+ .ptr = (void *)ddr_dmem_rdimm_1d_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [3] = {
+ .type_desc = &ddr_dmem_rdimm_2d_fw_hash,
+ .data = {
+ .ptr = (void *)ddr_dmem_rdimm_2d_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ }
+};
+
+static const auth_img_desc_t ddr_imem_rdimm_1d_img = {
+ .img_id = DDR_IMEM_RDIMM_1D_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &ddr_rdimm_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ddr_imem_rdimm_1d_fw_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_imem_rdimm_2d_img = {
+ .img_id = DDR_IMEM_RDIMM_2D_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &ddr_rdimm_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ddr_imem_rdimm_2d_fw_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_dmem_rdimm_1d_img = {
+ .img_id = DDR_DMEM_RDIMM_1D_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &ddr_rdimm_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ddr_dmem_rdimm_1d_fw_hash
+ }
+ }
+ }
+};
+static const auth_img_desc_t ddr_dmem_rdimm_2d_img = {
+ .img_id = DDR_DMEM_RDIMM_2D_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &ddr_rdimm_fw_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ddr_dmem_rdimm_2d_fw_hash
+ }
+ }
+ }
+};
+#endif
+
+/*
+ * TBBR Chain of trust definition
+ */
+
+static const auth_img_desc_t * const cot_desc[] = {
+ [TRUSTED_KEY_CERT_ID] = &trusted_key_cert,
+ [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert,
+ [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert,
+ [BL31_IMAGE_ID] = &bl31_image,
+ [SOC_FW_CONFIG_ID] = &soc_fw_config,
+ [TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert,
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
+ [BL32_IMAGE_ID] = &bl32_image,
+ [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image,
+ [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image,
+ [TOS_FW_CONFIG_ID] = &tos_fw_config,
+ [NON_TRUSTED_FW_KEY_CERT_ID] = &non_trusted_fw_key_cert,
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
+ [BL33_IMAGE_ID] = &bl33_image,
+ [NT_FW_CONFIG_ID] = &nt_fw_config,
+#ifdef CONFIG_DDR_FIP_IMAGE
+ [DDR_FW_KEY_CERT_ID] = &ddr_fw_key_cert,
+ [DDR_UDIMM_FW_CONTENT_CERT_ID] = &ddr_udimm_fw_content_cert,
+ [DDR_RDIMM_FW_CONTENT_CERT_ID] = &ddr_rdimm_fw_content_cert,
+ [DDR_IMEM_UDIMM_1D_IMAGE_ID] = &ddr_imem_udimm_1d_img,
+ [DDR_IMEM_UDIMM_2D_IMAGE_ID] = &ddr_imem_udimm_2d_img,
+ [DDR_DMEM_UDIMM_1D_IMAGE_ID] = &ddr_dmem_udimm_1d_img,
+ [DDR_DMEM_UDIMM_2D_IMAGE_ID] = &ddr_dmem_udimm_2d_img,
+ [DDR_IMEM_RDIMM_1D_IMAGE_ID] = &ddr_imem_rdimm_1d_img,
+ [DDR_IMEM_RDIMM_2D_IMAGE_ID] = &ddr_imem_rdimm_2d_img,
+ [DDR_DMEM_RDIMM_1D_IMAGE_ID] = &ddr_dmem_rdimm_1d_img,
+ [DDR_DMEM_RDIMM_2D_IMAGE_ID] = &ddr_dmem_rdimm_2d_img,
+#endif
+};
+
+/* Register the CoT in the authentication module */
+REGISTER_COT(cot_desc);
diff --git a/drivers/nxp/console/16550_console.S b/drivers/nxp/console/16550_console.S
new file mode 100644
index 0000000000..044d3d0740
--- /dev/null
+++ b/drivers/nxp/console/16550_console.S
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <console_macros.S>
+
+/* UART16550 Registers */
+#define UARTTX 0x0
+#define UARTRX 0x0
+#define UARTDLL 0x0
+#define UARTIER 0x1
+#define UARTDLLM 0x1
+#define UARTFCR 0x2
+#define UARTLCR 0x3
+#define UARTLSR 0x5
+#define UARTMCR 0x4
+
+/* FIFO Control Register bits */
+#define UARTFCR_FIFOMD_16450 (0 << 6)
+#define UARTFCR_FIFOMD_16550 (1 << 6)
+#define UARTFCR_RXTRIG_1 (0 << 6)
+#define UARTFCR_RXTRIG_4 (1 << 6)
+#define UARTFCR_RXTRIG_8 (2 << 6)
+#define UARTFCR_RXTRIG_16 (3 << 6)
+#define UARTFCR_TXTRIG_1 (0 << 4)
+#define UARTFCR_TXTRIG_4 (1 << 4)
+#define UARTFCR_TXTRIG_8 (2 << 4)
+#define UARTFCR_TXTRIG_16 (3 << 4)
+#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */
+#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */
+#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */
+#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */
+#define UARTFCR_64FIFO (1 << 5)
+
+/* Line Control Register bits */
+#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */
+#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */
+#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */
+#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */
+#define UARTLCR_PAR (1 << 3) /* Parity */
+#define UARTLCR_STOP (1 << 2) /* Stop Bit */
+#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */
+#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */
+#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */
+#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */
+
+/* Line Status Register bits */
+#define UARTLSR_RXFIFOEMT (1 << 9) /* Rx Fifo Empty */
+#define UARTLSR_TXFIFOFULL (1 << 8) /* Tx Fifo Full */
+#define UARTLSR_RXFIFOERR (1 << 7) /* Rx Fifo Error */
+#define UARTLSR_TEMT (1 << 6) /* Tx Shift Register Empty */
+#define UARTLSR_THRE (1 << 5) /* Tx Holding Register Empty */
+#define UARTLSR_BRK (1 << 4) /* Break Condition Detected */
+#define UARTLSR_FERR (1 << 3) /* Framing Error */
+#define UARTLSR_PERR (1 << 3) /* Parity Error */
+#define UARTLSR_OVRF (1 << 2) /* Rx Overrun Error */
+#define UARTLSR_RDR (1 << 2) /* Rx Data Ready */
+
+#define CONSOLE_T_16550_BASE CONSOLE_T_BASE
+
+ /*
+ * "core" functions are low-level implementations that don't require
+ * writable memory and are thus safe to call in BL1 crash context.
+ */
+ .globl nxp_console_16550_core_init
+ .globl nxp_console_16550_core_putc
+ .globl nxp_console_16550_core_getc
+ .globl nxp_console_16550_core_flush
+
+ .globl console_16550_putc
+ .globl console_16550_getc
+ .globl console_16550_flush
+
+ /* -----------------------------------------------
+ * int nxp_console_16550_core_init(uintptr_t base_addr,
+ * unsigned int uart_clk, unsigned int baud_rate)
+ * Function to initialize the console without a
+ * C Runtime to print debug information. This
+ * function will be accessed by console_init and
+ * crash reporting.
+ * In: x0 - console base address
+ * w1 - Uart clock in Hz
+ * w2 - Baud rate
+ * Out: return 1 on success, 0 on error
+ * Clobber list : x1, x2, x3
+ * -----------------------------------------------
+ */
+func nxp_console_16550_core_init
+ /* Check the input base address */
+ cbz x0, init_fail
+ /* Check baud rate and uart clock for sanity */
+ cbz w1, init_fail
+ cbz w2, init_fail
+
+ /* Program the baudrate */
+ /* Divisor = Uart clock / (16 * baudrate) */
+ lsl w2, w2, #4
+ udiv w2, w1, w2
+ and w1, w2, #0xff /* w1 = DLL */
+ lsr w2, w2, #8
+ and w2, w2, #0xff /* w2 = DLLM */
+ ldrb w3, [x0, #UARTLCR]
+ orr w3, w3, #UARTLCR_DLAB
+ strb w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */
+ strb w1, [x0, #UARTDLL] /* program DLL */
+ strb w2, [x0, #UARTDLLM] /* program DLLM */
+ mov w2, #~UARTLCR_DLAB
+ and w3, w3, w2
+ strb w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */
+
+ /* 8n1 */
+ mov w3, #3
+ strb w3, [x0, #UARTLCR]
+ /* no interrupt */
+ mov w3, #0
+ strb w3, [x0, #UARTIER]
+ /* enable fifo, DMA */
+ mov w3, #(UARTFCR_FIFOEN |UARTFCR_TXCLR | UARTFCR_RXCLR)
+ strb w3, [x0, #UARTFCR]
+ /* DTR + RTS */
+ mov w3, #3
+ str w3, [x0, #UARTMCR]
+ mov w0, #1
+ ret
+init_fail:
+ mov w0, #0
+ ret
+endfunc nxp_console_16550_core_init
+
+ .globl nxp_console_16550_register
+
+ /* -----------------------------------------------
+ * int nxp_console_16550_register(uintptr_t baseaddr,
+ * uint32_t clock, uint32_t baud,
+ * console_t *console);
+ * Function to initialize and register a new 16550
+ * console. Storage passed in for the console struct
+ * *must* be persistent (i.e. not from the stack).
+ * If w1 (UART clock) is 0, initialisation will be
+ * skipped, relying on previous code to have done
+ * this already. w2 is ignored then as well.
+ * In: x0 - UART register base address
+ * w1 - UART clock in Hz
+ * w2 - Baud rate (ignored if w1 is 0)
+ * x3 - pointer to empty console_t struct
+ * Out: return 1 on success, 0 on error
+ * Clobber list : x0, x1, x2, x6, x7, x14
+ * -----------------------------------------------
+ */
+func nxp_console_16550_register
+ mov x7, x30
+ mov x6, x3
+ cbz x6, register_fail
+ str x0, [x6, #CONSOLE_T_16550_BASE]
+
+ /* A clock rate of zero means to skip the initialisation. */
+ cbz w1, register_16550
+
+ bl nxp_console_16550_core_init
+ cbz x0, register_fail
+
+register_16550:
+ mov x0, x6
+ mov x30, x7
+ finish_console_register 16550 putc=1, getc=1, flush=1
+
+register_fail:
+ ret x7
+endfunc nxp_console_16550_register
+
+ /* --------------------------------------------------------
+ * int console_16550_core_putc(int c, uintptr_t base_addr)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In : w0 - character to be printed
+ * x1 - console base address
+ * Out : return -1 on error else return character.
+ * Clobber list : x2
+ * --------------------------------------------------------
+ */
+func nxp_console_16550_core_putc
+#if ENABLE_ASSERTIONS
+ cmp x1, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+ /* Prepend '\r' to '\n' */
+ cmp w0, #'\n'
+ b.ne 2f
+ /* Check if the transmit FIFO is full */
+1: ldrb w2, [x1, #UARTLSR]
+ and w2, w2, #UARTLSR_THRE /* #(UARTLSR_TEMT | UARTLSR_THRE)*/
+ cmp w2, #(UARTLSR_THRE)
+ b.ne 1b
+ mov w2, #'\r'
+ strb w2, [x1, #UARTTX]
+ ldrb w2, [x1, #UARTFCR]
+ orr w2, w2, #UARTFCR_TXCLR
+
+ /* Check if the transmit FIFO is full */
+2: ldrb w2, [x1, #UARTLSR]
+ and w2, w2, #(UARTLSR_THRE)
+ cmp w2, #(UARTLSR_THRE)
+ b.ne 2b
+ strb w0, [x1, #UARTTX]
+ ret
+endfunc nxp_console_16550_core_putc
+
+ /* --------------------------------------------------------
+ * int console_16550_putc(int c, console_t *console)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In : w0 - character to be printed
+ * x1 - pointer to console_t structure
+ * Out : return -1 on error else return character.
+ * Clobber list : x2
+ * --------------------------------------------------------
+ */
+func console_16550_putc
+#if ENABLE_ASSERTIONS
+ cmp x1, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr x1, [x1, #CONSOLE_T_16550_BASE]
+ b nxp_console_16550_core_putc
+endfunc console_16550_putc
+
+ /* ---------------------------------------------
+ * int console_16550_core_getc(uintptr_t base_addr)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on if no character is available.
+ * In : x0 - console base address
+ * Out : w0 - character if available, else -1
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func nxp_console_16550_core_getc
+#if ENABLE_ASSERTIONS
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+ /* Check if the receive FIFO is empty */
+1: ldrb w1, [x0, #UARTLSR]
+ tbz w1, #UARTLSR_RDR, 1b
+ ldrb w0, [x0, #UARTRX]
+ ret
+no_char:
+ mov w0, #ERROR_NO_PENDING_CHAR
+ ret
+endfunc nxp_console_16550_core_getc
+
+ /* ---------------------------------------------
+ * int console_16550_getc(console_t *console)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on if no character is available.
+ * In : x0 - pointer to console_t structure
+ * Out : w0 - character if available, else -1
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_16550_getc
+#if ENABLE_ASSERTIONS
+ cmp x1, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr x0, [x0, #CONSOLE_T_16550_BASE]
+ b nxp_console_16550_core_getc
+endfunc console_16550_getc
+
+ /* ---------------------------------------------
+ * int console_16550_core_flush(uintptr_t base_addr)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * In : x0 - console base address
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func nxp_console_16550_core_flush
+#if ENABLE_ASSERTIONS
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+
+ /* Loop until the transmit FIFO is empty */
+1: ldrb w1, [x0, #UARTLSR]
+ and w1, w1, #(UARTLSR_THRE)
+ cmp w1, #(UARTLSR_THRE)
+ b.ne 1b
+
+ mov w0, #0
+ ret
+endfunc nxp_console_16550_core_flush
+
+ /* ---------------------------------------------
+ * int console_16550_flush(console_t *console)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * In : x0 - pointer to console_t structure
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_16550_flush
+#if ENABLE_ASSERTIONS
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif /* ENABLE_ASSERTIONS */
+ ldr x0, [x0, #CONSOLE_T_16550_BASE]
+ b nxp_console_16550_core_flush
+endfunc console_16550_flush
diff --git a/drivers/nxp/console/console.mk b/drivers/nxp/console/console.mk
new file mode 100644
index 0000000000..22d13360e5
--- /dev/null
+++ b/drivers/nxp/console/console.mk
@@ -0,0 +1,46 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# Select the CORE files
+#
+# -----------------------------------------------------------------------------
+
+ifeq (${ADD_CONSOLE},)
+
+ADD_CONSOLE := 1
+
+PLAT_INCLUDES += -I$(PLAT_DRIVERS_PATH)/console
+
+ifeq ($(CONSOLE), NS16550)
+NXP_CONSOLE := NS16550
+
+$(eval $(call add_define_val,NXP_CONSOLE,${NXP_CONSOLE}))
+
+CONSOLE_SOURCES := $(PLAT_DRIVERS_PATH)/console/16550_console.S \
+ $(PLAT_DRIVERS_PATH)/console/console_16550.c
+else
+ifeq ($(CONSOLE), PL011)
+CONSOLE_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \
+ ${PLAT_DRIVERS_PATH}/console/console_pl011.c
+else
+ $(error -> CONSOLE not set!)
+endif
+endif
+
+ifeq (${BL_COMM_CONSOLE_NEEDED},yes)
+BL_COMMON_SOURCES += ${CONSOLE_SOURCES}
+else
+ifeq (${BL2_CONSOLE_NEEDED},yes)
+BL2_SOURCES += ${CONSOLE_SOURCES}
+endif
+ifeq (${BL31_CONSOLE_NEEDED},yes)
+BL31_SOURCES += ${CONSOLE_SOURCES}
+endif
+endif
+endif
+# -----------------------------------------------------------------------------
diff --git a/drivers/nxp/console/console_16550.c b/drivers/nxp/console/console_16550.c
new file mode 100644
index 0000000000..fa5c5bb271
--- /dev/null
+++ b/drivers/nxp/console/console_16550.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <dcfg.h>
+#include <lib/utils.h>
+#include <plat_console.h>
+
+/*
+ * Perform Arm specific early platform setup. At this moment we only initialize
+ * the console and the memory layout.
+ */
+void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div,
+ uint32_t baud)
+{
+ struct sysinfo sys;
+ static console_t nxp_console;
+
+ zeromem(&sys, sizeof(sys));
+ if (get_clocks(&sys)) {
+ ERROR("System clocks are not set\n");
+ panic();
+ }
+ nxp_console_16550_register(nxp_console_addr,
+ (sys.freq_platform/uart_clk_div),
+ baud, &nxp_console);
+}
diff --git a/drivers/nxp/console/console_pl011.c b/drivers/nxp/console/console_pl011.c
new file mode 100644
index 0000000000..93f2fc2fcd
--- /dev/null
+++ b/drivers/nxp/console/console_pl011.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <dcfg.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <lib/utils.h>
+
+/*
+ * Perform Arm specific early platform setup. At this moment we only initialize
+ * the console and the memory layout.
+ */
+void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div,
+ uint32_t baud)
+{
+ struct sysinfo sys;
+ static console_t nxp_console;
+
+ zeromem(&sys, sizeof(sys));
+ if (get_clocks(&sys)) {
+ ERROR("System clocks are not set\n");
+ panic();
+ }
+
+ console_pl011_register(nxp_console_addr,
+ (sys.freq_platform/uart_clk_div),
+ baud, &nxp_console);
+}
diff --git a/drivers/nxp/console/plat_console.h b/drivers/nxp/console/plat_console.h
new file mode 100644
index 0000000000..8b1b23a041
--- /dev/null
+++ b/drivers/nxp/console/plat_console.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_CONSOLE_H
+#define PLAT_CONSOLE_H
+
+#include <stdint.h>
+#include <drivers/console.h>
+
+#if (NXP_CONSOLE == NS16550)
+/*
+ * NXP specific UART - 16550 configuration
+ *
+ * Initialize a NXP 16550 console instance and register it with the console
+ * framework. The |console| pointer must point to storage that will be valid
+ * for the lifetime of the console, such as a global or static local variable.
+ * Its contents will be reinitialized from scratch.
+ * When |clock| has a value of 0, the UART will *not* be initialised. This
+ * means the UART should already be enabled and the baudrate and clock setup
+ * should have been done already, either by platform specific code or by
+ * previous firmware stages. The |baud| parameter will be ignored in this
+ * case as well.
+ */
+int nxp_console_16550_register(uintptr_t baseaddr, uint32_t clock,
+ uint32_t baud, console_t *console);
+#endif
+/*
+ * Function to initialize platform's console
+ * and register with console framework
+ */
+void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div,
+ uint32_t baud);
+
+#endif
diff --git a/drivers/nxp/crypto/caam/caam.mk b/drivers/nxp/crypto/caam/caam.mk
new file mode 100644
index 0000000000..548c7b1476
--- /dev/null
+++ b/drivers/nxp/crypto/caam/caam.mk
@@ -0,0 +1,28 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+ifeq (${ADD_CAAM},)
+
+ADD_CAAM := 1
+CAAM_DRIVER_PATH := drivers/nxp/crypto/caam
+
+CAAM_DRIVER_SOURCES += $(wildcard $(CAAM_DRIVER_PATH)/src/*.c)
+
+PLAT_INCLUDES += -I$(CAAM_DRIVER_PATH)/include
+
+ifeq (${BL_COMM_CRYPTO_NEEDED},yes)
+BL_COMMON_SOURCES += ${CAAM_DRIVER_SOURCES}
+else
+ifeq (${BL2_CRYPTO_NEEDED},yes)
+BL2_SOURCES += ${CAAM_DRIVER_SOURCES}
+endif
+ifeq (${BL31_CRYPTO_NEEDED},yes)
+BL31_SOURCES += ${CAAM_DRIVER_SOURCES}
+endif
+endif
+
+endif
diff --git a/drivers/nxp/crypto/caam/include/caam.h b/drivers/nxp/crypto/caam/include/caam.h
new file mode 100644
index 0000000000..580e133fc0
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/caam.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_H
+#define CAAM_H
+
+#include "caam_io.h"
+#include "sec_jr_driver.h"
+
+
+/* Job ring 3 is reserved for usage by sec firmware */
+#define DEFAULT_JR 3
+
+#if defined(CONFIG_CHASSIS_3_2) || defined(CONFIG_CHASSIS_2)
+#define CAAM_JR0_OFFSET 0x10000
+#define CAAM_JR1_OFFSET 0x20000
+#define CAAM_JR2_OFFSET 0x30000
+#define CAAM_JR3_OFFSET 0x40000
+#endif
+
+enum sig_alg {
+ RSA,
+ ECC
+};
+
+/* This function does basic SEC Initialization */
+int sec_init(uintptr_t nxp_caam_addr);
+int config_sec_block(void);
+uintptr_t get_caam_addr(void);
+
+/* This function is used to submit jobs to JR */
+int run_descriptor_jr(struct job_descriptor *desc);
+
+/* This function is used to instatiate the HW RNG is already not instantiated */
+int hw_rng_instantiate(void);
+
+/* This function is used to return random bytes of byte_len from HW RNG */
+int get_rand_bytes_hw(uint8_t *bytes, int byte_len);
+
+/* This function is used to set the hw unique key from HW CAAM */
+int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size);
+
+/* This function is used to fetch random number from
+ * CAAM of length either of 4 bytes or 8 bytes depending
+ * rngWidth value.
+ */
+unsigned long long get_random(int rngWidth);
+
+#endif /* CAAM_H */
diff --git a/drivers/nxp/crypto/caam/include/caam_io.h b/drivers/nxp/crypto/caam/include/caam_io.h
new file mode 100644
index 0000000000..4fdb04d6df
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/caam_io.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_IO_H
+#define CAAM_IO_H
+
+#include <endian.h>
+#include <lib/mmio.h>
+
+typedef unsigned long long phys_addr_t;
+typedef unsigned long long phys_size_t;
+
+/* Return higher 32 bits of physical address */
+#define PHYS_ADDR_HI(phys_addr) \
+ (uint32_t)(((uint64_t)phys_addr) >> 32)
+
+/* Return lower 32 bits of physical address */
+#define PHYS_ADDR_LO(phys_addr) \
+ (uint32_t)(((uint64_t)phys_addr) & 0xFFFFFFFF)
+
+#ifdef NXP_SEC_BE
+#define sec_in32(a) bswap32(mmio_read_32((uintptr_t)(a)))
+#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v))
+#define sec_in64(addr) ( \
+ ((uint64_t)sec_in32((uintptr_t)(addr)) << 32) | \
+ (sec_in32(((uintptr_t)(addr)) + 4)))
+#define sec_out64(addr, val) ({ \
+ sec_out32(((uintptr_t)(addr)), (uint32_t)((val) >> 32)); \
+ sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)(val)); })
+#elif defined(NXP_SEC_LE)
+#define sec_in32(a) mmio_read_32((uintptr_t)(a))
+#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), (v))
+#define sec_in64(addr) ( \
+ ((uint64_t)sec_in32((uintptr_t)(addr) + 4) << 32) | \
+ (sec_in32((uintptr_t)(addr))))
+#define sec_out64(addr, val) ({ \
+ sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)((val) >> 32)); \
+ sec_out32(((uintptr_t)(addr)), (uint32_t)(val)); })
+#else
+#error Please define CCSR SEC register endianness
+#endif
+
+static inline void *ptov(phys_addr_t *ptr)
+{
+ return (void *)ptr;
+}
+
+static inline phys_addr_t *vtop(void *ptr)
+{
+ return (phys_addr_t *)ptr;
+}
+#endif /* CAAM_IO_H */
diff --git a/drivers/nxp/crypto/caam/include/hash.h b/drivers/nxp/crypto/caam/include/hash.h
new file mode 100644
index 0000000000..946087d468
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/hash.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#include <stdbool.h>
+
+/* List of hash algorithms */
+enum hash_algo {
+ SHA1 = 0,
+ SHA256
+};
+
+/* number of bytes in the SHA256-256 digest */
+#define SHA256_DIGEST_SIZE 32
+
+/*
+ * number of words in the digest - Digest is kept internally
+ * as 8 32-bit words
+ */
+#define _SHA256_DIGEST_LENGTH 8
+
+/*
+ * block length - A block, treated as a sequence of
+ * 32-bit words
+ */
+#define SHA256_BLOCK_LENGTH 16
+
+/* number of bytes in the block */
+#define SHA256_DATA_SIZE 64
+
+#define MAX_SG 12
+
+struct sg_entry {
+#if defined(NXP_SEC_LE)
+ uint32_t addr_lo; /* Memory Address - lo */
+ uint32_t addr_hi; /* Memory Address of start of buffer - hi */
+#else
+ uint32_t addr_hi; /* Memory Address of start of buffer - hi */
+ uint32_t addr_lo; /* Memory Address - lo */
+#endif
+
+ uint32_t len_flag; /* Length of the data in the frame */
+#define SG_ENTRY_LENGTH_MASK 0x3FFFFFFF
+#define SG_ENTRY_EXTENSION_BIT 0x80000000
+#define SG_ENTRY_FINAL_BIT 0x40000000
+ uint32_t bpid_offset;
+#define SG_ENTRY_BPID_MASK 0x00FF0000
+#define SG_ENTRY_BPID_SHIFT 16
+#define SG_ENTRY_OFFSET_MASK 0x00001FFF
+#define SG_ENTRY_OFFSET_SHIFT 0
+};
+
+/*
+ * SHA256-256 context
+ * contain the following fields
+ * State
+ * count low
+ * count high
+ * block data buffer
+ * index to the buffer
+ */
+struct hash_ctx {
+ struct sg_entry sg_tbl[MAX_SG];
+ uint32_t hash_desc[64];
+ uint8_t hash[SHA256_DIGEST_SIZE];
+ uint32_t sg_num;
+ uint32_t len;
+ uint8_t *data;
+ enum hash_algo algo;
+ bool active;
+};
+
+int hash_init(enum hash_algo algo, void **ctx);
+int hash_update(enum hash_algo algo, void *context, void *data_ptr,
+ unsigned int data_len);
+int hash_final(enum hash_algo algo, void *context, void *hash_ptr,
+ unsigned int hash_len);
+
+#endif
diff --git a/drivers/nxp/crypto/caam/include/jobdesc.h b/drivers/nxp/crypto/caam/include/jobdesc.h
new file mode 100644
index 0000000000..5921f7be31
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/jobdesc.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __JOBDESC_H
+#define __JOBDESC_H
+
+#include <rsa.h>
+
+#define DESC_LEN_MASK 0x7f
+#define DESC_START_SHIFT 16
+
+#define KEY_BLOB_SIZE 32
+#define MAC_SIZE 16
+
+#define KEY_IDNFR_SZ_BYTES 16
+#define CLASS_SHIFT 25
+#define CLASS_2 (0x02 << CLASS_SHIFT)
+
+#define CMD_SHIFT 27
+#define CMD_OPERATION (U(0x10) << CMD_SHIFT)
+
+#define OP_TYPE_SHIFT 24
+#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
+
+/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
+#define OP_PCLID_SHIFT 16
+#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT)
+
+#define BLOB_PROTO_INFO 0x00000002
+
+uint32_t desc_length(uint32_t *desc);
+
+int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle,
+ uint32_t *add_inp, uint32_t add_ip_len,
+ uint8_t *out_data, uint32_t len);
+
+int cnstr_rng_instantiate_jobdesc(uint32_t *desc);
+
+/* Construct descriptor to generate hw key blob */
+int cnstr_hw_encap_blob_jobdesc(uint32_t *desc,
+ uint8_t *key_idnfr, uint32_t key_sz,
+ uint32_t key_class, uint8_t *plain_txt,
+ uint32_t in_sz, uint8_t *enc_blob,
+ uint32_t out_sz, uint32_t operation);
+
+void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz,
+ uint8_t *digest);
+
+void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
+ struct pk_in_params *pkin, uint8_t *out,
+ uint32_t out_siz);
+#endif
diff --git a/drivers/nxp/crypto/caam/include/jr_driver_config.h b/drivers/nxp/crypto/caam/include/jr_driver_config.h
new file mode 100644
index 0000000000..f25c42e4d1
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/jr_driver_config.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _JR_DRIVER_CONFIG_H_
+#define _JR_DRIVER_CONFIG_H_
+
+/* Helper defines */
+
+ /* Define used for setting a flag on */
+#define ON 1
+ /* Define used for setting a flag off */
+#define OFF 0
+
+ /* SEC is configured to start work in polling mode, */
+#define SEC_STARTUP_POLLING_MODE 0
+/*
+ * SEC is configured to start work in interrupt mode,
+ * when configured for NAPI notification style.
+ */
+#define SEC_STARTUP_INTERRUPT_MODE 1
+
+/*
+ * SEC driver will use ONLY interrupts to receive notifications
+ * for processed packets from SEC engine hardware.
+ */
+#define SEC_NOTIFICATION_TYPE_IRQ 1
+/*
+ * SEC driver will use ONLY polling to receive notifications
+ * for processed packets from SEC engine hardware.
+ */
+#define SEC_NOTIFICATION_TYPE_POLL 2
+
+/*
+ * Determines how SEC user space driver will receive notifications
+ * for processed packets from SEC engine.
+ * Valid values are: #SEC_NOTIFICATION_TYPE_POLL, #SEC_NOTIFICATION_TYPE_IRQ
+ */
+#define SEC_NOTIFICATION_TYPE SEC_NOTIFICATION_TYPE_POLL
+
+ /* Maximum number of job rings supported by SEC hardware */
+#define MAX_SEC_JOB_RINGS 1
+
+/*
+ * Size of cryptographic context that is used directly in communicating
+ * with SEC device.
+ * SEC device works only with physical addresses. This is the maximum size
+ * for a SEC descriptor ( = 64 words).
+ */
+
+#define SEC_CRYPTO_DESCRIPTOR_SIZE 256
+
+/*
+ * Size of job descriptor submitted to SEC device for each packet to be
+ * processed.
+ * Job descriptor contains 3 DMA address pointers:
+ * - to shared descriptor, to input buffer and to output buffer.
+ * The job descriptor contains other SEC specific commands as well:
+ * - HEADER command, SEQ IN PTR command SEQ OUT PTR command and opaque
+ * data, each measuring 4 bytes.
+ * Job descriptor size, depending on physical address representation:
+ * - 32 bit - size is 28 bytes - cacheline-aligned size is 64 bytes
+ * - 36 bit - size is 40 bytes - cacheline-aligned size is 64 bytes
+ * @note: Job descriptor must be cacheline-aligned to ensure efficient memory
+ * access.
+ * @note: If other format is used for job descriptor, then the size must be
+ * revised.
+ */
+
+#define SEC_JOB_DESCRIPTOR_SIZE 64
+
+/*
+ * Size of one entry in the input ring of a job ring.
+ * Input ring contains pointers to job descriptors.
+ * The memory used for an input ring and output ring must be physically
+ * contiguous.
+ */
+
+#define SEC_JOB_INPUT_RING_ENTRY_SIZE sizeof(phys_addr_t)
+
+/*
+ * Size of one entry in the output ring of a job ring.
+ * Output ring entry is a pointer to a job descriptor followed by a 4 byte
+ * status word.
+ * The memory used for an input ring and output ring must be physically
+ * contiguous.
+ * @note If desired to use also the optional SEQ OUT indication in output
+ * ring entries, then 4 more bytes must be added to the size.
+ */
+
+#define SEC_JOB_OUTPUT_RING_ENTRY_SIZE (SEC_JOB_INPUT_RING_ENTRY_SIZE + 4)
+
+ /* DMA memory required for an input ring of a job ring. */
+#define SEC_DMA_MEM_INPUT_RING_SIZE \
+ ((SEC_JOB_INPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE))
+
+/*
+ * DMA memory required for an output ring of a job ring.
+ * Required extra 4 byte for status word per each entry.
+ */
+#define SEC_DMA_MEM_OUTPUT_RING_SIZE \
+ ((SEC_JOB_OUTPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE))
+
+ /* DMA memory required for descriptors of a job ring. */
+#define SEC_DMA_MEM_DESCRIPTORS \
+ ((SEC_CRYPTO_DESCRIPTOR_SIZE)*(SEC_JOB_RING_SIZE))
+
+ /* DMA memory required for a job ring, including both input output rings. */
+#define SEC_DMA_MEM_JOB_RING_SIZE \
+ ((SEC_DMA_MEM_INPUT_RING_SIZE) + \
+ (SEC_DMA_MEM_OUTPUT_RING_SIZE))
+
+/*
+ * When calling sec_init() UA will provide an area of virtual memory
+ * of size #SEC_DMA_MEMORY_SIZE to be used internally by the driver
+ * to allocate data (like SEC descriptors) that needs to be passed to
+ * SEC device in physical addressing and later on retrieved from SEC device.
+ * At initialization the UA provides specialized ptov/vtop functions/macros to
+ * translate addresses allocated from this memory area.
+ */
+#define SEC_DMA_MEMORY_SIZE \
+ ((SEC_DMA_MEM_JOB_RING_SIZE) * (MAX_SEC_JOB_RINGS))
+
+/*
+ * SEC DEVICE related configuration.
+
+ * Enable/Disable logging support at compile time.
+ * Valid values:
+ * ON - enable logging
+ * OFF - disable logging
+ * The messages are logged at stdout.
+ */
+
+#define SEC_DRIVER_LOGGING OFF
+
+/*
+ * Configure logging level at compile time.
+ * Valid values:
+ * SEC_DRIVER_LOG_ERROR - log only errors
+ * SEC_DRIVER_LOG_INFO - log errors and info messages
+ * SEC_DRIVER_LOG_DEBUG - log errors, info and debug messages
+ */
+
+#define SEC_DRIVER_LOGGING_LEVEL SEC_DRIVER_LOG_DEBUG
+
+/*
+ * SEC JOB RING related configuration.
+
+ * Configure the size of the JOB RING.
+ * The maximum size of the ring is hardware limited to 1024.
+ * However the number of packets in flight in a time interval of
+ * 1ms can be calculated
+ * from the traffic rate (Mbps) and packet size.
+ * Here it was considered a packet size of 40 bytes.
+ * @note Round up to nearest power of 2 for optimized update
+ * of producer/consumer indexes of each job ring
+ * \todo Should set to 750, according to the calculation above, but
+ * the JR size must be power of 2, thus the next closest value must
+ * be chosen (i.e. 512 since 1024 is not available)
+ * For firmware choose this to be 16
+ */
+
+#define SEC_JOB_RING_SIZE 16
+
+/*
+ * Interrupt coalescing related configuration.
+ * NOTE: SEC hardware enabled interrupt
+ * coalescing is not supported on SEC version 3.1!
+ * SEC version 4.4 has support for interrupt
+ * coalescing.
+ */
+
+#if SEC_NOTIFICATION_TYPE != SEC_NOTIFICATION_TYPE_POLL
+
+#define SEC_INT_COALESCING_ENABLE ON
+/*
+ * Interrupt Coalescing Descriptor Count Threshold.
+ * While interrupt coalescing is enabled (ICEN=1), this value determines
+ * how many Descriptors are completed before raising an interrupt.
+ * Valid values for this field are from 0 to 255.
+ * Note that a value of 1 functionally defeats the advantages of interrupt
+ * coalescing since the threshold value is reached each time that a
+ * Job Descriptor is completed. A value of 0 is treated in the same
+ * manner as a value of 1.
+ *
+ */
+#define SEC_INTERRUPT_COALESCING_DESCRIPTOR_COUNT_THRESH 10
+
+/*
+ * Interrupt Coalescing Timer Threshold.
+ * While interrupt coalescing is enabled (ICEN=1), this value determines the
+ * maximum amount of time after processing a Descriptor before raising an
+ * interrupt.
+ * The threshold value is represented in units equal to 64 CAAM interface
+ * clocks. Valid values for this field are from 1 to 65535.
+ * A value of 0 results in behavior identical to that when interrupt
+ * coalescing is disabled.
+ */
+#define SEC_INTERRUPT_COALESCING_TIMER_THRESH 100
+#endif /* SEC_NOTIFICATION_TYPE_POLL */
+
+#endif /* _JR_DRIVER_CONFIG_H_ */
diff --git a/drivers/nxp/crypto/caam/include/rsa.h b/drivers/nxp/crypto/caam/include/rsa.h
new file mode 100644
index 0000000000..bd5dc71143
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/rsa.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _RSA_H__
+#define _RSA_H__
+
+/* RSA key size defines */
+#define RSA_4K_KEY_SZ 4096
+#define RSA_4K_KEY_SZ_BYTES (RSA_4K_KEY_SZ/8)
+#define RSA_2K_KEY_SZ 2048
+#define RSA_2K_KEY_SZ_BYTES (RSA_2K_KEY_SZ/8)
+#define RSA_1K_KEY_SZ 1024
+#define RSA_1K_KEY_SZ_BYTES (RSA_1K_KEY_SZ/8)
+
+#define SHA256_BYTES (256/8)
+
+struct pk_in_params {
+ uint8_t *e;
+ uint32_t e_siz;
+ uint8_t *n;
+ uint32_t n_siz;
+ uint8_t *a;
+ uint32_t a_siz;
+ uint8_t *b;
+ uint32_t b_siz;
+};
+
+struct rsa_context {
+ struct pk_in_params pkin;
+};
+
+int rsa_verify_signature(void *hash_ptr, unsigned int hash_len,
+ void *sig_ptr, unsigned int sig_len,
+ void *pk_ptr, unsigned int pk_len);
+
+#endif
diff --git a/drivers/nxp/crypto/caam/include/sec_hw_specific.h b/drivers/nxp/crypto/caam/include/sec_hw_specific.h
new file mode 100644
index 0000000000..a82a1a019b
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/sec_hw_specific.h
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _SEC_HW_SPECIFIC_H_
+#define _SEC_HW_SPECIFIC_H_
+
+#include "caam.h"
+#include "sec_jr_driver.h"
+
+ /* DEFINES AND MACROS */
+
+/* Used to retry resetting a job ring in SEC hardware. */
+#define SEC_TIMEOUT 100000
+
+/*
+ * Offset to the registers of a job ring.
+ *Is different for each job ring.
+ */
+#define CHAN_BASE(jr) ((phys_addr_t)(jr)->register_base_addr)
+
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+#define SEC_JOB_RING_IS_FULL(pi, ci, ring_max_size, ring_threshold) \
+ ((((pi) + 1 + ((ring_max_size) - (ring_threshold))) & \
+ (ring_max_size - 1)) == ((ci)))
+
+#define SEC_CIRCULAR_COUNTER(x, max) (((x) + 1) & (max - 1))
+
+ /* Struct representing various job ring registers */
+struct jobring_regs {
+#ifdef NXP_SEC_BE
+ unsigned int irba_h;
+ unsigned int irba_l;
+#else
+ unsigned int irba_l;
+ unsigned int irba_h;
+#endif
+ unsigned int rsvd1;
+ unsigned int irs;
+ unsigned int rsvd2;
+ unsigned int irsa;
+ unsigned int rsvd3;
+ unsigned int irja;
+#ifdef NXP_SEC_BE
+ unsigned int orba_h;
+ unsigned int orba_l;
+#else
+ unsigned int orba_l;
+ unsigned int orba_h;
+#endif
+ unsigned int rsvd4;
+ unsigned int ors;
+ unsigned int rsvd5;
+ unsigned int orjr;
+ unsigned int rsvd6;
+ unsigned int orsf;
+ unsigned int rsvd7;
+ unsigned int jrsta;
+ unsigned int rsvd8;
+ unsigned int jrint;
+ unsigned int jrcfg0;
+ unsigned int jrcfg1;
+ unsigned int rsvd9;
+ unsigned int irri;
+ unsigned int rsvd10;
+ unsigned int orwi;
+ unsigned int rsvd11;
+ unsigned int jrcr;
+};
+
+ /* Offsets representing common SEC Registers */
+#define SEC_REG_MCFGR_OFFSET 0x0004
+#define SEC_REG_SCFGR_OFFSET 0x000C
+#define SEC_REG_JR0ICIDR_MS_OFFSET 0x0010
+#define SEC_REG_JR0ICIDR_LS_OFFSET 0x0014
+#define SEC_REG_JR1ICIDR_MS_OFFSET 0x0018
+#define SEC_REG_JR1ICIDR_LS_OFFSET 0x001C
+#define SEC_REG_JR2ICIDR_MS_OFFSET 0x0020
+#define SEC_REG_JR2ICIDR_LS_OFFSET 0x0024
+#define SEC_REG_JR3ICIDR_MS_OFFSET 0x0028
+#define SEC_REG_JR3ICIDR_LS_OFFSET 0x002C
+#define SEC_REG_JRSTARTR_OFFSET 0x005C
+#define SEC_REG_CTPR_MS_OFFSET 0x0FA8
+
+ /* Offsets representing various RNG registers */
+#define RNG_REG_RTMCTL_OFFSET 0x0600
+#define RNG_REG_RTSDCTL_OFFSET 0x0610
+#define RNG_REG_RTFRQMIN_OFFSET 0x0618
+#define RNG_REG_RTFRQMAX_OFFSET 0x061C
+#define RNG_REG_RDSTA_OFFSET 0x06C0
+#define ALG_AAI_SH_SHIFT 4
+
+ /* SEC Registers Bitmasks */
+#define MCFGR_PS_SHIFT 16
+#define MCFGR_AWCACHE_SHIFT 8
+#define MCFGR_AWCACHE_MASK (0xF << MCFGR_AWCACHE_SHIFT)
+#define MCFGR_ARCACHE_SHIFT 12
+#define MCFGR_ARCACHE_MASK (0xF << MCFGR_ARCACHE_SHIFT)
+
+#define SCFGR_RNGSH0 0x00000200
+#define SCFGR_VIRT_EN 0x00008000
+
+#define JRICID_MS_LICID 0x80000000
+#define JRICID_MS_LAMTD 0x00020000
+#define JRICID_MS_AMTDT 0x00010000
+#define JRICID_MS_TZ 0x00008000
+#define JRICID_LS_SDID_MASK 0x00000FFF
+#define JRICID_LS_NSEQID_MASK 0x0FFF0000
+#define JRICID_LS_NSEQID_SHIFT 16
+#define JRICID_LS_SEQID_MASK 0x00000FFF
+
+#define JRSTARTR_STARTJR0 0x00000001
+#define JRSTARTR_STARTJR1 0x00000002
+#define JRSTARTR_STARTJR2 0x00000004
+#define JRSTARTR_STARTJR3 0x00000008
+
+#define CTPR_VIRT_EN_POR 0x00000002
+#define CTPR_VIRT_EN_INC 0x00000001
+
+ /* RNG RDSTA bitmask */
+#define RNG_STATE0_HANDLE_INSTANTIATED 0x00000001
+#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
+ /* use von Neumann data in both entropy shifter and statistical checker */
+#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC 0
+ /* use raw data in both entropy shifter and statistical checker */
+#define RTMCTL_SAMP_MODE_RAW_ES_SC 1
+ /* use von Neumann data in entropy shifter, raw data in statistical checker */
+#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_RAW_SC 2
+ /* invalid combination */
+#define RTMCTL_SAMP_MODE_INVALID 3
+#define RTSDCTL_ENT_DLY_MIN 3200
+#define RTSDCTL_ENT_DLY_MAX 12800
+#define RTSDCTL_ENT_DLY_SHIFT 16
+#define RTSDCTL_ENT_DLY_MASK (U(0xffff) << RTSDCTL_ENT_DLY_SHIFT)
+#define RTFRQMAX_DISABLE (1 << 20)
+
+ /* Constants for error handling on job ring */
+#define JR_REG_JRINT_ERR_TYPE_SHIFT 8
+#define JR_REG_JRINT_ERR_ORWI_SHIFT 16
+#define JR_REG_JRINIT_JRE_SHIFT 1
+
+#define JRINT_JRE (1 << JR_REG_JRINIT_JRE_SHIFT)
+#define JRINT_ERR_WRITE_STATUS (1 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_BAD_INPUT_BASE (3 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_BAD_OUTPUT_BASE (4 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_WRITE_2_IRBA (5 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_WRITE_2_ORBA (6 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_RES_B4_HALT (7 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_REM_TOO_MANY (8 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_ADD_TOO_MANY (9 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_HALT_MASK 0x0C
+#define JRINT_ERR_HALT_INPROGRESS 0x04
+#define JRINT_ERR_HALT_COMPLETE 0x08
+
+#define JR_REG_JRCR_VAL_RESET 0x00000001
+
+#define JR_REG_JRCFG_LO_ICTT_SHIFT 0x10
+#define JR_REG_JRCFG_LO_ICDCT_SHIFT 0x08
+#define JR_REG_JRCFG_LO_ICEN_EN 0x02
+#define JR_REG_JRCFG_LO_IMSK_EN 0x01
+
+ /* Constants for Descriptor Processing errors */
+#define SEC_HW_ERR_SSRC_NO_SRC 0x00
+#define SEC_HW_ERR_SSRC_CCB_ERR 0x02
+#define SEC_HW_ERR_SSRC_JMP_HALT_U 0x03
+#define SEC_HW_ERR_SSRC_DECO 0x04
+#define SEC_HW_ERR_SSRC_JR 0x06
+#define SEC_HW_ERR_SSRC_JMP_HALT_COND 0x07
+
+#define SEC_HW_ERR_DECO_HFN_THRESHOLD 0xF1
+#define SEC_HW_ERR_CCB_ICV_CHECK_FAIL 0x0A
+
+ /* Macros for extracting error codes for the job ring */
+
+#define JR_REG_JRINT_ERR_TYPE_EXTRACT(value) \
+ ((value) & 0x00000F00)
+
+#define JR_REG_JRINT_ERR_ORWI_EXTRACT(value) \
+ (((value) & 0x3FFF0000) >> \
+ JR_REG_JRINT_ERR_ORWI_SHIFT)
+
+#define JR_REG_JRINT_JRE_EXTRACT(value) \
+ ((value) & JRINT_JRE)
+
+ /* Macros for manipulating JR registers */
+typedef union {
+ uint64_t m_whole;
+ struct {
+#ifdef NXP_SEC_BE
+ uint32_t high;
+ uint32_t low;
+#else
+ uint32_t low;
+ uint32_t high;
+#endif
+ } m_halves;
+} ptr_addr_t;
+
+#if defined(CONFIG_PHYS_64BIT)
+#define sec_read_addr(a) sec_in64((a))
+#define sec_write_addr(a, v) sec_out64((a), (v))
+#else
+#define sec_read_addr(a) sec_in32((a))
+#define sec_write_addr(a, v) sec_out32((a), (v))
+#endif
+
+#define JR_REG(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET)
+#define JR_REG_LO(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET_LO)
+
+#define GET_JR_REG(name, jr) (sec_in32(JR_REG(name, (jr))))
+#define GET_JR_REG_LO(name, jr) (sec_in32(JR_REG_LO(name, (jr))))
+
+#define SET_JR_REG(name, jr, val) \
+ (sec_out32(JR_REG(name, (jr)), (val)))
+
+#define SET_JR_REG_LO(name, jr, val) \
+ (sec_out32(JR_REG_LO(name, (jr)), (val)))
+
+ /* STRUCTURES AND OTHER TYPEDEFS */
+ /* Lists the possible states for a job ring. */
+typedef enum sec_job_ring_state_e {
+ SEC_JOB_RING_STATE_STARTED, /* Job ring is initialized */
+ SEC_JOB_RING_STATE_RESET, /* Job ring reset is in progres */
+} sec_job_ring_state_t;
+
+struct sec_job_ring_t {
+ /*
+ * Consumer index for job ring (jobs array).
+ * @note: cidx and pidx are accessed from
+ * different threads.
+ * Place the cidx and pidx inside the structure
+ * so that they lay on different cachelines, to
+ * avoid false sharing between threads when the
+ * threads run on different cores!
+ */
+ uint32_t cidx;
+
+ /* Producer index for job ring (jobs array) */
+ uint32_t pidx;
+
+ /* Ring of input descriptors. Size of array is power of 2 to allow
+ * fast update of producer/consumer indexes with bitwise operations.
+ */
+ phys_addr_t *input_ring;
+
+ /* Ring of output descriptors. */
+ struct sec_outring_entry *output_ring;
+
+ /* The file descriptor used for polling for interrupts notifications */
+ uint32_t irq_fd;
+
+ /* Model used by SEC Driver to receive notifications from SEC.
+ * Can be either of the three:
+ * #SEC_NOTIFICATION_TYPE_IRQ or
+ * #SEC_NOTIFICATION_TYPE_POLL
+ */
+ uint32_t jr_mode;
+ /* Base address for SEC's register memory for this job ring. */
+ void *register_base_addr;
+ /* notifies if coelescing is enabled for the job ring */
+ uint8_t coalescing_en;
+ /* The state of this job ring */
+ sec_job_ring_state_t jr_state;
+};
+
+ /* Forward structure declaration */
+typedef struct sec_job_ring_t sec_job_ring_t;
+
+struct sec_outring_entry {
+ phys_addr_t desc; /* Pointer to completed descriptor */
+ uint32_t status; /* Status for completed descriptor */
+} __packed;
+
+ /* Lists the states possible for the SEC user space driver. */
+typedef enum sec_driver_state_e {
+ SEC_DRIVER_STATE_IDLE, /*< Driver not initialized */
+ SEC_DRIVER_STATE_STARTED, /*< Driver initialized and */
+ SEC_DRIVER_STATE_RELEASE, /*< Driver release is in progress */
+} sec_driver_state_t;
+
+ /* Union describing the possible error codes that */
+ /* can be set in the descriptor status word */
+
+union hw_error_code {
+ uint32_t error;
+ union {
+ struct {
+ uint32_t ssrc:4;
+ uint32_t ssed_val:28;
+ } __packed value;
+ struct {
+ uint32_t ssrc:4;
+ uint32_t res:28;
+ } __packed no_status_src;
+ struct {
+ uint32_t ssrc:4;
+ uint32_t jmp:1;
+ uint32_t res:11;
+ uint32_t desc_idx:8;
+ uint32_t cha_id:4;
+ uint32_t err_id:4;
+ } __packed ccb_status_src;
+ struct {
+ uint32_t ssrc:4;
+ uint32_t jmp:1;
+ uint32_t res:11;
+ uint32_t desc_idx:8;
+ uint32_t offset:8;
+ } __packed jmp_halt_user_src;
+ struct {
+ uint32_t ssrc:4;
+ uint32_t jmp:1;
+ uint32_t res:11;
+ uint32_t desc_idx:8;
+ uint32_t desc_err:8;
+ } __packed deco_src;
+ struct {
+ uint32_t ssrc:4;
+ uint32_t res:17;
+ uint32_t naddr:3;
+ uint32_t desc_err:8;
+ } __packed jr_src;
+ struct {
+ uint32_t ssrc:4;
+ uint32_t jmp:1;
+ uint32_t res:11;
+ uint32_t desc_idx:8;
+ uint32_t cond:8;
+ } __packed jmp_halt_cond_src;
+ } __packed error_desc;
+} __packed;
+
+ /* FUNCTION PROTOTYPES */
+
+/*
+ * @brief Initialize a job ring/channel in SEC device.
+ * Write configuration register/s to properly initialize a job ring.
+ *
+ * @param [in] job_ring The job ring
+ *
+ * @retval 0 for success
+ * @retval other for error
+ */
+int hw_reset_job_ring(sec_job_ring_t *job_ring);
+
+/*
+ * @brief Reset a job ring/channel in SEC device.
+ * Write configuration register/s to reset a job ring.
+ *
+ * @param [in] job_ring The job ring
+ *
+ * @retval 0 for success
+ * @retval -1 in case job ring reset failed
+ */
+int hw_shutdown_job_ring(sec_job_ring_t *job_ring);
+
+/*
+ * @brief Handle a job ring/channel error in SEC device.
+ * Identify the error type and clear error bits if required.
+ *
+ * @param [in] job_ring The job ring
+ * @param [in] sec_error_code error code as first read from SEC engine
+ */
+
+void hw_handle_job_ring_error(sec_job_ring_t *job_ring,
+ uint32_t sec_error_code);
+/*
+ * @brief Handle a job ring error in the device.
+ * Identify the error type and printout a explanatory
+ * messages.
+ *
+ * @param [in] job_ring The job ring
+ *
+ */
+
+int hw_job_ring_error(sec_job_ring_t *job_ring);
+
+/* @brief Set interrupt coalescing parameters on the Job Ring.
+ * @param [in] job_ring The job ring
+ * @param [in] irq_coalesing_timer
+ * Interrupt coalescing timer threshold.
+ * This value determines the maximum
+ * amount of time after processing a descriptor
+ * before raising an interrupt.
+ * @param [in] irq_coalescing_count
+ * Interrupt coalescing count threshold.
+ * This value determines how many descriptors
+ * are completed before raising an interrupt.
+ */
+
+int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring,
+ uint16_t irq_coalescing_timer,
+ uint8_t irq_coalescing_count);
+
+/* @brief Enable interrupt coalescing on a job ring
+ * @param [in] job_ring The job ring
+ */
+
+int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring);
+
+/*
+ * @brief Disable interrupt coalescing on a job ring
+ * @param [in] job_ring The job ring
+ */
+
+int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring);
+
+/*
+ * @brief Poll the HW for already processed jobs in the JR
+ * and notify the available jobs to UA.
+ *
+ * @param [in] job_ring The job ring to poll.
+ * @param [in] limit The maximum number of jobs to notify.
+ * If set to negative value, all available
+ * jobs are notified.
+ *
+ * @retval >=0 for No of jobs notified to UA.
+ * @retval -1 for error
+ */
+
+int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit);
+
+/* @brief Poll the HW for already processed jobs in the JR
+ * and silently discard the available jobs or notify them to UA
+ * with indicated error code.
+
+ * @param [in,out] job_ring The job ring to poll.
+ * @param [in] do_notify Can be #TRUE or #FALSE.
+ * Indicates if descriptors to be discarded
+ * or notified to UA with given error_code.
+ * @param [in] error_code The detailed SEC error code.
+ * @param [out] notified_descs Number of notified descriptors.
+ * Can be NULL if do_notify is #FALSE
+ */
+void hw_flush_job_ring(struct sec_job_ring_t *job_ring,
+ uint32_t do_notify,
+ uint32_t error_code, uint32_t *notified_descs);
+
+/*
+ * @brief Flush job rings of any processed descs.
+ * The processed descs are silently dropped,
+ * WITHOUT being notified to UA.
+ */
+void flush_job_rings(void);
+
+/*
+ * @brief Handle desc that generated error in SEC engine.
+ * Identify the exact type of error and handle the error.
+ * Depending on the error type, the job ring could be reset.
+ * All descs that are submitted for processing on this job ring
+ * are notified to User Application with error status and detailed error code.
+
+ * @param [in] job_ring Job ring
+ * @param [in] sec_error_code Error code read from job ring's Channel
+ * Status Register
+ * @param [out] notified_descs Number of notified descs. Can be NULL if
+ * do_notify is #FALSE
+ * @param [out] do_driver_shutdown If set to #TRUE, then UA is returned code
+ * #SEC_PROCESSING_ERROR
+ * which is indication that UA must call
+ * sec_release() after this.
+ */
+void sec_handle_desc_error(struct sec_job_ring_t *job_ring,
+ uint32_t sec_error_code,
+ uint32_t *notified_descs,
+ uint32_t *do_driver_shutdown);
+
+/*
+ * @brief Release the software and hardware resources tied to a job ring.
+ * @param [in] job_ring The job ring
+ * @retval 0 for success
+ * @retval -1 for error
+ */
+int shutdown_job_ring(struct sec_job_ring_t *job_ring);
+
+/*
+ * @brief Enable irqs on associated job ring.
+ * @param [in] job_ring The job ring
+ * @retval 0 for success
+ * @retval -1 for error
+ */
+int jr_enable_irqs(struct sec_job_ring_t *job_ring);
+
+/*
+ * @brief Disable irqs on associated job ring.
+ * @param [in] job_ring The job ring
+ * @retval 0 for success
+ * @retval -1 for error
+ */
+int jr_disable_irqs(struct sec_job_ring_t *job_ring);
+
+ /*
+ * IRJA - Input Ring Jobs Added Register shows
+ * how many new jobs were added to the Input Ring.
+ */
+static inline void hw_enqueue_desc_on_job_ring(struct jobring_regs *regs,
+ int num)
+{
+ sec_out32(&regs->irja, num);
+}
+
+#endif /* _SEC_HW_SPECIFIC_H_ */
diff --git a/drivers/nxp/crypto/caam/include/sec_jr_driver.h b/drivers/nxp/crypto/caam/include/sec_jr_driver.h
new file mode 100644
index 0000000000..1381eaba90
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/sec_jr_driver.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _JR_DRIVER_H_
+#define _JR_DRIVER_H_
+
+#include "jr_driver_config.h"
+
+/* The maximum size of a SEC descriptor, in WORDs (32 bits). */
+#define MAX_DESC_SIZE_WORDS 64
+
+#define CAAM_TIMEOUT 200000 /* ms */
+
+/* Return codes for JR user space driver APIs */
+typedef enum sec_return_code_e {
+ SEC_SUCCESS = 0,
+ SEC_INVALID_INPUT_PARAM,
+ SEC_OUT_OF_MEMORY,
+ SEC_DESCRIPTOR_IN_FLIGHT,
+ SEC_LAST_DESCRIPTOR_IN_FLIGHT,
+ SEC_PROCESSING_ERROR,
+ SEC_DESC_PROCESSING_ERROR,
+ SEC_JR_IS_FULL,
+ SEC_DRIVER_RELEASE_IN_PROGRESS,
+ SEC_DRIVER_ALREADY_INITIALIZED,
+ SEC_DRIVER_NOT_INITIALIZED,
+ SEC_JOB_RING_RESET_IN_PROGRESS,
+ SEC_RESET_ENGINE_FAILED,
+ SEC_ENABLE_IRQS_FAILED,
+ SEC_DISABLE_IRQS_FAILED,
+ SEC_RETURN_CODE_MAX_VALUE,
+} sec_return_code_t;
+
+/* STRUCTURES AND OTHER TYPEDEFS */
+
+/*
+ * @brief Function called by JR User Space driver to notify every processed
+ * descriptor.
+ *
+ * Callback provided by the User Application.
+ * Callback is invoked by JR User Space driver for each descriptor processed by
+ * SEC
+ * @param [in] status Status word indicating processing result for
+ * this descriptor.
+ * @param [in] arg Opaque data passed by User Application
+ * It is opaque from JR driver's point of view.
+ * @param [in] job_ring The job ring handle on which the processed
+ * descriptor word was enqueued
+ */
+typedef void (*user_callback) (uint32_t *desc, uint32_t status,
+ void *arg, void *job_ring);
+
+/*
+ * Structure encompassing a job descriptor which is to be processed
+ * by SEC. User should also initialise this structure with the callback
+ * function pointer which will be called by driver after recieving proccessed
+ * descriptor from SEC. User data is also passed in this data structure which
+ * will be sent as an argument to the user callback function.
+ */
+struct job_descriptor {
+ uint32_t desc[MAX_DESC_SIZE_WORDS];
+ void *arg;
+ user_callback callback;
+};
+
+/*
+ * @brief Initialize the JR User Space driver.
+ * This function will handle initialization of sec library
+ * along with registering platform specific callbacks,
+ * as well as local data initialization.
+ * Call once during application startup.
+ * @note Global SEC initialization is done in SEC kernel driver.
+ * @note The hardware IDs of the initialized Job Rings are opaque to the UA.
+ * The exact Job Rings used by this library are decided between SEC user
+ * space driver and SEC kernel driver. A static partitioning of Job Rings is
+ * assumed, configured in DTS(device tree specification) file.
+ * @param [in] platform_cb Registering the platform specific
+ * callbacks with driver
+ * @retval ::0 for successful execution
+ * @retval ::-1 failure
+ */
+int sec_jr_lib_init(void);
+
+/*
+ * @brief Initialize the software and hardware resources tied to a job ring.
+ * @param [in] jr_mode; Model to be used by SEC Driver to receive
+ * notifications from SEC. Can be either
+ * SEC_NOTIFICATION_TYPE_IRQ or
+ * SEC_NOTIFICATION_TYPE_POLL
+ * @param [in] irq_coalescing_timer This value determines the maximum
+ * amount of time after processing a
+ * descriptor before raising an interrupt.
+ * @param [in] irq_coalescing_count This value determines how many
+ * descriptors are completed before
+ * raising an interrupt.
+ * @param [in] reg_base_addr The job ring base address register
+ * @param [in] irq_id The job ring interrupt identification number.
+ * @retval job_ring_handle for successful job ring configuration
+ * @retval NULL on error
+ */
+void *init_job_ring(uint8_t jr_mode,
+ uint16_t irq_coalescing_timer,
+ uint8_t irq_coalescing_count,
+ void *reg_base_addr, uint32_t irq_id);
+
+/*
+ * @brief Release the resources used by the JR User Space driver.
+ * Reset and release SEC's job rings indicated by the User Application at
+ * init_job_ring() and free any memory allocated internally.
+ * Call once during application tear down.
+ * @note In case there are any descriptors in-flight (descriptors received by
+ * JR driver for processing and for which no response was yet provided to UA),
+ * the descriptors are discarded without any notifications to User Application.
+ * @retval ::0 is returned for a successful execution
+ * @retval ::-1 is returned if JR driver release is in progress
+ */
+int sec_release(void);
+
+/*
+ * @brief Submit a descriptor for SEC processing.
+ * This function creates a "job" which is meant to instruct SEC HW
+ * to perform the processing on the input buffer. The "job" is enqueued
+ * in the Job Ring associated. The function will return after the "job"
+ * enqueue is finished. The function will not wait for SEC to
+ * start or/and finish the "job" processing.
+ * After the processing is finished the SEC HW writes the processing result
+ * to the provided output buffer.
+ * The Caller must poll JR driver using jr_dequeue()
+ * to receive notifications of the processing completion
+ * status. The notifications are received by caller by means of callback
+ * (see ::user_callback).
+ * @param [in] job_ring_handle The handle of the job ring on which
+ * descriptor is to be enqueued
+ * @param [in] job_descriptor The job descriptor structure of type
+ * struct job_descriptor. This structure
+ * should be filled with job descriptor along
+ * with callback function to be called after
+ * processing of descriptor and some
+ * opaque data passed to be passed to the
+ * callback function
+ *
+ * @retval ::0 is returned for successful execution
+ * @retval ::-1 is returned if there is some enqueue failure
+ */
+int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr);
+
+/*
+ * @brief Polls for available descriptors processed by SEC on a specific
+ * Job Ring
+ * This function polls the SEC Job Rings and delivers processed descriptors
+ * Each processed descriptor has a user_callback registered.
+ * This user_callback is invoked for each processed descriptor.
+ * The polling is stopped when "limit" descriptors are notified or when
+ * there are no more descriptors to notify.
+ * @note The dequeue_jr() API cannot be called from within a user_callback
+ * function
+ * @param [in] job_ring_handle The Job Ring handle.
+ * @param [in] limit This value represents the maximum number
+ * of processed descriptors that can be
+ * notified API call on this Job Ring.
+ * Note that fewer descriptors may be notified
+ * if enough processed descriptors are not
+ * available.
+ * If limit has a negative value, then all
+ * ready descriptors will be notified.
+ *
+ * @retval :: >=0 is returned where retval is the total
+ * Number of descriptors notified
+ * during this function call.
+ * @retval :: -1 is returned in case of some error
+ */
+int dequeue_jr(void *job_ring_handle, int32_t limit);
+
+#endif /* _JR_DRIVER_H_ */
diff --git a/drivers/nxp/crypto/caam/src/auth/auth.mk b/drivers/nxp/crypto/caam/src/auth/auth.mk
new file mode 100644
index 0000000000..d1f8c75564
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/auth/auth.mk
@@ -0,0 +1,12 @@
+#
+# Copyright 2018-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+SEC_DRIVERS_PATH := drivers/nxp/crypto/caam
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+AUTH_SOURCES += $(wildcard $(SEC_DRIVERS_PATH)/src/auth/*.c)
+endif
diff --git a/drivers/nxp/crypto/caam/src/auth/hash.c b/drivers/nxp/crypto/caam/src/auth/hash.c
new file mode 100644
index 0000000000..1665df1a86
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/auth/hash.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+
+#include "hash.h"
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+/* Since no Allocator is available . Taking a global static ctx.
+ * This would mean that only one active ctx can be there at a time.
+ */
+
+static struct hash_ctx glbl_ctx;
+
+static void hash_done(uint32_t *desc, uint32_t status, void *arg,
+ void *job_ring)
+{
+ INFO("Hash Desc SUCCESS with status %x\n", status);
+}
+
+/***************************************************************************
+ * Function : hash_init
+ * Arguments : ctx - SHA context
+ * Return : init,
+ * Description : This function initializes the context for SHA calculation
+ ***************************************************************************/
+int hash_init(enum hash_algo algo, void **ctx)
+{
+ if (glbl_ctx.active == false) {
+ memset(&glbl_ctx, 0, sizeof(struct hash_ctx));
+ glbl_ctx.active = true;
+ glbl_ctx.algo = algo;
+ *ctx = &glbl_ctx;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+/***************************************************************************
+ * Function : hash_update
+ * Arguments : ctx - SHA context
+ * buffer - Data
+ * length - Length
+ * Return : -1 on error
+ * 0 on SUCCESS
+ * Description : This function creates SG entry of the data provided
+ ***************************************************************************/
+int hash_update(enum hash_algo algo, void *context, void *data_ptr,
+ unsigned int data_len)
+{
+ struct hash_ctx *ctx = context;
+ /* MAX_SG would be MAX_SG_ENTRIES + key + hdr + sg table */
+ if (ctx->sg_num >= MAX_SG) {
+ ERROR("Reached limit for calling %s\n", __func__);
+ ctx->active = false;
+ return -EINVAL;
+
+ }
+
+ if (ctx->algo != algo) {
+ ERROR("ctx for algo not correct\n");
+ ctx->active = false;
+ return -EINVAL;
+ }
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ flush_dcache_range((uintptr_t)data_ptr, data_len);
+ dmbsy();
+#endif
+
+#ifdef CONFIG_PHYS_64BIT
+ sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi,
+ (uint32_t) ((uintptr_t) data_ptr >> 32));
+#else
+ sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0);
+#endif
+ sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uintptr_t) data_ptr);
+
+ sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag,
+ (data_len & SG_ENTRY_LENGTH_MASK));
+
+ ctx->sg_num++;
+
+ ctx->len += data_len;
+
+ return 0;
+}
+
+/***************************************************************************
+ * Function : hash_final
+ * Arguments : ctx - SHA context
+ * Return : SUCCESS or FAILURE
+ * Description : This function sets the final bit and enqueues the decriptor
+ ***************************************************************************/
+int hash_final(enum hash_algo algo, void *context, void *hash_ptr,
+ unsigned int hash_len)
+{
+ int ret = 0;
+ struct hash_ctx *ctx = context;
+ uint32_t final = 0U;
+
+ struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE);
+
+ jobdesc.arg = NULL;
+ jobdesc.callback = hash_done;
+
+ if (ctx->algo != algo) {
+ ERROR("ctx for algo not correct\n");
+ ctx->active = false;
+ return -EINVAL;
+ }
+
+ final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) |
+ SG_ENTRY_FINAL_BIT;
+ sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final);
+
+ dsb();
+
+ /* create the hw_rng descriptor */
+ cnstr_hash_jobdesc(jobdesc.desc, (uint8_t *) ctx->sg_tbl,
+ ctx->len, hash_ptr);
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ flush_dcache_range((uintptr_t)ctx->sg_tbl,
+ (sizeof(struct sg_entry) * MAX_SG));
+ inv_dcache_range((uintptr_t)hash_ptr, hash_len);
+
+ dmbsy();
+#endif
+
+ /* Finally, generate the requested random data bytes */
+ ret = run_descriptor_jr(&jobdesc);
+ if (ret != 0) {
+ ERROR("Error in running descriptor\n");
+ ret = -1;
+ }
+ ctx->active = false;
+ return ret;
+}
diff --git a/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c b/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c
new file mode 100644
index 0000000000..646e981f70
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "caam.h"
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+
+#include "hash.h"
+#include "rsa.h"
+
+#define LIB_NAME "NXP crypto"
+
+/*
+ * Initialize the library and export the descriptor
+ */
+static void init(void)
+{
+ /* Initialize NXP crypto library`:*/
+ NOTICE("Initializing & configuring SEC block.\n");
+
+ if (config_sec_block() < 0) {
+ ERROR("Init & config failure for caam.\n");
+ }
+}
+
+/*
+ * Verify a signature.
+ *
+ * For IMG_PLAT - data points to a PKCS#1.5 encoded HASH
+ * sig_alg will be RSA or ECC
+ * Parameters are passed using the DER encoding format following the ASN.1
+ * structures detailed above.
+ */
+static int verify_signature(void *data_ptr, unsigned int data_len,
+ void *sig_ptr, unsigned int sig_len,
+ void *sign_alg, unsigned int sig_alg_len,
+ void *pk_ptr, unsigned int pk_len)
+{
+ int ret = CRYPTO_SUCCESS;
+
+ enum sig_alg alg = *(enum sig_alg *)sign_alg;
+
+ switch (alg) {
+ case RSA:
+ NOTICE("Verifying RSA\n");
+ ret = rsa_verify_signature(data_ptr, data_len, sig_ptr, sig_len,
+ pk_ptr, pk_len);
+ break;
+ case ECC:
+ default:
+ ret = CRYPTO_ERR_SIGNATURE;
+ break;
+ }
+
+ if (ret != 0) {
+ ERROR("RSA verification Failed\n");
+ }
+ return ret;
+
+}
+
+/*
+ * Match a hash
+ *
+ * Digest info is passed as a table of SHA-26 hashes and digest_info_len
+ * is number of entries in the table
+ * This implementation is very specific to the CSF header parser ROTPK
+ * comparison.
+ */
+static int verify_hash(void *data_ptr, unsigned int data_len,
+ void *digest_info_ptr, unsigned int digest_info_len)
+{
+ void *ctx = NULL;
+ int i = 0, ret = 0;
+ enum hash_algo algo = SHA256;
+ uint8_t hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE) = {0};
+ uint32_t digest_size = SHA256_BYTES;
+ uint8_t *hash_tbl = digest_info_ptr;
+
+ NOTICE("Verifying hash\n");
+ ret = hash_init(algo, &ctx);
+ if (ret != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ /* Update hash with that of SRK table */
+ ret = hash_update(algo, ctx, data_ptr, data_len);
+ if (ret != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ /* Copy hash at destination buffer */
+ ret = hash_final(algo, ctx, hash, digest_size);
+ if (ret != 0) {
+ return CRYPTO_ERR_HASH;
+ }
+
+ VERBOSE("%s Calculated hash\n", __func__);
+ for (i = 0; i < SHA256_BYTES/4; i++) {
+ VERBOSE("%x\n", *((uint32_t *)hash + i));
+ }
+
+ for (i = 0; i < digest_info_len; i++) {
+ if (memcmp(hash, (hash_tbl + (i * digest_size)),
+ digest_size) == 0) {
+ return CRYPTO_SUCCESS;
+ }
+ }
+
+ return CRYPTO_ERR_HASH;
+}
+
+/*
+ * Register crypto library descriptor
+ */
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
diff --git a/drivers/nxp/crypto/caam/src/auth/rsa.c b/drivers/nxp/crypto/caam/src/auth/rsa.c
new file mode 100644
index 0000000000..0c4446238d
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/auth/rsa.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+
+#include "jobdesc.h"
+#include "rsa.h"
+#include "sec_hw_specific.h"
+
+/* This array contains DER value for SHA-256 */
+static const uint8_t hash_identifier[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
+ 0x04, 0x20
+};
+
+static void rsa_done(uint32_t *desc, uint32_t status, void *arg,
+ void *job_ring)
+{
+ INFO("RSA Desc SUCCESS with status %x\n", status);
+}
+
+static int rsa_public_verif_sec(uint8_t *sign, uint8_t *to,
+ uint8_t *rsa_pub_key, uint32_t klen)
+{
+ int ret = 0;
+ struct rsa_context ctx __aligned(CACHE_WRITEBACK_GRANULE);
+ struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE);
+
+ jobdesc.arg = NULL;
+ jobdesc.callback = rsa_done;
+
+ memset(&ctx, 0, sizeof(struct rsa_context));
+
+ ctx.pkin.a = sign;
+ ctx.pkin.a_siz = klen;
+ ctx.pkin.n = rsa_pub_key;
+ ctx.pkin.n_siz = klen;
+ ctx.pkin.e = rsa_pub_key + klen;
+ ctx.pkin.e_siz = klen;
+
+ cnstr_jobdesc_pkha_rsaexp(jobdesc.desc, &ctx.pkin, to, klen);
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ flush_dcache_range((uintptr_t)sign, klen);
+ flush_dcache_range((uintptr_t)rsa_pub_key, 2 * klen);
+ flush_dcache_range((uintptr_t)&ctx.pkin, sizeof(ctx.pkin));
+ inv_dcache_range((uintptr_t)to, klen);
+
+ dmbsy();
+ dsbsy();
+ isb();
+#endif
+
+ /* Finally, generate the requested random data bytes */
+ ret = run_descriptor_jr(&jobdesc);
+ if (ret != 0) {
+ ERROR("Error in running descriptor\n");
+ ret = -1;
+ }
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ inv_dcache_range((uintptr_t)to, klen);
+ dmbsy();
+ dsbsy();
+ isb();
+#endif
+ return ret;
+}
+
+/*
+ * Construct encoded hash EM' wrt PKCSv1.5. This function calculates the
+ * pointers for padding, DER value and hash. And finally, constructs EM'
+ * which includes hash of complete CSF header and ESBC image. If SG flag
+ * is on, hash of SG table and entries is also included.
+ */
+static int construct_img_encoded_hash_second(uint8_t *hash, uint8_t hash_len,
+ uint8_t *encoded_hash_second,
+ unsigned int key_len)
+{
+ /*
+ * RSA PKCSv1.5 encoding format for encoded message is below
+ * EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash
+ * PS is Padding String
+ * DER is DER value for SHA-256
+ * Hash is SHA-256 hash
+ * *********************************************************
+ * representative points to first byte of EM initially and is
+ * filled with 0x0
+ * representative is incremented by 1 and second byte is filled
+ * with 0x1
+ * padding points to third byte of EM
+ * digest points to full length of EM - 32 bytes
+ * hash_id (DER value) points to 19 bytes before pDigest
+ * separator is one byte which separates padding and DER
+ */
+
+ unsigned int len;
+ uint8_t *representative;
+ uint8_t *padding, *digest;
+ uint8_t *hash_id, *separator;
+ int i;
+ int ret = 0;
+
+ if (hash_len != SHA256_BYTES) {
+ return -1;
+ }
+
+ /* Key length = Modulus length */
+ len = (key_len / 2U) - 1U;
+ representative = encoded_hash_second;
+ representative[0] = 0U;
+ representative[1] = 1U; /* block type 1 */
+
+ padding = &representative[2];
+ digest = &representative[1] + len - 32;
+ hash_id = digest - sizeof(hash_identifier);
+ separator = hash_id - 1;
+
+ /* fill padding area pointed by padding with 0xff */
+ memset(padding, 0xff, separator - padding);
+
+ /* fill byte pointed by separator */
+ *separator = 0U;
+
+ /* fill SHA-256 DER value pointed by HashId */
+ memcpy(hash_id, hash_identifier, sizeof(hash_identifier));
+
+ /* fill hash pointed by Digest */
+ for (i = 0; i < SHA256_BYTES; i++) {
+ digest[i] = hash[i];
+ }
+
+ return ret;
+}
+
+int rsa_verify_signature(void *hash_ptr, unsigned int hash_len,
+ void *sig_ptr, unsigned int sig_len,
+ void *pk_ptr, unsigned int pk_len)
+{
+ uint8_t img_encoded_hash_second[RSA_4K_KEY_SZ_BYTES];
+ uint8_t encoded_hash[RSA_4K_KEY_SZ_BYTES] __aligned(CACHE_WRITEBACK_GRANULE);
+ int ret = 0;
+
+ ret = construct_img_encoded_hash_second(hash_ptr, hash_len,
+ img_encoded_hash_second,
+ pk_len);
+ if (ret != 0) {
+ ERROR("Encoded Hash Failure\n");
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ ret = rsa_public_verif_sec(sig_ptr, encoded_hash, pk_ptr, pk_len / 2);
+ if (ret != 0) {
+ ERROR("RSA signature Failure\n");
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ ret = memcmp(img_encoded_hash_second, encoded_hash, sig_len);
+ if (ret != 0) {
+ ERROR("Comparison Failure\n");
+ return CRYPTO_ERR_SIGNATURE;
+ }
+
+ return CRYPTO_SUCCESS;
+}
diff --git a/drivers/nxp/crypto/caam/src/caam.c b/drivers/nxp/crypto/caam/src/caam.c
new file mode 100644
index 0000000000..e594f7bb9c
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/caam.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+static uintptr_t g_nxp_caam_addr;
+static void *job_ring;
+
+uintptr_t get_caam_addr(void)
+{
+ if (g_nxp_caam_addr == 0) {
+ ERROR("Sec Init is not done.\n");
+ panic();
+ }
+ return g_nxp_caam_addr;
+}
+
+/* This function sets the TZ bit for the Job ring number passed as @num */
+static void config_tz(int num)
+{
+ uint32_t jricid;
+
+ /* Setting TZ bit of job ring */
+ switch (num) {
+ case 0:
+ jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET);
+ sec_out32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET,
+ jricid | JRICID_MS_TZ);
+ break;
+ case 1:
+ jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET);
+ sec_out32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET,
+ jricid | JRICID_MS_TZ);
+ break;
+ case 2:
+ jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET);
+ sec_out32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET,
+ jricid | JRICID_MS_TZ);
+ break;
+ case 3:
+ jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET);
+ sec_out32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET,
+ jricid | JRICID_MS_TZ);
+ break;
+ default:
+ break;
+ }
+}
+
+/* This function checks if Virtualization is enabled for JR and
+ * accordingly sets the bot for starting JR<num> in JRSTARTR register
+ */
+static inline void start_jr(int num)
+{
+ uint32_t ctpr = sec_in32((g_nxp_caam_addr + SEC_REG_CTPR_MS_OFFSET));
+ uint32_t tmp = sec_in32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET));
+ uint32_t scfgr = sec_in32((g_nxp_caam_addr + SEC_REG_SCFGR_OFFSET));
+ bool start = false;
+
+ if ((ctpr & CTPR_VIRT_EN_INC) != 0U) {
+ if (((ctpr & CTPR_VIRT_EN_POR) != 0U) ||
+ ((scfgr & SCFGR_VIRT_EN) != 0U)) {
+ start = true;
+ }
+ } else {
+ if ((ctpr & CTPR_VIRT_EN_POR) != 0U) {
+ start = true;
+ }
+ }
+
+ if (start == true) {
+ switch (num) {
+ case 0:
+ tmp |= JRSTARTR_STARTJR0;
+ break;
+ case 1:
+ tmp |= JRSTARTR_STARTJR1;
+ break;
+ case 2:
+ tmp |= JRSTARTR_STARTJR2;
+ break;
+ case 3:
+ tmp |= JRSTARTR_STARTJR3;
+ break;
+ default:
+ break;
+ }
+ }
+ sec_out32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET), tmp);
+}
+
+/* This functions configures the Job Ring
+ * JR3 is reserved for use by Secure world
+ */
+static int configure_jr(int num)
+{
+ int ret;
+ void *reg_base_addr;
+
+ switch (num) {
+ case 0:
+ reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR0_OFFSET);
+ break;
+ case 1:
+ reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR1_OFFSET);
+ break;
+ case 2:
+ reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR2_OFFSET);
+ break;
+ case 3:
+ reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR3_OFFSET);
+ break;
+ default:
+ break;
+ }
+
+ /* Initialize the JR library */
+ ret = sec_jr_lib_init();
+ if (ret != 0) {
+ ERROR("Error in sec_jr_lib_init");
+ return -1;
+ }
+
+ start_jr(num);
+
+ /* Do HW configuration of the JR */
+ job_ring = init_job_ring(SEC_NOTIFICATION_TYPE_POLL, 0, 0,
+ reg_base_addr, 0);
+
+ if (job_ring == NULL) {
+ ERROR("Error in init_job_ring");
+ return -1;
+ }
+
+ return ret;
+}
+
+/* TBD - Configures and locks the ICID values for various JR */
+static inline void configure_icid(void)
+{
+}
+
+/* TBD configures the TZ settings of RTIC */
+static inline void configure_rtic(void)
+{
+}
+
+int sec_init(uintptr_t nxp_caam_addr)
+{
+ g_nxp_caam_addr = nxp_caam_addr;
+ return config_sec_block();
+}
+
+/* This function configure SEC block:
+ * - It does basic parameter setting
+ * - Configures the default Job ring assigned to TZ /secure world
+ * - Instantiates the RNG
+ */
+int config_sec_block(void)
+{
+ int ret = 0;
+ uint32_t mcfgr;
+
+ if (g_nxp_caam_addr == 0) {
+ ERROR("Sec Init is not done.\n");
+ return -1;
+ } else if (job_ring != NULL) {
+ NOTICE("Sec is already initialized and configured.\n");
+ return ret;
+ }
+
+ mcfgr = sec_in32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET);
+
+ /* Modify CAAM Read/Write attributes
+ * AXI Write - Cacheable, WB and WA
+ * AXI Read - Cacheable, RA
+ */
+#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS2088A)
+ mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0xb << MCFGR_AWCACHE_SHIFT);
+ mcfgr = (mcfgr & ~MCFGR_ARCACHE_MASK) | (0x6 << MCFGR_ARCACHE_SHIFT);
+#else
+ mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0x2 << MCFGR_AWCACHE_SHIFT);
+#endif
+
+ /* Set PS bit to 1 */
+#ifdef CONFIG_PHYS_64BIT
+ mcfgr |= (1 << MCFGR_PS_SHIFT);
+#endif
+ sec_out32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET, mcfgr);
+
+ /* Asssign ICID to all Job rings and lock them for usage */
+ configure_icid();
+
+ /* Configure the RTIC */
+ configure_rtic();
+
+ /* Configure the default JR for usage */
+ ret = configure_jr(DEFAULT_JR);
+ if (ret != 0) {
+ ERROR("\nFSL_JR: configuration failure\n");
+ return -1;
+ }
+ /* Do TZ configuration of default JR for sec firmware */
+ config_tz(DEFAULT_JR);
+
+#ifdef CONFIG_RNG_INIT
+ /* Instantiate the RNG */
+ ret = hw_rng_instantiate();
+ if (ret != 0) {
+ ERROR("\nRNG Instantiation failure\n");
+ return -1;
+ }
+#endif
+
+ return ret;
+}
+
+/* This function is used for sumbitting job to the Job Ring
+ * [param] [in] - jobdesc to be submitted
+ * Return - -1 in case of error and 0 in case of SUCCESS
+ */
+int run_descriptor_jr(struct job_descriptor *jobdesc)
+{
+ int i = 0, ret = 0;
+ uint32_t *desc_addr = jobdesc->desc;
+ uint32_t desc_len = desc_length(jobdesc->desc);
+ uint32_t desc_word;
+
+ for (i = 0; i < desc_len; i++) {
+ desc_word = desc_addr[i];
+ VERBOSE("%x\n", desc_word);
+ sec_out32((uint32_t *)&desc_addr[i], desc_word);
+ }
+ dsb();
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ flush_dcache_range((uintptr_t)desc_addr, desc_len * 4);
+ dmbsy();
+ dsbsy();
+ isb();
+#endif
+
+ ret = enq_jr_desc(job_ring, jobdesc);
+ if (ret == 0) {
+ VERBOSE("JR enqueue done...\n");
+ } else {
+ ERROR("Error in Enqueue\n");
+ return ret;
+ }
+
+ VERBOSE("Dequeue in progress");
+
+ ret = dequeue_jr(job_ring, -1);
+ if (ret >= 0) {
+ VERBOSE("Dequeue of %x desc success\n", ret);
+ ret = 0;
+ } else {
+ ERROR("deq_ret %x\n", ret);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+/* this function returns a random number using HW RNG Algo
+ * In case of failure, random number returned is 0
+ * prngWidth = 0 - 32 bit random number
+ * prngWidth > 0 means 64 bit random number
+ */
+unsigned long long get_random(int rngWidth)
+{
+ unsigned long long result = 0;
+ uint8_t rand_byte[64] __aligned(CACHE_WRITEBACK_GRANULE);
+ uint8_t rand_byte_swp[8];
+ int bytes = 0;
+ int i = 0;
+ int ret = 0;
+
+#ifdef CAAM_TEST
+ rand_byte[0] = U(0x12);
+ rand_byte[1] = U(0x34);
+ rand_byte[2] = U(0x56);
+ rand_byte[3] = U(0x78);
+ rand_byte[4] = U(0x9a);
+ rand_byte[5] = U(0xbc);
+ rand_byte[6] = U(0xde);
+ rand_byte[7] = U(0xf1);
+#endif
+
+ if (rngWidth == 0U) {
+ bytes = 4;
+ } else {
+ bytes = 8;
+ }
+
+ memset(rand_byte, 0, 64);
+
+ ret = get_rand_bytes_hw(rand_byte, bytes);
+
+ for (i = 0; i < bytes; i++) {
+ if (ret != 0) {
+ /* Return 0 in case of failure */
+ rand_byte_swp[i] = 0;
+ } else {
+ rand_byte_swp[i] = rand_byte[bytes - i - 1];
+ result = (result << 8) | rand_byte_swp[i];
+ }
+ }
+
+ INFO("result %llx\n", result);
+
+ return result;
+
+} /* _get_RNG() */
+
+unsigned int _get_hw_unq_key(uint64_t hw_key_phy_addr, unsigned int size)
+{
+ int ret = 0;
+ uint8_t *hw_key = (uint8_t *) ptov((phys_addr_t *) hw_key_phy_addr);
+
+ ret = get_hw_unq_key_blob_hw(hw_key, size);
+
+ return ret;
+}
diff --git a/drivers/nxp/crypto/caam/src/hw_key_blob.c b/drivers/nxp/crypto/caam/src/hw_key_blob.c
new file mode 100644
index 0000000000..0720695d3d
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/hw_key_blob.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+
+/* Callback function after Instantiation decsriptor is submitted to SEC
+ */
+static void blob_done(uint32_t *desc, uint32_t status, void *arg,
+ void *job_ring)
+{
+ INFO("Blob Desc SUCCESS with status %x\n", status);
+}
+
+/* @brief Submit descriptor to create blob
+ * @retval 0 on success
+ * @retval -1 on error
+ */
+int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size)
+{
+ int ret = 0;
+ int i = 0;
+
+ uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
+ uint8_t key_data[KEY_IDNFR_SZ_BYTES];
+ uint8_t in_data[16];
+ uint8_t out_data[16 + KEY_BLOB_SIZE + MAC_SIZE];
+ struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
+ struct job_descriptor *jobdesc = &desc;
+ uint32_t in_sz = 16U;
+
+ /* Output blob will have 32 bytes key blob in beginning and
+ * 16 byte HMAC identifier at end of data blob
+ */
+ uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE;
+
+ uint32_t operation = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL |
+ OP_PCLID_BLOB | BLOB_PROTO_INFO;
+
+ memset(key_data, 0xff, KEY_IDNFR_SZ_BYTES);
+ memset(in_data, 0x00, in_sz);
+ memset(out_data, 0x00, in_sz);
+
+ jobdesc->arg = NULL;
+ jobdesc->callback = blob_done;
+
+ INFO("\nGenerating Master Key Verification Blob.\n");
+
+ /* Create the hw_rng descriptor */
+ ret = cnstr_hw_encap_blob_jobdesc(jobdesc->desc, key_data, key_sz,
+ CLASS_2, in_data, in_sz, out_data,
+ out_sz, operation);
+
+ /* Finally, generate the blob. */
+ ret = run_descriptor_jr(jobdesc);
+ if (ret != 0) {
+ ERROR("Error in running hw unq key blob descriptor\n");
+ return -1;
+ }
+ /* Copying alternate bytes of the Master Key Verification Blob.
+ */
+ for (i = 0; i < size; i++) {
+ hw_key[i] = out_data[2 * i];
+ }
+
+ return ret;
+}
diff --git a/drivers/nxp/crypto/caam/src/jobdesc.c b/drivers/nxp/crypto/caam/src/jobdesc.c
new file mode 100644
index 0000000000..9c235af2e3
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/jobdesc.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "rsa.h"
+#include "sec_hw_specific.h"
+
+
+/* Return Length of desctiptr from first word */
+uint32_t desc_length(uint32_t *desc)
+{
+ return desc[0] & DESC_LEN_MASK;
+}
+
+/*Update start index in first word of descriptor */
+void desc_update_start_index(uint32_t *desc, uint32_t index)
+{
+ desc[0] |= (index << DESC_START_SHIFT);
+}
+
+/* Initialize the descriptor */
+void desc_init(uint32_t *desc)
+{
+ *desc = 0;
+}
+
+/* Add word in the descriptor and increment the length */
+void desc_add_word(uint32_t *desc, uint32_t word)
+{
+ uint32_t len = desc_length(desc);
+
+ /* Add Word at Last */
+ uint32_t *last = desc + len;
+ *last = word;
+
+ /* Increase the length */
+ desc[0] += 1;
+}
+
+/* Add Pointer to the descriptor */
+void desc_add_ptr(uint32_t *desc, phys_addr_t *ptr)
+{
+ uint32_t len = desc_length(desc);
+
+ /* Add Word at Last */
+ phys_addr_t *last = (phys_addr_t *) (desc + len);
+
+#ifdef CONFIG_PHYS_64BIT
+ ptr_addr_t *ptr_addr = (ptr_addr_t *) last;
+
+ ptr_addr->m_halves.high = PHYS_ADDR_HI(ptr);
+ ptr_addr->m_halves.low = PHYS_ADDR_LO(ptr);
+#else
+ *last = ptr;
+#endif
+
+ /* Increase the length */
+ desc[0] += (uint32_t) (sizeof(phys_addr_t) / sizeof(uint32_t));
+}
+
+/* Descriptor to generate Random words */
+int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle,
+ uint32_t *add_inp, uint32_t add_ip_len,
+ uint8_t *out_data, uint32_t len)
+{
+ phys_addr_t *phys_addr_out = vtop(out_data);
+
+ /* Current descriptor support only 64K length */
+ if (len > U(0xffff))
+ return -1;
+ /* Additional Input not supported by current descriptor */
+ if (add_ip_len > 0U)
+ return -1;
+
+ VERBOSE("Constructing descriptor\n");
+ desc_init(desc);
+ /* Class1 Alg Operation,RNG Optype, Generate */
+ desc_add_word(desc, U(0xb0800000));
+ desc_add_word(desc, U(0x82500000) | (state_handle << ALG_AAI_SH_SHIFT));
+ desc_add_word(desc, U(0x60340000) | len);
+ desc_add_ptr(desc, phys_addr_out);
+
+ return 0;
+
+}
+
+/* Construct descriptor to instantiate RNG */
+int cnstr_rng_instantiate_jobdesc(uint32_t *desc)
+{
+ desc_init(desc);
+ desc_add_word(desc, U(0xb0800000));
+ /* Class1 Alg Operation,RNG Optype, Instantiate */
+ desc_add_word(desc, U(0x82500004));
+ /* Wait for done */
+ desc_add_word(desc, U(0xa2000001));
+ /*Load to clear written */
+ desc_add_word(desc, U(0x10880004));
+ /*Pri Mode Reg clear */
+ desc_add_word(desc, U(0x00000001));
+ /* Generate secure keys */
+ desc_add_word(desc, U(0x82501000));
+
+ return 0;
+}
+
+/* Construct descriptor to generate hw key blob */
+int cnstr_hw_encap_blob_jobdesc(uint32_t *desc,
+ uint8_t *key_idnfr, uint32_t key_sz,
+ uint32_t key_class, uint8_t *plain_txt,
+ uint32_t in_sz, uint8_t *enc_blob,
+ uint32_t out_sz, uint32_t operation)
+{
+ phys_addr_t *phys_key_idnfr, *phys_addr_in, *phys_addr_out;
+ int i = 0;
+
+ phys_key_idnfr = vtop((void *)key_idnfr);
+ phys_addr_in = vtop((void *)plain_txt);
+ phys_addr_out = vtop((void *)enc_blob);
+
+ desc_init(desc);
+
+ desc_add_word(desc, U(0xb0800000));
+
+ /* Key Identifier */
+ desc_add_word(desc, (key_class | key_sz));
+ desc_add_ptr(desc, phys_key_idnfr);
+
+ /* Source Address */
+ desc_add_word(desc, U(0xf0400000));
+ desc_add_ptr(desc, phys_addr_in);
+
+ /* In Size = 0x10 */
+ desc_add_word(desc, in_sz);
+
+ /* Out Address */
+ desc_add_word(desc, U(0xf8400000));
+ desc_add_ptr(desc, phys_addr_out);
+
+ /* Out Size = 0x10 */
+ desc_add_word(desc, out_sz);
+
+ /* Operation */
+ desc_add_word(desc, operation);
+
+ for (i = 0; i < 15; i++)
+ VERBOSE("desc word %x\n", desc[i]);
+
+ return 0;
+}
+
+/***************************************************************************
+ * Function : inline_cnstr_jobdesc_pkha_rsaexp
+ * Arguments : desc - Pointer to Descriptor
+ * pkin - Pointer to Input Params
+ * out - Pointer to Output
+ * out_siz - Output Size
+ * Return : Void
+ * Description : Creates the descriptor for PKHA RSA
+ ***************************************************************************/
+void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
+ struct pk_in_params *pkin, uint8_t *out,
+ uint32_t out_siz)
+{
+ phys_addr_t *ptr_addr_e, *ptr_addr_a, *ptr_addr_n, *ptr_addr_out;
+
+ ptr_addr_e = vtop((void *)(pkin->e));
+ ptr_addr_a = vtop((void *)(pkin->a));
+ ptr_addr_n = vtop((void *)(pkin->n));
+ ptr_addr_out = vtop((void *)(out));
+
+ desc_init(desc);
+ desc_add_word(desc, U(0xb0800000));
+ desc_add_word(desc, U(0x02010000) | pkin->e_siz);
+ desc_add_ptr(desc, ptr_addr_e);
+ desc_add_word(desc, U(0x220c0000) | pkin->a_siz);
+ desc_add_ptr(desc, ptr_addr_a);
+ desc_add_word(desc, U(0x22080000) | pkin->n_siz);
+ desc_add_ptr(desc, ptr_addr_n);
+ desc_add_word(desc, U(0x81800006));
+ desc_add_word(desc, U(0x620d0000) | out_siz);
+ desc_add_ptr(desc, ptr_addr_out);
+}
+
+/***************************************************************************
+ * Function : inline_cnstr_jobdesc_sha256
+ * Arguments : desc - Pointer to Descriptor
+ * msg - Pointer to SG Table
+ * msgsz - Size of SG Table
+ * digest - Pointer to Output Digest
+ * Return : Void
+ * Description : Creates the descriptor for SHA256 HASH calculation
+ ***************************************************************************/
+void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz,
+ uint8_t *digest)
+{
+ /* SHA 256 , output is of length 32 words */
+ phys_addr_t *ptr_addr_in, *ptr_addr_out;
+
+ ptr_addr_in = (void *)vtop(msg);
+ ptr_addr_out = (void *)vtop(digest);
+
+ desc_init(desc);
+ desc_add_word(desc, U(0xb0800000));
+
+ /* Operation Command
+ * OP_TYPE_CLASS2_ALG | OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HASH |
+ * OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT | OP_ALG_ICV_OFF)
+ */
+ desc_add_word(desc, U(0x8443000d));
+
+ if (msgsz > U(0xffff)) {
+ desc_add_word(desc, U(0x25540000)); /* FIFO Load */
+ desc_add_ptr(desc, ptr_addr_in); /* Pointer to msg */
+ desc_add_word(desc, msgsz); /* Size */
+ desc_add_word(desc, U(0x54200020)); /* FIFO Store */
+ desc_add_ptr(desc, ptr_addr_out); /* Pointer to Result */
+ } else {
+ desc_add_word(desc, U(0x25140000) | msgsz);
+ desc_add_ptr(desc, ptr_addr_in);
+ desc_add_word(desc, U(0x54200020));
+ desc_add_ptr(desc, ptr_addr_out);
+ }
+
+}
diff --git a/drivers/nxp/crypto/caam/src/rng.c b/drivers/nxp/crypto/caam/src/rng.c
new file mode 100644
index 0000000000..0b9d87de41
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/rng.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+
+/* Callback function after Instantiation decsriptor is submitted to SEC */
+static void rng_done(uint32_t *desc, uint32_t status, void *arg,
+ void *job_ring)
+{
+ INFO("RNG Desc SUCCESS with status %x\n", status);
+}
+
+/* Is the HW RNG instantiated?
+ * Return code:
+ * 0 - Not in the instantiated state
+ * 1 - In the instantiated state
+ * state_handle - 0 for SH0, 1 for SH1
+ */
+static int is_hw_rng_instantiated(uint32_t *state_handle)
+{
+ int ret_code = 0;
+ uint32_t rdsta;
+
+ rdsta = sec_in32(get_caam_addr() + RNG_REG_RDSTA_OFFSET);
+
+ /*Check if either of the two state handles has been instantiated */
+ if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
+ *state_handle = 0;
+ ret_code = 1;
+ } else if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
+ *state_handle = 1;
+ ret_code = 1;
+ }
+
+ return ret_code;
+}
+
+/* @brief Kick the TRNG block of the RNG HW Engine
+ * @param [in] ent_delay Entropy delay to be used
+ * By default, the TRNG runs for 200 clocks per sample;
+ * 1200 clocks per sample generates better entropy.
+ * @retval 0 on success
+ * @retval -1 on error
+ */
+static void kick_trng(int ent_delay)
+{
+ uint32_t val;
+
+ /* put RNG4 into program mode */
+ val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
+ val = val | RTMCTL_PRGM;
+ sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);
+
+ /* rtsdctl bits 0-15 contain "Entropy Delay, which defines the
+ * length (in system clocks) of each Entropy sample taken
+ */
+ val = sec_in32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET);
+ val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+ (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
+ sec_out32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET, val);
+ /* min. freq. count, equal to 1/4 of the entropy sample length */
+ sec_out32(get_caam_addr() + RNG_REG_RTFRQMIN_OFFSET, ent_delay >> 2);
+ /* disable maximum frequency count */
+ sec_out32(get_caam_addr() + RNG_REG_RTFRQMAX_OFFSET, RTFRQMAX_DISABLE);
+
+ /* select raw sampling in both entropy shifter
+ * and statistical checker
+ */
+ val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
+ val = val | RTMCTL_SAMP_MODE_RAW_ES_SC;
+ sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);
+
+ /* put RNG4 into run mode */
+ val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
+ val = val & ~RTMCTL_PRGM;
+ sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);
+}
+
+/* @brief Submit descriptor to instantiate the RNG
+ * @retval 0 on success
+ * @retval -1 on error
+ */
+static int instantiate_rng(void)
+{
+ int ret = 0;
+ struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
+ struct job_descriptor *jobdesc = &desc;
+
+ jobdesc->arg = NULL;
+ jobdesc->callback = rng_done;
+
+ /* create the hw_rng descriptor */
+ cnstr_rng_instantiate_jobdesc(jobdesc->desc);
+
+ /* Finally, generate the requested random data bytes */
+ ret = run_descriptor_jr(jobdesc);
+ if (ret != 0) {
+ ERROR("Error in running descriptor\n");
+ ret = -1;
+ }
+ return ret;
+}
+
+/* Generate Random Data using HW RNG
+ * Parameters:
+ * uint8_t* add_input - user specified optional input byte array
+ * uint32_t add_input_len - number of bytes of additional input
+ * uint8_t* out - user specified output byte array
+ * uint32_t out_len - number of bytes to store in output byte array
+ * Return code:
+ * 0 - SUCCESS
+ * -1 - ERROR
+ */
+static int
+hw_rng_generate(uint32_t *add_input, uint32_t add_input_len,
+ uint8_t *out, uint32_t out_len, uint32_t state_handle)
+{
+ int ret = 0;
+ struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
+ struct job_descriptor *jobdesc = &desc;
+
+ jobdesc->arg = NULL;
+ jobdesc->callback = rng_done;
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ inv_dcache_range((uintptr_t)out, out_len);
+ dmbsy();
+#endif
+
+ /* create the hw_rng descriptor */
+ ret = cnstr_rng_jobdesc(jobdesc->desc, state_handle,
+ add_input, add_input_len, out, out_len);
+ if (ret != 0) {
+ ERROR("Descriptor construction failed\n");
+ ret = -1;
+ goto out;
+ }
+ /* Finally, generate the requested random data bytes */
+ ret = run_descriptor_jr(jobdesc);
+ if (ret != 0) {
+ ERROR("Error in running descriptor\n");
+ ret = -1;
+ }
+
+out:
+ return ret;
+}
+
+/* this function instantiates the rng
+ *
+ * Return code:
+ * 0 - All is well
+ * <0 - Error occurred somewhere
+ */
+int hw_rng_instantiate(void)
+{
+ int ret = 0;
+ int ent_delay = RTSDCTL_ENT_DLY_MIN;
+ uint32_t state_handle;
+
+ ret = is_hw_rng_instantiated(&state_handle);
+ if (ret != 0) {
+ NOTICE("RNG already instantiated\n");
+ return 0;
+ }
+ do {
+ kick_trng(ent_delay);
+ ent_delay += 400;
+ /*if instantiate_rng(...) fails, the loop will rerun
+ *and the kick_trng(...) function will modify the
+ *upper and lower limits of the entropy sampling
+ *interval, leading to a sucessful initialization of
+ */
+ ret = instantiate_rng();
+ } while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+ if (ret != 0) {
+ ERROR("RNG: Failed to instantiate RNG\n");
+ return ret;
+ }
+
+ NOTICE("RNG: INSTANTIATED\n");
+
+ /* Enable RDB bit so that RNG works faster */
+ // sec_setbits32(&sec->scfgr, SEC_SCFGR_RDBENABLE);
+
+ return ret;
+}
+
+/* Generate random bytes, and stuff them into the bytes buffer
+ *
+ * If the HW RNG has not already been instantiated,
+ * it will be instantiated before data is generated.
+ *
+ * Parameters:
+ * uint8_t* bytes - byte buffer large enough to hold the requested random date
+ * int byte_len - number of random bytes to generate
+ *
+ * Return code:
+ * 0 - All is well
+ * ~0 - Error occurred somewhere
+ */
+int get_rand_bytes_hw(uint8_t *bytes, int byte_len)
+{
+ int ret_code = 0;
+ uint32_t state_handle;
+
+ /* If this is the first time this routine is called,
+ * then the hash_drbg will not already be instantiated.
+ * Therefore, before generating data, instantiate the hash_drbg
+ */
+ ret_code = is_hw_rng_instantiated(&state_handle);
+ if (ret_code == 0) {
+ INFO("Instantiating the HW RNG\n");
+
+ /* Instantiate the hw RNG */
+ ret_code = hw_rng_instantiate();
+ if (ret_code != 0) {
+ ERROR("HW RNG Instantiate failed\n");
+ return ret_code;
+ }
+ }
+ /* If HW RNG is still not instantiated, something must have gone wrong,
+ * it must be in the error state, we will not generate any random data
+ */
+ if (is_hw_rng_instantiated(&state_handle) == 0) {
+ ERROR("HW RNG is in an Error state, and cannot be used\n");
+ return -1;
+ }
+ /* Generate a random 256-bit value, as 32 bytes */
+ ret_code = hw_rng_generate(0, 0, bytes, byte_len, state_handle);
+ if (ret_code != 0) {
+ ERROR("HW RNG Generate failed\n");
+ return ret_code;
+ }
+
+ return ret_code;
+}
diff --git a/drivers/nxp/crypto/caam/src/sec_hw_specific.c b/drivers/nxp/crypto/caam/src/sec_hw_specific.c
new file mode 100644
index 0000000000..92b7762420
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/sec_hw_specific.c
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+
+/* Job rings used for communication with SEC HW */
+extern struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS];
+
+/* The current state of SEC user space driver */
+extern volatile sec_driver_state_t g_driver_state;
+
+/* The number of job rings used by SEC user space driver */
+extern int g_job_rings_no;
+
+/* LOCAL FUNCTIONS */
+static inline void hw_set_input_ring_start_addr(struct jobring_regs *regs,
+ phys_addr_t *start_addr)
+{
+#if defined(CONFIG_PHYS_64BIT)
+ sec_out32(&regs->irba_h, PHYS_ADDR_HI(start_addr));
+#else
+ sec_out32(&regs->irba_h, 0);
+#endif
+ sec_out32(&regs->irba_l, PHYS_ADDR_LO(start_addr));
+}
+
+static inline void hw_set_output_ring_start_addr(struct jobring_regs *regs,
+ phys_addr_t *start_addr)
+{
+#if defined(CONFIG_PHYS_64BIT)
+ sec_out32(&regs->orba_h, PHYS_ADDR_HI(start_addr));
+#else
+ sec_out32(&regs->orba_h, 0);
+#endif
+ sec_out32(&regs->orba_l, PHYS_ADDR_LO(start_addr));
+}
+
+/* ORJR - Output Ring Jobs Removed Register shows how many jobs were
+ * removed from the Output Ring for processing by software. This is done after
+ * the software has processed the entries.
+ */
+static inline void hw_remove_entries(sec_job_ring_t *jr, int num)
+{
+ struct jobring_regs *regs =
+ (struct jobring_regs *)jr->register_base_addr;
+
+ sec_out32(&regs->orjr, num);
+}
+
+/* IRSA - Input Ring Slots Available register holds the number of entries in
+ * the Job Ring's input ring. Once a job is enqueued, the value returned is
+ * decremented by the hardware by the number of jobs enqueued.
+ */
+static inline int hw_get_available_slots(sec_job_ring_t *jr)
+{
+ struct jobring_regs *regs =
+ (struct jobring_regs *)jr->register_base_addr;
+
+ return sec_in32(&regs->irsa);
+}
+
+/* ORSFR - Output Ring Slots Full register holds the number of jobs which were
+ * processed by the SEC and can be retrieved by the software. Once a job has
+ * been processed by software, the user will call hw_remove_one_entry in order
+ * to notify the SEC that the entry was processed
+ */
+static inline int hw_get_no_finished_jobs(sec_job_ring_t *jr)
+{
+ struct jobring_regs *regs =
+ (struct jobring_regs *)jr->register_base_addr;
+
+ return sec_in32(&regs->orsf);
+}
+
+/* @brief Process Jump Halt Condition related errors
+ * @param [in] error_code The error code in the descriptor status word
+ */
+static inline void hw_handle_jmp_halt_cond_err(union hw_error_code error_code)
+{
+ ERROR("JMP %x\n", error_code.error_desc.jmp_halt_cond_src.jmp);
+ ERROR("Descriptor Index: %d\n",
+ error_code.error_desc.jmp_halt_cond_src.desc_idx);
+ ERROR(" Condition %x\n", error_code.error_desc.jmp_halt_cond_src.cond);
+}
+
+/* @brief Process DECO related errors
+ * @param [in] error_code The error code in the descriptor status word
+ */
+static inline void hw_handle_deco_err(union hw_error_code error_code)
+{
+ ERROR("JMP %x\n", error_code.error_desc.deco_src.jmp);
+ ERROR("Descriptor Index: 0x%x",
+ error_code.error_desc.deco_src.desc_idx);
+
+ switch (error_code.error_desc.deco_src.desc_err) {
+ case SEC_HW_ERR_DECO_HFN_THRESHOLD:
+ WARN(" Descriptor completed but exceeds the Threshold");
+ break;
+ default:
+ ERROR("Error 0x%04x not implemented",
+ error_code.error_desc.deco_src.desc_err);
+ break;
+ }
+}
+
+/* @brief Process Jump Halt User Status related errors
+ * @param [in] error_code The error code in the descriptor status word
+ */
+static inline void hw_handle_jmp_halt_user_err(union hw_error_code error_code)
+{
+ WARN(" Not implemented");
+}
+
+/* @brief Process CCB related errors
+ * @param [in] error_code The error code in the descriptor status word
+ */
+static inline void hw_handle_ccb_err(union hw_error_code hw_error_code)
+{
+ WARN(" Not implemented");
+}
+
+/* @brief Process Job Ring related errors
+ * @param [in] error_code The error code in the descriptor status word
+ */
+static inline void hw_handle_jr_err(union hw_error_code hw_error_code)
+{
+ WARN(" Not implemented");
+}
+
+/* GLOBAL FUNCTIONS */
+
+int hw_reset_job_ring(sec_job_ring_t *job_ring)
+{
+ int ret = 0;
+ struct jobring_regs *regs =
+ (struct jobring_regs *)job_ring->register_base_addr;
+
+ /* First reset the job ring in hw */
+ ret = hw_shutdown_job_ring(job_ring);
+ if (ret != 0) {
+ ERROR("Failed resetting job ring in hardware");
+ return ret;
+ }
+ /* In order to have the HW JR in a workable state
+ *after a reset, I need to re-write the input
+ * queue size, input start address, output queue
+ * size and output start address
+ * Write the JR input queue size to the HW register
+ */
+ sec_out32(&regs->irs, SEC_JOB_RING_SIZE);
+
+ /* Write the JR output queue size to the HW register */
+ sec_out32(&regs->ors, SEC_JOB_RING_SIZE);
+
+ /* Write the JR input queue start address */
+ hw_set_input_ring_start_addr(regs, vtop(job_ring->input_ring));
+
+ /* Write the JR output queue start address */
+ hw_set_output_ring_start_addr(regs, vtop(job_ring->output_ring));
+
+ return 0;
+}
+
+int hw_shutdown_job_ring(sec_job_ring_t *job_ring)
+{
+ struct jobring_regs *regs =
+ (struct jobring_regs *)job_ring->register_base_addr;
+ unsigned int timeout = SEC_TIMEOUT;
+ uint32_t tmp = 0U;
+
+ VERBOSE("Resetting Job ring\n");
+
+ /*
+ * Mask interrupts since we are going to poll
+ * for reset completion status
+ * Also, at POR, interrupts are ENABLED on a JR, thus
+ * this is the point where I can disable them without
+ * changing the code logic too much
+ */
+
+ jr_disable_irqs(job_ring);
+
+ /* initiate flush (required prior to reset) */
+ sec_out32(&regs->jrcr, JR_REG_JRCR_VAL_RESET);
+
+ /* dummy read */
+ tmp = sec_in32(&regs->jrcr);
+
+ do {
+ tmp = sec_in32(&regs->jrint);
+ } while (((tmp & JRINT_ERR_HALT_MASK) ==
+ JRINT_ERR_HALT_INPROGRESS) && ((--timeout) != 0U));
+
+ if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE ||
+ timeout == 0U) {
+ ERROR("Failed to flush hw job ring %x\n %u", tmp, timeout);
+ /* unmask interrupts */
+ if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+ jr_enable_irqs(job_ring);
+ }
+ return -1;
+ }
+ /* Initiate reset */
+ timeout = SEC_TIMEOUT;
+ sec_out32(&regs->jrcr, JR_REG_JRCR_VAL_RESET);
+
+ do {
+ tmp = sec_in32(&regs->jrcr);
+ } while (((tmp & JR_REG_JRCR_VAL_RESET) != 0U) &&
+ ((--timeout) != 0U));
+
+ if (timeout == 0U) {
+ ERROR("Failed to reset hw job ring\n");
+ /* unmask interrupts */
+ if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+ jr_enable_irqs(job_ring);
+ }
+ return -1;
+ }
+ /* unmask interrupts */
+ if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+ jr_enable_irqs(job_ring);
+ }
+ return 0;
+
+}
+
+void hw_handle_job_ring_error(sec_job_ring_t *job_ring, uint32_t error_code)
+{
+ union hw_error_code hw_err_code;
+
+ hw_err_code.error = error_code;
+
+ switch (hw_err_code.error_desc.value.ssrc) {
+ case SEC_HW_ERR_SSRC_NO_SRC:
+ INFO("No Status Source ");
+ break;
+ case SEC_HW_ERR_SSRC_CCB_ERR:
+ INFO("CCB Status Source");
+ hw_handle_ccb_err(hw_err_code);
+ break;
+ case SEC_HW_ERR_SSRC_JMP_HALT_U:
+ INFO("Jump Halt User Status Source");
+ hw_handle_jmp_halt_user_err(hw_err_code);
+ break;
+ case SEC_HW_ERR_SSRC_DECO:
+ INFO("DECO Status Source");
+ hw_handle_deco_err(hw_err_code);
+ break;
+ case SEC_HW_ERR_SSRC_JR:
+ INFO("Job Ring Status Source");
+ hw_handle_jr_err(hw_err_code);
+ break;
+ case SEC_HW_ERR_SSRC_JMP_HALT_COND:
+ INFO("Jump Halt Condition Codes");
+ hw_handle_jmp_halt_cond_err(hw_err_code);
+ break;
+ default:
+ INFO("Unknown SSRC");
+ break;
+ }
+}
+
+int hw_job_ring_error(sec_job_ring_t *job_ring)
+{
+ uint32_t jrint_error_code;
+ struct jobring_regs *regs =
+ (struct jobring_regs *)job_ring->register_base_addr;
+
+ if (JR_REG_JRINT_JRE_EXTRACT(sec_in32(&regs->jrint)) == 0) {
+ return 0;
+ }
+
+ jrint_error_code =
+ JR_REG_JRINT_ERR_TYPE_EXTRACT(sec_in32(&regs->jrint));
+ switch (jrint_error_code) {
+ case JRINT_ERR_WRITE_STATUS:
+ ERROR("Error writing status to Output Ring ");
+ break;
+ case JRINT_ERR_BAD_INPUT_BASE:
+ ERROR("Bad Input Ring Base (not on a 4-byte boundary)\n");
+ break;
+ case JRINT_ERR_BAD_OUTPUT_BASE:
+ ERROR("Bad Output Ring Base (not on a 4-byte boundary)\n");
+ break;
+ case JRINT_ERR_WRITE_2_IRBA:
+ ERROR("Invalid write to Input Ring Base Address Register\n");
+ break;
+ case JRINT_ERR_WRITE_2_ORBA:
+ ERROR("Invalid write to Output Ring Base Address Register\n");
+ break;
+ case JRINT_ERR_RES_B4_HALT:
+ ERROR("Job Ring released before Job Ring is halted\n");
+ break;
+ case JRINT_ERR_REM_TOO_MANY:
+ ERROR("Removed too many jobs from job ring\n");
+ break;
+ case JRINT_ERR_ADD_TOO_MANY:
+ ERROR("Added too many jobs on job ring\n");
+ break;
+ default:
+ ERROR("Unknown SEC JR Error :%d\n", jrint_error_code);
+ break;
+ }
+ return jrint_error_code;
+}
+
+int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring,
+ uint16_t irq_coalescing_timer,
+ uint8_t irq_coalescing_count)
+{
+ uint32_t reg_val = 0U;
+ struct jobring_regs *regs =
+ (struct jobring_regs *)job_ring->register_base_addr;
+
+ /* Set descriptor count coalescing */
+ reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT);
+
+ /* Set coalescing timer value */
+ reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT);
+
+ /* Update parameters in HW */
+ sec_out32(&regs->jrcfg1, reg_val);
+
+ VERBOSE("Set coalescing params on jr\n");
+
+ return 0;
+}
+
+int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring)
+{
+ uint32_t reg_val = 0U;
+ struct jobring_regs *regs =
+ (struct jobring_regs *)job_ring->register_base_addr;
+
+ /* Get the current value of the register */
+ reg_val = sec_in32(&regs->jrcfg1);
+
+ /* Enable coalescing */
+ reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
+
+ /* Write in hw */
+ sec_out32(&regs->jrcfg1, reg_val);
+
+ VERBOSE("Enabled coalescing on jr\n");
+
+ return 0;
+}
+
+int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring)
+{
+ uint32_t reg_val = 0U;
+ struct jobring_regs *regs =
+ (struct jobring_regs *)job_ring->register_base_addr;
+
+ /* Get the current value of the register */
+ reg_val = sec_in32(&regs->jrcfg1);
+
+ /* Disable coalescing */
+ reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
+
+ /* Write in hw */
+ sec_out32(&regs->jrcfg1, reg_val);
+
+ VERBOSE("Disabled coalescing on jr");
+
+ return 0;
+
+}
+
+void hw_flush_job_ring(struct sec_job_ring_t *job_ring,
+ uint32_t do_notify,
+ uint32_t error_code, uint32_t *notified_descs)
+{
+ int32_t jobs_no_to_discard = 0;
+ int32_t discarded_descs_no = 0;
+ int32_t number_of_jobs_available = 0;
+
+ VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx);
+ VERBOSE("error code %x\n", error_code);
+ VERBOSE("Notify_desc = %d\n", do_notify);
+
+ number_of_jobs_available = hw_get_no_finished_jobs(job_ring);
+
+ /* Discard all jobs */
+ jobs_no_to_discard = number_of_jobs_available;
+
+ VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx);
+ VERBOSE("Discarding desc = %d\n", jobs_no_to_discard);
+
+ while (jobs_no_to_discard > discarded_descs_no) {
+ discarded_descs_no++;
+ /* Now increment the consumer index for the current job ring,
+ * AFTER saving job in temporary location!
+ * Increment the consumer index for the current job ring
+ */
+
+ job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx,
+ SEC_JOB_RING_SIZE);
+
+ hw_remove_entries(job_ring, 1);
+ }
+
+ if (do_notify == true) {
+ if (notified_descs == NULL) {
+ return;
+ }
+ *notified_descs = discarded_descs_no;
+ }
+}
+
+/* return >0 in case of success
+ * -1 in case of error from SEC block
+ * 0 in case job not yet processed by SEC
+ * or Descriptor returned is NULL after dequeue
+ */
+int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit)
+{
+ int32_t jobs_no_to_notify = 0;
+ int32_t number_of_jobs_available = 0;
+ int32_t notified_descs_no = 0;
+ uint32_t error_descs_no = 0U;
+ uint32_t sec_error_code = 0U;
+ uint32_t do_driver_shutdown = false;
+ phys_addr_t *fnptr, *arg_addr;
+ user_callback usercall = NULL;
+ uint8_t *current_desc;
+ void *arg;
+ uintptr_t current_desc_addr;
+ phys_addr_t current_desc_loc;
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ inv_dcache_range((uintptr_t)job_ring->register_base_addr, sizeof(struct jobring_regs));
+ dmbsy();
+#endif
+
+ /* check here if any JR error that cannot be written
+ * in the output status word has occurred
+ */
+ sec_error_code = hw_job_ring_error(job_ring);
+ if (unlikely(sec_error_code) != 0) {
+ ERROR("Error here itself %x\n", sec_error_code);
+ return -1;
+ }
+ /* Compute the number of notifications that need to be raised to UA
+ * If limit < 0 -> notify all done jobs
+ * If limit > total number of done jobs -> notify all done jobs
+ * If limit = 0 -> error
+ * If limit > 0 && limit < total number of done jobs -> notify a number
+ * of done jobs equal with limit
+ */
+
+ /*compute the number of jobs available in the job ring based on the
+ * producer and consumer index values.
+ */
+
+ number_of_jobs_available = hw_get_no_finished_jobs(job_ring);
+ jobs_no_to_notify = (limit < 0 || limit > number_of_jobs_available) ?
+ number_of_jobs_available : limit;
+ VERBOSE("JR - pi %d, ci %d, ", job_ring->pidx, job_ring->cidx);
+ VERBOSE("Jobs submitted %d", number_of_jobs_available);
+ VERBOSE("Jobs to notify %d\n", jobs_no_to_notify);
+
+ while (jobs_no_to_notify > notified_descs_no) {
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ inv_dcache_range(
+ (uintptr_t)(&job_ring->output_ring[job_ring->cidx]),
+ sizeof(struct sec_outring_entry));
+ dmbsy();
+#endif
+
+ /* Get job status here */
+ sec_error_code =
+ sec_in32(&(job_ring->output_ring[job_ring->cidx].status));
+
+ /* Get completed descriptor
+ */
+ current_desc_loc = (uintptr_t)
+ &job_ring->output_ring[job_ring->cidx].desc;
+ current_desc_addr = sec_read_addr(current_desc_loc);
+
+ current_desc = ptov((phys_addr_t *) current_desc_addr);
+ if (current_desc == 0) {
+ ERROR("No descriptor returned from SEC");
+ assert(current_desc);
+ return 0;
+ }
+ /* now increment the consumer index for the current job ring,
+ * AFTER saving job in temporary location!
+ */
+ job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx,
+ SEC_JOB_RING_SIZE);
+
+ if (sec_error_code != 0) {
+ ERROR("desc at cidx %d\n ", job_ring->cidx);
+ ERROR("generated error %x\n", sec_error_code);
+
+ sec_handle_desc_error(job_ring,
+ sec_error_code,
+ &error_descs_no,
+ &do_driver_shutdown);
+ hw_remove_entries(job_ring, 1);
+
+ return -1;
+ }
+ /* Signal that the job has been processed & the slot is free */
+ hw_remove_entries(job_ring, 1);
+ notified_descs_no++;
+
+ arg_addr = (phys_addr_t *) (current_desc +
+ (MAX_DESC_SIZE_WORDS * sizeof(uint32_t)));
+
+ fnptr = (phys_addr_t *) (current_desc +
+ (MAX_DESC_SIZE_WORDS * sizeof(uint32_t)
+ + sizeof(void *)));
+
+ arg = (void *)*(arg_addr);
+ if (*fnptr != 0) {
+ VERBOSE("Callback Function called\n");
+ usercall = (user_callback) *(fnptr);
+ (*usercall) ((uint32_t *) current_desc,
+ sec_error_code, arg, job_ring);
+ }
+ }
+
+ return notified_descs_no;
+}
+
+void sec_handle_desc_error(sec_job_ring_t *job_ring,
+ uint32_t sec_error_code,
+ uint32_t *notified_descs,
+ uint32_t *do_driver_shutdown)
+{
+ /* Analyze the SEC error on this job ring */
+ hw_handle_job_ring_error(job_ring, sec_error_code);
+}
+
+void flush_job_rings(void)
+{
+ struct sec_job_ring_t *job_ring = NULL;
+ int i = 0;
+
+ for (i = 0; i < g_job_rings_no; i++) {
+ job_ring = &g_job_rings[i];
+ /* Producer index is frozen. If consumer index is not equal
+ * with producer index, then we have descs to flush.
+ */
+ while (job_ring->pidx != job_ring->cidx) {
+ hw_flush_job_ring(job_ring, false, 0, /* no error */
+ NULL);
+ }
+ }
+}
+
+int shutdown_job_ring(struct sec_job_ring_t *job_ring)
+{
+ int ret = 0;
+
+ ret = hw_shutdown_job_ring(job_ring);
+ if (ret != 0) {
+ ERROR("Failed to shutdown hardware job ring\n");
+ return ret;
+ }
+
+ if (job_ring->coalescing_en != 0) {
+ hw_job_ring_disable_coalescing(job_ring);
+ }
+
+ if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+ ret = jr_disable_irqs(job_ring);
+ if (ret != 0) {
+ ERROR("Failed to disable irqs for job ring");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int jr_enable_irqs(struct sec_job_ring_t *job_ring)
+{
+ uint32_t reg_val = 0U;
+ struct jobring_regs *regs =
+ (struct jobring_regs *)job_ring->register_base_addr;
+
+ /* Get the current value of the register */
+ reg_val = sec_in32(&regs->jrcfg1);
+
+ /* Enable interrupts by disabling interrupt masking*/
+ reg_val &= ~JR_REG_JRCFG_LO_IMSK_EN;
+
+ /* Update parameters in HW */
+ sec_out32(&regs->jrcfg1, reg_val);
+
+ VERBOSE("Enable interrupts on JR\n");
+
+ return 0;
+}
+
+int jr_disable_irqs(struct sec_job_ring_t *job_ring)
+{
+ uint32_t reg_val = 0U;
+ struct jobring_regs *regs =
+ (struct jobring_regs *)job_ring->register_base_addr;
+
+ /* Get the current value of the register */
+ reg_val = sec_in32(&regs->jrcfg1);
+
+ /* Disable interrupts by enabling interrupt masking*/
+ reg_val |= JR_REG_JRCFG_LO_IMSK_EN;
+
+ /* Update parameters in HW */
+ sec_out32(&regs->jrcfg1, reg_val);
+
+ VERBOSE("Disable interrupts on JR\n");
+
+ return 0;
+}
diff --git a/drivers/nxp/crypto/caam/src/sec_jr_driver.c b/drivers/nxp/crypto/caam/src/sec_jr_driver.c
new file mode 100644
index 0000000000..1fe700718e
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/sec_jr_driver.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "nxp_timer.h"
+#include "sec_hw_specific.h"
+#include "sec_jr_driver.h"
+
+
+/* Job rings used for communication with SEC HW */
+struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS];
+
+/* The current state of SEC user space driver */
+volatile sec_driver_state_t g_driver_state = SEC_DRIVER_STATE_IDLE;
+
+int g_job_rings_no;
+
+uint8_t ip_ring[SEC_DMA_MEM_INPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE);
+uint8_t op_ring[SEC_DMA_MEM_OUTPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE);
+
+void *init_job_ring(uint8_t jr_mode,
+ uint16_t irq_coalescing_timer,
+ uint8_t irq_coalescing_count,
+ void *reg_base_addr, uint32_t irq_id)
+{
+ struct sec_job_ring_t *job_ring = &g_job_rings[g_job_rings_no++];
+ int ret = 0;
+
+ job_ring->register_base_addr = reg_base_addr;
+ job_ring->jr_mode = jr_mode;
+ job_ring->irq_fd = irq_id;
+
+ job_ring->input_ring = vtop(ip_ring);
+ memset(job_ring->input_ring, 0, SEC_DMA_MEM_INPUT_RING_SIZE);
+
+ job_ring->output_ring = (struct sec_outring_entry *)vtop(op_ring);
+ memset(job_ring->output_ring, 0, SEC_DMA_MEM_OUTPUT_RING_SIZE);
+
+ dsb();
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ flush_dcache_range((uintptr_t)(job_ring->input_ring),
+ SEC_DMA_MEM_INPUT_RING_SIZE),
+ flush_dcache_range((uintptr_t)(job_ring->output_ring),
+ SEC_DMA_MEM_OUTPUT_RING_SIZE),
+
+ dmbsy();
+#endif
+ /* Reset job ring in SEC hw and configure job ring registers */
+ ret = hw_reset_job_ring(job_ring);
+ if (ret != 0) {
+ ERROR("Failed to reset hardware job ring\n");
+ return NULL;
+ }
+
+ if (jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
+ /* Enable IRQ if driver work sin interrupt mode */
+ ERROR("Enabling DONE IRQ generation on job ring\n");
+ ret = jr_enable_irqs(job_ring);
+ if (ret != 0) {
+ ERROR("Failed to enable irqs for job ring\n");
+ return NULL;
+ }
+ }
+ if ((irq_coalescing_timer != 0) || (irq_coalescing_count != 0)) {
+ hw_job_ring_set_coalescing_param(job_ring,
+ irq_coalescing_timer,
+ irq_coalescing_count);
+
+ hw_job_ring_enable_coalescing(job_ring);
+ job_ring->coalescing_en = 1;
+ }
+
+ job_ring->jr_state = SEC_JOB_RING_STATE_STARTED;
+
+ return job_ring;
+}
+
+int sec_release(void)
+{
+ int i;
+
+ /* Validate driver state */
+ if (g_driver_state == SEC_DRIVER_STATE_RELEASE) {
+ ERROR("Driver release is already in progress");
+ return SEC_DRIVER_RELEASE_IN_PROGRESS;
+ }
+ /* Update driver state */
+ g_driver_state = SEC_DRIVER_STATE_RELEASE;
+
+ /* If any descriptors in flight , poll and wait
+ * until all descriptors are received and silently discarded.
+ */
+
+ flush_job_rings();
+
+ for (i = 0; i < g_job_rings_no; i++) {
+ shutdown_job_ring(&g_job_rings[i]);
+ }
+ g_job_rings_no = 0;
+ g_driver_state = SEC_DRIVER_STATE_IDLE;
+
+ return SEC_SUCCESS;
+}
+
+int sec_jr_lib_init(void)
+{
+ /* Validate driver state */
+ if (g_driver_state != SEC_DRIVER_STATE_IDLE) {
+ ERROR("Driver already initialized\n");
+ return 0;
+ }
+
+ memset(g_job_rings, 0, sizeof(g_job_rings));
+ g_job_rings_no = 0;
+
+ /* Update driver state */
+ g_driver_state = SEC_DRIVER_STATE_STARTED;
+ return 0;
+}
+
+int dequeue_jr(void *job_ring_handle, int32_t limit)
+{
+ int ret = 0;
+ int notified_descs_no = 0;
+ struct sec_job_ring_t *job_ring = (sec_job_ring_t *) job_ring_handle;
+ uint64_t start_time;
+
+ /* Validate driver state */
+ if (g_driver_state != SEC_DRIVER_STATE_STARTED) {
+ ERROR("Driver release in progress or driver not initialized\n");
+ return -1;
+ }
+
+ /* Validate input arguments */
+ if (job_ring == NULL) {
+ ERROR("job_ring_handle is NULL\n");
+ return -1;
+ }
+ if (((limit == 0) || (limit > SEC_JOB_RING_SIZE))) {
+ ERROR("Invalid limit parameter configuration\n");
+ return -1;
+ }
+
+ VERBOSE("JR Polling limit[%d]\n", limit);
+
+ /* Poll job ring
+ * If limit < 0 -> poll JR until no more notifications are available.
+ * If limit > 0 -> poll JR until limit is reached.
+ */
+
+ start_time = get_timer_val(0);
+
+ while (notified_descs_no == 0) {
+ /* Run hw poll job ring */
+ notified_descs_no = hw_poll_job_ring(job_ring, limit);
+ if (notified_descs_no < 0) {
+ ERROR("Error polling SEC engine job ring ");
+ return notified_descs_no;
+ }
+ VERBOSE("Jobs notified[%d]. ", notified_descs_no);
+
+ if (get_timer_val(start_time) >= CAAM_TIMEOUT) {
+ break;
+ }
+ }
+
+ if (job_ring->jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
+
+ /* Always enable IRQ generation when in pure IRQ mode */
+ ret = jr_enable_irqs(job_ring);
+ if (ret != 0) {
+ ERROR("Failed to enable irqs for job ring");
+ return ret;
+ }
+ }
+ return notified_descs_no;
+}
+
+int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr)
+{
+ struct sec_job_ring_t *job_ring;
+
+ job_ring = (struct sec_job_ring_t *)job_ring_handle;
+
+ /* Validate driver state */
+ if (g_driver_state != SEC_DRIVER_STATE_STARTED) {
+ ERROR("Driver release in progress or driver not initialized\n");
+ return -1;
+ }
+
+ /* Check job ring state */
+ if (job_ring->jr_state != SEC_JOB_RING_STATE_STARTED) {
+ ERROR("Job ring is currently resetting\n");
+ return -1;
+ }
+
+ if (SEC_JOB_RING_IS_FULL(job_ring->pidx, job_ring->cidx,
+ SEC_JOB_RING_SIZE, SEC_JOB_RING_SIZE)) {
+ ERROR("Job ring is full\n");
+ return -1;
+ }
+
+ /* Set ptr in input ring to current descriptor */
+ sec_write_addr(&job_ring->input_ring[job_ring->pidx],
+ (phys_addr_t) vtop(jobdescr->desc));
+
+ dsb();
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+ flush_dcache_range((uintptr_t)(&job_ring->input_ring[job_ring->pidx]),
+ sizeof(phys_addr_t));
+
+ inv_dcache_range((uintptr_t)(&job_ring->output_ring[job_ring->cidx]),
+ sizeof(struct sec_outring_entry));
+ dmbsy();
+#endif
+ /* Notify HW that a new job is enqueued */
+ hw_enqueue_desc_on_job_ring(
+ (struct jobring_regs *)job_ring->register_base_addr, 1);
+
+ /* increment the producer index for the current job ring */
+ job_ring->pidx = SEC_CIRCULAR_COUNTER(job_ring->pidx,
+ SEC_JOB_RING_SIZE);
+
+ return 0;
+}
diff --git a/drivers/nxp/csu/csu.c b/drivers/nxp/csu/csu.c
new file mode 100644
index 0000000000..9f90fe030c
--- /dev/null
+++ b/drivers/nxp/csu/csu.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <endian.h>
+
+#include <common/debug.h>
+#include <csu.h>
+#include <lib/mmio.h>
+
+void enable_layerscape_ns_access(struct csu_ns_dev_st *csu_ns_dev,
+ uint32_t num, uintptr_t nxp_csu_addr)
+{
+ uint32_t *base = (uint32_t *)nxp_csu_addr;
+ uint32_t *reg;
+ uint32_t val;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ reg = base + csu_ns_dev[i].ind / 2U;
+ val = be32toh(mmio_read_32((uintptr_t)reg));
+ if (csu_ns_dev[i].ind % 2U == 0U) {
+ val &= 0x0000ffffU;
+ val |= csu_ns_dev[i].val << 16U;
+ } else {
+ val &= 0xffff0000U;
+ val |= csu_ns_dev[i].val;
+ }
+ mmio_write_32((uintptr_t)reg, htobe32(val));
+ }
+}
diff --git a/drivers/nxp/csu/csu.h b/drivers/nxp/csu/csu.h
new file mode 100644
index 0000000000..9f82feb0a3
--- /dev/null
+++ b/drivers/nxp/csu/csu.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CSU_H
+#define CSU_H
+
+#define CSU_SEC_ACCESS_REG_OFFSET (0x0021CU)
+
+/* Macros defining access permissions to configure
+ * the regions controlled by Central Security Unit.
+ */
+enum csu_cslx_access {
+ CSU_NS_SUP_R = (0x8U),
+ CSU_NS_SUP_W = (0x80U),
+ CSU_NS_SUP_RW = (0x88U),
+ CSU_NS_USER_R = (0x4U),
+ CSU_NS_USER_W = (0x40U),
+ CSU_NS_USER_RW = (0x44U),
+ CSU_S_SUP_R = (0x2U),
+ CSU_S_SUP_W = (0x20U),
+ CSU_S_SUP_RW = (0x22U),
+ CSU_S_USER_R = (0x1U),
+ CSU_S_USER_W = (0x10U),
+ CSU_S_USER_RW = (0x11U),
+ CSU_ALL_RW = (0xffU),
+};
+
+struct csu_ns_dev_st {
+ uintptr_t ind;
+ uint32_t val;
+};
+
+void enable_layerscape_ns_access(struct csu_ns_dev_st *csu_ns_dev,
+ uint32_t num, uintptr_t nxp_csu_addr);
+
+#endif
diff --git a/drivers/nxp/csu/csu.mk b/drivers/nxp/csu/csu.mk
new file mode 100644
index 0000000000..ebdf674835
--- /dev/null
+++ b/drivers/nxp/csu/csu.mk
@@ -0,0 +1,28 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-----------------------------------------------------------------------------
+ifeq (${CSU_ADDED},)
+
+CSU_ADDED := 1
+
+CSU_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/csu
+
+PLAT_INCLUDES += -I$(CSU_DRIVERS_PATH)
+
+CSU_SOURCES += $(CSU_DRIVERS_PATH)/csu.c
+
+ifeq (${BL_COMM_CSU_NEEDED},yes)
+BL_COMMON_SOURCES += ${CSU_SOURCES}
+else
+ifeq (${BL2_CSU_NEEDED},yes)
+BL2_SOURCES += ${CSU_SOURCES}
+endif
+ifeq (${BL31_CSU_NEEDED},yes)
+BL31_SOURCES += ${CSU_SOURCES}
+endif
+endif
+
+endif
diff --git a/drivers/nxp/dcfg/dcfg.c b/drivers/nxp/dcfg/dcfg.c
new file mode 100644
index 0000000000..2e813e7806
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/debug.h>
+#include "dcfg.h"
+#include <lib/mmio.h>
+#ifdef NXP_SFP_ENABLED
+#include <sfp.h>
+#endif
+
+static soc_info_t soc_info = {0};
+static devdisr5_info_t devdisr5_info = {0};
+static dcfg_init_info_t *dcfg_init_info;
+
+/* Read the PORSR1 register */
+uint32_t read_reg_porsr1(void)
+{
+ unsigned int *porsr1_addr = NULL;
+
+ if (dcfg_init_info->porsr1 != 0U) {
+ return dcfg_init_info->porsr1;
+ }
+
+ porsr1_addr = (void *)
+ (dcfg_init_info->g_nxp_dcfg_addr + DCFG_PORSR1_OFFSET);
+ dcfg_init_info->porsr1 = gur_in32(porsr1_addr);
+
+ return dcfg_init_info->porsr1;
+}
+
+
+const soc_info_t *get_soc_info(void)
+{
+ uint32_t reg;
+
+ if (soc_info.is_populated == true) {
+ return (const soc_info_t *) &soc_info;
+ }
+
+ reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_SVR_OFFSET);
+
+ soc_info.mfr_id = (reg & SVR_MFR_ID_MASK) >> SVR_MFR_ID_SHIFT;
+#if defined(CONFIG_CHASSIS_3_2)
+ soc_info.family = (reg & SVR_FAMILY_MASK) >> SVR_FAMILY_SHIFT;
+ soc_info.dev_id = (reg & SVR_DEV_ID_MASK) >> SVR_DEV_ID_SHIFT;
+#endif
+ /* zero means SEC enabled. */
+ soc_info.sec_enabled =
+ (((reg & SVR_SEC_MASK) >> SVR_SEC_SHIFT) == 0) ? true : false;
+
+ soc_info.personality = (reg & SVR_PERSONALITY_MASK)
+ >> SVR_PERSONALITY_SHIFT;
+ soc_info.maj_ver = (reg & SVR_MAJ_VER_MASK) >> SVR_MAJ_VER_SHIFT;
+ soc_info.min_ver = reg & SVR_MIN_VER_MASK;
+
+ soc_info.is_populated = true;
+ return (const soc_info_t *) &soc_info;
+}
+
+void dcfg_init(dcfg_init_info_t *dcfg_init_data)
+{
+ dcfg_init_info = dcfg_init_data;
+ read_reg_porsr1();
+ get_soc_info();
+}
+
+bool is_sec_enabled(void)
+{
+ return soc_info.sec_enabled;
+}
+
+const devdisr5_info_t *get_devdisr5_info(void)
+{
+ uint32_t reg;
+
+ if (devdisr5_info.is_populated == true)
+ return (const devdisr5_info_t *) &devdisr5_info;
+
+ reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_DEVDISR5_OFFSET);
+
+#if defined(CONFIG_CHASSIS_3_2)
+ devdisr5_info.ddrc1_present = (reg & DISR5_DDRC1_MASK) ? 0 : 1;
+ devdisr5_info.ddrc2_present = (reg & DISR5_DDRC2_MASK) ? 0 : 1;
+ devdisr5_info.ocram_present = (reg & DISR5_OCRAM_MASK) ? 0 : 1;
+#elif defined(CONFIG_CHASSIS_2)
+ devdisr5_info.ddrc1_present = (reg & DISR5_DDRC1_MASK) ? 0 : 1;
+ devdisr5_info.ocram_present = (reg & DISR5_OCRAM_MASK) ? 0 : 1;
+#endif
+ devdisr5_info.is_populated = true;
+
+ return (const devdisr5_info_t *) &devdisr5_info;
+}
+
+int get_clocks(struct sysinfo *sys)
+{
+ unsigned int *rcwsr0 = NULL;
+ const unsigned long sysclk = dcfg_init_info->nxp_sysclk_freq;
+ const unsigned long ddrclk = dcfg_init_info->nxp_ddrclk_freq;
+
+ rcwsr0 = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR0_OFFSET);
+ sys->freq_platform = sysclk;
+ sys->freq_ddr_pll0 = ddrclk;
+ sys->freq_ddr_pll1 = ddrclk;
+
+ sys->freq_platform *= (gur_in32(rcwsr0) >>
+ RCWSR0_SYS_PLL_RAT_SHIFT) &
+ RCWSR0_SYS_PLL_RAT_MASK;
+
+ sys->freq_platform /= dcfg_init_info->nxp_plat_clk_divider;
+
+ sys->freq_ddr_pll0 *= (gur_in32(rcwsr0) >>
+ RCWSR0_MEM_PLL_RAT_SHIFT) &
+ RCWSR0_MEM_PLL_RAT_MASK;
+ sys->freq_ddr_pll1 *= (gur_in32(rcwsr0) >>
+ RCWSR0_MEM2_PLL_RAT_SHIFT) &
+ RCWSR0_MEM2_PLL_RAT_MASK;
+ if (sys->freq_platform == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+#ifdef NXP_SFP_ENABLED
+/*******************************************************************************
+ * Returns true if secur eboot is enabled on board
+ * mode = 0 (development mode - sb_en = 1)
+ * mode = 1 (production mode - ITS = 1)
+ ******************************************************************************/
+bool check_boot_mode_secure(uint32_t *mode)
+{
+ uint32_t val = 0U;
+ uint32_t *rcwsr = NULL;
+ *mode = 0U;
+
+ if (sfp_check_its() == 1) {
+ /* ITS =1 , Production mode */
+ *mode = 1U;
+ return true;
+ }
+
+ rcwsr = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR_SB_EN_OFFSET);
+
+ val = (gur_in32(rcwsr) >> RCWSR_SBEN_SHIFT) &
+ RCWSR_SBEN_MASK;
+
+ if (val == RCWSR_SBEN_MASK) {
+ *mode = 0U;
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+void error_handler(int error_code)
+{
+ /* Dump error code in SCRATCH4 register */
+ INFO("Error in Fuse Provisioning: %x\n", error_code);
+ gur_out32((void *)
+ (dcfg_init_info->g_nxp_dcfg_addr + DCFG_SCRATCH4_OFFSET),
+ error_code);
+}
diff --git a/drivers/nxp/dcfg/dcfg.h b/drivers/nxp/dcfg/dcfg.h
new file mode 100644
index 0000000000..161e2950f9
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DCFG_H
+#define DCFG_H
+
+#include <endian.h>
+
+#if defined(CONFIG_CHASSIS_2)
+#include <dcfg_lsch2.h>
+#elif defined(CONFIG_CHASSIS_3_2)
+#include <dcfg_lsch3.h>
+#endif
+
+#ifdef NXP_GUR_BE
+#define gur_in32(a) bswap32(mmio_read_32((uintptr_t)(a)))
+#define gur_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v))
+#elif defined(NXP_GUR_LE)
+#define gur_in32(a) mmio_read_32((uintptr_t)(a))
+#define gur_out32(a, v) mmio_write_32((uintptr_t)(a), v)
+#else
+#error Please define CCSR GUR register endianness
+#endif
+
+typedef struct {
+ bool is_populated;
+ uint8_t mfr_id;
+#if defined(CONFIG_CHASSIS_3_2)
+ uint8_t family;
+ uint8_t dev_id;
+#endif
+ uint8_t personality;
+ bool sec_enabled;
+ uint8_t maj_ver;
+ uint8_t min_ver;
+} soc_info_t;
+
+typedef struct {
+ bool is_populated;
+ uint8_t ocram_present;
+ uint8_t ddrc1_present;
+#if defined(CONFIG_CHASSIS_3_2)
+ uint8_t ddrc2_present;
+#endif
+} devdisr5_info_t;
+
+typedef struct {
+ uint32_t porsr1;
+ uintptr_t g_nxp_dcfg_addr;
+ unsigned long nxp_sysclk_freq;
+ unsigned long nxp_ddrclk_freq;
+ unsigned int nxp_plat_clk_divider;
+} dcfg_init_info_t;
+
+
+struct sysinfo {
+ unsigned long freq_platform;
+ unsigned long freq_ddr_pll0;
+ unsigned long freq_ddr_pll1;
+};
+
+int get_clocks(struct sysinfo *sys);
+
+/* Read the PORSR1 register */
+uint32_t read_reg_porsr1(void);
+
+/*******************************************************************************
+ * Returns true if secur eboot is enabled on board
+ * mode = 0 (development mode - sb_en = 1)
+ * mode = 1 (production mode - ITS = 1)
+ ******************************************************************************/
+bool check_boot_mode_secure(uint32_t *mode);
+
+const soc_info_t *get_soc_info();
+const devdisr5_info_t *get_devdisr5_info();
+
+void dcfg_init(dcfg_init_info_t *dcfg_init_data);
+bool is_sec_enabled(void);
+
+void error_handler(int error_code);
+#endif /* DCFG_H */
diff --git a/drivers/nxp/dcfg/dcfg.mk b/drivers/nxp/dcfg/dcfg.mk
new file mode 100644
index 0000000000..61d1850458
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg.mk
@@ -0,0 +1,28 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq (${ADD_DCFG},)
+
+ADD_DCFG := 1
+
+DCFG_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/dcfg
+
+PLAT_INCLUDES += -I$(DCFG_DRIVERS_PATH)
+
+DCFG_SOURCES += $(DCFG_DRIVERS_PATH)/dcfg.c
+
+ifeq (${BL_COMM_DCFG_NEEDED},yes)
+BL_COMMON_SOURCES += ${DCFG_SOURCES}
+else
+ifeq (${BL2_DCFG_NEEDED},yes)
+BL2_SOURCES += ${DCFG_SOURCES}
+endif
+ifeq (${BL31_DCFG_NEEDED},yes)
+BL31_SOURCES += ${DCFG_SOURCES}
+endif
+endif
+
+endif
diff --git a/drivers/nxp/dcfg/dcfg_lsch2.h b/drivers/nxp/dcfg/dcfg_lsch2.h
new file mode 100644
index 0000000000..c021aa1631
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg_lsch2.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DCFG_LSCH2_H
+#define DCFG_LSCH2_H
+
+/* dcfg block register offsets and bitfields */
+#define DCFG_PORSR1_OFFSET 0x00
+#define DCFG_DEVDISR1_OFFSET 0x070
+#define DCFG_DEVDISR4_OFFSET 0x07C
+#define DCFG_DEVDISR5_OFFSET 0x080
+#define DCFG_COREDISR_OFFSET 0x094
+#define RCWSR0_OFFSET 0x100
+#define RCWSR5_OFFSET 0x118
+#define DCFG_BOOTLOCPTRL_OFFSET 0x400
+#define DCFG_BOOTLOCPTRH_OFFSET 0x404
+#define DCFG_COREDISABLEDSR_OFFSET 0x990
+#define DCFG_SCRATCH4_OFFSET 0x20C
+#define DCFG_SVR_OFFSET 0x0A4
+#define DCFG_BRR_OFFSET 0x0E4
+
+#define DCFG_RSTCR_OFFSET 0x0B0
+#define RSTCR_RESET_REQ 0x2
+
+#define DCFG_RSTRQSR1_OFFSET 0x0C8
+#define DCFG_RSTRQMR1_OFFSET 0x0C0
+
+/* DCFG DCSR Macros */
+#define DCFG_DCSR_PORCR1_OFFSET 0x0
+
+#define SVR_MFR_ID_MASK 0xF0000000
+#define SVR_MFR_ID_SHIFT 28
+#define SVR_FAMILY_MASK 0xF000000
+#define SVR_FAMILY_SHIFT 24
+#define SVR_DEV_ID_MASK 0x3F0000
+#define SVR_DEV_ID_SHIFT 16
+#define SVR_PERSONALITY_MASK 0x3E00
+#define SVR_PERSONALITY_SHIFT 9
+#define SVR_SEC_MASK 0x100
+#define SVR_SEC_SHIFT 8
+#define SVR_MAJ_VER_MASK 0xF0
+#define SVR_MAJ_VER_SHIFT 4
+#define SVR_MIN_VER_MASK 0xF
+
+#define DISR5_DDRC1_MASK 0x1
+#define DISR5_OCRAM_MASK 0x40
+
+/* DCFG regsiters bit masks */
+#define RCWSR0_SYS_PLL_RAT_SHIFT 25
+#define RCWSR0_SYS_PLL_RAT_MASK 0x1f
+#define RCWSR0_MEM_PLL_RAT_SHIFT 16
+#define RCWSR0_MEM_PLL_RAT_MASK 0x3f
+#define RCWSR0_MEM2_PLL_RAT_SHIFT 18
+#define RCWSR0_MEM2_PLL_RAT_MASK 0x3f
+
+#define RCWSR_SB_EN_OFFSET RCWSR5_OFFSET
+#define RCWSR_SBEN_MASK 0x1
+#define RCWSR_SBEN_SHIFT 21
+
+/* RCW SRC NAND */
+#define RCW_SRC_NAND_MASK (0x100)
+#define RCW_SRC_NAND_VAL (0x100)
+#define NAND_RESERVED_MASK (0xFC)
+#define NAND_RESERVED_1 (0x0)
+#define NAND_RESERVED_2 (0x80)
+
+/* RCW SRC NOR */
+#define RCW_SRC_NOR_MASK (0x1F0)
+#define NOR_8B_VAL (0x10)
+#define NOR_16B_VAL (0x20)
+#define SD_VAL (0x40)
+#define QSPI_VAL1 (0x44)
+#define QSPI_VAL2 (0x45)
+
+#endif /* DCFG_LSCH2_H */
diff --git a/drivers/nxp/dcfg/dcfg_lsch3.h b/drivers/nxp/dcfg/dcfg_lsch3.h
new file mode 100644
index 0000000000..8144542530
--- /dev/null
+++ b/drivers/nxp/dcfg/dcfg_lsch3.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DCFG_LSCH3_H
+#define DCFG_LSCH3_H
+
+/* dcfg block register offsets and bitfields */
+#define DCFG_PORSR1_OFFSET 0x00
+
+#define DCFG_DEVDISR1_OFFSET 0x70
+#define DCFG_DEVDISR1_SEC (1 << 22)
+
+#define DCFG_DEVDISR2_OFFSET 0x74
+
+#define DCFG_DEVDISR3_OFFSET 0x78
+#define DCFG_DEVDISR3_QBMAIN (1 << 12)
+
+#define DCFG_DEVDISR4_OFFSET 0x7C
+#define DCFG_DEVDISR4_SPI_QSPI (1 << 4 | 1 << 5)
+
+#define DCFG_DEVDISR5_OFFSET 0x80
+#define DISR5_DDRC1_MASK 0x1
+#define DISR5_DDRC2_MASK 0x2
+#define DISR5_OCRAM_MASK 0x1000
+#define DEVDISR5_MASK_ALL_MEM 0x00001003
+#define DEVDISR5_MASK_DDR 0x00000003
+#define DEVDISR5_MASK_DBG 0x00000400
+
+#define DCFG_DEVDISR6_OFFSET 0x84
+//#define DEVDISR6_MASK 0x00000001
+
+#define DCFG_COREDISR_OFFSET 0x94
+
+#define DCFG_SVR_OFFSET 0x0A4
+#define SVR_MFR_ID_MASK 0xF0000000
+#define SVR_MFR_ID_SHIFT 28
+#define SVR_FAMILY_MASK 0xF000000
+#define SVR_FAMILY_SHIFT 24
+#define SVR_DEV_ID_MASK 0x3F0000
+#define SVR_DEV_ID_SHIFT 16
+#define SVR_PERSONALITY_MASK 0x3E00
+#define SVR_PERSONALITY_SHIFT 9
+#define SVR_SEC_MASK 0x100
+#define SVR_SEC_SHIFT 8
+#define SVR_MAJ_VER_MASK 0xF0
+#define SVR_MAJ_VER_SHIFT 4
+#define SVR_MIN_VER_MASK 0xF
+
+#define RCWSR0_OFFSET 0x100
+#define RCWSR0_SYS_PLL_RAT_SHIFT 2
+#define RCWSR0_SYS_PLL_RAT_MASK 0x1f
+#define RCWSR0_MEM_PLL_RAT_SHIFT 10
+#define RCWSR0_MEM_PLL_RAT_MASK 0x3f
+#define RCWSR0_MEM2_PLL_RAT_SHIFT 18
+#define RCWSR0_MEM2_PLL_RAT_MASK 0x3f
+
+#define RCWSR5_OFFSET 0x110
+#define RCWSR9_OFFSET 0x120
+#define RCWSR_SB_EN_OFFSET RCWSR9_OFFSET
+#define RCWSR_SBEN_MASK 0x1
+#define RCWSR_SBEN_SHIFT 10
+
+#define RCW_SR27_OFFSET 0x168
+/* DCFG register to dump error code */
+#define DCFG_SCRATCH4_OFFSET 0x20C
+#define DCFG_SCRATCHRW5_OFFSET 0x210
+#define DCFG_SCRATCHRW6_OFFSET 0x214
+#define DCFG_SCRATCHRW7_OFFSET 0x218
+#define DCFG_BOOTLOCPTRL_OFFSET 0x400
+#define DCFG_BOOTLOCPTRH_OFFSET 0x404
+#define DCFG_COREDISABLEDSR_OFFSET 0x990
+
+#endif /* DCFG_LSCH3_H */
diff --git a/drivers/nxp/dcfg/scfg.h b/drivers/nxp/dcfg/scfg.h
new file mode 100644
index 0000000000..81df9a61a9
--- /dev/null
+++ b/drivers/nxp/dcfg/scfg.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef SCFG_H
+#define SCFG_H
+
+#ifdef CONFIG_CHASSIS_2
+
+/* SCFG register offsets */
+#define SCFG_CORE0_SFT_RST_OFFSET 0x0130
+#define SCFG_SNPCNFGCR_OFFSET 0x01A4
+#define SCFG_CORESRENCR_OFFSET 0x0204
+#define SCFG_RVBAR0_0_OFFSET 0x0220
+#define SCFG_RVBAR0_1_OFFSET 0x0224
+#define SCFG_COREBCR_OFFSET 0x0680
+#define SCFG_RETREQCR_OFFSET 0x0424
+
+#define SCFG_COREPMCR_OFFSET 0x042C
+#define COREPMCR_WFIL2 0x1
+
+#define SCFG_GIC400_ADDR_ALIGN_OFFSET 0x0188
+#define SCFG_BOOTLOCPTRH_OFFSET 0x0600
+#define SCFG_BOOTLOCPTRL_OFFSET 0x0604
+#define SCFG_SCRATCHRW2_OFFSET 0x0608
+#define SCFG_SCRATCHRW3_OFFSET 0x060C
+
+/* SCFG bit fields */
+#define SCFG_SNPCNFGCR_SECRDSNP 0x80000000
+#define SCFG_SNPCNFGCR_SECWRSNP 0x40000000
+#endif /* CONFIG_CHASSIS_2 */
+
+#ifndef __ASSEMBLER__
+#include <endian.h>
+#include <lib/mmio.h>
+
+#ifdef NXP_SCFG_BE
+#define scfg_in32(a) bswap32(mmio_read_32((uintptr_t)(a)))
+#define scfg_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v))
+#define scfg_setbits32(a, v) mmio_setbits_32((uintptr_t)(a), v)
+#define scfg_clrbits32(a, v) mmio_clrbits_32((uintptr_t)(a), v)
+#define scfg_clrsetbits32(a, clear, set) \
+ mmio_clrsetbits_32((uintptr_t)(a), clear, set)
+#elif defined(NXP_GUR_LE)
+#define scfg_in32(a) mmio_read_32((uintptr_t)(a))
+#define scfg_out32(a, v) mmio_write_32((uintptr_t)(a), v)
+#define scfg_setbits32(a, v) mmio_setbits_32((uintptr_t)(a), v)
+#define scfg_clrbits32(a, v) mmio_clrbits_32((uintptr_t)(a), v)
+#define scfg_clrsetbits32(a, clear, set) \
+ mmio_clrsetbits_32((uintptr_t)(a), clear, set)
+#else
+#error Please define CCSR SCFG register endianness
+#endif
+#endif /* __ASSEMBLER__ */
+
+#endif /* SCFG_H */
diff --git a/drivers/nxp/ddr/fsl-mmdc/ddr.mk b/drivers/nxp/ddr/fsl-mmdc/ddr.mk
new file mode 100644
index 0000000000..e6cc7c1d0c
--- /dev/null
+++ b/drivers/nxp/ddr/fsl-mmdc/ddr.mk
@@ -0,0 +1,19 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-----------------------------------------------------------------------------
+
+# MMDC ddr cntlr driver files
+
+DDR_DRIVERS_PATH := drivers/nxp/ddr
+
+DDR_CNTLR_SOURCES := ${DDR_DRIVERS_PATH}/fsl-mmdc/fsl_mmdc.c \
+ ${DDR_DRIVERS_PATH}/nxp-ddr/utility.c \
+ ${DDR_DRIVERS_PATH}/nxp-ddr/ddr.c \
+ ${DDR_DRIVERS_PATH}/nxp-ddr/ddrc.c
+
+PLAT_INCLUDES += -I$(DDR_DRIVERS_PATH)/include \
+ -I$(DDR_DRIVERS_PATH)/fsl-mmdc
+#------------------------------------------------
diff --git a/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c b/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c
new file mode 100644
index 0000000000..7e6504e9e7
--- /dev/null
+++ b/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Generic driver for Freescale MMDC(Multi Mode DDR Controller).
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include "ddr_io.h"
+#include <drivers/delay_timer.h>
+#include <fsl_mmdc.h>
+
+static void set_wait_for_bits_clear(void *ptr, unsigned int value,
+ unsigned int bits)
+{
+ int timeout = 1000;
+
+ ddr_out32(ptr, value);
+
+ while ((ddr_in32(ptr) & bits) != 0) {
+ udelay(100);
+ timeout--;
+ }
+ if (timeout <= 0) {
+ INFO("Error: %llx", (unsigned long long)ptr);
+ INFO(" wait for clear timeout.\n");
+ }
+}
+
+void mmdc_init(const struct fsl_mmdc_info *priv, uintptr_t nxp_ddr_addr)
+{
+ struct mmdc_regs *mmdc = (struct mmdc_regs *)nxp_ddr_addr;
+ unsigned int tmp;
+
+ /* 1. set configuration request */
+ ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ);
+
+ /* 2. configure the desired timing parameters */
+ ddr_out32(&mmdc->mdotc, priv->mdotc);
+ ddr_out32(&mmdc->mdcfg0, priv->mdcfg0);
+ ddr_out32(&mmdc->mdcfg1, priv->mdcfg1);
+ ddr_out32(&mmdc->mdcfg2, priv->mdcfg2);
+
+ /* 3. configure DDR type and other miscellaneous parameters */
+ ddr_out32(&mmdc->mdmisc, priv->mdmisc);
+ ddr_out32(&mmdc->mpmur0, MMDC_MPMUR0_FRC_MSR);
+ ddr_out32(&mmdc->mdrwd, priv->mdrwd);
+ ddr_out32(&mmdc->mpodtctrl, priv->mpodtctrl);
+
+ /* 4. configure the required delay while leaving reset */
+ ddr_out32(&mmdc->mdor, priv->mdor);
+
+ /* 5. configure DDR physical parameters */
+ /* set row/column address width, burst length, data bus width */
+ tmp = priv->mdctl & ~(MDCTL_SDE0 | MDCTL_SDE1);
+ ddr_out32(&mmdc->mdctl, tmp);
+ /* configure address space partition */
+ ddr_out32(&mmdc->mdasp, priv->mdasp);
+
+ /* 6. perform a ZQ calibration - not needed here, doing in #8b */
+
+ /* 7. enable MMDC with the desired chip select */
+#if (DDRC_NUM_CS == 1)
+ ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0);
+#elif (DDRC_NUM_CS == 2)
+ ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0 | MDCTL_SDE1);
+#else
+#error "Unsupported DDRC_NUM_CS"
+#endif
+
+ /* 8a. dram init sequence: update MRs for ZQ, ODT, PRE, etc */
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(8) |
+ MDSCR_ENABLE_CON_REQ |
+ CMD_LOAD_MODE_REG |
+ CMD_BANK_ADDR_2);
+
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0) |
+ MDSCR_ENABLE_CON_REQ |
+ CMD_LOAD_MODE_REG |
+ CMD_BANK_ADDR_3);
+
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) |
+ MDSCR_ENABLE_CON_REQ |
+ CMD_LOAD_MODE_REG |
+ CMD_BANK_ADDR_1);
+
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x19) |
+ CMD_ADDR_LSB_MR_ADDR(0x30) |
+ MDSCR_ENABLE_CON_REQ |
+ CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0);
+
+ /* 8b. ZQ calibration */
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x4) |
+ MDSCR_ENABLE_CON_REQ |
+ CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0);
+
+ set_wait_for_bits_clear(&mmdc->mpzqhwctrl, priv->mpzqhwctrl,
+ MPZQHWCTRL_ZQ_HW_FORCE);
+
+ /* 9a. calibrations now, wr lvl */
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0x84) | MDSCR_WL_EN |
+ MDSCR_ENABLE_CON_REQ |
+ CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1);
+
+ set_wait_for_bits_clear(&mmdc->mpwlgcr, MPWLGCR_HW_WL_EN,
+ MPWLGCR_HW_WL_EN);
+
+ mdelay(1);
+
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) |
+ MDSCR_ENABLE_CON_REQ |
+ CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1);
+
+ ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ);
+
+ mdelay(1);
+
+ /* 9b. read DQS gating calibration */
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ |
+ CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0);
+
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ |
+ CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3);
+
+ ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN);
+
+ /* set absolute read delay offset */
+ if (priv->mprddlctl != 0) {
+ ddr_out32(&mmdc->mprddlctl, priv->mprddlctl);
+ } else {
+ ddr_out32(&mmdc->mprddlctl, MMDC_MPRDDLCTL_DEFAULT_DELAY);
+ }
+
+ set_wait_for_bits_clear(&mmdc->mpdgctrl0,
+ AUTO_RD_DQS_GATING_CALIBRATION_EN,
+ AUTO_RD_DQS_GATING_CALIBRATION_EN);
+
+ ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG |
+ CMD_BANK_ADDR_3);
+
+ /* 9c. read calibration */
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ |
+ CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0);
+ ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ |
+ CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3);
+ ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN);
+ set_wait_for_bits_clear(&mmdc->mprddlhwctl,
+ MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN,
+ MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN);
+
+ ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG |
+ CMD_BANK_ADDR_3);
+
+ /* 10. configure power-down, self-refresh entry, exit parameters */
+ ddr_out32(&mmdc->mdpdc, priv->mdpdc);
+ ddr_out32(&mmdc->mapsr, MMDC_MAPSR_PWR_SAV_CTRL_STAT);
+
+ /* 11. ZQ config again? do nothing here */
+
+ /* 12. refresh scheme */
+ set_wait_for_bits_clear(&mmdc->mdref, priv->mdref,
+ MDREF_START_REFRESH);
+
+ /* 13. disable CON_REQ */
+ ddr_out32(&mmdc->mdscr, MDSCR_DISABLE_CFG_REQ);
+}
diff --git a/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h b/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h
new file mode 100644
index 0000000000..31db55230e
--- /dev/null
+++ b/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef FSL_MMDC_H
+#define FSL_MMDC_H
+
+/* PHY Write Leveling Configuration and Error Status Register (MPWLGCR) */
+#define MPWLGCR_HW_WL_EN (1 << 0)
+
+/* PHY Pre-defined Compare and CA delay-line Configuration (MPPDCMPR2) */
+#define MPPDCMPR2_MPR_COMPARE_EN (1 << 0)
+
+
+/* MMDC PHY Read DQS gating control register 0 (MPDGCTRL0) */
+#define AUTO_RD_DQS_GATING_CALIBRATION_EN (1 << 28)
+
+/* MMDC PHY Read Delay HW Calibration Control Register (MPRDDLHWCTL) */
+#define MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN (1 << 4)
+
+/* MMDC Core Power Saving Control and Status Register (MMDC_MAPSR) */
+#define MMDC_MAPSR_PWR_SAV_CTRL_STAT 0x00001067
+
+/* MMDC Core Refresh Control Register (MMDC_MDREF) */
+#define MDREF_START_REFRESH (1 << 0)
+
+/* MMDC Core Special Command Register (MDSCR) */
+#define CMD_ADDR_MSB_MR_OP(x) (x << 24)
+#define CMD_ADDR_LSB_MR_ADDR(x) (x << 16)
+#define MDSCR_DISABLE_CFG_REQ (0 << 15)
+#define MDSCR_ENABLE_CON_REQ (1 << 15)
+#define MDSCR_CON_ACK (1 << 14)
+#define MDSCR_WL_EN (1 << 9)
+#define CMD_NORMAL (0 << 4)
+#define CMD_PRECHARGE (1 << 4)
+#define CMD_AUTO_REFRESH (2 << 4)
+#define CMD_LOAD_MODE_REG (3 << 4)
+#define CMD_ZQ_CALIBRATION (4 << 4)
+#define CMD_PRECHARGE_BANK_OPEN (5 << 4)
+#define CMD_MRR (6 << 4)
+#define CMD_BANK_ADDR_0 0x0
+#define CMD_BANK_ADDR_1 0x1
+#define CMD_BANK_ADDR_2 0x2
+#define CMD_BANK_ADDR_3 0x3
+#define CMD_BANK_ADDR_4 0x4
+#define CMD_BANK_ADDR_5 0x5
+#define CMD_BANK_ADDR_6 0x6
+#define CMD_BANK_ADDR_7 0x7
+
+/* MMDC Core Control Register (MDCTL) */
+#define MDCTL_SDE0 (U(1) << 31)
+#define MDCTL_SDE1 (1 << 30)
+
+/* MMDC PHY ZQ HW control register (MMDC_MPZQHWCTRL) */
+#define MPZQHWCTRL_ZQ_HW_FORCE (1 << 16)
+
+/* MMDC PHY Measure Unit Register (MMDC_MPMUR0) */
+#define MMDC_MPMUR0_FRC_MSR (1 << 11)
+
+/* MMDC PHY Read delay-lines Configuration Register (MMDC_MPRDDLCTL) */
+/* default 64 for a quarter cycle delay */
+#define MMDC_MPRDDLCTL_DEFAULT_DELAY 0x40404040
+
+/* MMDC Registers */
+struct mmdc_regs {
+ unsigned int mdctl;
+ unsigned int mdpdc;
+ unsigned int mdotc;
+ unsigned int mdcfg0;
+ unsigned int mdcfg1;
+ unsigned int mdcfg2;
+ unsigned int mdmisc;
+ unsigned int mdscr;
+ unsigned int mdref;
+ unsigned int res1[2];
+ unsigned int mdrwd;
+ unsigned int mdor;
+ unsigned int mdmrr;
+ unsigned int mdcfg3lp;
+ unsigned int mdmr4;
+ unsigned int mdasp;
+ unsigned int res2[239];
+ unsigned int maarcr;
+ unsigned int mapsr;
+ unsigned int maexidr0;
+ unsigned int maexidr1;
+ unsigned int madpcr0;
+ unsigned int madpcr1;
+ unsigned int madpsr0;
+ unsigned int madpsr1;
+ unsigned int madpsr2;
+ unsigned int madpsr3;
+ unsigned int madpsr4;
+ unsigned int madpsr5;
+ unsigned int masbs0;
+ unsigned int masbs1;
+ unsigned int res3[2];
+ unsigned int magenp;
+ unsigned int res4[239];
+ unsigned int mpzqhwctrl;
+ unsigned int mpzqswctrl;
+ unsigned int mpwlgcr;
+ unsigned int mpwldectrl0;
+ unsigned int mpwldectrl1;
+ unsigned int mpwldlst;
+ unsigned int mpodtctrl;
+ unsigned int mprddqby0dl;
+ unsigned int mprddqby1dl;
+ unsigned int mprddqby2dl;
+ unsigned int mprddqby3dl;
+ unsigned int mpwrdqby0dl;
+ unsigned int mpwrdqby1dl;
+ unsigned int mpwrdqby2dl;
+ unsigned int mpwrdqby3dl;
+ unsigned int mpdgctrl0;
+ unsigned int mpdgctrl1;
+ unsigned int mpdgdlst0;
+ unsigned int mprddlctl;
+ unsigned int mprddlst;
+ unsigned int mpwrdlctl;
+ unsigned int mpwrdlst;
+ unsigned int mpsdctrl;
+ unsigned int mpzqlp2ctl;
+ unsigned int mprddlhwctl;
+ unsigned int mpwrdlhwctl;
+ unsigned int mprddlhwst0;
+ unsigned int mprddlhwst1;
+ unsigned int mpwrdlhwst0;
+ unsigned int mpwrdlhwst1;
+ unsigned int mpwlhwerr;
+ unsigned int mpdghwst0;
+ unsigned int mpdghwst1;
+ unsigned int mpdghwst2;
+ unsigned int mpdghwst3;
+ unsigned int mppdcmpr1;
+ unsigned int mppdcmpr2;
+ unsigned int mpswdar0;
+ unsigned int mpswdrdr0;
+ unsigned int mpswdrdr1;
+ unsigned int mpswdrdr2;
+ unsigned int mpswdrdr3;
+ unsigned int mpswdrdr4;
+ unsigned int mpswdrdr5;
+ unsigned int mpswdrdr6;
+ unsigned int mpswdrdr7;
+ unsigned int mpmur0;
+ unsigned int mpwrcadl;
+ unsigned int mpdccr;
+};
+
+struct fsl_mmdc_info {
+ unsigned int mdctl;
+ unsigned int mdpdc;
+ unsigned int mdotc;
+ unsigned int mdcfg0;
+ unsigned int mdcfg1;
+ unsigned int mdcfg2;
+ unsigned int mdmisc;
+ unsigned int mdref;
+ unsigned int mdrwd;
+ unsigned int mdor;
+ unsigned int mdasp;
+ unsigned int mpodtctrl;
+ unsigned int mpzqhwctrl;
+ unsigned int mprddlctl;
+};
+
+void mmdc_init(const struct fsl_mmdc_info *priv, uintptr_t nxp_ddr_addr);
+
+#endif /* FSL_MMDC_H */
diff --git a/drivers/nxp/ddr/include/ddr.h b/drivers/nxp/ddr/include/ddr.h
new file mode 100644
index 0000000000..0ef28706fb
--- /dev/null
+++ b/drivers/nxp/ddr/include/ddr.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DDR_H
+#define DDR_H
+
+#include "ddr_io.h"
+#include "dimm.h"
+#include "immap.h"
+
+#ifndef DDRC_NUM_CS
+#define DDRC_NUM_CS 4
+#endif
+
+/*
+ * This is irrespective of what is the number of DDR controller,
+ * number of DIMM used. This is set to maximum
+ * Max controllers = 2
+ * Max num of DIMM per controlle = 2
+ * MAX NUM CS = 4
+ * Not to be changed.
+ */
+#define MAX_DDRC_NUM 2
+#define MAX_DIMM_NUM 2
+#define MAX_CS_NUM 4
+
+#include "opts.h"
+#include "regs.h"
+#include "utility.h"
+
+#ifdef DDR_DEBUG
+#define debug(...) INFO(__VA_ARGS__)
+#else
+#define debug(...) VERBOSE(__VA_ARGS__)
+#endif
+
+#ifndef DDRC_NUM_DIMM
+#define DDRC_NUM_DIMM 1
+#endif
+
+#define CONFIG_CS_PER_SLOT \
+ (DDRC_NUM_CS / DDRC_NUM_DIMM)
+
+/* Record of register values computed */
+struct ddr_cfg_regs {
+ struct {
+ unsigned int bnds;
+ unsigned int config;
+ unsigned int config_2;
+ } cs[MAX_CS_NUM];
+ unsigned int dec[10];
+ unsigned int timing_cfg[10];
+ unsigned int sdram_cfg[3];
+ unsigned int sdram_mode[16];
+ unsigned int md_cntl;
+ unsigned int interval;
+ unsigned int data_init;
+ unsigned int clk_cntl;
+ unsigned int init_addr;
+ unsigned int init_ext_addr;
+ unsigned int zq_cntl;
+ unsigned int wrlvl_cntl[3];
+ unsigned int ddr_sr_cntr;
+ unsigned int sdram_rcw[6];
+ unsigned int dq_map[4];
+ unsigned int eor;
+ unsigned int cdr[2];
+ unsigned int err_disable;
+ unsigned int err_int_en;
+ unsigned int tx_cfg[4];
+ unsigned int debug[64];
+};
+
+struct ddr_conf {
+ int dimm_in_use[MAX_DIMM_NUM];
+ int cs_in_use; /* bitmask, bit 0 for cs0, bit 1 for cs1, etc. */
+ int cs_on_dimm[MAX_DIMM_NUM]; /* bitmask */
+ unsigned long long cs_base_addr[MAX_CS_NUM];
+ unsigned long long cs_size[MAX_CS_NUM];
+ unsigned long long base_addr;
+ unsigned long long total_mem;
+};
+
+struct ddr_info {
+ unsigned long clk;
+ unsigned long long mem_base;
+ unsigned int num_ctlrs;
+ unsigned int dimm_on_ctlr;
+ struct dimm_params dimm;
+ struct memctl_opt opt;
+ struct ddr_conf conf;
+ struct ddr_cfg_regs ddr_reg;
+ struct ccsr_ddr *ddr[MAX_DDRC_NUM];
+ uint16_t *phy[MAX_DDRC_NUM];
+ int *spd_addr;
+ unsigned int ip_rev;
+ uintptr_t phy_gen2_fw_img_buf;
+ void *img_loadr;
+ int warm_boot_flag;
+};
+
+struct rc_timing {
+ unsigned int speed_bin;
+ unsigned int clk_adj;
+ unsigned int wrlvl;
+};
+
+struct board_timing {
+ unsigned int rc;
+ struct rc_timing const *p;
+ unsigned int add1;
+ unsigned int add2;
+};
+
+enum warm_boot {
+ DDR_COLD_BOOT = 0,
+ DDR_WARM_BOOT = 1,
+ DDR_WRM_BOOT_NT_SUPPORTED = -1,
+};
+
+int disable_unused_ddrc(struct ddr_info *priv, int mask,
+ uintptr_t nxp_ccn_hn_f0_addr);
+int ddr_board_options(struct ddr_info *priv);
+int compute_ddrc(const unsigned long clk,
+ const struct memctl_opt *popts,
+ const struct ddr_conf *conf,
+ struct ddr_cfg_regs *ddr,
+ const struct dimm_params *dimm_params,
+ const unsigned int ip_rev);
+int compute_ddr_phy(struct ddr_info *priv);
+int ddrc_set_regs(const unsigned long clk,
+ const struct ddr_cfg_regs *regs,
+ const struct ccsr_ddr *ddr,
+ int twopass);
+int cal_board_params(struct ddr_info *priv,
+ const struct board_timing *dimm,
+ int len);
+/* return bit mask of used DIMM(s) */
+int ddr_get_ddr_params(struct dimm_params *pdimm, struct ddr_conf *conf);
+long long dram_init(struct ddr_info *priv
+#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
+ , uintptr_t nxp_ccn_hn_f0_addr
+#endif
+ );
+long long board_static_ddr(struct ddr_info *info);
+
+#endif /* DDR_H */
diff --git a/drivers/nxp/ddr/include/ddr_io.h b/drivers/nxp/ddr/include/ddr_io.h
new file mode 100644
index 0000000000..fbd7e974d5
--- /dev/null
+++ b/drivers/nxp/ddr/include/ddr_io.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DDR_IO_H
+#define DDR_IO_H
+
+#include <endian.h>
+
+#include <lib/mmio.h>
+
+#define min(a, b) (((a) > (b)) ? (b) : (a))
+
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+
+/* macro for memory barrier */
+#define mb() asm volatile("dsb sy" : : : "memory")
+
+#ifdef NXP_DDR_BE
+#define ddr_in32(a) bswap32(mmio_read_32((uintptr_t)(a)))
+#define ddr_out32(a, v) mmio_write_32((uintptr_t)(a),\
+ bswap32(v))
+#elif defined(NXP_DDR_LE)
+#define ddr_in32(a) mmio_read_32((uintptr_t)(a))
+#define ddr_out32(a, v) mmio_write_32((uintptr_t)(a), v)
+#else
+#error Please define CCSR DDR register endianness
+#endif
+
+#define ddr_setbits32(a, v) ddr_out32((a), ddr_in32(a) | (v))
+#define ddr_clrbits32(a, v) ddr_out32((a), ddr_in32(a) & ~(v))
+#define ddr_clrsetbits32(a, c, s) ddr_out32((a), (ddr_in32(a) & ~(c)) \
+ | (s))
+
+#endif /* DDR_IO_H */
diff --git a/drivers/nxp/ddr/include/dimm.h b/drivers/nxp/ddr/include/dimm.h
new file mode 100644
index 0000000000..fcae179845
--- /dev/null
+++ b/drivers/nxp/ddr/include/dimm.h
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DIMM_H
+#define DIMM_H
+
+#define SPD_MEMTYPE_DDR4 0x0C
+
+#define DDR4_SPD_MODULETYPE_MASK 0x0f
+#define DDR4_SPD_MODULETYPE_EXT 0x00
+#define DDR4_SPD_RDIMM 0x01
+#define DDR4_SPD_UDIMM 0x02
+#define DDR4_SPD_SO_DIMM 0x03
+#define DDR4_SPD_LRDIMM 0x04
+#define DDR4_SPD_MINI_RDIMM 0x05
+#define DDR4_SPD_MINI_UDIMM 0x06
+#define DDR4_SPD_72B_SO_RDIMM 0x08
+#define DDR4_SPD_72B_SO_UDIMM 0x09
+#define DDR4_SPD_16B_SO_DIMM 0x0c
+#define DDR4_SPD_32B_SO_DIMM 0x0d
+
+#define SPD_SPA0_ADDRESS 0x36
+#define SPD_SPA1_ADDRESS 0x37
+
+#define spd_to_ps(mtb, ftb) \
+ ((mtb) * pdimm->mtb_ps + ((ftb) * pdimm->ftb_10th_ps) / 10)
+
+#ifdef DDR_DEBUG
+#define dump_spd(spd, len) { \
+ register int i; \
+ register unsigned char *buf = (void *)(spd); \
+ \
+ for (i = 0; i < (len); i++) { \
+ print_uint(i); \
+ puts("\t: 0x"); \
+ print_hex(buf[i]); \
+ puts("\n"); \
+ } \
+}
+#else
+#define dump_spd(spd, len) {}
+#endif
+
+/* From JEEC Standard No. 21-C release 23A */
+struct ddr4_spd {
+ /* General Section: Bytes 0-127 */
+ unsigned char info_size_crc; /* 0 # bytes */
+ unsigned char spd_rev; /* 1 Total # bytes of SPD */
+ unsigned char mem_type; /* 2 Key Byte / mem type */
+ unsigned char module_type; /* 3 Key Byte / Module Type */
+ unsigned char density_banks; /* 4 Density and Banks */
+ unsigned char addressing; /* 5 Addressing */
+ unsigned char package_type; /* 6 Package type */
+ unsigned char opt_feature; /* 7 Optional features */
+ unsigned char thermal_ref; /* 8 Thermal and refresh */
+ unsigned char oth_opt_features; /* 9 Other optional features */
+ unsigned char res_10; /* 10 Reserved */
+ unsigned char module_vdd; /* 11 Module nominal voltage */
+ unsigned char organization; /* 12 Module Organization */
+ unsigned char bus_width; /* 13 Module Memory Bus Width */
+ unsigned char therm_sensor; /* 14 Module Thermal Sensor */
+ unsigned char ext_type; /* 15 Extended module type */
+ unsigned char res_16;
+ unsigned char timebases; /* 17 MTb and FTB */
+ unsigned char tck_min; /* 18 tCKAVGmin */
+ unsigned char tck_max; /* 19 TCKAVGmax */
+ unsigned char caslat_b1; /* 20 CAS latencies, 1st byte */
+ unsigned char caslat_b2; /* 21 CAS latencies, 2nd byte */
+ unsigned char caslat_b3; /* 22 CAS latencies, 3rd byte */
+ unsigned char caslat_b4; /* 23 CAS latencies, 4th byte */
+ unsigned char taa_min; /* 24 Min CAS Latency Time */
+ unsigned char trcd_min; /* 25 Min RAS# to CAS# Delay Time */
+ unsigned char trp_min; /* 26 Min Row Precharge Delay Time */
+ unsigned char tras_trc_ext; /* 27 Upper Nibbles for tRAS and tRC */
+ unsigned char tras_min_lsb; /* 28 tRASmin, lsb */
+ unsigned char trc_min_lsb; /* 29 tRCmin, lsb */
+ unsigned char trfc1_min_lsb; /* 30 Min Refresh Recovery Delay Time */
+ unsigned char trfc1_min_msb; /* 31 Min Refresh Recovery Delay Time */
+ unsigned char trfc2_min_lsb; /* 32 Min Refresh Recovery Delay Time */
+ unsigned char trfc2_min_msb; /* 33 Min Refresh Recovery Delay Time */
+ unsigned char trfc4_min_lsb; /* 34 Min Refresh Recovery Delay Time */
+ unsigned char trfc4_min_msb; /* 35 Min Refresh Recovery Delay Time */
+ unsigned char tfaw_msb; /* 36 Upper Nibble for tFAW */
+ unsigned char tfaw_min; /* 37 tFAW, lsb */
+ unsigned char trrds_min; /* 38 tRRD_Smin, MTB */
+ unsigned char trrdl_min; /* 39 tRRD_Lmin, MTB */
+ unsigned char tccdl_min; /* 40 tCCS_Lmin, MTB */
+ unsigned char res_41[60-41]; /* 41 Rserved */
+ unsigned char mapping[78-60]; /* 60~77 Connector to SDRAM bit map */
+ unsigned char res_78[117-78]; /* 78~116, Reserved */
+ signed char fine_tccdl_min; /* 117 Fine offset for tCCD_Lmin */
+ signed char fine_trrdl_min; /* 118 Fine offset for tRRD_Lmin */
+ signed char fine_trrds_min; /* 119 Fine offset for tRRD_Smin */
+ signed char fine_trc_min; /* 120 Fine offset for tRCmin */
+ signed char fine_trp_min; /* 121 Fine offset for tRPmin */
+ signed char fine_trcd_min; /* 122 Fine offset for tRCDmin */
+ signed char fine_taa_min; /* 123 Fine offset for tAAmin */
+ signed char fine_tck_max; /* 124 Fine offset for tCKAVGmax */
+ signed char fine_tck_min; /* 125 Fine offset for tCKAVGmin */
+ /* CRC: Bytes 126-127 */
+ unsigned char crc[2]; /* 126-127 SPD CRC */
+
+ /* Module-Specific Section: Bytes 128-255 */
+ union {
+ struct {
+ /* 128 (Unbuffered) Module Nominal Height */
+ unsigned char mod_height;
+ /* 129 (Unbuffered) Module Maximum Thickness */
+ unsigned char mod_thickness;
+ /* 130 (Unbuffered) Reference Raw Card Used */
+ unsigned char ref_raw_card;
+ /* 131 (Unbuffered) Address Mapping from
+ * Edge Connector to DRAM
+ */
+ unsigned char addr_mapping;
+ /* 132~253 (Unbuffered) Reserved */
+ unsigned char res_132[254-132];
+ /* 254~255 CRC */
+ unsigned char crc[2];
+ } unbuffered;
+ struct {
+ /* 128 (Registered) Module Nominal Height */
+ unsigned char mod_height;
+ /* 129 (Registered) Module Maximum Thickness */
+ unsigned char mod_thickness;
+ /* 130 (Registered) Reference Raw Card Used */
+ unsigned char ref_raw_card;
+ /* 131 DIMM Module Attributes */
+ unsigned char modu_attr;
+ /* 132 RDIMM Thermal Heat Spreader Solution */
+ unsigned char thermal;
+ /* 133 Register Manufacturer ID Code, LSB */
+ unsigned char reg_id_lo;
+ /* 134 Register Manufacturer ID Code, MSB */
+ unsigned char reg_id_hi;
+ /* 135 Register Revision Number */
+ unsigned char reg_rev;
+ /* 136 Address mapping from register to DRAM */
+ unsigned char reg_map;
+ unsigned char ca_stren;
+ unsigned char clk_stren;
+ /* 139~253 Reserved */
+ unsigned char res_139[254-139];
+ /* 254~255 CRC */
+ unsigned char crc[2];
+ } registered;
+ struct {
+ /* 128 (Loadreduced) Module Nominal Height */
+ unsigned char mod_height;
+ /* 129 (Loadreduced) Module Maximum Thickness */
+ unsigned char mod_thickness;
+ /* 130 (Loadreduced) Reference Raw Card Used */
+ unsigned char ref_raw_card;
+ /* 131 DIMM Module Attributes */
+ unsigned char modu_attr;
+ /* 132 RDIMM Thermal Heat Spreader Solution */
+ unsigned char thermal;
+ /* 133 Register Manufacturer ID Code, LSB */
+ unsigned char reg_id_lo;
+ /* 134 Register Manufacturer ID Code, MSB */
+ unsigned char reg_id_hi;
+ /* 135 Register Revision Number */
+ unsigned char reg_rev;
+ /* 136 Address mapping from register to DRAM */
+ unsigned char reg_map;
+ /* 137 Register Output Drive Strength for CMD/Add*/
+ unsigned char reg_drv;
+ /* 138 Register Output Drive Strength for CK */
+ unsigned char reg_drv_ck;
+ /* 139 Data Buffer Revision Number */
+ unsigned char data_buf_rev;
+ /* 140 DRAM VrefDQ for Package Rank 0 */
+ unsigned char vrefqe_r0;
+ /* 141 DRAM VrefDQ for Package Rank 1 */
+ unsigned char vrefqe_r1;
+ /* 142 DRAM VrefDQ for Package Rank 2 */
+ unsigned char vrefqe_r2;
+ /* 143 DRAM VrefDQ for Package Rank 3 */
+ unsigned char vrefqe_r3;
+ /* 144 Data Buffer VrefDQ for DRAM Interface */
+ unsigned char data_intf;
+ /*
+ * 145 Data Buffer MDQ Drive Strength and RTT
+ * for data rate <= 1866
+ */
+ unsigned char data_drv_1866;
+ /*
+ * 146 Data Buffer MDQ Drive Strength and RTT
+ * for 1866 < data rate <= 2400
+ */
+ unsigned char data_drv_2400;
+ /*
+ * 147 Data Buffer MDQ Drive Strength and RTT
+ * for 2400 < data rate <= 3200
+ */
+ unsigned char data_drv_3200;
+ /* 148 DRAM Drive Strength */
+ unsigned char dram_drv;
+ /*
+ * 149 DRAM ODT (RTT_WR, RTT_NOM)
+ * for data rate <= 1866
+ */
+ unsigned char dram_odt_1866;
+ /*
+ * 150 DRAM ODT (RTT_WR, RTT_NOM)
+ * for 1866 < data rate <= 2400
+ */
+ unsigned char dram_odt_2400;
+ /*
+ * 151 DRAM ODT (RTT_WR, RTT_NOM)
+ * for 2400 < data rate <= 3200
+ */
+ unsigned char dram_odt_3200;
+ /*
+ * 152 DRAM ODT (RTT_PARK)
+ * for data rate <= 1866
+ */
+ unsigned char dram_odt_park_1866;
+ /*
+ * 153 DRAM ODT (RTT_PARK)
+ * for 1866 < data rate <= 2400
+ */
+ unsigned char dram_odt_park_2400;
+ /*
+ * 154 DRAM ODT (RTT_PARK)
+ * for 2400 < data rate <= 3200
+ */
+ unsigned char dram_odt_park_3200;
+ unsigned char res_155[254-155]; /* Reserved */
+ /* 254~255 CRC */
+ unsigned char crc[2];
+ } loadreduced;
+ unsigned char uc[128]; /* 128-255 Module-Specific Section */
+ } mod_section;
+
+ unsigned char res_256[320-256]; /* 256~319 Reserved */
+
+ /* Module supplier's data: Byte 320~383 */
+ unsigned char mmid_lsb; /* 320 Module MfgID Code LSB */
+ unsigned char mmid_msb; /* 321 Module MfgID Code MSB */
+ unsigned char mloc; /* 322 Mfg Location */
+ unsigned char mdate[2]; /* 323~324 Mfg Date */
+ unsigned char sernum[4]; /* 325~328 Module Serial Number */
+ unsigned char mpart[20]; /* 329~348 Mfg's Module Part Number */
+ unsigned char mrev; /* 349 Module Revision Code */
+ unsigned char dmid_lsb; /* 350 DRAM MfgID Code LSB */
+ unsigned char dmid_msb; /* 351 DRAM MfgID Code MSB */
+ unsigned char stepping; /* 352 DRAM stepping */
+ unsigned char msd[29]; /* 353~381 Mfg's Specific Data */
+ unsigned char res_382[2]; /* 382~383 Reserved */
+};
+
+/* Parameters for a DDR dimm computed from the SPD */
+struct dimm_params {
+ /* DIMM organization parameters */
+ char mpart[19]; /* guaranteed null terminated */
+
+ unsigned int n_ranks;
+ unsigned int die_density;
+ unsigned long long rank_density;
+ unsigned long long capacity;
+ unsigned int primary_sdram_width;
+ unsigned int ec_sdram_width;
+ unsigned int rdimm;
+ unsigned int package_3ds; /* number of dies in 3DS */
+ unsigned int device_width; /* x4, x8, x16 components */
+ unsigned int rc;
+
+ /* SDRAM device parameters */
+ unsigned int n_row_addr;
+ unsigned int n_col_addr;
+ unsigned int edc_config; /* 0 = none, 1 = parity, 2 = ECC */
+ unsigned int bank_addr_bits;
+ unsigned int bank_group_bits;
+ unsigned int burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */
+
+ /* mirrored DIMMs */
+ unsigned int mirrored_dimm; /* only for ddr3 */
+
+ /* DIMM timing parameters */
+
+ int mtb_ps; /* medium timebase ps */
+ int ftb_10th_ps; /* fine timebase, in 1/10 ps */
+ int taa_ps; /* minimum CAS latency time */
+ int tfaw_ps; /* four active window delay */
+
+ /*
+ * SDRAM clock periods
+ * The range for these are 1000-10000 so a short should be sufficient
+ */
+ int tckmin_x_ps;
+ int tckmax_ps;
+
+ /* SPD-defined CAS latencies */
+ unsigned int caslat_x;
+
+ /* basic timing parameters */
+ int trcd_ps;
+ int trp_ps;
+ int tras_ps;
+
+ int trfc1_ps;
+ int trfc2_ps;
+ int trfc4_ps;
+ int trrds_ps;
+ int trrdl_ps;
+ int tccdl_ps;
+ int trfc_slr_ps;
+
+ int trc_ps; /* maximum = 254 ns + .75 ns = 254750 ps */
+ int twr_ps; /* 15ns for all speed bins */
+
+ unsigned int refresh_rate_ps;
+ unsigned int extended_op_srt;
+
+ /* RDIMM */
+ unsigned char rcw[16]; /* Register Control Word 0-15 */
+ unsigned int dq_mapping[18];
+ unsigned int dq_mapping_ors;
+};
+
+int read_spd(unsigned char chip, void *buf, int len);
+int crc16(unsigned char *ptr, int count);
+int cal_dimm_params(const struct ddr4_spd *spd, struct dimm_params *pdimm);
+
+#endif /* DIMM_H */
diff --git a/drivers/nxp/ddr/include/immap.h b/drivers/nxp/ddr/include/immap.h
new file mode 100644
index 0000000000..83b4de6ef7
--- /dev/null
+++ b/drivers/nxp/ddr/include/immap.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DDR_IMMAP_H
+#define DDR_IMMAP_H
+
+#define DDR_DBUS_64 0
+#define DDR_DBUS_32 1
+#define DDR_DBUS_16 2
+
+/*
+ * DDRC register file for DDRC 5.0 and above
+ */
+struct ccsr_ddr {
+ struct {
+ unsigned int a; /* 0x0, 0x8, 0x10, 0x18 */
+ unsigned int res; /* 0x4, 0xc, 0x14, 0x1c */
+ } bnds[4];
+ unsigned char res_20[0x40 - 0x20];
+ unsigned int dec[10]; /* 0x40 */
+ unsigned char res_68[0x80 - 0x68];
+ unsigned int csn_cfg[4]; /* 0x80, 0x84, 0x88, 0x8c */
+ unsigned char res_90[48];
+ unsigned int csn_cfg_2[4]; /* 0xc0, 0xc4, 0xc8, 0xcc */
+ unsigned char res_d0[48];
+ unsigned int timing_cfg_3; /* SDRAM Timing Configuration 3 */
+ unsigned int timing_cfg_0; /* SDRAM Timing Configuration 0 */
+ unsigned int timing_cfg_1; /* SDRAM Timing Configuration 1 */
+ unsigned int timing_cfg_2; /* SDRAM Timing Configuration 2 */
+ unsigned int sdram_cfg; /* SDRAM Control Configuration */
+ unsigned int sdram_cfg_2; /* SDRAM Control Configuration 2 */
+ unsigned int sdram_mode; /* SDRAM Mode Configuration */
+ unsigned int sdram_mode_2; /* SDRAM Mode Configuration 2 */
+ unsigned int sdram_md_cntl; /* SDRAM Mode Control */
+ unsigned int sdram_interval; /* SDRAM Interval Configuration */
+ unsigned int sdram_data_init; /* SDRAM Data initialization */
+ unsigned char res_12c[4];
+ unsigned int sdram_clk_cntl; /* SDRAM Clock Control */
+ unsigned char res_134[20];
+ unsigned int init_addr; /* training init addr */
+ unsigned int init_ext_addr; /* training init extended addr */
+ unsigned char res_150[16];
+ unsigned int timing_cfg_4; /* SDRAM Timing Configuration 4 */
+ unsigned int timing_cfg_5; /* SDRAM Timing Configuration 5 */
+ unsigned int timing_cfg_6; /* SDRAM Timing Configuration 6 */
+ unsigned int timing_cfg_7; /* SDRAM Timing Configuration 7 */
+ unsigned int zq_cntl; /* ZQ calibration control*/
+ unsigned int wrlvl_cntl; /* write leveling control*/
+ unsigned char reg_178[4];
+ unsigned int ddr_sr_cntr; /* self refresh counter */
+ unsigned int ddr_sdram_rcw_1; /* Control Words 1 */
+ unsigned int ddr_sdram_rcw_2; /* Control Words 2 */
+ unsigned char reg_188[8];
+ unsigned int ddr_wrlvl_cntl_2; /* write leveling control 2 */
+ unsigned int ddr_wrlvl_cntl_3; /* write leveling control 3 */
+ unsigned char res_198[0x1a0-0x198];
+ unsigned int ddr_sdram_rcw_3;
+ unsigned int ddr_sdram_rcw_4;
+ unsigned int ddr_sdram_rcw_5;
+ unsigned int ddr_sdram_rcw_6;
+ unsigned char res_1b0[0x200-0x1b0];
+ unsigned int sdram_mode_3; /* SDRAM Mode Configuration 3 */
+ unsigned int sdram_mode_4; /* SDRAM Mode Configuration 4 */
+ unsigned int sdram_mode_5; /* SDRAM Mode Configuration 5 */
+ unsigned int sdram_mode_6; /* SDRAM Mode Configuration 6 */
+ unsigned int sdram_mode_7; /* SDRAM Mode Configuration 7 */
+ unsigned int sdram_mode_8; /* SDRAM Mode Configuration 8 */
+ unsigned char res_218[0x220-0x218];
+ unsigned int sdram_mode_9; /* SDRAM Mode Configuration 9 */
+ unsigned int sdram_mode_10; /* SDRAM Mode Configuration 10 */
+ unsigned int sdram_mode_11; /* SDRAM Mode Configuration 11 */
+ unsigned int sdram_mode_12; /* SDRAM Mode Configuration 12 */
+ unsigned int sdram_mode_13; /* SDRAM Mode Configuration 13 */
+ unsigned int sdram_mode_14; /* SDRAM Mode Configuration 14 */
+ unsigned int sdram_mode_15; /* SDRAM Mode Configuration 15 */
+ unsigned int sdram_mode_16; /* SDRAM Mode Configuration 16 */
+ unsigned char res_240[0x250-0x240];
+ unsigned int timing_cfg_8; /* SDRAM Timing Configuration 8 */
+ unsigned int timing_cfg_9; /* SDRAM Timing Configuration 9 */
+ unsigned int timing_cfg_10; /* SDRAM Timing COnfigurtion 10 */
+ unsigned char res_258[0x260-0x25c];
+ unsigned int sdram_cfg_3;
+ unsigned char res_264[0x270-0x264];
+ unsigned int sdram_md_cntl_2;
+ unsigned char res_274[0x400-0x274];
+ unsigned int dq_map[4];
+ unsigned char res_410[0x800-0x410];
+ unsigned int tx_cfg[4];
+ unsigned char res_810[0xb20-0x810];
+ unsigned int ddr_dsr1; /* Debug Status 1 */
+ unsigned int ddr_dsr2; /* Debug Status 2 */
+ unsigned int ddr_cdr1; /* Control Driver 1 */
+ unsigned int ddr_cdr2; /* Control Driver 2 */
+ unsigned char res_b30[200];
+ unsigned int ip_rev1; /* IP Block Revision 1 */
+ unsigned int ip_rev2; /* IP Block Revision 2 */
+ unsigned int eor; /* Enhanced Optimization Register */
+ unsigned char res_c04[252];
+ unsigned int mtcr; /* Memory Test Control Register */
+ unsigned char res_d04[28];
+ unsigned int mtp[10]; /* Memory Test Patterns */
+ unsigned char res_d48[184];
+ unsigned int data_err_inject_hi; /* Data Path Err Injection Mask Hi*/
+ unsigned int data_err_inject_lo;/* Data Path Err Injection Mask Lo*/
+ unsigned int ecc_err_inject; /* Data Path Err Injection Mask ECC */
+ unsigned char res_e0c[20];
+ unsigned int capture_data_hi; /* Data Path Read Capture High */
+ unsigned int capture_data_lo; /* Data Path Read Capture Low */
+ unsigned int capture_ecc; /* Data Path Read Capture ECC */
+ unsigned char res_e2c[20];
+ unsigned int err_detect; /* Error Detect */
+ unsigned int err_disable; /* Error Disable */
+ unsigned int err_int_en;
+ unsigned int capture_attributes; /* Error Attrs Capture */
+ unsigned int capture_address; /* Error Addr Capture */
+ unsigned int capture_ext_address; /* Error Extended Addr Capture */
+ unsigned int err_sbe; /* Single-Bit ECC Error Management */
+ unsigned char res_e5c[164];
+ unsigned int debug[64]; /* debug_1 to debug_64 */
+};
+#endif /* DDR_IMMAP_H */
diff --git a/drivers/nxp/ddr/include/opts.h b/drivers/nxp/ddr/include/opts.h
new file mode 100644
index 0000000000..f32891bc85
--- /dev/null
+++ b/drivers/nxp/ddr/include/opts.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DDR_OPTS_H
+#define DDR_OPTS_H
+
+#define SDRAM_TYPE_DDR4 5 /* sdram_cfg register */
+
+#define DDR_BC4 4 /* burst chop */
+#define DDR_OTF 6 /* on-the-fly BC4 and BL8 */
+#define DDR_BL8 8 /* burst length 8 */
+
+#define DDR4_RTT_OFF 0
+#define DDR4_RTT_60_OHM 1 /* RZQ/4 */
+#define DDR4_RTT_120_OHM 2 /* RZQ/2 */
+#define DDR4_RTT_40_OHM 3 /* RZQ/6 */
+#define DDR4_RTT_240_OHM 4 /* RZQ/1 */
+#define DDR4_RTT_48_OHM 5 /* RZQ/5 */
+#define DDR4_RTT_80_OHM 6 /* RZQ/3 */
+#define DDR4_RTT_34_OHM 7 /* RZQ/7 */
+#define DDR4_RTT_WR_OFF 0
+#define DDR4_RTT_WR_120_OHM 1
+#define DDR4_RTT_WR_240_OHM 2
+#define DDR4_RTT_WR_HZ 3
+#define DDR4_RTT_WR_80_OHM 4
+#define DDR_ODT_NEVER 0x0
+#define DDR_ODT_CS 0x1
+#define DDR_ODT_ALL_OTHER_CS 0x2
+#define DDR_ODT_OTHER_DIMM 0x3
+#define DDR_ODT_ALL 0x4
+#define DDR_ODT_SAME_DIMM 0x5
+#define DDR_ODT_CS_AND_OTHER_DIMM 0x6
+#define DDR_ODT_OTHER_CS_ONSAMEDIMM 0x7
+#define DDR_BA_INTLV_CS01 0x40
+#define DDR_BA_INTLV_CS0123 0x64
+#define DDR_BA_NONE 0
+#define DDR_256B_INTLV 0x8
+
+struct memctl_opt {
+ int rdimm;
+ unsigned int dbw_cap_shift;
+ struct local_opts_s {
+ unsigned int auto_precharge;
+ unsigned int odt_rd_cfg;
+ unsigned int odt_wr_cfg;
+ unsigned int odt_rtt_norm;
+ unsigned int odt_rtt_wr;
+ } cs_odt[DDRC_NUM_CS];
+ int ctlr_intlv;
+ unsigned int ctlr_intlv_mode;
+ unsigned int ba_intlv;
+ int addr_hash;
+ int ecc_mode;
+ int ctlr_init_ecc;
+ int self_refresh_in_sleep;
+ int self_refresh_irq_en;
+ int dynamic_power;
+ /* memory data width 0 = 64-bit, 1 = 32-bit, 2 = 16-bit */
+ unsigned int data_bus_dimm;
+ unsigned int data_bus_used; /* on individual board */
+ unsigned int burst_length; /* BC4, OTF and BL8 */
+ int otf_burst_chop_en;
+ int mirrored_dimm;
+ int quad_rank_present;
+ int output_driver_impedance;
+ int ap_en;
+ int x4_en;
+
+ int caslat_override;
+ unsigned int caslat_override_value;
+ int addt_lat_override;
+ unsigned int addt_lat_override_value;
+
+ unsigned int clk_adj;
+ unsigned int cpo_sample;
+ unsigned int wr_data_delay;
+
+ unsigned int cswl_override;
+ unsigned int wrlvl_override;
+ unsigned int wrlvl_sample;
+ unsigned int wrlvl_start;
+ unsigned int wrlvl_ctl_2;
+ unsigned int wrlvl_ctl_3;
+
+ int half_strength_drive_en;
+ int twot_en;
+ int threet_en;
+ unsigned int bstopre;
+ unsigned int tfaw_ps;
+
+ int rtt_override;
+ unsigned int rtt_override_value;
+ unsigned int rtt_wr_override_value;
+ unsigned int rtt_park;
+
+ int auto_self_refresh_en;
+ unsigned int sr_it;
+ unsigned int ddr_cdr1;
+ unsigned int ddr_cdr2;
+
+ unsigned int trwt_override;
+ unsigned int trwt;
+ unsigned int twrt;
+ unsigned int trrt;
+ unsigned int twwt;
+
+ unsigned int vref_phy;
+ unsigned int vref_dimm;
+ unsigned int odt;
+ unsigned int phy_tx_impedance;
+ unsigned int phy_atx_impedance;
+ unsigned int skip2d;
+};
+
+#endif /* DDR_OPTS_H */
diff --git a/drivers/nxp/ddr/include/regs.h b/drivers/nxp/ddr/include/regs.h
new file mode 100644
index 0000000000..e85fd8fa85
--- /dev/null
+++ b/drivers/nxp/ddr/include/regs.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DDR_REG_H
+#define DDR_REG_H
+
+#define SDRAM_CS_CONFIG_EN 0x80000000
+
+/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration
+ */
+#define SDRAM_CFG_MEM_EN 0x80000000
+#define SDRAM_CFG_SREN 0x40000000
+#define SDRAM_CFG_ECC_EN 0x20000000
+#define SDRAM_CFG_RD_EN 0x10000000
+#define SDRAM_CFG_SDRAM_TYPE_MASK 0x07000000
+#define SDRAM_CFG_SDRAM_TYPE_SHIFT 24
+#define SDRAM_CFG_DYN_PWR 0x00200000
+#define SDRAM_CFG_DBW_MASK 0x00180000
+#define SDRAM_CFG_DBW_SHIFT 19
+#define SDRAM_CFG_32_BW 0x00080000
+#define SDRAM_CFG_16_BW 0x00100000
+#define SDRAM_CFG_8_BW 0x00180000
+#define SDRAM_CFG_8_BE 0x00040000
+#define SDRAM_CFG_2T_EN 0x00008000
+#define SDRAM_CFG_MEM_HLT 0x00000002
+#define SDRAM_CFG_BI 0x00000001
+
+#define SDRAM_CFG2_FRC_SR 0x80000000
+#define SDRAM_CFG2_FRC_SR_CLEAR ~(SDRAM_CFG2_FRC_SR)
+#define SDRAM_CFG2_D_INIT 0x00000010
+#define SDRAM_CFG2_AP_EN 0x00000020
+#define SDRAM_CFG2_ODT_ONLY_READ 2
+
+#define SDRAM_CFG3_DDRC_RST 0x80000000
+
+#define SDRAM_INTERVAL_REFINT 0xFFFF0000
+#define SDRAM_INTERVAL_REFINT_CLEAR ~(SDRAM_INTERVAL_REFINT)
+#define SDRAM_INTERVAL_BSTOPRE 0x3FFF
+
+/* DDR_MD_CNTL */
+#define MD_CNTL_MD_EN 0x80000000
+#define MD_CNTL_CS_SEL(x) (((x) & 0x7) << 28)
+#define MD_CNTL_MD_SEL(x) (((x) & 0xf) << 24)
+#define MD_CNTL_CKE(x) (((x) & 0x3) << 20)
+
+/* DDR_CDR1 */
+#define DDR_CDR1_DHC_EN 0x80000000
+#define DDR_CDR1_ODT_SHIFT 17
+#define DDR_CDR1_ODT_MASK 0x6
+#define DDR_CDR2_ODT_MASK 0x1
+#define DDR_CDR1_ODT(x) ((x & DDR_CDR1_ODT_MASK) << DDR_CDR1_ODT_SHIFT)
+#define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK)
+#define DDR_CDR2_VREF_OVRD(x) (0x00008080 | ((((x) - 37) & 0x3F) << 8))
+#define DDR_CDR2_VREF_TRAIN_EN 0x00000080
+#define DDR_CDR2_VREF_RANGE_2 0x00000040
+#define DDR_CDR_ODT_OFF 0x0
+#define DDR_CDR_ODT_100ohm 0x1
+#define DDR_CDR_ODT_120OHM 0x2
+#define DDR_CDR_ODT_80ohm 0x3
+#define DDR_CDR_ODT_60ohm 0x4
+#define DDR_CDR_ODT_40ohm 0x5
+#define DDR_CDR_ODT_50ohm 0x6
+#define DDR_CDR_ODT_30ohm 0x7
+
+
+/* DDR ERR_DISABLE */
+#define DDR_ERR_DISABLE_APED (1 << 8) /* Address parity error disable */
+#define DDR_ERR_DISABLE_SBED (1 << 2) /* Address parity error disable */
+#define DDR_ERR_DISABLE_MBED (1 << 3) /* Address parity error disable */
+
+/* Mode Registers */
+#define DDR_MR5_CA_PARITY_LAT_4_CLK 0x1 /* for DDR4-1600/1866/2133 */
+#define DDR_MR5_CA_PARITY_LAT_5_CLK 0x2 /* for DDR4-2400 */
+
+/* DDR DSR2 register */
+#define DDR_DSR_2_PHY_INIT_CMPLT 0x4
+
+/* SDRAM TIMING_CFG_10 register */
+#define DDR_TIMING_CFG_10_T_STAB 0x7FFF
+
+/* DEBUG 2 register */
+#define DDR_DBG_2_MEM_IDLE 0x00000002
+
+/* DEBUG 26 register */
+#define DDR_DEBUG_26_BIT_6 (0x1 << 6)
+#define DDR_DEBUG_26_BIT_7 (0x1 << 7)
+#define DDR_DEBUG_26_BIT_12 (0x1 << 12)
+#define DDR_DEBUG_26_BIT_13 (0x1 << 13)
+#define DDR_DEBUG_26_BIT_14 (0x1 << 14)
+#define DDR_DEBUG_26_BIT_15 (0x1 << 15)
+#define DDR_DEBUG_26_BIT_16 (0x1 << 16)
+#define DDR_DEBUG_26_BIT_17 (0x1 << 17)
+#define DDR_DEBUG_26_BIT_18 (0x1 << 18)
+#define DDR_DEBUG_26_BIT_19 (0x1 << 19)
+#define DDR_DEBUG_26_BIT_24 (0x1 << 24)
+#define DDR_DEBUG_26_BIT_25 (0x1 << 25)
+
+#define DDR_DEBUG_26_BIT_24_CLEAR ~(DDR_DEBUG_26_BIT_24)
+
+/* DEBUG_29 register */
+#define DDR_TX_BD_DIS (1 << 10) /* Transmit Bit Deskew Disable */
+
+#define DDR_INIT_ADDR_EXT_UIA (1 << 31)
+
+#endif /* DDR_REG_H */
diff --git a/drivers/nxp/ddr/include/utility.h b/drivers/nxp/ddr/include/utility.h
new file mode 100644
index 0000000000..2e22ad5c36
--- /dev/null
+++ b/drivers/nxp/ddr/include/utility.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef UTILITY_H
+#define UTILITY_H
+
+#include <dcfg.h>
+
+#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
+#define CCN_HN_F_SAM_CTL 0x8
+#define CCN_HN_F_REGION_SIZE 0x10000
+#endif
+
+unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num);
+unsigned int get_memory_clk_ps(unsigned long clk);
+unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos);
+unsigned int get_ddrc_version(const struct ccsr_ddr *ddr);
+void print_ddr_info(struct ccsr_ddr *ddr);
+
+#endif
diff --git a/drivers/nxp/ddr/nxp-ddr/README.odt b/drivers/nxp/ddr/nxp-ddr/README.odt
new file mode 100644
index 0000000000..8796302836
--- /dev/null
+++ b/drivers/nxp/ddr/nxp-ddr/README.odt
@@ -0,0 +1,31 @@
+Table for dynamic ODT for DDR4 with PHY generation 2
+====================================================
+Two-slot system
+Only symmetric configurations are supported for interleaving. Non-symmetric
+configurations are possible but not covered here. First slot empty is possbile
+but prohibited for simplicity.
++-----------------------+-------------+---------------+-----------------------------+-----------------------------+
+| Configuration | |DRAM controller| Slot 1 | Slot 2 |
++-----------+-----------+-------------+-------+-------+--------------+--------------+--------------+--------------+
+| | | | | | Rank 1 | Rank 2 | Rank 1 | Rank 2 |
+| Slot 1 | Slot 2 | Write/Read | Write | Read |-------+------+-------+------+-------+------+-------+------+
+| | | | | | Write | Read | Write | Read | Write | Read | Write | Read |
++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+| | | |Rank 1| off | 60 | 240 | off | 60 | 240 | 60 | 60 | 60 | 60 |
+| | |Slot 1|------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+| | | |Rank 2| off | 60 | 60 | 240 | 240 | off | 60 | 60 | 60 | 60 |
+| Dual Rank | Dual Rank |------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+| | | |Rank 1| off | 60 | 60 | 60 | 60 | 60 | 240 | off | 60 | 240 |
+| | |Slot 2|------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+| | | |Rank 2| off | 60 | 60 | 60 | 60 | 60 | 60 | 240 | 240 | off |
++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+| | | Slot 1 | off | 60 | 80 | off | | | | | | |
+|Single Rank|Single Rank|-------------+-------+-------+-------+------+-------+------+-------+------+-------+------+
+| | | Slot 2 | off | 60 | | | | | 80 | off |
++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+
+| | | |Rank 1| off | 80 | 80 | off | off | off |
+| Dual Rank | |Slot 1|------+-------+-------+-------+------+-------+------+
+| | | |Rank 2| off | 80 | 80 | off | off | off |
++-----------+-----------+-------------+-------+-------+-------+------+-------+------+
+|Single Rank| | Slot 1 | off | 80 | 80 | off |
++-----------+-----------+-------------+-------+-------+-------+------+
diff --git a/drivers/nxp/ddr/nxp-ddr/ddr.c b/drivers/nxp/ddr/nxp-ddr/ddr.c
new file mode 100644
index 0000000000..216e05c7c3
--- /dev/null
+++ b/drivers/nxp/ddr/nxp-ddr/ddr.c
@@ -0,0 +1,930 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#ifndef CONFIG_DDR_NODIMM
+#include <i2c.h>
+#endif
+#include <nxp_timer.h>
+
+struct dynamic_odt {
+ unsigned int odt_rd_cfg;
+ unsigned int odt_wr_cfg;
+ unsigned int odt_rtt_norm;
+ unsigned int odt_rtt_wr;
+};
+
+#ifndef CONFIG_STATIC_DDR
+#if defined(PHY_GEN2_FW_IMAGE_BUFFER) && !defined(NXP_DDR_PHY_GEN2)
+#error Missing NXP_DDR_PHY_GEN2
+#endif
+#ifdef NXP_DDR_PHY_GEN2
+static const struct dynamic_odt single_D[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_ALL,
+ DDR4_RTT_80_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ { /* cs1 */
+ DDR_ODT_NEVER,
+ DDR_ODT_NEVER,
+ DDR4_RTT_OFF,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ {}
+};
+
+static const struct dynamic_odt single_S[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_ALL,
+ DDR4_RTT_80_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ {},
+ {},
+};
+
+static const struct dynamic_odt dual_DD[4] = {
+ { /* cs0 */
+ DDR_ODT_OTHER_DIMM,
+ DDR_ODT_ALL,
+ DDR4_RTT_60_OHM,
+ DDR4_RTT_WR_240_OHM
+ },
+ { /* cs1 */
+ DDR_ODT_OTHER_DIMM,
+ DDR_ODT_ALL,
+ DDR4_RTT_60_OHM,
+ DDR4_RTT_WR_240_OHM
+ },
+ { /* cs2 */
+ DDR_ODT_OTHER_DIMM,
+ DDR_ODT_ALL,
+ DDR4_RTT_60_OHM,
+ DDR4_RTT_WR_240_OHM
+ },
+ { /* cs3 */
+ DDR_ODT_OTHER_DIMM,
+ DDR_ODT_ALL,
+ DDR4_RTT_60_OHM,
+ DDR4_RTT_WR_240_OHM
+ }
+};
+
+static const struct dynamic_odt dual_SS[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_ALL,
+ DDR4_RTT_80_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ { /* cs2 */
+ DDR_ODT_NEVER,
+ DDR_ODT_ALL,
+ DDR4_RTT_80_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ {}
+};
+
+static const struct dynamic_odt dual_D0[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_SAME_DIMM,
+ DDR4_RTT_80_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ { /* cs1 */
+ DDR_ODT_NEVER,
+ DDR_ODT_NEVER,
+ DDR4_RTT_80_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ {}
+};
+
+static const struct dynamic_odt dual_S0[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_CS,
+ DDR4_RTT_80_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ {},
+ {}
+};
+#else
+static const struct dynamic_odt single_D[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_ALL,
+ DDR4_RTT_40_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ { /* cs1 */
+ DDR_ODT_NEVER,
+ DDR_ODT_NEVER,
+ DDR4_RTT_OFF,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ {}
+};
+
+static const struct dynamic_odt single_S[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_ALL,
+ DDR4_RTT_40_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ {},
+ {},
+};
+
+static const struct dynamic_odt dual_DD[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_SAME_DIMM,
+ DDR4_RTT_120_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ { /* cs1 */
+ DDR_ODT_OTHER_DIMM,
+ DDR_ODT_OTHER_DIMM,
+ DDR4_RTT_34_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ { /* cs2 */
+ DDR_ODT_NEVER,
+ DDR_ODT_SAME_DIMM,
+ DDR4_RTT_120_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ { /* cs3 */
+ DDR_ODT_OTHER_DIMM,
+ DDR_ODT_OTHER_DIMM,
+ DDR4_RTT_34_OHM,
+ DDR4_RTT_WR_OFF
+ }
+};
+
+static const struct dynamic_odt dual_SS[4] = {
+ { /* cs0 */
+ DDR_ODT_OTHER_DIMM,
+ DDR_ODT_ALL,
+ DDR4_RTT_34_OHM,
+ DDR4_RTT_WR_120_OHM
+ },
+ {},
+ { /* cs2 */
+ DDR_ODT_OTHER_DIMM,
+ DDR_ODT_ALL,
+ DDR4_RTT_34_OHM,
+ DDR4_RTT_WR_120_OHM
+ },
+ {}
+};
+
+static const struct dynamic_odt dual_D0[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_SAME_DIMM,
+ DDR4_RTT_40_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ { /* cs1 */
+ DDR_ODT_NEVER,
+ DDR_ODT_NEVER,
+ DDR4_RTT_OFF,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ {}
+};
+
+static const struct dynamic_odt dual_S0[4] = {
+ { /* cs0 */
+ DDR_ODT_NEVER,
+ DDR_ODT_CS,
+ DDR4_RTT_40_OHM,
+ DDR4_RTT_WR_OFF
+ },
+ {},
+ {},
+ {}
+};
+#endif /* NXP_DDR_PHY_GEN2 */
+
+/*
+ * Automatically select bank interleaving mode based on DIMMs
+ * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null.
+ * This function only deal with one or two slots per controller.
+ */
+static inline unsigned int auto_bank_intlv(const int cs_in_use,
+ const struct dimm_params *pdimm)
+{
+ switch (cs_in_use) {
+ case 0xf:
+ return DDR_BA_INTLV_CS0123;
+ case 0x3:
+ return DDR_BA_INTLV_CS01;
+ case 0x1:
+ return DDR_BA_NONE;
+ case 0x5:
+ return DDR_BA_NONE;
+ default:
+ break;
+ }
+
+ return 0U;
+}
+
+static int cal_odt(const unsigned int clk,
+ struct memctl_opt *popts,
+ struct ddr_conf *conf,
+ struct dimm_params *pdimm,
+ const int dimm_slot_per_ctrl)
+
+{
+ unsigned int i;
+ const struct dynamic_odt *pdodt = NULL;
+
+ const static struct dynamic_odt *table[2][5] = {
+ {single_S, single_D, NULL, NULL},
+ {dual_SS, dual_DD, NULL, NULL},
+ };
+
+ if (dimm_slot_per_ctrl != 1 && dimm_slot_per_ctrl != 2) {
+ ERROR("Unsupported number of DIMMs\n");
+ return -EINVAL;
+ }
+
+ pdodt = table[dimm_slot_per_ctrl - 1][pdimm->n_ranks - 1];
+ if (pdodt == dual_SS) {
+ pdodt = (conf->cs_in_use == 0x5) ? dual_SS :
+ ((conf->cs_in_use == 0x1) ? dual_S0 : NULL);
+ } else if (pdodt == dual_DD) {
+ pdodt = (conf->cs_in_use == 0xf) ? dual_DD :
+ ((conf->cs_in_use == 0x3) ? dual_D0 : NULL);
+ }
+ if (pdodt == dual_DD && pdimm->package_3ds) {
+ ERROR("Too many 3DS DIMMs.\n");
+ return -EINVAL;
+ }
+
+ if (pdodt == NULL) {
+ ERROR("Error determing ODT.\n");
+ return -EINVAL;
+ }
+
+ /* Pick chip-select local options. */
+ for (i = 0U; i < DDRC_NUM_CS; i++) {
+ debug("cs %d\n", i);
+ popts->cs_odt[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
+ debug(" odt_rd_cfg 0x%x\n",
+ popts->cs_odt[i].odt_rd_cfg);
+ popts->cs_odt[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
+ debug(" odt_wr_cfg 0x%x\n",
+ popts->cs_odt[i].odt_wr_cfg);
+ popts->cs_odt[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
+ debug(" odt_rtt_norm 0x%x\n",
+ popts->cs_odt[i].odt_rtt_norm);
+ popts->cs_odt[i].odt_rtt_wr = pdodt[i].odt_rtt_wr;
+ debug(" odt_rtt_wr 0x%x\n",
+ popts->cs_odt[i].odt_rtt_wr);
+ popts->cs_odt[i].auto_precharge = 0;
+ debug(" auto_precharge %d\n",
+ popts->cs_odt[i].auto_precharge);
+ }
+
+ return 0;
+}
+
+static int cal_opts(const unsigned int clk,
+ struct memctl_opt *popts,
+ struct ddr_conf *conf,
+ struct dimm_params *pdimm,
+ const int dimm_slot_per_ctrl,
+ const unsigned int ip_rev)
+{
+ popts->rdimm = pdimm->rdimm;
+ popts->mirrored_dimm = pdimm->mirrored_dimm;
+#ifdef CONFIG_DDR_ECC_EN
+ popts->ecc_mode = pdimm->edc_config == 0x02 ? 1 : 0;
+#endif
+ popts->ctlr_init_ecc = popts->ecc_mode;
+ debug("ctlr_init_ecc %d\n", popts->ctlr_init_ecc);
+ popts->self_refresh_in_sleep = 1;
+ popts->dynamic_power = 0;
+
+ /*
+ * check sdram width, allow platform override
+ * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
+ */
+ if (pdimm->primary_sdram_width == 64) {
+ popts->data_bus_dimm = DDR_DBUS_64;
+ popts->otf_burst_chop_en = 1;
+ } else if (pdimm->primary_sdram_width == 32) {
+ popts->data_bus_dimm = DDR_DBUS_32;
+ popts->otf_burst_chop_en = 0;
+ } else if (pdimm->primary_sdram_width == 16) {
+ popts->data_bus_dimm = DDR_DBUS_16;
+ popts->otf_burst_chop_en = 0;
+ } else {
+ ERROR("primary sdram width invalid!\n");
+ return -EINVAL;
+ }
+ popts->data_bus_used = popts->data_bus_dimm;
+ popts->x4_en = (pdimm->device_width == 4) ? 1 : 0;
+ debug("x4_en %d\n", popts->x4_en);
+
+ /* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */
+ if (popts->rdimm != 0) {
+ popts->ap_en = 1; /* 0 = disable, 1 = enable */
+ } else {
+ popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */
+ }
+
+ if (ip_rev == 0x50500) {
+ popts->ap_en = 0;
+ }
+
+ debug("ap_en %d\n", popts->ap_en);
+
+ /* BSTTOPRE precharge interval uses 1/4 of refint value. */
+ popts->bstopre = picos_to_mclk(clk, pdimm->refresh_rate_ps) >> 2;
+ popts->tfaw_ps = pdimm->tfaw_ps;
+
+ return 0;
+}
+
+static void cal_intlv(const int num_ctlrs,
+ struct memctl_opt *popts,
+ struct ddr_conf *conf,
+ struct dimm_params *pdimm)
+{
+#ifdef NXP_DDR_INTLV_256B
+ if (num_ctlrs == 2) {
+ popts->ctlr_intlv = 1;
+ popts->ctlr_intlv_mode = DDR_256B_INTLV;
+ }
+#endif
+ debug("ctlr_intlv %d\n", popts->ctlr_intlv);
+ debug("ctlr_intlv_mode %d\n", popts->ctlr_intlv_mode);
+
+ popts->ba_intlv = auto_bank_intlv(conf->cs_in_use, pdimm);
+ debug("ba_intlv 0x%x\n", popts->ba_intlv);
+}
+
+static int update_burst_length(struct memctl_opt *popts)
+{
+ /* Choose burst length. */
+ if ((popts->data_bus_used == DDR_DBUS_32) ||
+ (popts->data_bus_used == DDR_DBUS_16)) {
+ /* 32-bit or 16-bit bus */
+ popts->otf_burst_chop_en = 0;
+ popts->burst_length = DDR_BL8;
+ } else if (popts->otf_burst_chop_en != 0) { /* on-the-fly burst chop */
+ popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */
+ } else {
+ popts->burst_length = DDR_BL8;
+ }
+ debug("data_bus_used %d\n", popts->data_bus_used);
+ debug("otf_burst_chop_en %d\n", popts->otf_burst_chop_en);
+ debug("burst_length 0x%x\n", popts->burst_length);
+ /*
+ * If a reduced data width is requested, but the SPD
+ * specifies a physically wider device, adjust the
+ * computed dimm capacities accordingly before
+ * assigning addresses.
+ * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
+ */
+ if (popts->data_bus_dimm > popts->data_bus_used) {
+ ERROR("Data bus configuration error\n");
+ return -EINVAL;
+ }
+ popts->dbw_cap_shift = popts->data_bus_used - popts->data_bus_dimm;
+ debug("dbw_cap_shift %d\n", popts->dbw_cap_shift);
+
+ return 0;
+}
+
+int cal_board_params(struct ddr_info *priv,
+ const struct board_timing *dimm,
+ int len)
+{
+ const unsigned long speed = priv->clk / 1000000;
+ const struct dimm_params *pdimm = &priv->dimm;
+ struct memctl_opt *popts = &priv->opt;
+ struct rc_timing const *prt = NULL;
+ struct rc_timing const *chosen = NULL;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (pdimm->rc == dimm[i].rc) {
+ prt = dimm[i].p;
+ break;
+ }
+ }
+ if (prt == NULL) {
+ ERROR("Board parameters no match.\n");
+ return -EINVAL;
+ }
+ while (prt->speed_bin != 0) {
+ if (speed <= prt->speed_bin) {
+ chosen = prt;
+ break;
+ }
+ prt++;
+ }
+ if (chosen == NULL) {
+ ERROR("timing no match for speed %lu\n", speed);
+ return -EINVAL;
+ }
+ popts->clk_adj = prt->clk_adj;
+ popts->wrlvl_start = prt->wrlvl;
+ popts->wrlvl_ctl_2 = (prt->wrlvl * 0x01010101 + dimm[i].add1) &
+ 0xFFFFFFFF;
+ popts->wrlvl_ctl_3 = (prt->wrlvl * 0x01010101 + dimm[i].add2) &
+ 0xFFFFFFFF;
+
+ return 0;
+}
+
+static int synthesize_ctlr(struct ddr_info *priv)
+{
+ int ret;
+
+ ret = cal_odt(priv->clk,
+ &priv->opt,
+ &priv->conf,
+ &priv->dimm,
+ priv->dimm_on_ctlr);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = cal_opts(priv->clk,
+ &priv->opt,
+ &priv->conf,
+ &priv->dimm,
+ priv->dimm_on_ctlr,
+ priv->ip_rev);
+
+ if (ret != 0) {
+ return ret;
+ }
+
+ cal_intlv(priv->num_ctlrs, &priv->opt, &priv->conf, &priv->dimm);
+ ret = ddr_board_options(priv);
+ if (ret != 0) {
+ ERROR("Failed matching board timing.\n");
+ }
+
+ ret = update_burst_length(&priv->opt);
+
+ return ret;
+}
+
+/* Return the bit mask of valid DIMMs found */
+static int parse_spd(struct ddr_info *priv)
+{
+ struct ddr_conf *conf = &priv->conf;
+ struct dimm_params *dimm = &priv->dimm;
+ int j, valid_mask = 0;
+
+#ifdef CONFIG_DDR_NODIMM
+ valid_mask = ddr_get_ddr_params(dimm, conf);
+ if (valid_mask < 0) {
+ ERROR("DDR params error\n");
+ return valid_mask;
+ }
+#else
+ const int *spd_addr = priv->spd_addr;
+ const int num_ctlrs = priv->num_ctlrs;
+ const int num_dimm = priv->dimm_on_ctlr;
+ struct ddr4_spd spd[2];
+ unsigned int spd_checksum[2];
+ int addr_idx = 0;
+ int spd_idx = 0;
+ int ret, addr, i;
+
+ /* Scan all DIMMs */
+ for (i = 0; i < num_ctlrs; i++) {
+ debug("Controller %d\n", i);
+ for (j = 0; j < num_dimm; j++, addr_idx++) {
+ debug("DIMM %d\n", j);
+ addr = spd_addr[addr_idx];
+ if (addr == 0) {
+ if (j == 0) {
+ ERROR("First SPD addr wrong.\n");
+ return -EINVAL;
+ }
+ continue;
+ }
+ debug("addr 0x%x\n", addr);
+ ret = read_spd(addr, &spd[spd_idx],
+ sizeof(struct ddr4_spd));
+ if (ret != 0) { /* invalid */
+ debug("Invalid SPD at address 0x%x\n", addr);
+ continue;
+ }
+
+ spd_checksum[spd_idx] =
+ (spd[spd_idx].crc[1] << 24) |
+ (spd[spd_idx].crc[0] << 16) |
+ (spd[spd_idx].mod_section.uc[127] << 8) |
+ (spd[spd_idx].mod_section.uc[126] << 0);
+ debug("checksum 0x%x\n", spd_checksum[spd_idx]);
+ if (spd_checksum[spd_idx] == 0) {
+ debug("Bad checksum, ignored.\n");
+ continue;
+ }
+ if (spd_idx == 0) {
+ /* first valid SPD */
+ ret = cal_dimm_params(&spd[0], dimm);
+ if (ret != 0) {
+ ERROR("SPD calculation error\n");
+ return -EINVAL;
+ }
+ }
+
+ if (spd_idx != 0 && spd_checksum[0] !=
+ spd_checksum[spd_idx]) {
+ ERROR("Not identical DIMMs.\n");
+ return -EINVAL;
+ }
+ conf->dimm_in_use[j] = 1;
+ valid_mask |= 1 << addr_idx;
+ spd_idx = 1;
+ }
+ debug("done with controller %d\n", i);
+ }
+ switch (num_ctlrs) {
+ case 1:
+ if ((valid_mask & 0x1) == 0) {
+ ERROR("First slot cannot be empty.\n");
+ return -EINVAL;
+ }
+ break;
+ case 2:
+ switch (num_dimm) {
+ case 1:
+ if (valid_mask == 0) {
+ ERROR("Both slot empty\n");
+ return -EINVAL;
+ }
+ break;
+ case 2:
+ if (valid_mask != 0x5 &&
+ valid_mask != 0xf &&
+ (valid_mask & 0x7) != 0x4 &&
+ (valid_mask & 0xd) != 0x1) {
+ ERROR("Invalid DIMM combination.\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ ERROR("Invalid number of DIMMs.\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ ERROR("Invalid number of controllers.\n");
+ return -EINVAL;
+ }
+ /* now we have valid and identical DIMMs on controllers */
+#endif /* CONFIG_DDR_NODIMM */
+
+ debug("cal cs\n");
+ conf->cs_in_use = 0;
+ for (j = 0; j < DDRC_NUM_DIMM; j++) {
+ if (conf->dimm_in_use[j] == 0) {
+ continue;
+ }
+ switch (dimm->n_ranks) {
+ case 4:
+ ERROR("Quad-rank DIMM not supported\n");
+ return -EINVAL;
+ case 2:
+ conf->cs_on_dimm[j] = 0x3 << (j * CONFIG_CS_PER_SLOT);
+ conf->cs_in_use |= conf->cs_on_dimm[j];
+ break;
+ case 1:
+ conf->cs_on_dimm[j] = 0x1 << (j * CONFIG_CS_PER_SLOT);
+ conf->cs_in_use |= conf->cs_on_dimm[j];
+ break;
+ default:
+ ERROR("SPD error with n_ranks\n");
+ return -EINVAL;
+ }
+ debug("cs_in_use = %x\n", conf->cs_in_use);
+ debug("cs_on_dimm[%d] = %x\n", j, conf->cs_on_dimm[j]);
+ }
+#ifndef CONFIG_DDR_NODIMM
+ if (priv->dimm.rdimm != 0) {
+ NOTICE("RDIMM %s\n", priv->dimm.mpart);
+ } else {
+ NOTICE("UDIMM %s\n", priv->dimm.mpart);
+ }
+#else
+ NOTICE("%s\n", priv->dimm.mpart);
+#endif
+
+ return valid_mask;
+}
+
+static unsigned long long assign_intlv_addr(
+ const struct dimm_params *pdimm,
+ const struct memctl_opt *opt,
+ struct ddr_conf *conf,
+ const unsigned long long current_mem_base)
+{
+ int i;
+ int ctlr_density_mul = 0;
+ const unsigned long long rank_density = pdimm->rank_density >>
+ opt->dbw_cap_shift;
+ unsigned long long total_ctlr_mem;
+
+ debug("rank density 0x%llx\n", rank_density);
+ switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) {
+ case DDR_BA_INTLV_CS0123:
+ ctlr_density_mul = 4;
+ break;
+ case DDR_BA_INTLV_CS01:
+ ctlr_density_mul = 2;
+ break;
+ default:
+ ctlr_density_mul = 1;
+ break;
+ }
+ debug("ctlr density mul %d\n", ctlr_density_mul);
+ switch (opt->ctlr_intlv_mode) {
+ case DDR_256B_INTLV:
+ total_ctlr_mem = 2 * ctlr_density_mul * rank_density;
+ break;
+ default:
+ ERROR("Unknown interleaving mode");
+ return 0;
+ }
+ conf->base_addr = current_mem_base;
+ conf->total_mem = total_ctlr_mem;
+
+ /* overwrite cs_in_use bitmask with controller interleaving */
+ conf->cs_in_use = (1 << ctlr_density_mul) - 1;
+ debug("Overwrite cs_in_use as %x\n", conf->cs_in_use);
+
+ /* Fill addr with each cs in use */
+ for (i = 0; i < ctlr_density_mul; i++) {
+ conf->cs_base_addr[i] = current_mem_base;
+ conf->cs_size[i] = total_ctlr_mem;
+ debug("CS %d\n", i);
+ debug(" base_addr 0x%llx\n", conf->cs_base_addr[i]);
+ debug(" size 0x%llx\n", conf->cs_size[i]);
+ }
+
+ return total_ctlr_mem;
+}
+
+static unsigned long long assign_non_intlv_addr(
+ const struct dimm_params *pdimm,
+ const struct memctl_opt *opt,
+ struct ddr_conf *conf,
+ unsigned long long current_mem_base)
+{
+ int i;
+ const unsigned long long rank_density = pdimm->rank_density >>
+ opt->dbw_cap_shift;
+ unsigned long long total_ctlr_mem = 0ULL;
+
+ debug("rank density 0x%llx\n", rank_density);
+ conf->base_addr = current_mem_base;
+
+ /* assign each cs */
+ switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) {
+ case DDR_BA_INTLV_CS0123:
+ for (i = 0; i < DDRC_NUM_CS; i++) {
+ conf->cs_base_addr[i] = current_mem_base;
+ conf->cs_size[i] = rank_density << 2;
+ total_ctlr_mem += rank_density;
+ }
+ break;
+ case DDR_BA_INTLV_CS01:
+ for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && i < 2; i++) {
+ conf->cs_base_addr[i] = current_mem_base;
+ conf->cs_size[i] = rank_density << 1;
+ total_ctlr_mem += rank_density;
+ }
+ current_mem_base += total_ctlr_mem;
+ for (; ((conf->cs_in_use & (1 << i)) != 0) && i < DDRC_NUM_CS;
+ i++) {
+ conf->cs_base_addr[i] = current_mem_base;
+ conf->cs_size[i] = rank_density;
+ total_ctlr_mem += rank_density;
+ current_mem_base += rank_density;
+ }
+ break;
+ case DDR_BA_NONE:
+ for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) &&
+ (i < DDRC_NUM_CS); i++) {
+ conf->cs_base_addr[i] = current_mem_base;
+ conf->cs_size[i] = rank_density;
+ current_mem_base += rank_density;
+ total_ctlr_mem += rank_density;
+ }
+ break;
+ default:
+ ERROR("Unsupported bank interleaving\n");
+ return 0;
+ }
+ for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) &&
+ (i < DDRC_NUM_CS); i++) {
+ debug("CS %d\n", i);
+ debug(" base_addr 0x%llx\n", conf->cs_base_addr[i]);
+ debug(" size 0x%llx\n", conf->cs_size[i]);
+ }
+
+ return total_ctlr_mem;
+}
+
+unsigned long long assign_addresses(struct ddr_info *priv)
+ __attribute__ ((weak));
+
+unsigned long long assign_addresses(struct ddr_info *priv)
+{
+ struct memctl_opt *opt = &priv->opt;
+ const struct dimm_params *dimm = &priv->dimm;
+ struct ddr_conf *conf = &priv->conf;
+ unsigned long long current_mem_base = priv->mem_base;
+ unsigned long long total_mem;
+
+ total_mem = 0ULL;
+ debug("ctlr_intlv %d\n", opt->ctlr_intlv);
+ if (opt->ctlr_intlv != 0) {
+ total_mem = assign_intlv_addr(dimm, opt, conf,
+ current_mem_base);
+ } else {
+ /*
+ * Simple linear assignment if memory controllers are not
+ * interleaved. This is only valid for SoCs with single DDRC.
+ */
+ total_mem = assign_non_intlv_addr(dimm, opt, conf,
+ current_mem_base);
+ }
+ conf->total_mem = total_mem;
+ debug("base 0x%llx\n", current_mem_base);
+ debug("Total mem by assignment is 0x%llx\n", total_mem);
+
+ return total_mem;
+}
+
+static int cal_ddrc_regs(struct ddr_info *priv)
+{
+ int ret;
+
+ ret = compute_ddrc(priv->clk,
+ &priv->opt,
+ &priv->conf,
+ &priv->ddr_reg,
+ &priv->dimm,
+ priv->ip_rev);
+ if (ret != 0) {
+ ERROR("Calculating DDR registers failed\n");
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_STATIC_DDR */
+
+static int write_ddrc_regs(struct ddr_info *priv)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < priv->num_ctlrs; i++) {
+ ret = ddrc_set_regs(priv->clk, &priv->ddr_reg, priv->ddr[i], 0);
+ if (ret != 0) {
+ ERROR("Writing DDR register(s) failed\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+long long dram_init(struct ddr_info *priv
+#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
+ , uintptr_t nxp_ccn_hn_f0_addr
+#endif
+ )
+{
+ uint64_t time __unused;
+ long long dram_size;
+ int ret;
+ const uint64_t time_base = get_timer_val(0);
+ unsigned int ip_rev = get_ddrc_version(priv->ddr[0]);
+
+ int valid_spd_mask __unused;
+ int scratch = 0x0;
+
+ priv->ip_rev = ip_rev;
+
+#ifndef CONFIG_STATIC_DDR
+ INFO("time base %llu ms\n", time_base);
+ debug("Parse DIMM SPD(s)\n");
+ valid_spd_mask = parse_spd(priv);
+
+ if (valid_spd_mask < 0) {
+ ERROR("Parsing DIMM Error\n");
+ return valid_spd_mask;
+ }
+
+#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
+ if (priv->num_ctlrs == 2 || priv->num_ctlrs == 1) {
+ ret = disable_unused_ddrc(priv, valid_spd_mask,
+ nxp_ccn_hn_f0_addr);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+#endif
+
+ time = get_timer_val(time_base);
+ INFO("Time after parsing SPD %llu ms\n", time);
+ debug("Synthesize configurations\n");
+ ret = synthesize_ctlr(priv);
+ if (ret != 0) {
+ ERROR("Synthesize config error\n");
+ return ret;
+ }
+
+ debug("Assign binding addresses\n");
+ dram_size = assign_addresses(priv);
+ if (dram_size == 0) {
+ ERROR("Assigning address error\n");
+ return -EINVAL;
+ }
+
+ debug("Calculate controller registers\n");
+ ret = cal_ddrc_regs(priv);
+ if (ret != 0) {
+ ERROR("Calculate register error\n");
+ return ret;
+ }
+
+ ret = compute_ddr_phy(priv);
+ if (ret != 0)
+ ERROR("Calculating DDR PHY registers failed.\n");
+
+#else
+ dram_size = board_static_ddr(priv);
+ if (dram_size == 0) {
+ ERROR("Error getting static DDR settings.\n");
+ return -EINVAL;
+ }
+#endif
+
+ if (priv->warm_boot_flag == DDR_WARM_BOOT) {
+ scratch = (priv->ddr_reg).sdram_cfg[1];
+ scratch = scratch & ~(SDRAM_CFG2_D_INIT);
+ priv->ddr_reg.sdram_cfg[1] = scratch;
+ }
+
+ time = get_timer_val(time_base);
+ INFO("Time before programming controller %llu ms\n", time);
+ debug("Program controller registers\n");
+ ret = write_ddrc_regs(priv);
+ if (ret != 0) {
+ ERROR("Programing DDRC error\n");
+ return ret;
+ }
+
+ puts("");
+ NOTICE("%lld GB ", dram_size >> 30);
+ print_ddr_info(priv->ddr[0]);
+
+ time = get_timer_val(time_base);
+ INFO("Time used by DDR driver %llu ms\n", time);
+
+ return dram_size;
+}
diff --git a/drivers/nxp/ddr/nxp-ddr/ddr.mk b/drivers/nxp/ddr/nxp-ddr/ddr.mk
new file mode 100644
index 0000000000..866c092169
--- /dev/null
+++ b/drivers/nxp/ddr/nxp-ddr/ddr.mk
@@ -0,0 +1,79 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+DDR_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/ddr
+
+ifeq ($(PLAT_DDR_PHY), PHY_GEN2)
+$(eval $(call add_define, PHY_GEN2))
+PLAT_DDR_PHY_DIR := phy-gen2
+ifeq (${APPLY_MAX_CDD},yes)
+$(eval $(call add_define,NXP_APPLY_MAX_CDD))
+endif
+
+ifeq (${ERRATA_DDR_A011396}, 1)
+$(eval $(call add_define,ERRATA_DDR_A011396))
+endif
+
+ifeq (${ERRATA_DDR_A050450}, 1)
+$(eval $(call add_define,ERRATA_DDR_A050450))
+endif
+
+endif
+
+ifeq ($(PLAT_DDR_PHY), PHY_GEN1)
+PLAT_DDR_PHY_DIR := phy-gen1
+
+ifeq (${ERRATA_DDR_A008511},1)
+$(eval $(call add_define,ERRATA_DDR_A008511))
+endif
+
+ifeq (${ERRATA_DDR_A009803},1)
+$(eval $(call add_define,ERRATA_DDR_A009803))
+endif
+
+ifeq (${ERRATA_DDR_A009942},1)
+$(eval $(call add_define,ERRATA_DDR_A009942))
+endif
+
+ifeq (${ERRATA_DDR_A010165},1)
+$(eval $(call add_define,ERRATA_DDR_A010165))
+endif
+
+endif
+
+ifeq ($(DDR_BIST), yes)
+$(eval $(call add_define, BIST_EN))
+endif
+
+ifeq ($(DDR_DEBUG), yes)
+$(eval $(call add_define, DDR_DEBUG))
+endif
+
+ifeq ($(DDR_PHY_DEBUG), yes)
+$(eval $(call add_define, DDR_PHY_DEBUG))
+endif
+
+ifeq ($(DEBUG_PHY_IO), yes)
+$(eval $(call add_define, DEBUG_PHY_IO))
+endif
+
+ifeq ($(DEBUG_WARM_RESET), yes)
+$(eval $(call add_define, DEBUG_WARM_RESET))
+endif
+
+ifeq ($(DEBUG_DDR_INPUT_CONFIG), yes)
+$(eval $(call add_define, DEBUG_DDR_INPUT_CONFIG))
+endif
+
+DDR_CNTLR_SOURCES := $(DDR_DRIVERS_PATH)/nxp-ddr/ddr.c \
+ $(DDR_DRIVERS_PATH)/nxp-ddr/ddrc.c \
+ $(DDR_DRIVERS_PATH)/nxp-ddr/dimm.c \
+ $(DDR_DRIVERS_PATH)/nxp-ddr/regs.c \
+ $(DDR_DRIVERS_PATH)/nxp-ddr/utility.c \
+ $(DDR_DRIVERS_PATH)/$(PLAT_DDR_PHY_DIR)/phy.c
+
+PLAT_INCLUDES += -I$(DDR_DRIVERS_PATH)/nxp-ddr \
+ -I$(DDR_DRIVERS_PATH)/include
diff --git a/drivers/nxp/ddr/nxp-ddr/ddrc.c b/drivers/nxp/ddr/nxp-ddr/ddrc.c
new file mode 100644
index 0000000000..17a2b6a474
--- /dev/null
+++ b/drivers/nxp/ddr/nxp-ddr/ddrc.c
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <drivers/delay_timer.h>
+#include <immap.h>
+
+#define BIST_CR 0x80060000
+#define BIST_CR_EN 0x80000000
+#define BIST_CR_STAT 0x00000001
+#define CTLR_INTLV_MASK 0x20000000
+
+#pragma weak run_bist
+
+bool run_bist(void)
+{
+#ifdef BIST_EN
+ return true;
+#else
+ return false;
+#endif
+}
+
+/*
+ * Perform build-in test on memory
+ * timeout value in 10ms
+ */
+int bist(const struct ccsr_ddr *ddr, int timeout)
+{
+ const unsigned int test_pattern[10] = {
+ 0xffffffff,
+ 0x00000000,
+ 0xaaaaaaaa,
+ 0x55555555,
+ 0xcccccccc,
+ 0x33333333,
+ 0x12345678,
+ 0xabcdef01,
+ 0xaa55aa55,
+ 0x55aa55aa
+ };
+ unsigned int mtcr, err_detect, err_sbe;
+ unsigned int cs0_config;
+ unsigned int csn_bnds[4];
+ int ret = 0;
+ uint32_t i;
+#ifdef CONFIG_DDR_ADDR_DEC
+ uint32_t dec_9 = ddr_in32(&ddr->dec[9]);
+ uint32_t pos = 0U;
+ uint32_t map_save = 0U;
+ uint32_t temp32 = 0U;
+ uint32_t map, shift, highest;
+#endif
+
+ cs0_config = ddr_in32(&ddr->csn_cfg[0]);
+ if ((cs0_config & CTLR_INTLV_MASK) != 0U) {
+ /* set bnds to non-interleaving */
+ for (i = 0U; i < 4U; i++) {
+ csn_bnds[i] = ddr_in32(&ddr->bnds[i].a);
+ ddr_out32(&ddr->bnds[i].a,
+ (csn_bnds[i] & U(0xfffefffe)) >> 1U);
+ }
+ ddr_out32(&ddr->csn_cfg[0], cs0_config & ~CTLR_INTLV_MASK);
+#ifdef CONFIG_DDR_ADDR_DEC
+ if ((dec_9 & 0x1U) != 0U) {
+ highest = (dec_9 >> 26U) == U(0x3F) ? 0U : dec_9 >> 26U;
+ pos = 37U;
+ for (i = 0U; i < 36U; i++) { /* Go through all 37 */
+ if ((i % 4U) == 0U) {
+ temp32 = ddr_in32(&ddr->dec[i >> 2U]);
+ }
+ shift = (3U - i % 4U) * 8U + 2U;
+ map = (temp32 >> shift) & U(0x3F);
+ if (map > highest && map != U(0x3F)) {
+ highest = map;
+ pos = i;
+ }
+ }
+ debug("\nFound highest position %d, mapping to %d, ",
+ pos, highest);
+ map_save = ddr_in32(&ddr->dec[pos >> 2]);
+ shift = (3U - pos % 4U) * 8U + 2U;
+ debug("in dec[%d], bit %d (0x%x)\n",
+ pos >> 2U, shift, map_save);
+ temp32 = map_save & ~(U(0x3F) << shift);
+ temp32 |= 8U << shift;
+ ddr_out32(&ddr->dec[pos >> 2U], temp32);
+ timeout <<= 2U;
+ debug("Increase wait time to %d ms\n", timeout * 10);
+ }
+#endif
+ }
+ for (i = 0U; i < 10U; i++) {
+ ddr_out32(&ddr->mtp[i], test_pattern[i]);
+ }
+ mtcr = BIST_CR;
+ ddr_out32(&ddr->mtcr, mtcr);
+ do {
+ mdelay(10);
+ mtcr = ddr_in32(&ddr->mtcr);
+ } while (timeout-- > 0 && ((mtcr & BIST_CR_EN) != 0));
+ if (timeout <= 0) {
+ ERROR("Timeout\n");
+ } else {
+ debug("Timer remains %d\n", timeout);
+ }
+
+ err_detect = ddr_in32(&ddr->err_detect);
+ err_sbe = ddr_in32(&ddr->err_sbe);
+ if (err_detect != 0U || ((err_sbe & U(0xffff)) != 0U)) {
+ ERROR("ECC error detected\n");
+ ret = -EIO;
+ }
+
+ if ((cs0_config & CTLR_INTLV_MASK) != 0) {
+ for (i = 0U; i < 4U; i++) {
+ ddr_out32(&ddr->bnds[i].a, csn_bnds[i]);
+ }
+ ddr_out32(&ddr->csn_cfg[0], cs0_config);
+#ifdef CONFIG_DDR_ADDR_DEC
+ if ((dec_9 & U(0x1)) != 0U) {
+ ddr_out32(&ddr->dec[pos >> 2], map_save);
+ }
+#endif
+ }
+ if ((mtcr & BIST_CR_STAT) != 0) {
+ ERROR("Built-in self test failed\n");
+ ret = -EIO;
+ } else {
+ NOTICE("Build-in self test passed\n");
+ }
+
+ return ret;
+}
+
+void dump_ddrc(unsigned int *ddr)
+{
+#ifdef DDR_DEBUG
+ uint32_t i;
+ unsigned long val;
+
+ for (i = 0U; i < U(0x400); i++, ddr++) {
+ val = ddr_in32(ddr);
+ if (val != 0U) { /* skip zeros */
+ debug("*0x%lx = 0x%lx\n", (unsigned long)ddr, val);
+ }
+ }
+#endif
+}
+
+#ifdef ERRATA_DDR_A009803
+static void set_wait_for_bits_clear(const void *ptr,
+ unsigned int value,
+ unsigned int bits)
+{
+ int timeout = 1000;
+
+ ddr_out32(ptr, value);
+ do {
+ udelay(100);
+ } while (timeout-- > 0 && ((ddr_in32(ptr) & bits) != 0));
+
+ if (timeout <= 0) {
+ ERROR("wait for clear timeout.\n");
+ }
+}
+#endif
+
+#if (DDRC_NUM_CS > 4)
+#error Invalid setting for DDRC_NUM_CS
+#endif
+
+/*
+ * If supported by the platform, writing to DDR controller takes two
+ * passes to deassert DDR reset to comply with JEDEC specs for RDIMMs.
+ */
+int ddrc_set_regs(const unsigned long clk,
+ const struct ddr_cfg_regs *regs,
+ const struct ccsr_ddr *ddr,
+ int twopass)
+{
+ unsigned int i, bus_width;
+ unsigned int temp_sdram_cfg;
+ unsigned int total_mem_per_ctrl, total_mem_per_ctrl_adj;
+ const int mod_bnds = regs->cs[0].config & CTLR_INTLV_MASK;
+ int timeout;
+ int ret = 0;
+#if defined(ERRATA_DDR_A009942) || defined(ERRATA_DDR_A010165)
+ unsigned long ddr_freq;
+ unsigned int tmp;
+#ifdef ERRATA_DDR_A009942
+ unsigned int check;
+ unsigned int cpo_min = U(0xff);
+ unsigned int cpo_max = 0U;
+#endif
+#endif
+
+ if (twopass == 2U) {
+ goto after_reset;
+ }
+
+ /* Set cdr1 first in case 0.9v VDD is enabled for some SoCs*/
+ ddr_out32(&ddr->ddr_cdr1, regs->cdr[0]);
+
+ ddr_out32(&ddr->sdram_clk_cntl, regs->clk_cntl);
+
+ for (i = 0U; i < DDRC_NUM_CS; i++) {
+ if (mod_bnds != 0U) {
+ ddr_out32(&ddr->bnds[i].a,
+ (regs->cs[i].bnds & U(0xfffefffe)) >> 1U);
+ } else {
+ ddr_out32(&ddr->bnds[i].a, regs->cs[i].bnds);
+ }
+ ddr_out32(&ddr->csn_cfg_2[i], regs->cs[i].config_2);
+ }
+
+ ddr_out32(&ddr->timing_cfg_0, regs->timing_cfg[0]);
+ ddr_out32(&ddr->timing_cfg_1, regs->timing_cfg[1]);
+ ddr_out32(&ddr->timing_cfg_2, regs->timing_cfg[2]);
+ ddr_out32(&ddr->timing_cfg_3, regs->timing_cfg[3]);
+ ddr_out32(&ddr->timing_cfg_4, regs->timing_cfg[4]);
+ ddr_out32(&ddr->timing_cfg_5, regs->timing_cfg[5]);
+ ddr_out32(&ddr->timing_cfg_6, regs->timing_cfg[6]);
+ ddr_out32(&ddr->timing_cfg_7, regs->timing_cfg[7]);
+ ddr_out32(&ddr->timing_cfg_8, regs->timing_cfg[8]);
+ ddr_out32(&ddr->timing_cfg_9, regs->timing_cfg[9]);
+ ddr_out32(&ddr->zq_cntl, regs->zq_cntl);
+ for (i = 0U; i < 4U; i++) {
+ ddr_out32(&ddr->dq_map[i], regs->dq_map[i]);
+ }
+ ddr_out32(&ddr->sdram_cfg_3, regs->sdram_cfg[2]);
+ ddr_out32(&ddr->sdram_mode, regs->sdram_mode[0]);
+ ddr_out32(&ddr->sdram_mode_2, regs->sdram_mode[1]);
+ ddr_out32(&ddr->sdram_mode_3, regs->sdram_mode[2]);
+ ddr_out32(&ddr->sdram_mode_4, regs->sdram_mode[3]);
+ ddr_out32(&ddr->sdram_mode_5, regs->sdram_mode[4]);
+ ddr_out32(&ddr->sdram_mode_6, regs->sdram_mode[5]);
+ ddr_out32(&ddr->sdram_mode_7, regs->sdram_mode[6]);
+ ddr_out32(&ddr->sdram_mode_8, regs->sdram_mode[7]);
+ ddr_out32(&ddr->sdram_mode_9, regs->sdram_mode[8]);
+ ddr_out32(&ddr->sdram_mode_10, regs->sdram_mode[9]);
+ ddr_out32(&ddr->sdram_mode_11, regs->sdram_mode[10]);
+ ddr_out32(&ddr->sdram_mode_12, regs->sdram_mode[11]);
+ ddr_out32(&ddr->sdram_mode_13, regs->sdram_mode[12]);
+ ddr_out32(&ddr->sdram_mode_14, regs->sdram_mode[13]);
+ ddr_out32(&ddr->sdram_mode_15, regs->sdram_mode[14]);
+ ddr_out32(&ddr->sdram_mode_16, regs->sdram_mode[15]);
+ ddr_out32(&ddr->sdram_md_cntl, regs->md_cntl);
+#ifdef ERRATA_DDR_A009663
+ ddr_out32(&ddr->sdram_interval,
+ regs->interval & ~SDRAM_INTERVAL_BSTOPRE);
+#else
+ ddr_out32(&ddr->sdram_interval, regs->interval);
+#endif
+ ddr_out32(&ddr->sdram_data_init, regs->data_init);
+ if (regs->eor != 0) {
+ ddr_out32(&ddr->eor, regs->eor);
+ }
+
+ ddr_out32(&ddr->wrlvl_cntl, regs->wrlvl_cntl[0]);
+#ifndef NXP_DDR_EMU
+ /*
+ * Skip these two registers if running on emulator
+ * because emulator doesn't have skew between bytes.
+ */
+
+ if (regs->wrlvl_cntl[1] != 0) {
+ ddr_out32(&ddr->ddr_wrlvl_cntl_2, regs->wrlvl_cntl[1]);
+ }
+ if (regs->wrlvl_cntl[2] != 0) {
+ ddr_out32(&ddr->ddr_wrlvl_cntl_3, regs->wrlvl_cntl[2]);
+ }
+#endif
+
+ ddr_out32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr);
+ ddr_out32(&ddr->ddr_sdram_rcw_1, regs->sdram_rcw[0]);
+ ddr_out32(&ddr->ddr_sdram_rcw_2, regs->sdram_rcw[1]);
+ ddr_out32(&ddr->ddr_sdram_rcw_3, regs->sdram_rcw[2]);
+ ddr_out32(&ddr->ddr_sdram_rcw_4, regs->sdram_rcw[3]);
+ ddr_out32(&ddr->ddr_sdram_rcw_5, regs->sdram_rcw[4]);
+ ddr_out32(&ddr->ddr_sdram_rcw_6, regs->sdram_rcw[5]);
+ ddr_out32(&ddr->ddr_cdr2, regs->cdr[1]);
+ ddr_out32(&ddr->sdram_cfg_2, regs->sdram_cfg[1]);
+ ddr_out32(&ddr->init_addr, regs->init_addr);
+ ddr_out32(&ddr->init_ext_addr, regs->init_ext_addr);
+
+#ifdef ERRATA_DDR_A009803
+ /* part 1 of 2 */
+ if ((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) {
+ if ((regs->sdram_cfg[0] & SDRAM_CFG_RD_EN) != 0) {
+ ddr_out32(&ddr->ddr_sdram_rcw_2,
+ regs->sdram_rcw[1] & ~0xf0);
+ }
+
+ ddr_out32(&ddr->err_disable,
+ regs->err_disable | DDR_ERR_DISABLE_APED);
+ }
+#else
+ ddr_out32(&ddr->err_disable, regs->err_disable);
+#endif
+ ddr_out32(&ddr->err_int_en, regs->err_int_en);
+
+ /* For DDRC 5.05 only */
+ if (get_ddrc_version(ddr) == 0x50500) {
+ ddr_out32(&ddr->tx_cfg[1], 0x1f1f1f1f);
+ ddr_out32(&ddr->debug[3], 0x124a02c0);
+ }
+
+ for (i = 0U; i < 4U; i++) {
+ if (regs->tx_cfg[i] != 0) {
+ ddr_out32(&ddr->tx_cfg[i], regs->tx_cfg[i]);
+ }
+ }
+ for (i = 0U; i < 64U; i++) {
+ if (regs->debug[i] != 0) {
+#ifdef ERRATA_DDR_A009942
+ if (i == 28U) {
+ continue;
+ }
+#endif
+ ddr_out32(&ddr->debug[i], regs->debug[i]);
+ }
+ }
+#ifdef CONFIG_DDR_ADDR_DEC
+ if ((regs->dec[9] & 1) != 0U) {
+ for (i = 0U; i < 10U; i++) {
+ ddr_out32(&ddr->dec[i], regs->dec[i]);
+ }
+ if (mod_bnds != 0) {
+ debug("Disable address decoding\n");
+ ddr_out32(&ddr->dec[9], 0);
+ }
+ }
+#endif
+
+#ifdef ERRATA_DDR_A008511
+ /* Part 1 of 2 */
+ /* This erraum only applies to verion 5.2.1 */
+ if (get_ddrc_version(ddr) == 0x50200) {
+ ERROR("Unsupported SoC.\n");
+ } else if (get_ddrc_version(ddr) == 0x50201) {
+ ddr_out32(&ddr->debug[37], (U(1) << 31));
+ ddr_out32(&ddr->ddr_cdr2,
+ regs->cdr[1] | DDR_CDR2_VREF_TRAIN_EN);
+ } else {
+ debug("Erratum A008511 doesn't apply.\n");
+ }
+#endif
+
+#ifdef ERRATA_DDR_A009942
+ ddr_freq = clk / 1000000U;
+ tmp = ddr_in32(&ddr->debug[28]);
+ tmp &= U(0xff0fff00);
+ tmp |= ddr_freq <= 1333U ? U(0x0080006a) :
+ (ddr_freq <= 1600U ? U(0x0070006f) :
+ (ddr_freq <= 1867U ? U(0x00700076) : U(0x0060007b)));
+ if (regs->debug[28] != 0) {
+ tmp &= ~0xff;
+ tmp |= regs->debug[28] & 0xff;
+ } else {
+ WARN("Warning: Optimal CPO value not set.\n");
+ }
+ ddr_out32(&ddr->debug[28], tmp);
+#endif
+
+#ifdef ERRATA_DDR_A010165
+ ddr_freq = clk / 1000000U;
+ if ((ddr_freq > 1900) && (ddr_freq < 2300)) {
+ tmp = ddr_in32(&ddr->debug[28]);
+ ddr_out32(&ddr->debug[28], tmp | 0x000a0000);
+ }
+#endif
+ /*
+ * For RDIMMs, JEDEC spec requires clocks to be stable before reset is
+ * deasserted. Clocks start when any chip select is enabled and clock
+ * control register is set. Because all DDR components are connected to
+ * one reset signal, this needs to be done in two steps. Step 1 is to
+ * get the clocks started. Step 2 resumes after reset signal is
+ * deasserted.
+ */
+ if (twopass == 1) {
+ udelay(200);
+ return 0;
+ }
+
+ /* As per new sequence flow shall be write CSn_CONFIG registers needs to
+ * be set after all the other DDR controller registers are set, then poll
+ * for PHY_INIT_CMPLT = 1 , then wait at least 100us (micro seconds),
+ * then set the MEM_EN = 1
+ */
+ for (i = 0U; i < DDRC_NUM_CS; i++) {
+ if (mod_bnds != 0U && i == 0U) {
+ ddr_out32(&ddr->csn_cfg[i],
+ (regs->cs[i].config & ~CTLR_INTLV_MASK));
+ } else {
+ ddr_out32(&ddr->csn_cfg[i], regs->cs[i].config);
+ }
+ }
+
+after_reset:
+ /* Set, but do not enable the memory */
+ temp_sdram_cfg = regs->sdram_cfg[0];
+ temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
+ ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg);
+
+ if (get_ddrc_version(ddr) < U(0x50500)) {
+ /*
+ * 500 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ * DDR2 need 200 us, and DDR3 need 500 us from spec,
+ * we choose the max, that is 500 us for all of case.
+ */
+ udelay(500);
+ /* applied memory barrier */
+ mb();
+ isb();
+ } else {
+ /* wait for PHY complete */
+ timeout = 40;
+ while (((ddr_in32(&ddr->ddr_dsr2) & 0x4) != 0) &&
+ (timeout > 0)) {
+ udelay(500);
+ timeout--;
+ }
+ if (timeout <= 0) {
+ printf("PHY handshake timeout, ddr_dsr2 = %x\n",
+ ddr_in32(&ddr->ddr_dsr2));
+ } else {
+ debug("PHY handshake completed, timer remains %d\n",
+ timeout);
+ }
+ }
+
+ temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg);
+ /* Let the controller go */
+ udelay(100);
+ ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
+
+ /* applied memory barrier */
+ mb();
+ isb();
+
+ total_mem_per_ctrl = 0;
+ for (i = 0; i < DDRC_NUM_CS; i++) {
+ if ((regs->cs[i].config & 0x80000000) == 0) {
+ continue;
+ }
+ total_mem_per_ctrl += 1 << (
+ ((regs->cs[i].config >> 14) & 0x3) + 2 +
+ ((regs->cs[i].config >> 8) & 0x7) + 12 +
+ ((regs->cs[i].config >> 4) & 0x3) + 0 +
+ ((regs->cs[i].config >> 0) & 0x7) + 8 +
+ ((regs->sdram_cfg[2] >> 4) & 0x3) +
+ 3 - ((regs->sdram_cfg[0] >> 19) & 0x3) -
+ 26); /* minus 26 (count of 64M) */
+ }
+ total_mem_per_ctrl_adj = total_mem_per_ctrl;
+ /*
+ * total memory / bus width = transactions needed
+ * transactions needed / data rate = seconds
+ * to add plenty of buffer, double the time
+ * For example, 2GB on 666MT/s 64-bit bus takes about 402ms
+ * Let's wait for 800ms
+ */
+ bus_width = 3 - ((ddr_in32(&ddr->sdram_cfg) & SDRAM_CFG_DBW_MASK)
+ >> SDRAM_CFG_DBW_SHIFT);
+ timeout = ((total_mem_per_ctrl_adj << (6 - bus_width)) * 100 /
+ (clk >> 20)) << 2;
+ total_mem_per_ctrl_adj >>= 4; /* shift down to gb size */
+ if ((ddr_in32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) != 0) {
+ debug("total size %d GB\n", total_mem_per_ctrl_adj);
+ debug("Need to wait up to %d ms\n", timeout * 10);
+
+ do {
+ mdelay(10);
+ } while (timeout-- > 0 &&
+ ((ddr_in32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT)) != 0);
+
+ if (timeout <= 0) {
+ if (ddr_in32(&ddr->debug[1]) & 0x3d00) {
+ ERROR("Found training error(s): 0x%x\n",
+ ddr_in32(&ddr->debug[1]));
+ }
+ ERROR("Error: Waiting for D_INIT timeout.\n");
+ return -EIO;
+ }
+ }
+
+ if (mod_bnds != 0U) {
+ debug("Restore original bnds\n");
+ for (i = 0U; i < DDRC_NUM_CS; i++) {
+ ddr_out32(&ddr->bnds[i].a, regs->cs[i].bnds);
+ }
+ ddr_out32(&ddr->csn_cfg[0], regs->cs[0].config);
+#ifdef CONFIG_DDR_ADDR_DEC
+ if ((regs->dec[9] & U(0x1)) != 0U) {
+ debug("Restore address decoding\n");
+ ddr_out32(&ddr->dec[9], regs->dec[9]);
+ }
+#endif
+ }
+
+#ifdef ERRATA_DDR_A009803
+ /* Part 2 of 2 */
+ if ((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) {
+ timeout = 400;
+ do {
+ mdelay(1);
+ } while (timeout-- > 0 && ((ddr_in32(&ddr->debug[1]) & 0x2) == 0));
+
+ if ((regs->sdram_cfg[0] & SDRAM_CFG_RD_EN) != 0) {
+ for (i = 0U; i < DDRC_NUM_CS; i++) {
+ if ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) == 0) {
+ continue;
+ }
+ set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL(i) |
+ 0x070000ed,
+ MD_CNTL_MD_EN);
+ udelay(1);
+ }
+ }
+
+ ddr_out32(&ddr->err_disable,
+ regs->err_disable & ~DDR_ERR_DISABLE_APED);
+ }
+#endif
+
+#ifdef ERRATA_DDR_A009663
+ ddr_out32(&ddr->sdram_interval, regs->interval);
+#endif
+
+#ifdef ERRATA_DDR_A009942
+ timeout = 400;
+ do {
+ mdelay(1);
+ } while (timeout-- > 0 && ((ddr_in32(&ddr->debug[1]) & 0x2) == 0));
+ tmp = (regs->sdram_cfg[0] >> 19) & 0x3;
+ check = (tmp == DDR_DBUS_64) ? 4 : ((tmp == DDR_DBUS_32) ? 2 : 1);
+ for (i = 0; i < check; i++) {
+ tmp = ddr_in32(&ddr->debug[9 + i]);
+ debug("Reading debug[%d] as 0x%x\n", i + 9, tmp);
+ cpo_min = min(cpo_min,
+ min((tmp >> 24) & 0xff, (tmp >> 8) & 0xff));
+ cpo_max = max(cpo_max,
+ max((tmp >> 24) & 0xff, (tmp >> 8) & 0xff));
+ }
+ if ((regs->sdram_cfg[0] & SDRAM_CFG_ECC_EN) != 0) {
+ tmp = ddr_in32(&ddr->debug[13]);
+ cpo_min = min(cpo_min, (tmp >> 24) & 0xff);
+ cpo_max = max(cpo_max, (tmp >> 24) & 0xff);
+ }
+ debug("cpo_min 0x%x\n", cpo_min);
+ debug("cpo_max 0x%x\n", cpo_max);
+ tmp = ddr_in32(&ddr->debug[28]);
+ debug("debug[28] 0x%x\n", tmp);
+ if ((cpo_min + 0x3B) < (tmp & 0xff)) {
+ WARN("Warning: A009942 requires setting cpo_sample to 0x%x\n",
+ (cpo_min + cpo_max) / 2 + 0x27);
+ } else {
+ debug("Optimal cpo_sample 0x%x\n",
+ (cpo_min + cpo_max) / 2 + 0x27);
+ }
+#endif
+ if (run_bist() != 0) {
+ if ((ddr_in32(&ddr->debug[1]) &
+ ((get_ddrc_version(ddr) == 0x50500) ? 0x3c00 : 0x3d00)) != 0) {
+ ERROR("Found training error(s): 0x%x\n",
+ ddr_in32(&ddr->debug[1]));
+ return -EIO;
+ }
+ INFO("Running built-in self test ...\n");
+ /* give it 10x time to cover whole memory */
+ timeout = ((total_mem_per_ctrl << (6 - bus_width)) *
+ 100 / (clk >> 20)) * 10;
+ INFO("\tWait up to %d ms\n", timeout * 10);
+ ret = bist(ddr, timeout);
+ }
+ dump_ddrc((void *)ddr);
+
+ return ret;
+}
diff --git a/drivers/nxp/ddr/nxp-ddr/dimm.c b/drivers/nxp/ddr/nxp-ddr/dimm.c
new file mode 100644
index 0000000000..16efcbaacd
--- /dev/null
+++ b/drivers/nxp/ddr/nxp-ddr/dimm.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <dimm.h>
+#include <i2c.h>
+#include <lib/utils.h>
+
+int read_spd(unsigned char chip, void *buf, int len)
+{
+ unsigned char dummy = 0U;
+ int ret;
+
+ if (len < 256) {
+ ERROR("Invalid SPD length\n");
+ return -EINVAL;
+ }
+
+ i2c_write(SPD_SPA0_ADDRESS, 0, 1, &dummy, 1);
+ ret = i2c_read(chip, 0, 1, buf, 256);
+ if (ret == 0) {
+ i2c_write(SPD_SPA1_ADDRESS, 0, 1, &dummy, 1);
+ ret = i2c_read(chip, 0, 1, buf + 256, min(256, len - 256));
+ }
+ if (ret != 0) {
+ zeromem(buf, len);
+ }
+
+ return ret;
+}
+
+int crc16(unsigned char *ptr, int count)
+{
+ int i;
+ int crc = 0;
+
+ while (--count >= 0) {
+ crc = crc ^ (int)*ptr++ << 8;
+ for (i = 0; i < 8; ++i) {
+ if ((crc & 0x8000) != 0) {
+ crc = crc << 1 ^ 0x1021;
+ } else {
+ crc = crc << 1;
+ }
+ }
+ }
+ return crc & 0xffff;
+}
+
+static int ddr4_spd_check(const struct ddr4_spd *spd)
+{
+ void *p = (void *)spd;
+ int csum16;
+ int len;
+ char crc_lsb; /* byte 126 */
+ char crc_msb; /* byte 127 */
+
+ len = 126;
+ csum16 = crc16(p, len);
+
+ crc_lsb = (char) (csum16 & 0xff);
+ crc_msb = (char) (csum16 >> 8);
+
+ if (spd->crc[0] != crc_lsb || spd->crc[1] != crc_msb) {
+ ERROR("SPD CRC = 0x%x%x, computed CRC = 0x%x%x\n",
+ spd->crc[1], spd->crc[0], crc_msb, crc_lsb);
+ return -EINVAL;
+ }
+
+ p = (void *)spd + 128;
+ len = 126;
+ csum16 = crc16(p, len);
+
+ crc_lsb = (char) (csum16 & 0xff);
+ crc_msb = (char) (csum16 >> 8);
+
+ if (spd->mod_section.uc[126] != crc_lsb ||
+ spd->mod_section.uc[127] != crc_msb) {
+ ERROR("SPD CRC = 0x%x%x, computed CRC = 0x%x%x\n",
+ spd->mod_section.uc[127], spd->mod_section.uc[126],
+ crc_msb, crc_lsb);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static unsigned long long
+compute_ranksize(const struct ddr4_spd *spd)
+{
+ unsigned long long bsize;
+
+ int nbit_sdram_cap_bsize = 0;
+ int nbit_primary_bus_width = 0;
+ int nbit_sdram_width = 0;
+ int die_count = 0;
+ bool package_3ds;
+
+ if ((spd->density_banks & 0xf) <= 7) {
+ nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
+ }
+ if ((spd->bus_width & 0x7) < 4) {
+ nbit_primary_bus_width = (spd->bus_width & 0x7) + 3;
+ }
+ if ((spd->organization & 0x7) < 4) {
+ nbit_sdram_width = (spd->organization & 0x7) + 2;
+ }
+ package_3ds = (spd->package_type & 0x3) == 0x2;
+ if (package_3ds) {
+ die_count = (spd->package_type >> 4) & 0x7;
+ }
+
+ bsize = 1ULL << (nbit_sdram_cap_bsize - 3 +
+ nbit_primary_bus_width - nbit_sdram_width +
+ die_count);
+
+ return bsize;
+}
+
+int cal_dimm_params(const struct ddr4_spd *spd, struct dimm_params *pdimm)
+{
+ int ret;
+ int i;
+ static const unsigned char udimm_rc_e_dq[18] = {
+ 0x0c, 0x2c, 0x15, 0x35, 0x15, 0x35, 0x0b, 0x2c, 0x15,
+ 0x35, 0x0b, 0x35, 0x0b, 0x2c, 0x0b, 0x35, 0x15, 0x36
+ };
+ int spd_error = 0;
+ unsigned char *ptr;
+ unsigned char val;
+
+ if (spd->mem_type != SPD_MEMTYPE_DDR4) {
+ ERROR("Not a DDR4 DIMM.\n");
+ return -EINVAL;
+ }
+
+ ret = ddr4_spd_check(spd);
+ if (ret != 0) {
+ ERROR("DIMM SPD checksum mismatch\n");
+ return -EINVAL;
+ }
+
+ /*
+ * The part name in ASCII in the SPD EEPROM is not null terminated.
+ * Guarantee null termination here by presetting all bytes to 0
+ * and copying the part name in ASCII from the SPD onto it
+ */
+ if ((spd->info_size_crc & 0xF) > 2) {
+ memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+ }
+
+ /* DIMM organization parameters */
+ pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
+ debug("n_ranks %d\n", pdimm->n_ranks);
+ pdimm->rank_density = compute_ranksize(spd);
+ if (pdimm->rank_density == 0) {
+ return -EINVAL;
+ }
+
+ debug("rank_density 0x%llx\n", pdimm->rank_density);
+ pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+ debug("capacity 0x%llx\n", pdimm->capacity);
+ pdimm->die_density = spd->density_banks & 0xf;
+ debug("die density 0x%x\n", pdimm->die_density);
+ pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
+ debug("primary_sdram_width %d\n", pdimm->primary_sdram_width);
+ if (((spd->bus_width >> 3) & 0x3) != 0) {
+ pdimm->ec_sdram_width = 8;
+ } else {
+ pdimm->ec_sdram_width = 0;
+ }
+ debug("ec_sdram_width %d\n", pdimm->ec_sdram_width);
+ pdimm->device_width = 1 << ((spd->organization & 0x7) + 2);
+ debug("device_width %d\n", pdimm->device_width);
+ pdimm->package_3ds = (spd->package_type & 0x3) == 0x2 ?
+ (spd->package_type >> 4) & 0x7 : 0;
+ debug("package_3ds %d\n", pdimm->package_3ds);
+
+ switch (spd->module_type & DDR4_SPD_MODULETYPE_MASK) {
+ case DDR4_SPD_RDIMM:
+ case DDR4_SPD_MINI_RDIMM:
+ case DDR4_SPD_72B_SO_RDIMM:
+ pdimm->rdimm = 1;
+ pdimm->rc = spd->mod_section.registered.ref_raw_card & 0x8f;
+ if ((spd->mod_section.registered.reg_map & 0x1) != 0) {
+ pdimm->mirrored_dimm = 1;
+ }
+ val = spd->mod_section.registered.ca_stren;
+ pdimm->rcw[3] = val >> 4;
+ pdimm->rcw[4] = ((val & 0x3) << 2) | ((val & 0xc) >> 2);
+ val = spd->mod_section.registered.clk_stren;
+ pdimm->rcw[5] = ((val & 0x3) << 2) | ((val & 0xc) >> 2);
+ pdimm->rcw[6] = 0xf;
+ /* A17 used for 16Gb+, C[2:0] used for 3DS */
+ pdimm->rcw[8] = pdimm->die_density >= 0x6 ? 0x0 : 0x8 |
+ (pdimm->package_3ds > 0x3 ? 0x0 :
+ (pdimm->package_3ds > 0x1 ? 0x1 :
+ (pdimm->package_3ds > 0 ? 0x2 : 0x3)));
+ if (pdimm->package_3ds != 0 || pdimm->n_ranks != 4) {
+ pdimm->rcw[13] = 0x4;
+ } else {
+ pdimm->rcw[13] = 0x5;
+ }
+ pdimm->rcw[13] |= pdimm->mirrored_dimm ? 0x8 : 0;
+ break;
+
+ case DDR4_SPD_UDIMM:
+ case DDR4_SPD_SO_DIMM:
+ case DDR4_SPD_MINI_UDIMM:
+ case DDR4_SPD_72B_SO_UDIMM:
+ case DDR4_SPD_16B_SO_DIMM:
+ case DDR4_SPD_32B_SO_DIMM:
+ pdimm->rc = spd->mod_section.unbuffered.ref_raw_card & 0x8f;
+ if ((spd->mod_section.unbuffered.addr_mapping & 0x1) != 0) {
+ pdimm->mirrored_dimm = 1;
+ }
+ if ((spd->mod_section.unbuffered.mod_height & 0xe0) == 0 &&
+ (spd->mod_section.unbuffered.ref_raw_card == 0x04)) {
+ /* Fix SPD error found on DIMMs with raw card E0 */
+ for (i = 0; i < 18; i++) {
+ if (spd->mapping[i] == udimm_rc_e_dq[i]) {
+ continue;
+ }
+ spd_error = 1;
+ ptr = (unsigned char *)&spd->mapping[i];
+ *ptr = udimm_rc_e_dq[i];
+ }
+ if (spd_error != 0) {
+ INFO("SPD DQ mapping error fixed\n");
+ }
+ }
+ break;
+
+ default:
+ ERROR("Unknown module_type 0x%x\n", spd->module_type);
+ return -EINVAL;
+ }
+ debug("rdimm %d\n", pdimm->rdimm);
+ debug("mirrored_dimm %d\n", pdimm->mirrored_dimm);
+ debug("rc 0x%x\n", pdimm->rc);
+
+ /* SDRAM device parameters */
+ pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
+ debug("n_row_addr %d\n", pdimm->n_row_addr);
+ pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
+ debug("n_col_addr %d\n", pdimm->n_col_addr);
+ pdimm->bank_addr_bits = (spd->density_banks >> 4) & 0x3;
+ debug("bank_addr_bits %d\n", pdimm->bank_addr_bits);
+ pdimm->bank_group_bits = (spd->density_banks >> 6) & 0x3;
+ debug("bank_group_bits %d\n", pdimm->bank_group_bits);
+
+ if (pdimm->ec_sdram_width != 0) {
+ pdimm->edc_config = 0x02;
+ } else {
+ pdimm->edc_config = 0x00;
+ }
+ debug("edc_config %d\n", pdimm->edc_config);
+
+ /* DDR4 spec has BL8 -bit3, BC4 -bit2 */
+ pdimm->burst_lengths_bitmask = 0x0c;
+ debug("burst_lengths_bitmask 0x%x\n", pdimm->burst_lengths_bitmask);
+
+ /* MTB - medium timebase
+ * The MTB in the SPD spec is 125ps,
+ *
+ * FTB - fine timebase
+ * use 1/10th of ps as our unit to avoid floating point
+ * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps
+ */
+ if ((spd->timebases & 0xf) == 0x0) {
+ pdimm->mtb_ps = 125;
+ pdimm->ftb_10th_ps = 10;
+
+ } else {
+ ERROR("Unknown Timebases\n");
+ return -EINVAL;
+ }
+
+ /* sdram minimum cycle time */
+ pdimm->tckmin_x_ps = spd_to_ps(spd->tck_min, spd->fine_tck_min);
+ debug("tckmin_x_ps %d\n", pdimm->tckmin_x_ps);
+
+ /* sdram max cycle time */
+ pdimm->tckmax_ps = spd_to_ps(spd->tck_max, spd->fine_tck_max);
+ debug("tckmax_ps %d\n", pdimm->tckmax_ps);
+
+ /*
+ * CAS latency supported
+ * bit0 - CL7
+ * bit4 - CL11
+ * bit8 - CL15
+ * bit12- CL19
+ * bit16- CL23
+ */
+ pdimm->caslat_x = (spd->caslat_b1 << 7) |
+ (spd->caslat_b2 << 15) |
+ (spd->caslat_b3 << 23);
+ debug("caslat_x 0x%x\n", pdimm->caslat_x);
+
+ if (spd->caslat_b4 != 0) {
+ WARN("Unhandled caslat_b4 value\n");
+ }
+
+ /*
+ * min CAS latency time
+ */
+ pdimm->taa_ps = spd_to_ps(spd->taa_min, spd->fine_taa_min);
+ debug("taa_ps %d\n", pdimm->taa_ps);
+
+ /*
+ * min RAS to CAS delay time
+ */
+ pdimm->trcd_ps = spd_to_ps(spd->trcd_min, spd->fine_trcd_min);
+ debug("trcd_ps %d\n", pdimm->trcd_ps);
+
+ /*
+ * Min Row Precharge Delay Time
+ */
+ pdimm->trp_ps = spd_to_ps(spd->trp_min, spd->fine_trp_min);
+ debug("trp_ps %d\n", pdimm->trp_ps);
+
+ /* min active to precharge delay time */
+ pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) +
+ spd->tras_min_lsb) * pdimm->mtb_ps;
+ debug("tras_ps %d\n", pdimm->tras_ps);
+
+ /* min active to actice/refresh delay time */
+ pdimm->trc_ps = spd_to_ps((((spd->tras_trc_ext & 0xf0) << 4) +
+ spd->trc_min_lsb), spd->fine_trc_min);
+ debug("trc_ps %d\n", pdimm->trc_ps);
+ /* Min Refresh Recovery Delay Time */
+ pdimm->trfc1_ps = ((spd->trfc1_min_msb << 8) | (spd->trfc1_min_lsb)) *
+ pdimm->mtb_ps;
+ debug("trfc1_ps %d\n", pdimm->trfc1_ps);
+ pdimm->trfc2_ps = ((spd->trfc2_min_msb << 8) | (spd->trfc2_min_lsb)) *
+ pdimm->mtb_ps;
+ debug("trfc2_ps %d\n", pdimm->trfc2_ps);
+ pdimm->trfc4_ps = ((spd->trfc4_min_msb << 8) | (spd->trfc4_min_lsb)) *
+ pdimm->mtb_ps;
+ debug("trfc4_ps %d\n", pdimm->trfc4_ps);
+ /* min four active window delay time */
+ pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) *
+ pdimm->mtb_ps;
+ debug("tfaw_ps %d\n", pdimm->tfaw_ps);
+
+ /* min row active to row active delay time, different bank group */
+ pdimm->trrds_ps = spd_to_ps(spd->trrds_min, spd->fine_trrds_min);
+ debug("trrds_ps %d\n", pdimm->trrds_ps);
+ /* min row active to row active delay time, same bank group */
+ pdimm->trrdl_ps = spd_to_ps(spd->trrdl_min, spd->fine_trrdl_min);
+ debug("trrdl_ps %d\n", pdimm->trrdl_ps);
+ /* min CAS to CAS Delay Time (tCCD_Lmin), same bank group */
+ pdimm->tccdl_ps = spd_to_ps(spd->tccdl_min, spd->fine_tccdl_min);
+ debug("tccdl_ps %d\n", pdimm->tccdl_ps);
+ if (pdimm->package_3ds != 0) {
+ if (pdimm->die_density > 5) {
+ debug("Unsupported logical rank density 0x%x\n",
+ pdimm->die_density);
+ return -EINVAL;
+ }
+ pdimm->trfc_slr_ps = (pdimm->die_density <= 4) ?
+ 260000 : 350000;
+ }
+ debug("trfc_slr_ps %d\n", pdimm->trfc_slr_ps);
+
+ /* 15ns for all speed bins */
+ pdimm->twr_ps = 15000;
+ debug("twr_ps %d\n", pdimm->twr_ps);
+
+ /*
+ * Average periodic refresh interval
+ * tREFI = 7.8 us at normal temperature range
+ */
+ pdimm->refresh_rate_ps = 7800000;
+ debug("refresh_rate_ps %d\n", pdimm->refresh_rate_ps);
+
+ for (i = 0; i < 18; i++) {
+ pdimm->dq_mapping[i] = spd->mapping[i];
+ debug("dq_mapping 0x%x\n", pdimm->dq_mapping[i]);
+ }
+
+ pdimm->dq_mapping_ors = ((spd->mapping[0] >> 6) & 0x3) == 0 ? 1 : 0;
+ debug("dq_mapping_ors %d\n", pdimm->dq_mapping_ors);
+
+ return 0;
+}
diff --git a/drivers/nxp/ddr/nxp-ddr/regs.c b/drivers/nxp/ddr/nxp-ddr/regs.c
new file mode 100644
index 0000000000..cedd7ca09e
--- /dev/null
+++ b/drivers/nxp/ddr/nxp-ddr/regs.c
@@ -0,0 +1,1394 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+
+static inline unsigned int cal_cwl(const unsigned long clk)
+{
+ const unsigned int mclk_ps = get_memory_clk_ps(clk);
+
+ return mclk_ps >= 1250U ? 9U :
+ (mclk_ps >= 1070U ? 10U :
+ (mclk_ps >= 935U ? 11U :
+ (mclk_ps >= 833U ? 12U :
+ (mclk_ps >= 750U ? 14U :
+ (mclk_ps >= 625U ? 16U : 18U)))));
+}
+
+static void cal_csn_config(int i,
+ struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts,
+ const struct dimm_params *pdimm)
+{
+ unsigned int intlv_en = 0U;
+ unsigned int intlv_ctl = 0U;
+ const unsigned int cs_n_en = 1U;
+ const unsigned int ap_n_en = popts->cs_odt[i].auto_precharge;
+ const unsigned int odt_rd_cfg = popts->cs_odt[i].odt_rd_cfg;
+ const unsigned int odt_wr_cfg = popts->cs_odt[i].odt_wr_cfg;
+ const unsigned int ba_bits_cs_n = pdimm->bank_addr_bits;
+ const unsigned int row_bits_cs_n = pdimm->n_row_addr - 12U;
+ const unsigned int col_bits_cs_n = pdimm->n_col_addr - 8U;
+ const unsigned int bg_bits_cs_n = pdimm->bank_group_bits;
+
+ if (i == 0) {
+ /* These fields only available in CS0_CONFIG */
+ if (popts->ctlr_intlv != 0) {
+ switch (popts->ctlr_intlv_mode) {
+ case DDR_256B_INTLV:
+ intlv_en = popts->ctlr_intlv;
+ intlv_ctl = popts->ctlr_intlv_mode;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ regs->cs[i].config = ((cs_n_en & 0x1) << 31) |
+ ((intlv_en & 0x3) << 29) |
+ ((intlv_ctl & 0xf) << 24) |
+ ((ap_n_en & 0x1) << 23) |
+ ((odt_rd_cfg & 0x7) << 20) |
+ ((odt_wr_cfg & 0x7) << 16) |
+ ((ba_bits_cs_n & 0x3) << 14) |
+ ((row_bits_cs_n & 0x7) << 8) |
+ ((bg_bits_cs_n & 0x3) << 4) |
+ ((col_bits_cs_n & 0x7) << 0);
+ debug("cs%d\n", i);
+ debug(" _config = 0x%x\n", regs->cs[i].config);
+}
+
+static inline int avoid_odt_overlap(const struct ddr_conf *conf,
+ const struct dimm_params *pdimm)
+{
+ if ((conf->cs_in_use == 0xf) != 0) {
+ return 2;
+ }
+
+#if DDRC_NUM_DIMM >= 2
+ if (conf->dimm_in_use[0] != 0 && conf->dimm_in_use[1] != 0) {
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/* Requires rcw2 set first */
+static void cal_timing_cfg(const unsigned long clk,
+ struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts,
+ const struct dimm_params *pdimm,
+ const struct ddr_conf *conf,
+ unsigned int cas_latency,
+ unsigned int additive_latency)
+{
+ const unsigned int mclk_ps = get_memory_clk_ps(clk);
+ /* tXP=max(4nCK, 6ns) */
+ const int txp = max((int)mclk_ps * 4, 6000);
+ /* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */
+ static const int wrrec_table[] = {
+ 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10,
+ 12, 12, 14, 14, 16,
+ 16, 18, 18, 20, 20,
+ 24, 24, 24, 24,
+ };
+ int trwt_mclk = (clk / 1000000 > 1900) ? 3 : 2;
+ int twrt_mclk;
+ int trrt_mclk;
+ int twwt_mclk;
+ const int act_pd_exit_mclk = picos_to_mclk(clk, txp);
+ const int pre_pd_exit_mclk = act_pd_exit_mclk;
+ const int taxpd_mclk = 0;
+ /*
+ * MRS_CYC = max(tMRD, tMOD)
+ * tMRD = 8nCK, tMOD = max(24nCK, 15ns)
+ */
+ const int tmrd_mclk = max(24U, picos_to_mclk(clk, 15000));
+ const int pretoact_mclk = picos_to_mclk(clk, pdimm->trp_ps);
+ const int acttopre_mclk = picos_to_mclk(clk, pdimm->tras_ps);
+ const int acttorw_mclk = picos_to_mclk(clk, pdimm->trcd_ps);
+ const int caslat_ctrl = (cas_latency - 1) << 1;
+ const int trfc1_min = pdimm->die_density >= 0x3 ? 16000 :
+ (pdimm->die_density == 0x4 ? 26000 :
+ (pdimm->die_density == 0x5 ? 35000 :
+ 55000));
+ const int refrec_ctrl = picos_to_mclk(clk,
+ pdimm->trfc1_ps) - 8;
+ int wrrec_mclk = picos_to_mclk(clk, pdimm->twr_ps);
+ const int acttoact_mclk = max(picos_to_mclk(clk,
+ pdimm->trrds_ps),
+ 4U);
+ int wrtord_mclk = max(2U, picos_to_mclk(clk, 2500));
+ const unsigned int cpo = 0U;
+ const int wr_lat = cal_cwl(clk);
+ int rd_to_pre = picos_to_mclk(clk, 7500);
+ const int wr_data_delay = popts->wr_data_delay;
+ const int cke_pls = max(3U, picos_to_mclk(clk, 5000));
+#ifdef ERRATA_DDR_A050450
+ const unsigned short four_act = ((popts->twot_en == 0) &&
+ (popts->threet_en == 0) &&
+ (popts->tfaw_ps % 2 == 0)) ?
+ (picos_to_mclk(clk, popts->tfaw_ps) + 1) :
+ picos_to_mclk(clk, popts->tfaw_ps);
+#else
+ const unsigned short four_act = picos_to_mclk(clk,
+ popts->tfaw_ps);
+#endif
+ const unsigned int cntl_adj = 0U;
+ const unsigned int ext_pretoact = picos_to_mclk(clk,
+ pdimm->trp_ps) >> 4U;
+ const unsigned int ext_acttopre = picos_to_mclk(clk,
+ pdimm->tras_ps) >> 4U;
+ const unsigned int ext_acttorw = picos_to_mclk(clk,
+ pdimm->trcd_ps) >> 4U;
+ const unsigned int ext_caslat = (2U * cas_latency - 1U) >> 4U;
+ const unsigned int ext_add_lat = additive_latency >> 4U;
+ const unsigned int ext_refrec = (picos_to_mclk(clk,
+ pdimm->trfc1_ps) - 8U) >> 4U;
+ const unsigned int ext_wrrec = (picos_to_mclk(clk, pdimm->twr_ps) +
+ (popts->otf_burst_chop_en ? 2U : 0U)) >> 4U;
+ const unsigned int rwt_same_cs = 0U;
+ const unsigned int wrt_same_cs = 0U;
+ const unsigned int rrt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U;
+ const unsigned int wwt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U;
+ const unsigned int dll_lock = 2U;
+ unsigned int rodt_on = 0U;
+ const unsigned int rodt_off = 4U;
+ const unsigned int wodt_on = 1U;
+ const unsigned int wodt_off = 4U;
+ const unsigned int hs_caslat = 0U;
+ const unsigned int hs_wrlat = 0U;
+ const unsigned int hs_wrrec = 0U;
+ const unsigned int hs_clkadj = 0U;
+ const unsigned int hs_wrlvl_start = 0U;
+ const unsigned int txpr = max(5U,
+ picos_to_mclk(clk,
+ pdimm->trfc1_ps + 10000U));
+ const unsigned int tcksre = max(5U, picos_to_mclk(clk, 10000U));
+ const unsigned int tcksrx = max(5U, picos_to_mclk(clk, 10000U));
+ const unsigned int cs_to_cmd = 0U;
+ const unsigned int cke_rst = txpr <= 200U ? 0U :
+ (txpr <= 256U ? 1U :
+ (txpr <= 512U ? 2U : 3U));
+ const unsigned int cksre = tcksre <= 19U ? tcksre - 5U : 15U;
+ const unsigned int cksrx = tcksrx <= 19U ? tcksrx - 5U : 15U;
+ unsigned int par_lat = 0U;
+ const int tccdl = max(5U, picos_to_mclk(clk, pdimm->tccdl_ps));
+ int rwt_bg = cas_latency + 2 + 4 - wr_lat;
+ int wrt_bg = wr_lat + 4 + 1 - cas_latency;
+ const int rrt_bg = popts->burst_length == DDR_BL8 ?
+ tccdl - 4 : tccdl - 2;
+ const int wwt_bg = popts->burst_length == DDR_BL8 ?
+ tccdl - 4 : tccdl - 2;
+ const unsigned int acttoact_bg = picos_to_mclk(clk, pdimm->trrdl_ps);
+ const unsigned int wrtord_bg = max(4U, picos_to_mclk(clk, 7500)) +
+ (popts->otf_burst_chop_en ? 2 : 0);
+ const unsigned int pre_all_rec = 0;
+ const unsigned int refrec_cid_mclk = pdimm->package_3ds ?
+ picos_to_mclk(clk, pdimm->trfc_slr_ps) : 0;
+ const unsigned int acttoact_cid_mclk = pdimm->package_3ds ? 4U : 0;
+
+
+ /* for two dual-rank DIMMs to avoid ODT overlap */
+ if (avoid_odt_overlap(conf, pdimm) == 2) {
+ twrt_mclk = 2;
+ twwt_mclk = 2;
+ trrt_mclk = 2;
+ } else {
+ twrt_mclk = 1;
+ twwt_mclk = 1;
+ trrt_mclk = 0;
+ }
+
+ if (popts->trwt_override != 0) {
+ trwt_mclk = popts->trwt;
+ if (popts->twrt != 0) {
+ twrt_mclk = popts->twrt;
+ }
+ if (popts->trrt != 0) {
+ trrt_mclk = popts->trrt;
+ }
+ if (popts->twwt != 0) {
+ twwt_mclk = popts->twwt;
+ }
+ }
+ regs->timing_cfg[0] = (((trwt_mclk & 0x3) << 30) |
+ ((twrt_mclk & 0x3) << 28) |
+ ((trrt_mclk & 0x3) << 26) |
+ ((twwt_mclk & 0x3) << 24) |
+ ((act_pd_exit_mclk & 0xf) << 20) |
+ ((pre_pd_exit_mclk & 0xF) << 16) |
+ ((taxpd_mclk & 0xf) << 8) |
+ ((tmrd_mclk & 0x1f) << 0));
+ debug("timing_cfg[0] = 0x%x\n", regs->timing_cfg[0]);
+
+ if ((wrrec_mclk < 1) || (wrrec_mclk > 24)) {
+ ERROR("WRREC doesn't support clock %d\n", wrrec_mclk);
+ } else {
+ wrrec_mclk = wrrec_table[wrrec_mclk - 1];
+ }
+
+ if (popts->otf_burst_chop_en != 0) {
+ wrrec_mclk += 2;
+ wrtord_mclk += 2;
+ }
+
+ if (pdimm->trfc1_ps < trfc1_min) {
+ ERROR("trfc1_ps (%d) < %d\n", pdimm->trfc1_ps, trfc1_min);
+ }
+
+ regs->timing_cfg[1] = (((pretoact_mclk & 0x0F) << 28) |
+ ((acttopre_mclk & 0x0F) << 24) |
+ ((acttorw_mclk & 0xF) << 20) |
+ ((caslat_ctrl & 0xF) << 16) |
+ ((refrec_ctrl & 0xF) << 12) |
+ ((wrrec_mclk & 0x0F) << 8) |
+ ((acttoact_mclk & 0x0F) << 4) |
+ ((wrtord_mclk & 0x0F) << 0));
+ debug("timing_cfg[1] = 0x%x\n", regs->timing_cfg[1]);
+
+ if (rd_to_pre < 4) {
+ rd_to_pre = 4;
+ }
+ if (popts->otf_burst_chop_en) {
+ rd_to_pre += 2;
+ }
+
+ regs->timing_cfg[2] = (((additive_latency & 0xf) << 28) |
+ ((cpo & 0x1f) << 23) |
+ ((wr_lat & 0xf) << 19) |
+ (((wr_lat & 0x10) >> 4) << 18) |
+ ((rd_to_pre & 0xf) << 13) |
+ ((wr_data_delay & 0xf) << 9) |
+ ((cke_pls & 0x7) << 6) |
+ ((four_act & 0x3f) << 0));
+ debug("timing_cfg[2] = 0x%x\n", regs->timing_cfg[2]);
+
+ regs->timing_cfg[3] = (((ext_pretoact & 0x1) << 28) |
+ ((ext_acttopre & 0x3) << 24) |
+ ((ext_acttorw & 0x1) << 22) |
+ ((ext_refrec & 0x3F) << 16) |
+ ((ext_caslat & 0x3) << 12) |
+ ((ext_add_lat & 0x1) << 10) |
+ ((ext_wrrec & 0x1) << 8) |
+ ((cntl_adj & 0x7) << 0));
+ debug("timing_cfg[3] = 0x%x\n", regs->timing_cfg[3]);
+
+ regs->timing_cfg[4] = (((rwt_same_cs & 0xf) << 28) |
+ ((wrt_same_cs & 0xf) << 24) |
+ ((rrt_same_cs & 0xf) << 20) |
+ ((wwt_same_cs & 0xf) << 16) |
+ ((trwt_mclk & 0xc) << 12) |
+ ((twrt_mclk & 0x4) << 10) |
+ ((trrt_mclk & 0x4) << 8) |
+ ((twwt_mclk & 0x4) << 6) |
+ (dll_lock & 0x3));
+ debug("timing_cfg[4] = 0x%x\n", regs->timing_cfg[4]);
+
+ /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
+ if (cas_latency >= wr_lat) {
+ rodt_on = cas_latency - wr_lat + 1;
+ }
+
+ regs->timing_cfg[5] = (((rodt_on & 0x1f) << 24) |
+ ((rodt_off & 0x7) << 20) |
+ ((wodt_on & 0x1f) << 12) |
+ (wodt_off & 0x7) << 8);
+ debug("timing_cfg[5] = 0x%x\n", regs->timing_cfg[5]);
+
+ regs->timing_cfg[6] = (((hs_caslat & 0x1f) << 24) |
+ ((hs_wrlat & 0x1f) << 19) |
+ ((hs_wrrec & 0x1f) << 12) |
+ ((hs_clkadj & 0x1f) << 6) |
+ ((hs_wrlvl_start & 0x1f) << 0));
+ debug("timing_cfg[6] = 0x%x\n", regs->timing_cfg[6]);
+
+ if (popts->ap_en != 0) {
+ par_lat = (regs->sdram_rcw[1] & 0xf) + 1;
+ debug("PAR_LAT = 0x%x\n", par_lat);
+ }
+
+ regs->timing_cfg[7] = (((cke_rst & 0x3) << 28) |
+ ((cksre & 0xf) << 24) |
+ ((cksrx & 0xf) << 20) |
+ ((par_lat & 0xf) << 16) |
+ ((cs_to_cmd & 0xf) << 4));
+ debug("timing_cfg[7] = 0x%x\n", regs->timing_cfg[7]);
+
+ if (rwt_bg < tccdl) {
+ rwt_bg = tccdl - rwt_bg;
+ } else {
+ rwt_bg = 0;
+ }
+ if (wrt_bg < tccdl) {
+ wrt_bg = tccdl - wrt_bg;
+ } else {
+ wrt_bg = 0;
+ }
+ regs->timing_cfg[8] = (((rwt_bg & 0xf) << 28) |
+ ((wrt_bg & 0xf) << 24) |
+ ((rrt_bg & 0xf) << 20) |
+ ((wwt_bg & 0xf) << 16) |
+ ((acttoact_bg & 0xf) << 12) |
+ ((wrtord_bg & 0xf) << 8) |
+ ((pre_all_rec & 0x1f) << 0));
+ debug("timing_cfg[8] = 0x%x\n", regs->timing_cfg[8]);
+
+ regs->timing_cfg[9] = (refrec_cid_mclk & 0x3ff) << 16 |
+ (acttoact_cid_mclk & 0xf) << 8;
+ debug("timing_cfg[9] = 0x%x\n", regs->timing_cfg[9]);
+}
+
+static void cal_ddr_sdram_rcw(const unsigned long clk,
+ struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts,
+ const struct dimm_params *pdimm)
+{
+ const unsigned int freq = clk / 1000000U;
+ unsigned int rc0a, rc0f;
+
+ if (pdimm->rdimm == 0) {
+ return;
+ }
+
+ rc0a = freq > 3200U ? 7U :
+ (freq > 2933U ? 6U :
+ (freq > 2666U ? 5U :
+ (freq > 2400U ? 4U :
+ (freq > 2133U ? 3U :
+ (freq > 1866U ? 2U :
+ (freq > 1600U ? 1U : 0U))))));
+ rc0f = freq > 3200U ? 3U :
+ (freq > 2400U ? 2U :
+ (freq > 2133U ? 1U : 0U));
+ rc0f = (regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) ? rc0f : 4;
+ regs->sdram_rcw[0] =
+ pdimm->rcw[0] << 28 |
+ pdimm->rcw[1] << 24 |
+ pdimm->rcw[2] << 20 |
+ pdimm->rcw[3] << 16 |
+ pdimm->rcw[4] << 12 |
+ pdimm->rcw[5] << 8 |
+ pdimm->rcw[6] << 4 |
+ pdimm->rcw[7];
+ regs->sdram_rcw[1] =
+ pdimm->rcw[8] << 28 |
+ pdimm->rcw[9] << 24 |
+ rc0a << 20 |
+ pdimm->rcw[11] << 16 |
+ pdimm->rcw[12] << 12 |
+ pdimm->rcw[13] << 8 |
+ pdimm->rcw[14] << 4 |
+ rc0f;
+ regs->sdram_rcw[2] =
+ ((freq - 1260 + 19) / 20) << 8;
+
+ debug("sdram_rcw[0] = 0x%x\n", regs->sdram_rcw[0]);
+ debug("sdram_rcw[1] = 0x%x\n", regs->sdram_rcw[1]);
+ debug("sdram_rcw[2] = 0x%x\n", regs->sdram_rcw[2]);
+}
+
+static void cal_ddr_sdram_cfg(const unsigned long clk,
+ struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts,
+ const struct dimm_params *pdimm,
+ const unsigned int ip_rev)
+{
+ const unsigned int mem_en = 1U;
+ const unsigned int sren = popts->self_refresh_in_sleep;
+ const unsigned int ecc_en = popts->ecc_mode;
+ const unsigned int rd_en = (pdimm->rdimm != 0U) ? 1U : 0U;
+ const unsigned int dyn_pwr = popts->dynamic_power;
+ const unsigned int dbw = popts->data_bus_used;
+ const unsigned int eight_be = (dbw == 1U ||
+ popts->burst_length == DDR_BL8) ? 1U : 0U;
+ const unsigned int ncap = 0U;
+ const unsigned int threet_en = popts->threet_en;
+ const unsigned int twot_en = pdimm->rdimm ?
+ 0U : popts->twot_en;
+ const unsigned int ba_intlv = popts->ba_intlv;
+ const unsigned int x32_en = 0U;
+ const unsigned int pchb8 = 0U;
+ const unsigned int hse = popts->half_strength_drive_en;
+ const unsigned int acc_ecc_en = (dbw != 0U && ecc_en == 1U) ? 1U : 0U;
+ const unsigned int mem_halt = 0U;
+#ifdef PHY_GEN2
+ const unsigned int bi = 1U;
+#else
+ const unsigned int bi = 0U;
+#endif
+ const unsigned int sdram_type = SDRAM_TYPE_DDR4;
+ unsigned int odt_cfg = 0U;
+ const unsigned int frc_sr = 0U;
+ const unsigned int sr_ie = popts->self_refresh_irq_en;
+ const unsigned int num_pr = pdimm->package_3ds + 1U;
+ const unsigned int slow = (clk < 1249000000U) ? 1U : 0U;
+ const unsigned int x4_en = popts->x4_en;
+ const unsigned int obc_cfg = popts->otf_burst_chop_en;
+ const unsigned int ap_en = ip_rev == 0x50500U ? 0U : popts->ap_en;
+ const unsigned int d_init = popts->ctlr_init_ecc;
+ const unsigned int rcw_en = popts->rdimm;
+ const unsigned int md_en = popts->mirrored_dimm;
+ const unsigned int qd_en = popts->quad_rank_present;
+ const unsigned int unq_mrs_en = ip_rev < 0x50500U ? 1U : 0U;
+ const unsigned int rd_pre = popts->quad_rank_present;
+ int i;
+
+ regs->sdram_cfg[0] = ((mem_en & 0x1) << 31) |
+ ((sren & 0x1) << 30) |
+ ((ecc_en & 0x1) << 29) |
+ ((rd_en & 0x1) << 28) |
+ ((sdram_type & 0x7) << 24) |
+ ((dyn_pwr & 0x1) << 21) |
+ ((dbw & 0x3) << 19) |
+ ((eight_be & 0x1) << 18) |
+ ((ncap & 0x1) << 17) |
+ ((threet_en & 0x1) << 16) |
+ ((twot_en & 0x1) << 15) |
+ ((ba_intlv & 0x7F) << 8) |
+ ((x32_en & 0x1) << 5) |
+ ((pchb8 & 0x1) << 4) |
+ ((hse & 0x1) << 3) |
+ ((acc_ecc_en & 0x1) << 2) |
+ ((mem_halt & 0x1) << 1) |
+ ((bi & 0x1) << 0);
+ debug("sdram_cfg[0] = 0x%x\n", regs->sdram_cfg[0]);
+
+ for (i = 0; i < DDRC_NUM_CS; i++) {
+ if (popts->cs_odt[i].odt_rd_cfg != 0 ||
+ popts->cs_odt[i].odt_wr_cfg != 0) {
+ odt_cfg = SDRAM_CFG2_ODT_ONLY_READ;
+ break;
+ }
+ }
+
+ regs->sdram_cfg[1] = (0
+ | ((frc_sr & 0x1) << 31)
+ | ((sr_ie & 0x1) << 30)
+ | ((odt_cfg & 0x3) << 21)
+ | ((num_pr & 0xf) << 12)
+ | ((slow & 1) << 11)
+ | (x4_en << 10)
+ | (qd_en << 9)
+ | (unq_mrs_en << 8)
+ | ((obc_cfg & 0x1) << 6)
+ | ((ap_en & 0x1) << 5)
+ | ((d_init & 0x1) << 4)
+ | ((rcw_en & 0x1) << 2)
+ | ((md_en & 0x1) << 0)
+ );
+ debug("sdram_cfg[1] = 0x%x\n", regs->sdram_cfg[1]);
+
+ regs->sdram_cfg[2] = (rd_pre & 0x1) << 16 |
+ (popts->rdimm ? 1 : 0);
+ if (pdimm->package_3ds != 0) {
+ if (((pdimm->package_3ds + 1) & 0x1) != 0) {
+ WARN("Unsupported 3DS DIMM\n");
+ } else {
+ regs->sdram_cfg[2] |= ((pdimm->package_3ds + 1) >> 1)
+ << 4;
+ }
+ }
+ debug("sdram_cfg[2] = 0x%x\n", regs->sdram_cfg[2]);
+}
+
+
+static void cal_ddr_sdram_interval(const unsigned long clk,
+ struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts,
+ const struct dimm_params *pdimm)
+{
+ const unsigned int refint = picos_to_mclk(clk, pdimm->refresh_rate_ps);
+ const unsigned int bstopre = popts->bstopre;
+
+ regs->interval = ((refint & 0xFFFF) << 16) |
+ ((bstopre & 0x3FFF) << 0);
+ debug("interval = 0x%x\n", regs->interval);
+}
+
+/* Require cs and cfg first */
+static void cal_ddr_sdram_mode(const unsigned long clk,
+ struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts,
+ const struct ddr_conf *conf,
+ const struct dimm_params *pdimm,
+ unsigned int cas_latency,
+ unsigned int additive_latency,
+ const unsigned int ip_rev)
+{
+ int i;
+ unsigned short esdmode; /* Extended SDRAM mode */
+ unsigned short sdmode; /* SDRAM mode */
+
+ /* Mode Register - MR1 */
+ const unsigned int qoff = 0;
+ const unsigned int tdqs_en = 0;
+ unsigned int rtt;
+ const unsigned int wrlvl_en = 0;
+ unsigned int al = 0;
+ unsigned int dic = 0;
+ const unsigned int dll_en = 1;
+
+ /* Mode Register - MR0 */
+ unsigned int wr = 0;
+ const unsigned int dll_rst = 0;
+ const unsigned int mode = 0;
+ unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
+ /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+ const unsigned int bt = 0;
+ const unsigned int bl = popts->burst_length == DDR_BL8 ? 0 :
+ (popts->burst_length == DDR_BC4 ? 2 : 1);
+
+ const unsigned int wr_mclk = picos_to_mclk(clk, pdimm->twr_ps);
+ /* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
+ static const int wr_table[] = {
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6
+ };
+ /* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
+ static const int cas_latency_table[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 13, 8,
+ 14, 9, 15, 10, 12, 11, 16, 17,
+ 18, 19, 20, 21, 22, 23
+ };
+ const unsigned int unq_mrs_en = ip_rev < U(0x50500) ? 1U : 0U;
+ unsigned short esdmode2 = 0U;
+ unsigned short esdmode3 = 0U;
+ const unsigned int wr_crc = 0U;
+ unsigned int rtt_wr = 0U;
+ const unsigned int srt = 0U;
+ unsigned int cwl = cal_cwl(clk);
+ const unsigned int mpr = 0U;
+ const unsigned int mclk_ps = get_memory_clk_ps(clk);
+ const unsigned int wc_lat = 0U;
+ unsigned short esdmode4 = 0U;
+ unsigned short esdmode5;
+ int rtt_park_all = 0;
+ unsigned int rtt_park;
+ const bool four_cs = conf->cs_in_use == 0xf ? true : false;
+ unsigned short esdmode6 = 0U; /* Extended SDRAM mode 6 */
+ unsigned short esdmode7 = 0U; /* Extended SDRAM mode 7 */
+ const unsigned int tccdl_min = max(5U,
+ picos_to_mclk(clk, pdimm->tccdl_ps));
+
+ if (popts->rtt_override != 0U) {
+ rtt = popts->rtt_override_value;
+ } else {
+ rtt = popts->cs_odt[0].odt_rtt_norm;
+ }
+
+ if (additive_latency == (cas_latency - 1)) {
+ al = 1;
+ }
+ if (additive_latency == (cas_latency - 2)) {
+ al = 2;
+ }
+
+ if (popts->quad_rank_present != 0 || popts->output_driver_impedance != 0) {
+ dic = 1; /* output driver impedance 240/7 ohm */
+ }
+
+ esdmode = (((qoff & 0x1) << 12) |
+ ((tdqs_en & 0x1) << 11) |
+ ((rtt & 0x7) << 8) |
+ ((wrlvl_en & 0x1) << 7) |
+ ((al & 0x3) << 3) |
+ ((dic & 0x3) << 1) |
+ ((dll_en & 0x1) << 0));
+
+ if (wr_mclk >= 10 && wr_mclk <= 24) {
+ wr = wr_table[wr_mclk - 10];
+ } else {
+ ERROR("unsupported wc_mclk = %d for mode register\n", wr_mclk);
+ }
+
+ /* look up table to get the cas latency bits */
+ if (cas_latency >= 9 && cas_latency <= 32) {
+ caslat = cas_latency_table[cas_latency - 9];
+ } else {
+ WARN("Error: unsupported cas latency for mode register\n");
+ }
+
+ sdmode = (((caslat & 0x10) << 8) |
+ ((wr & 0x7) << 9) |
+ ((dll_rst & 0x1) << 8) |
+ ((mode & 0x1) << 7) |
+ (((caslat >> 1) & 0x7) << 4) |
+ ((bt & 0x1) << 3) |
+ ((caslat & 1) << 2) |
+ ((bl & 0x3) << 0));
+
+ regs->sdram_mode[0] = (((esdmode & 0xFFFF) << 16) |
+ ((sdmode & 0xFFFF) << 0));
+ debug("sdram_mode[0] = 0x%x\n", regs->sdram_mode[0]);
+
+ switch (cwl) {
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ cwl -= 9;
+ break;
+ case 14:
+ cwl -= 10;
+ break;
+ case 16:
+ cwl -= 11;
+ break;
+ case 18:
+ cwl -= 12;
+ break;
+ case 20:
+ cwl -= 13;
+ break;
+ default:
+ printf("Error CWL\n");
+ break;
+ }
+
+ if (popts->rtt_override != 0) {
+ rtt_wr = popts->rtt_wr_override_value;
+ } else {
+ rtt_wr = popts->cs_odt[0].odt_rtt_wr;
+ }
+
+ esdmode2 = ((wr_crc & 0x1) << 12) |
+ ((rtt_wr & 0x7) << 9) |
+ ((srt & 0x3) << 6) |
+ ((cwl & 0x7) << 3);
+ esdmode3 = ((mpr & 0x3) << 11) | ((wc_lat & 0x3) << 9);
+
+ regs->sdram_mode[1] = ((esdmode2 & 0xFFFF) << 16) |
+ ((esdmode3 & 0xFFFF) << 0);
+ debug("sdram_mode[1] = 0x%x\n", regs->sdram_mode[1]);
+
+ esdmode6 = ((tccdl_min - 4) & 0x7) << 10;
+ if (popts->vref_dimm != 0) {
+ esdmode6 |= popts->vref_dimm & 0x7f;
+ } else if ((popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2) != 0) {
+ esdmode6 |= 1 << 6; /* Range 2 */
+ }
+
+ regs->sdram_mode[9] = ((esdmode6 & 0xffff) << 16) |
+ ((esdmode7 & 0xffff) << 0);
+ debug("sdram_mode[9] = 0x%x\n", regs->sdram_mode[9]);
+
+ rtt_park = (popts->rtt_park != 0) ? popts->rtt_park : 240;
+ switch (rtt_park) {
+ case 240:
+ rtt_park = 0x4;
+ break;
+ case 120:
+ rtt_park = 0x2;
+ break;
+ case 80:
+ rtt_park = 0x6;
+ break;
+ case 60:
+ rtt_park = 0x1;
+ break;
+ case 48:
+ rtt_park = 0x5;
+ break;
+ case 40:
+ rtt_park = 0x3;
+ break;
+ case 34:
+ rtt_park = 0x7;
+ break;
+ default:
+ rtt_park = 0;
+ break;
+ }
+
+ for (i = 0; i < DDRC_NUM_CS; i++) {
+ if (i != 0 && unq_mrs_en == 0) {
+ break;
+ }
+
+ if (popts->rtt_override != 0) {
+ rtt = popts->rtt_override_value;
+ rtt_wr = popts->rtt_wr_override_value;
+ } else {
+ rtt = popts->cs_odt[i].odt_rtt_norm;
+ rtt_wr = popts->cs_odt[i].odt_rtt_wr;
+ }
+
+ esdmode &= 0xF8FF; /* clear bit 10,9,8 for rtt */
+ esdmode |= (rtt & 0x7) << 8;
+ esdmode2 &= 0xF9FF; /* clear bit 10, 9 */
+ esdmode2 |= (rtt_wr & 0x3) << 9;
+ esdmode5 = (popts->x4_en) ? 0 : 0x400; /* data mask */
+
+ if (rtt_park_all == 0 &&
+ ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) != 0)) {
+ esdmode5 |= rtt_park << 6;
+ rtt_park_all = four_cs ? 0 : 1;
+ }
+
+ if (((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) &&
+ (popts->rdimm == 0)) {
+ if (mclk_ps >= 935) {
+ esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
+ } else if (mclk_ps >= 833) {
+ esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
+ } else {
+ esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
+ WARN("mclk_ps not supported %d", mclk_ps);
+
+ }
+ }
+
+ switch (i) {
+ case 0:
+ regs->sdram_mode[8] = ((esdmode4 & 0xffff) << 16) |
+ ((esdmode5 & 0xffff) << 0);
+ debug("sdram_mode[8] = 0x%x\n", regs->sdram_mode[8]);
+ break;
+ case 1:
+ regs->sdram_mode[2] = (((esdmode & 0xFFFF) << 16) |
+ ((sdmode & 0xFFFF) << 0));
+ regs->sdram_mode[3] = ((esdmode2 & 0xFFFF) << 16) |
+ ((esdmode3 & 0xFFFF) << 0);
+ regs->sdram_mode[10] = ((esdmode4 & 0xFFFF) << 16) |
+ ((esdmode5 & 0xFFFF) << 0);
+ regs->sdram_mode[11] = ((esdmode6 & 0xFFFF) << 16) |
+ ((esdmode7 & 0xFFFF) << 0);
+ debug("sdram_mode[2] = 0x%x\n", regs->sdram_mode[2]);
+ debug("sdram_mode[3] = 0x%x\n", regs->sdram_mode[3]);
+ debug("sdram_mode[10] = 0x%x\n", regs->sdram_mode[10]);
+ debug("sdram_mode[11] = 0x%x\n", regs->sdram_mode[11]);
+ break;
+ case 2:
+ regs->sdram_mode[4] = (((esdmode & 0xFFFF) << 16) |
+ ((sdmode & 0xFFFF) << 0));
+ regs->sdram_mode[5] = ((esdmode2 & 0xFFFF) << 16) |
+ ((esdmode3 & 0xFFFF) << 0);
+ regs->sdram_mode[12] = ((esdmode4 & 0xFFFF) << 16) |
+ ((esdmode5 & 0xFFFF) << 0);
+ regs->sdram_mode[13] = ((esdmode6 & 0xFFFF) << 16) |
+ ((esdmode7 & 0xFFFF) << 0);
+ debug("sdram_mode[4] = 0x%x\n", regs->sdram_mode[4]);
+ debug("sdram_mode[5] = 0x%x\n", regs->sdram_mode[5]);
+ debug("sdram_mode[12] = 0x%x\n", regs->sdram_mode[12]);
+ debug("sdram_mode[13] = 0x%x\n", regs->sdram_mode[13]);
+ break;
+ case 3:
+ regs->sdram_mode[6] = (((esdmode & 0xFFFF) << 16) |
+ ((sdmode & 0xFFFF) << 0));
+ regs->sdram_mode[7] = ((esdmode2 & 0xFFFF) << 16) |
+ ((esdmode3 & 0xFFFF) << 0);
+ regs->sdram_mode[14] = ((esdmode4 & 0xFFFF) << 16) |
+ ((esdmode5 & 0xFFFF) << 0);
+ regs->sdram_mode[15] = ((esdmode6 & 0xFFFF) << 16) |
+ ((esdmode7 & 0xFFFF) << 0);
+ debug("sdram_mode[6] = 0x%x\n", regs->sdram_mode[6]);
+ debug("sdram_mode[7] = 0x%x\n", regs->sdram_mode[7]);
+ debug("sdram_mode[14] = 0x%x\n", regs->sdram_mode[14]);
+ debug("sdram_mode[15] = 0x%x\n", regs->sdram_mode[15]);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+#ifndef CONFIG_MEM_INIT_VALUE
+#define CONFIG_MEM_INIT_VALUE 0xDEADBEEF
+#endif
+static void cal_ddr_data_init(struct ddr_cfg_regs *regs)
+{
+ regs->data_init = CONFIG_MEM_INIT_VALUE;
+}
+
+static void cal_ddr_dq_mapping(struct ddr_cfg_regs *regs,
+ const struct dimm_params *pdimm)
+{
+ const unsigned int acc_ecc_en = (regs->sdram_cfg[0] >> 2) & 0x1;
+/* FIXME: revert the dq mapping from DIMM */
+ regs->dq_map[0] = ((pdimm->dq_mapping[0] & 0x3F) << 26) |
+ ((pdimm->dq_mapping[1] & 0x3F) << 20) |
+ ((pdimm->dq_mapping[2] & 0x3F) << 14) |
+ ((pdimm->dq_mapping[3] & 0x3F) << 8) |
+ ((pdimm->dq_mapping[4] & 0x3F) << 2);
+
+ regs->dq_map[1] = ((pdimm->dq_mapping[5] & 0x3F) << 26) |
+ ((pdimm->dq_mapping[6] & 0x3F) << 20) |
+ ((pdimm->dq_mapping[7] & 0x3F) << 14) |
+ ((pdimm->dq_mapping[10] & 0x3F) << 8) |
+ ((pdimm->dq_mapping[11] & 0x3F) << 2);
+
+ regs->dq_map[2] = ((pdimm->dq_mapping[12] & 0x3F) << 26) |
+ ((pdimm->dq_mapping[13] & 0x3F) << 20) |
+ ((pdimm->dq_mapping[14] & 0x3F) << 14) |
+ ((pdimm->dq_mapping[15] & 0x3F) << 8) |
+ ((pdimm->dq_mapping[16] & 0x3F) << 2);
+
+ /* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */
+ regs->dq_map[3] = ((pdimm->dq_mapping[17] & 0x3F) << 26) |
+ ((pdimm->dq_mapping[8] & 0x3F) << 20) |
+ ((acc_ecc_en != 0) ? 0 :
+ (pdimm->dq_mapping[9] & 0x3F) << 14) |
+ pdimm->dq_mapping_ors;
+ debug("dq_map[0] = 0x%x\n", regs->dq_map[0]);
+ debug("dq_map[1] = 0x%x\n", regs->dq_map[1]);
+ debug("dq_map[2] = 0x%x\n", regs->dq_map[2]);
+ debug("dq_map[3] = 0x%x\n", regs->dq_map[3]);
+}
+static void cal_ddr_zq_cntl(struct ddr_cfg_regs *regs)
+{
+ const unsigned int zqinit = 10U; /* 1024 clocks */
+ const unsigned int zqoper = 9U; /* 512 clocks */
+ const unsigned int zqcs = 7U; /* 128 clocks */
+ const unsigned int zqcs_init = 5U; /* 1024 refresh seqences */
+ const unsigned int zq_en = 1U; /* enabled */
+
+ regs->zq_cntl = ((zq_en & 0x1) << 31) |
+ ((zqinit & 0xF) << 24) |
+ ((zqoper & 0xF) << 16) |
+ ((zqcs & 0xF) << 8) |
+ ((zqcs_init & 0xF) << 0);
+ debug("zq_cntl = 0x%x\n", regs->zq_cntl);
+}
+
+static void cal_ddr_sr_cntr(struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts)
+{
+ const unsigned int sr_it = (popts->auto_self_refresh_en) ?
+ popts->sr_it : 0;
+
+ regs->ddr_sr_cntr = (sr_it & 0xF) << 16;
+ debug("ddr_sr_cntr = 0x%x\n", regs->ddr_sr_cntr);
+}
+
+static void cal_ddr_eor(struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts)
+{
+ if (popts->addr_hash != 0) {
+ regs->eor = 0x40000000; /* address hash enable */
+ debug("eor = 0x%x\n", regs->eor);
+ }
+}
+
+static void cal_ddr_csn_bnds(struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts,
+ const struct ddr_conf *conf,
+ const struct dimm_params *pdimm)
+{
+ int i;
+ unsigned long long ea, sa;
+
+ /* Chip Select Memory Bounds (CSn_BNDS) */
+ for (i = 0;
+ i < DDRC_NUM_CS && conf->cs_size[i];
+ i++) {
+ debug("cs_in_use = 0x%x\n", conf->cs_in_use);
+ if (conf->cs_in_use != 0) {
+ sa = conf->cs_base_addr[i];
+ ea = sa + conf->cs_size[i] - 1;
+ sa >>= 24;
+ ea >>= 24;
+ regs->cs[i].bnds = ((sa & 0xffff) << 16) |
+ ((ea & 0xffff) << 0);
+ cal_csn_config(i, regs, popts, pdimm);
+ } else {
+ /* setting bnds to 0xffffffff for inactive CS */
+ regs->cs[i].bnds = 0xffffffff;
+ }
+
+ debug("cs[%d].bnds = 0x%x\n", i, regs->cs[i].bnds);
+ }
+}
+
+static void cal_ddr_addr_dec(struct ddr_cfg_regs *regs)
+{
+#ifdef CONFIG_DDR_ADDR_DEC
+ unsigned int ba_bits __unused;
+ char p __unused;
+ const unsigned int cs0_config = regs->cs[0].config;
+ const int cacheline = PLATFORM_CACHE_LINE_SHIFT;
+ unsigned int bg_bits;
+ unsigned int row_bits;
+ unsigned int col_bits;
+ unsigned int cs;
+ unsigned int map_row[18];
+ unsigned int map_col[11];
+ unsigned int map_ba[2];
+ unsigned int map_cid[2] = {0x3F, 0x3F};
+ unsigned int map_bg[2] = {0x3F, 0x3F};
+ unsigned int map_cs[2] = {0x3F, 0x3F};
+ unsigned int dbw;
+ unsigned int ba_intlv;
+ int placement;
+ int intlv;
+ int abort = 0;
+ int i;
+ int j;
+
+ col_bits = (cs0_config >> 0) & 0x7;
+ if (col_bits < 4) {
+ col_bits += 8;
+ } else if (col_bits < 7 || col_bits > 10) {
+ ERROR("Error %s col_bits = %d\n", __func__, col_bits);
+ }
+ row_bits = ((cs0_config >> 8) & 0x7) + 12;
+ ba_bits = ((cs0_config >> 14) & 0x3) + 2;
+ bg_bits = ((cs0_config >> 4) & 0x3) + 0;
+ intlv = (cs0_config >> 24) & 0xf;
+ ba_intlv = (regs->sdram_cfg[0] >> 8) & 0x7f;
+ switch (ba_intlv) {
+ case DDR_BA_INTLV_CS01:
+ cs = 1;
+ break;
+ case DDR_BA_INTLV_CS0123:
+ cs = 2;
+ break;
+ case DDR_BA_NONE:
+ cs = 0;
+ break;
+ default:
+ ERROR("%s ba_intlv 0x%x\n", __func__, ba_intlv);
+ return;
+ }
+ debug("col %d, row %d, ba %d, bg %d, intlv %d\n",
+ col_bits, row_bits, ba_bits, bg_bits, intlv);
+ /*
+ * Example mapping of 15x2x2x10
+ * ---- --rr rrrr rrrr rrrr rCBB Gccc cccI cGcc cbbb
+ */
+ dbw = (regs->sdram_cfg[0] >> 19) & 0x3;
+ switch (dbw) {
+ case 0: /* 64-bit */
+ placement = 3;
+ break;
+ case 1: /* 32-bit */
+ placement = 2;
+ break;
+ default:
+ ERROR("%s dbw = %d\n", __func__, dbw);
+ return;
+ }
+ debug("cacheline size %d\n", cacheline);
+ for (i = 0; placement < cacheline; i++) {
+ map_col[i] = placement++;
+ }
+ map_bg[0] = placement++;
+ for ( ; i < col_bits; i++) {
+ map_col[i] = placement++;
+ if (placement == intlv) {
+ placement++;
+ }
+ }
+ for ( ; i < 11; i++) {
+ map_col[i] = 0x3F; /* unused col bits */
+ }
+
+ if (bg_bits >= 2) {
+ map_bg[1] = placement++;
+ }
+ map_ba[0] = placement++;
+ map_ba[1] = placement++;
+ if (cs != 0U) {
+ map_cs[0] = placement++;
+ if (cs == 2U) {
+ map_cs[1] = placement++;
+ }
+ } else {
+ map_cs[0] = U(0x3F);
+ }
+
+ for (i = 0; i < row_bits; i++) {
+ map_row[i] = placement++;
+ }
+
+ for ( ; i < 18; i++) {
+ map_row[i] = 0x3F; /* unused row bits */
+ }
+
+ for (i = 39; i >= 0 ; i--) {
+ if (i == intlv) {
+ placement = 8;
+ p = 'I';
+ } else if (i < 3) {
+ p = 'b';
+ placement = 0;
+ } else {
+ placement = 0;
+ p = '-';
+ }
+ for (j = 0; j < 18; j++) {
+ if (map_row[j] != i) {
+ continue;
+ }
+ if (placement != 0) {
+ abort = 1;
+ ERROR("%s wrong address bit %d\n", __func__, i);
+ }
+ placement = i;
+ p = 'r';
+ }
+ for (j = 0; j < 11; j++) {
+ if (map_col[j] != i) {
+ continue;
+ }
+ if (placement != 0) {
+ abort = 1;
+ ERROR("%s wrong address bit %d\n", __func__, i);
+ }
+ placement = i;
+ p = 'c';
+ }
+ for (j = 0; j < 2; j++) {
+ if (map_ba[j] != i) {
+ continue;
+ }
+ if (placement != 0) {
+ abort = 1;
+ ERROR("%s wrong address bit %d\n", __func__, i);
+ }
+ placement = i;
+ p = 'B';
+ }
+ for (j = 0; j < 2; j++) {
+ if (map_bg[j] != i) {
+ continue;
+ }
+ if (placement != 0) {
+ abort = 1;
+ ERROR("%s wrong address bit %d\n", __func__, i);
+ }
+ placement = i;
+ p = 'G';
+ }
+ for (j = 0; j < 2; j++) {
+ if (map_cs[j] != i) {
+ continue;
+ }
+ if (placement != 0) {
+ abort = 1;
+ ERROR("%s wrong address bit %d\n", __func__, i);
+ }
+ placement = i;
+ p = 'C';
+ }
+#ifdef DDR_DEBUG
+ printf("%c", p);
+ if ((i % 4) == 0) {
+ printf(" ");
+ }
+#endif
+ }
+#ifdef DDR_DEBUG
+ puts("\n");
+#endif
+
+ if (abort != 0) {
+ return;
+ }
+
+ regs->dec[0] = map_row[17] << 26 |
+ map_row[16] << 18 |
+ map_row[15] << 10 |
+ map_row[14] << 2;
+ regs->dec[1] = map_row[13] << 26 |
+ map_row[12] << 18 |
+ map_row[11] << 10 |
+ map_row[10] << 2;
+ regs->dec[2] = map_row[9] << 26 |
+ map_row[8] << 18 |
+ map_row[7] << 10 |
+ map_row[6] << 2;
+ regs->dec[3] = map_row[5] << 26 |
+ map_row[4] << 18 |
+ map_row[3] << 10 |
+ map_row[2] << 2;
+ regs->dec[4] = map_row[1] << 26 |
+ map_row[0] << 18 |
+ map_col[10] << 10 |
+ map_col[9] << 2;
+ regs->dec[5] = map_col[8] << 26 |
+ map_col[7] << 18 |
+ map_col[6] << 10 |
+ map_col[5] << 2;
+ regs->dec[6] = map_col[4] << 26 |
+ map_col[3] << 18 |
+ map_col[2] << 10 |
+ map_col[1] << 2;
+ regs->dec[7] = map_col[0] << 26 |
+ map_ba[1] << 18 |
+ map_ba[0] << 10 |
+ map_cid[1] << 2;
+ regs->dec[8] = map_cid[1] << 26 |
+ map_cs[1] << 18 |
+ map_cs[0] << 10 |
+ map_bg[1] << 2;
+ regs->dec[9] = map_bg[0] << 26 |
+ 1;
+ for (i = 0; i < 10; i++) {
+ debug("dec[%d] = 0x%x\n", i, regs->dec[i]);
+ }
+#endif
+}
+static unsigned int skip_caslat(unsigned int tckmin_ps,
+ unsigned int taamin_ps,
+ unsigned int mclk_ps,
+ unsigned int package_3ds)
+{
+ int i, j, k;
+ struct cas {
+ const unsigned int tckmin_ps;
+ const unsigned int caslat[4];
+ };
+ struct speed {
+ const struct cas *cl;
+ const unsigned int taamin_ps[4];
+ };
+ const struct cas cl_3200[] = {
+ {625, {0xa00000, 0xb00000, 0xf000000,} },
+ {750, { 0x20000, 0x60000, 0xe00000,} },
+ {833, { 0x8000, 0x18000, 0x38000,} },
+ {937, { 0x4000, 0x4000, 0xc000,} },
+ {1071, { 0x1000, 0x1000, 0x3000,} },
+ {1250, { 0x400, 0x400, 0xc00,} },
+ {1500, { 0, 0x600, 0x200,} },
+ };
+ const struct cas cl_2933[] = {
+ {682, { 0, 0x80000, 0x180000, 0x380000} },
+ {750, { 0x20000, 0x60000, 0x60000, 0xe0000} },
+ {833, { 0x8000, 0x18000, 0x18000, 0x38000} },
+ {937, { 0x4000, 0x4000, 0x4000, 0xc000} },
+ {1071, { 0x1000, 0x1000, 0x1000, 0x3000} },
+ {1250, { 0x400, 0x400, 0x400, 0xc00} },
+ {1500, { 0, 0x200, 0x200, 0x200} },
+ };
+ const struct cas cl_2666[] = {
+ {750, { 0, 0x20000, 0x60000, 0xe0000} },
+ {833, { 0x8000, 0x18000, 0x18000, 0x38000} },
+ {937, { 0x4000, 0x4000, 0x4000, 0xc000} },
+ {1071, { 0x1000, 0x1000, 0x1000, 0x3000} },
+ {1250, { 0x400, 0x400, 0x400, 0xc00} },
+ {1500, { 0, 0, 0x200, 0x200} },
+ };
+ const struct cas cl_2400[] = {
+ {833, { 0, 0x8000, 0x18000, 0x38000} },
+ {937, { 0xc000, 0x4000, 0x4000, 0xc000} },
+ {1071, { 0x3000, 0x1000, 0x1000, 0x3000} },
+ {1250, { 0xc00, 0x400, 0x400, 0xc00} },
+ {1500, { 0, 0x400, 0x200, 0x200} },
+ };
+ const struct cas cl_2133[] = {
+ {937, { 0, 0x4000, 0xc000,} },
+ {1071, { 0x2000, 0, 0x2000,} },
+ {1250, { 0x800, 0, 0x800,} },
+ {1500, { 0, 0x400, 0x200,} },
+ };
+ const struct cas cl_1866[] = {
+ {1071, { 0, 0x1000, 0x3000,} },
+ {1250, { 0xc00, 0x400, 0xc00,} },
+ {1500, { 0, 0x400, 0x200,} },
+ };
+ const struct cas cl_1600[] = {
+ {1250, { 0, 0x400, 0xc00,} },
+ {1500, { 0, 0x400, 0x200,} },
+ };
+ const struct speed bin_0[] = {
+ {cl_3200, {12500, 13750, 15000,} },
+ {cl_2933, {12960, 13640, 13750, 15000,} },
+ {cl_2666, {12750, 13500, 13750, 15000,} },
+ {cl_2400, {12500, 13320, 13750, 15000,} },
+ {cl_2133, {13130, 13500, 15000,} },
+ {cl_1866, {12850, 13500, 15000,} },
+ {cl_1600, {12500, 13500, 15000,} }
+ };
+ const struct cas cl_3200_3ds[] = {
+ {625, { 0xa000000, 0xb000000, 0xf000000,} },
+ {750, { 0xaa00000, 0xab00000, 0xef00000,} },
+ {833, { 0xaac0000, 0xaac0000, 0xebc0000,} },
+ {937, { 0xaab0000, 0xaab0000, 0xeaf0000,} },
+ {1071, { 0xaaa4000, 0xaaac000, 0xeaec000,} },
+ {1250, { 0xaaa0000, 0xaaa2000, 0xeaeb000,} },
+ };
+ const struct cas cl_2666_3ds[] = {
+ {750, { 0xa00000, 0xb00000, 0xf00000,} },
+ {833, { 0xac0000, 0xac0000, 0xbc0000,} },
+ {937, { 0xab0000, 0xab0000, 0xaf0000,} },
+ {1071, { 0xaa4000, 0xaac000, 0xaac000,} },
+ {1250, { 0xaa0000, 0xaaa000, 0xaaa000,} },
+ };
+ const struct cas cl_2400_3ds[] = {
+ {833, { 0xe00000, 0xe40000, 0xec0000, 0xb00000} },
+ {937, { 0xe00000, 0xe00000, 0xea0000, 0xae0000} },
+ {1071, { 0xe00000, 0xe04000, 0xeac000, 0xaec000} },
+ {1250, { 0xe00000, 0xe00000, 0xeaa000, 0xae2000} },
+ };
+ const struct cas cl_2133_3ds[] = {
+ {937, { 0x90000, 0xb0000, 0xf0000,} },
+ {1071, { 0x84000, 0xac000, 0xec000,} },
+ {1250, { 0x80000, 0xa2000, 0xe2000,} },
+ };
+ const struct cas cl_1866_3ds[] = {
+ {1071, { 0, 0x4000, 0xc000,} },
+ {1250, { 0, 0x1000, 0x3000,} },
+ };
+ const struct cas cl_1600_3ds[] = {
+ {1250, { 0, 0x1000, 0x3000,} },
+ };
+ const struct speed bin_3ds[] = {
+ {cl_3200_3ds, {15000, 16250, 17140,} },
+ {cl_2666_3ds, {15000, 16500, 17140,} },
+ {cl_2400_3ds, {15000, 15830, 16670, 17140} },
+ {cl_2133_3ds, {15950, 16880, 17140,} },
+ {cl_1866_3ds, {15000, 16070, 17140,} },
+ {cl_1600_3ds, {15000, 16250, 17500,} },
+ };
+ const struct speed *bin;
+ int size;
+ unsigned int taamin_max, tck_max;
+
+ if (taamin_ps > ((package_3ds != 0) ? 21500 : 18000)) {
+ ERROR("taamin_ps %u invalid\n", taamin_ps);
+ return 0;
+ }
+ if (package_3ds != 0) {
+ bin = bin_3ds;
+ size = ARRAY_SIZE(bin_3ds);
+ taamin_max = 1250;
+ tck_max = 1500;
+ } else {
+ bin = bin_0;
+ size = ARRAY_SIZE(bin_0);
+ taamin_max = 1500;
+ tck_max = 1600;
+ }
+ if (mclk_ps < 625 || mclk_ps > tck_max) {
+ ERROR("mclk %u invalid\n", mclk_ps);
+ return 0;
+ }
+
+ for (i = 0; i < size; i++) {
+ if (bin[i].cl[0].tckmin_ps >= tckmin_ps) {
+ break;
+ }
+ }
+ if (i >= size) {
+ ERROR("speed bin not found\n");
+ return 0;
+ }
+ if (bin[i].cl[0].tckmin_ps > tckmin_ps && i > 0) {
+ i--;
+ }
+
+ for (j = 0; j < 4; j++) {
+ if ((bin[i].taamin_ps[j] == 0) ||
+ bin[i].taamin_ps[j] >= taamin_ps) {
+ break;
+ }
+ }
+
+ if (j >= 4) {
+ ERROR("taamin_ps out of range.\n");
+ return 0;
+ }
+
+ if ((bin[i].taamin_ps[j] == 0) ||
+ (bin[i].taamin_ps[j] > taamin_ps && j > 0)) {
+ j--;
+ }
+
+ for (k = 0; bin[i].cl[k].tckmin_ps < mclk_ps &&
+ bin[i].cl[k].tckmin_ps < taamin_max; k++)
+ ;
+ if (bin[i].cl[k].tckmin_ps > mclk_ps && k > 0) {
+ k--;
+ }
+
+ debug("Skip CL mask for this speed 0x%x\n", bin[i].cl[k].caslat[j]);
+
+ return bin[i].cl[k].caslat[j];
+}
+
+int compute_ddrc(const unsigned long clk,
+ const struct memctl_opt *popts,
+ const struct ddr_conf *conf,
+ struct ddr_cfg_regs *regs,
+ const struct dimm_params *pdimm,
+ unsigned int ip_rev)
+{
+ unsigned int cas_latency;
+ unsigned int caslat_skip;
+ unsigned int additive_latency;
+ const unsigned int mclk_ps = get_memory_clk_ps(clk);
+ int i;
+
+ zeromem(regs, sizeof(struct ddr_cfg_regs));
+
+ if (mclk_ps < pdimm->tckmin_x_ps) {
+ ERROR("DDR Clk: MCLK cycle is %u ps.\n", mclk_ps);
+ ERROR("DDR Clk is faster than DIMM can support.\n");
+ }
+
+ /* calculate cas latency, override first */
+ cas_latency = (popts->caslat_override != 0) ?
+ popts->caslat_override_value :
+ (pdimm->taa_ps + mclk_ps - 1) / mclk_ps;
+
+ /* skip unsupported caslat based on speed bin */
+ caslat_skip = skip_caslat(pdimm->tckmin_x_ps,
+ pdimm->taa_ps,
+ mclk_ps,
+ pdimm->package_3ds);
+ debug("Skip caslat 0x%x\n", caslat_skip);
+
+ /* Check if DIMM supports the cas latency */
+ i = 24;
+ while (((pdimm->caslat_x & ~caslat_skip & (1 << cas_latency)) == 0) &&
+ (i-- > 0)) {
+ cas_latency++;
+ }
+
+ if (i <= 0) {
+ ERROR("Failed to find a proper cas latency\n");
+ return -EINVAL;
+ }
+ /* Verify cas latency does not exceed 18ns for DDR4 */
+ if (cas_latency * mclk_ps > 18000) {
+ ERROR("cas latency is too large %d\n", cas_latency);
+ return -EINVAL;
+ }
+
+ additive_latency = (popts->addt_lat_override != 0) ?
+ popts->addt_lat_override_value : 0;
+
+ cal_ddr_csn_bnds(regs, popts, conf, pdimm);
+ cal_ddr_sdram_cfg(clk, regs, popts, pdimm, ip_rev);
+ cal_ddr_sdram_rcw(clk, regs, popts, pdimm);
+ cal_timing_cfg(clk, regs, popts, pdimm, conf, cas_latency,
+ additive_latency);
+ cal_ddr_dq_mapping(regs, pdimm);
+
+ if (ip_rev >= 0x50500) {
+ cal_ddr_addr_dec(regs);
+ }
+
+ cal_ddr_sdram_mode(clk, regs, popts, conf, pdimm, cas_latency,
+ additive_latency, ip_rev);
+ cal_ddr_eor(regs, popts);
+ cal_ddr_data_init(regs);
+ cal_ddr_sdram_interval(clk, regs, popts, pdimm);
+ cal_ddr_zq_cntl(regs);
+ cal_ddr_sr_cntr(regs, popts);
+
+ return 0;
+}
diff --git a/drivers/nxp/ddr/nxp-ddr/utility.c b/drivers/nxp/ddr/nxp-ddr/utility.c
new file mode 100644
index 0000000000..d33ad77839
--- /dev/null
+++ b/drivers/nxp/ddr/nxp-ddr/utility.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <immap.h>
+#include <lib/mmio.h>
+
+#define UL_5POW12 244140625UL
+#define ULL_2E12 2000000000000ULL
+#define UL_2POW13 (1UL << 13)
+#define ULL_8FS 0xFFFFFFFFULL
+
+#define do_div(n, base) ({ \
+ unsigned int __base = (base); \
+ unsigned int __rem; \
+ __rem = ((unsigned long long)(n)) % __base; \
+ (n) = ((unsigned long long)(n)) / __base; \
+ __rem; \
+})
+
+#define CCN_HN_F_SAM_NODEID_MASK 0x7f
+#ifdef NXP_HAS_CCN504
+#define CCN_HN_F_SAM_NODEID_DDR0 0x4
+#define CCN_HN_F_SAM_NODEID_DDR1 0xe
+#elif defined(NXP_HAS_CCN508)
+#define CCN_HN_F_SAM_NODEID_DDR0 0x8
+#define CCN_HN_F_SAM_NODEID_DDR1 0x18
+#endif
+
+unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num)
+{
+ if (sys->freq_ddr_pll0 == 0) {
+ get_clocks(sys);
+ }
+
+ switch (ctrl_num) {
+ case 0:
+ return sys->freq_ddr_pll0;
+ case 1:
+ return sys->freq_ddr_pll0;
+ case 2:
+ return sys->freq_ddr_pll1;
+ }
+
+ return 0;
+}
+
+unsigned int get_memory_clk_ps(const unsigned long data_rate)
+{
+ unsigned int result;
+ /* Round to nearest 10ps, being careful about 64-bit multiply/divide */
+ unsigned long long rem, mclk_ps = ULL_2E12;
+
+ /* Now perform the big divide, the result fits in 32-bits */
+ rem = do_div(mclk_ps, data_rate);
+ result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps;
+
+ return result;
+}
+
+unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos)
+{
+ unsigned long long clks, clks_rem;
+
+ /* Short circuit for zero picos */
+ if ((picos == 0U) || (data_rate == 0UL)) {
+ return 0U;
+ }
+
+ /* First multiply the time by the data rate (32x32 => 64) */
+ clks = picos * (unsigned long long)data_rate;
+ /*
+ * Now divide by 5^12 and track the 32-bit remainder, then divide
+ * by 2*(2^12) using shifts (and updating the remainder).
+ */
+ clks_rem = do_div(clks, UL_5POW12);
+ clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12;
+ clks >>= 13U;
+
+ /* If we had a remainder greater than the 1ps error, then round up */
+ if (clks_rem > data_rate) {
+ clks++;
+ }
+
+ /* Clamp to the maximum representable value */
+ if (clks > ULL_8FS) {
+ clks = ULL_8FS;
+ }
+ return (unsigned int) clks;
+}
+
+/* valid_spd_mask has been checked by parse_spd */
+int disable_unused_ddrc(struct ddr_info *priv,
+ int valid_spd_mask, uintptr_t nxp_ccn_hn_f0_addr)
+{
+#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
+ void *hnf_sam_ctrl = (void *)(nxp_ccn_hn_f0_addr + CCN_HN_F_SAM_CTL);
+ uint32_t val, nodeid;
+#ifdef NXP_HAS_CCN504
+ uint32_t num_hnf_nodes = 4U;
+#else
+ uint32_t num_hnf_nodes = 8U;
+#endif
+ int disable_ddrc = 0;
+ int i;
+
+ if (priv->num_ctlrs < 2) {
+ debug("%s: nothing to do.\n", __func__);
+ }
+
+ switch (priv->dimm_on_ctlr) {
+ case 1:
+ disable_ddrc = ((valid_spd_mask &0x2) == 0) ? 2 : 0;
+ disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc;
+ break;
+ case 2:
+ disable_ddrc = ((valid_spd_mask &0x4) == 0) ? 2 : 0;
+ disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc;
+ break;
+ default:
+ ERROR("Invalid number of DIMMs %d\n", priv->dimm_on_ctlr);
+ return -EINVAL;
+ }
+
+ if (disable_ddrc != 0) {
+ debug("valid_spd_mask = 0x%x\n", valid_spd_mask);
+ }
+
+ switch (disable_ddrc) {
+ case 1:
+ priv->num_ctlrs = 1;
+ priv->spd_addr = &priv->spd_addr[priv->dimm_on_ctlr];
+ priv->ddr[0] = priv->ddr[1];
+ priv->ddr[1] = NULL;
+ priv->phy[0] = priv->phy[0];
+ priv->phy[1] = NULL;
+ debug("Disable first DDR controller\n");
+ break;
+ case 2:
+ priv->num_ctlrs = 1;
+ priv->ddr[1] = NULL;
+ priv->phy[1] = NULL;
+ debug("Disable second DDR controller\n");
+ /* fallthrough */
+ case 0:
+ break;
+ default:
+ ERROR("Program error.\n");
+ return -EINVAL;
+ }
+
+ if (disable_ddrc == 0) {
+ debug("Both controllers in use.\n");
+ return 0;
+ }
+
+ for (i = 0; i < num_hnf_nodes; i++) {
+ val = mmio_read_64((uintptr_t)hnf_sam_ctrl);
+ nodeid = disable_ddrc == 1 ? CCN_HN_F_SAM_NODEID_DDR1 :
+ (disable_ddrc == 2 ? CCN_HN_F_SAM_NODEID_DDR0 :
+ (i < 4 ? CCN_HN_F_SAM_NODEID_DDR0
+ : CCN_HN_F_SAM_NODEID_DDR1));
+ if (nodeid != (val & CCN_HN_F_SAM_NODEID_MASK)) {
+ debug("Setting HN-F node %d\n", i);
+ debug("nodeid = 0x%x\n", nodeid);
+ val &= ~CCN_HN_F_SAM_NODEID_MASK;
+ val |= nodeid;
+ mmio_write_64((uintptr_t)hnf_sam_ctrl, val);
+ }
+ hnf_sam_ctrl += CCN_HN_F_REGION_SIZE;
+ }
+#endif
+ return 0;
+}
+
+unsigned int get_ddrc_version(const struct ccsr_ddr *ddr)
+{
+ unsigned int ver;
+
+ ver = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8U;
+ ver |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8U;
+
+ return ver;
+}
+
+void print_ddr_info(struct ccsr_ddr *ddr)
+{
+ unsigned int cs0_config = ddr_in32(&ddr->csn_cfg[0]);
+ unsigned int sdram_cfg = ddr_in32(&ddr->sdram_cfg);
+ int cas_lat;
+
+ if ((sdram_cfg & SDRAM_CFG_MEM_EN) == 0U) {
+ printf(" (DDR not enabled)\n");
+ return;
+ }
+
+ printf("DDR");
+ switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
+ SDRAM_CFG_SDRAM_TYPE_SHIFT) {
+ case SDRAM_TYPE_DDR4:
+ printf("4");
+ break;
+ default:
+ printf("?");
+ break;
+ }
+
+ switch (sdram_cfg & SDRAM_CFG_DBW_MASK) {
+ case SDRAM_CFG_32_BW:
+ printf(", 32-bit");
+ break;
+ case SDRAM_CFG_16_BW:
+ printf(", 16-bit");
+ break;
+ case SDRAM_CFG_8_BW:
+ printf(", 8-bit");
+ break;
+ default:
+ printf(", 64-bit");
+ break;
+ }
+
+ /* Calculate CAS latency based on timing cfg values */
+ cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
+ cas_lat += 2; /* for DDRC newer than 4.4 */
+ cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4;
+ printf(", CL=%d", cas_lat >> 1);
+ if ((cas_lat & 0x1) != 0) {
+ printf(".5");
+ }
+
+ if ((sdram_cfg & SDRAM_CFG_ECC_EN) != 0) {
+ printf(", ECC on");
+ } else {
+ printf(", ECC off");
+ }
+
+ if ((cs0_config & 0x20000000) != 0) {
+ printf(", ");
+ switch ((cs0_config >> 24) & 0xf) {
+ case DDR_256B_INTLV:
+ printf("256B");
+ break;
+ default:
+ printf("invalid");
+ break;
+ }
+ }
+
+ if (((sdram_cfg >> 8) & 0x7f) != 0) {
+ printf(", ");
+ switch (sdram_cfg >> 8 & 0x7f) {
+ case DDR_BA_INTLV_CS0123:
+ printf("CS0+CS1+CS2+CS3");
+ break;
+ case DDR_BA_INTLV_CS01:
+ printf("CS0+CS1");
+ break;
+ default:
+ printf("invalid");
+ break;
+ }
+ }
+ printf("\n");
+}
diff --git a/drivers/nxp/ddr/phy-gen1/phy.c b/drivers/nxp/ddr/phy-gen1/phy.c
new file mode 100644
index 0000000000..4b66d3897c
--- /dev/null
+++ b/drivers/nxp/ddr/phy-gen1/phy.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+
+static void cal_ddr_sdram_clk_cntl(struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts)
+{
+ const unsigned int clk_adj = popts->clk_adj;
+ const unsigned int ss_en = 0U;
+
+ regs->clk_cntl = ((ss_en & U(0x1)) << 31U) |
+ ((clk_adj & U(0x1F)) << 22U);
+ debug("clk_cntl = 0x%x\n", regs->clk_cntl);
+}
+
+static void cal_ddr_cdr(struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts)
+{
+ regs->cdr[0] = popts->ddr_cdr1;
+ regs->cdr[1] = popts->ddr_cdr2;
+ debug("cdr[0] = 0x%x\n", regs->cdr[0]);
+ debug("cdr[1] = 0x%x\n", regs->cdr[1]);
+}
+
+static void cal_ddr_wrlvl_cntl(struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts)
+{
+ const unsigned int wrlvl_en = 1U; /* enabled */
+ const unsigned int wrlvl_mrd = U(0x6); /* > 40nCK */
+ const unsigned int wrlvl_odten = U(0x7); /* 128 */
+ const unsigned int wrlvl_dqsen = U(0x5); /* > 25nCK */
+ const unsigned int wrlvl_wlr = U(0x6); /* > tWLO + 6 */
+ const unsigned int wrlvl_smpl = popts->wrlvl_override ?
+ popts->wrlvl_sample : U(0xf);
+ const unsigned int wrlvl_start = popts->wrlvl_start;
+
+ regs->wrlvl_cntl[0] = ((wrlvl_en & U(0x1)) << 31U) |
+ ((wrlvl_mrd & U(0x7)) << 24U) |
+ ((wrlvl_odten & U(0x7)) << 20U) |
+ ((wrlvl_dqsen & U(0x7)) << 16U) |
+ ((wrlvl_smpl & U(0xf)) << 12U) |
+ ((wrlvl_wlr & U(0x7)) << 8U) |
+ ((wrlvl_start & U(0x1F)) << 0U);
+ regs->wrlvl_cntl[1] = popts->wrlvl_ctl_2;
+ regs->wrlvl_cntl[2] = popts->wrlvl_ctl_3;
+ debug("wrlvl_cntl[0] = 0x%x\n", regs->wrlvl_cntl[0]);
+ debug("wrlvl_cntl[1] = 0x%x\n", regs->wrlvl_cntl[1]);
+ debug("wrlvl_cntl[2] = 0x%x\n", regs->wrlvl_cntl[2]);
+
+}
+
+static void cal_ddr_dbg(struct ddr_cfg_regs *regs,
+ const struct memctl_opt *popts)
+{
+ if (popts->cswl_override != 0) {
+ regs->debug[18] = popts->cswl_override;
+ }
+
+#ifdef CONFIG_SYS_FSL_DDR_EMU
+ /* disable DDR training for emulator */
+ regs->debug[2] = U(0x00000400);
+ regs->debug[4] = U(0xff800800);
+ regs->debug[5] = U(0x08000800);
+ regs->debug[6] = U(0x08000800);
+ regs->debug[7] = U(0x08000800);
+ regs->debug[8] = U(0x08000800);
+#endif
+ if (popts->cpo_sample != 0U) {
+ regs->debug[28] = popts->cpo_sample;
+ debug("debug[28] = 0x%x\n", regs->debug[28]);
+ }
+}
+
+int compute_ddr_phy(struct ddr_info *priv)
+{
+ const struct memctl_opt *popts = &priv->opt;
+ struct ddr_cfg_regs *regs = &priv->ddr_reg;
+
+ cal_ddr_sdram_clk_cntl(regs, popts);
+ cal_ddr_cdr(regs, popts);
+ cal_ddr_wrlvl_cntl(regs, popts);
+ cal_ddr_dbg(regs, popts);
+
+ return 0;
+}
diff --git a/drivers/nxp/ddr/phy-gen2/csr.h b/drivers/nxp/ddr/phy-gen2/csr.h
new file mode 100644
index 0000000000..ee7b4d831d
--- /dev/null
+++ b/drivers/nxp/ddr/phy-gen2/csr.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2021 NXP
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CSR_H
+#define CSR_H
+
+#define t_anib 0
+#define t_dbyte 0x10000
+#define t_master 0x20000
+#define t_acsm 0x40000
+#define t_initeng 0x90000
+#define t_drtub 0xc0000
+#define t_apbonly 0xd0000
+#define csr_dbyte_misc_mode_addr 0x00
+#define csr_micro_cont_mux_sel_addr 0x00
+#define csr_uct_shadow_regs 0x04
+#define csr_cal_uclk_info_addr 0x08
+#define csr_seq0bdly0_addr 0x0b
+#define csr_seq0bdly1_addr 0x0c
+#define csr_seq0bdly2_addr 0x0d
+#define csr_seq0bdly3_addr 0x0e
+#define csr_seq0bdisable_flag0_addr 0x0c
+#define csr_seq0bdisable_flag1_addr 0x0d
+#define csr_seq0bdisable_flag2_addr 0x0e
+#define csr_seq0bdisable_flag3_addr 0x0f
+#define csr_seq0bdisable_flag4_addr 0x10
+#define csr_seq0bdisable_flag5_addr 0x11
+#define csr_seq0bdisable_flag6_addr 0x12
+#define csr_seq0bdisable_flag7_addr 0x13
+#define csr_dfi_mode_addr 0x18
+#define csr_tristate_mode_ca_addr 0x19
+#define csr_dfiphyupd_addr 0x21
+#define csr_dqs_preamble_control_addr 0x24
+#define csr_master_x4config_addr 0x25
+#define csr_enable_cs_multicast_addr 0x27
+#define csr_acx4_anib_dis_addr 0x2c
+#define csr_dmipin_present_addr 0x2d
+#define csr_ard_ptr_init_val_addr 0x2e
+#define csr_dct_write_prot 0x31
+#define csr_uct_write_only_shadow 0x32
+#define csr_uct_write_prot 0x33
+#define csr_uct_dat_write_only_shadow 0x34
+#define csr_dbyte_dll_mode_cntrl_addr 0x3a
+#define csr_atx_impedance_addr 0x43
+#define csr_dq_dqs_rcv_cntrl_addr 0x43
+#define csr_cal_offsets_addr 0x45
+#define csr_tx_impedance_ctrl1_addr 0x49
+#define csr_dq_dqs_rcv_cntrl1_addr 0x4a
+#define csr_tx_odt_drv_stren_addr 0x4d
+#define csr_cal_drv_str0_addr 0x50
+#define csr_atx_slew_rate_addr 0x55
+#define csr_proc_odt_time_ctl_addr 0x56
+#define csr_mem_alert_control_addr 0x5b
+#define csr_mem_alert_control2_addr 0x5c
+#define csr_tx_slew_rate_addr 0x5f
+#define csr_mem_reset_l_addr 0x60
+#define csr_dfi_camode_addr 0x75
+#define csr_dll_gain_ctl_addr 0x7c
+#define csr_dll_lockparam_addr 0x7d
+#define csr_ucclk_hclk_enables_addr 0x80
+#define csr_acsm_playback0x0_addr 0x80
+#define csr_acsm_playback1x0_addr 0x81
+#define csr_cal_rate_addr 0x88
+#define csr_cal_zap_addr 0x89
+#define csr_cal_misc2_addr 0x98
+#define csr_micro_reset_addr 0x99
+#define csr_dfi_rd_data_cs_dest_map_addr 0xb0
+#define csr_vref_in_global_addr 0xb2
+#define csr_dfi_wr_data_cs_dest_map_addr 0xb4
+#define csr_pll_pwr_dn_addr 0xc3
+#define csr_pll_ctrl2_addr 0xc5
+#define csr_pll_ctrl1_addr 0xc7
+#define csr_pll_test_mode_addr 0xca
+#define csr_pll_ctrl4_addr 0xcc
+#define csr_dfi_freq_xlat0_addr 0xf0
+#define csr_acsm_ctrl0_addr 0xf0
+#define csr_dfi_freq_ratio_addr 0xfa
+#define csr_acsm_ctrl13_addr 0xfd
+#define csr_tx_pre_drv_mode_lsb 8
+#define csr_tx_pre_n_lsb 4
+#define csr_tx_pre_p_lsb 0
+#define csr_atx_pre_drv_mode_lsb 8
+#define csr_atx_pre_n_lsb 4
+#define csr_atx_pre_p_lsb 0
+#define csr_wdqsextension_lsb 8
+#define csr_lp4sttc_pre_bridge_rx_en_lsb 7
+#define csr_lp4postamble_ext_lsb 6
+#define csr_lp4tgl_two_tck_tx_dqs_pre_lsb 5
+#define csr_position_dfe_init_lsb 2
+#define csr_two_tck_tx_dqs_pre_lsb 1
+#define csr_two_tck_rx_dqs_pre_lsb 0
+#define csr_dll_rx_preamble_mode_lsb 1
+#define csr_odtstren_n_lsb 6
+#define csr_drv_stren_fsdq_n_lsb 6
+#define csr_drv_stren_fsdq_p_lsb 0
+#define csr_adrv_stren_n_lsb 5
+#define csr_adrv_stren_p_lsb 0
+#define csr_cal_drv_str_pu50_lsb 4
+#define csr_cal_once_lsb 5
+#define csr_cal_interval_lsb 0
+#define csr_cal_run_lsb 4
+#define csr_global_vref_in_dac_lsb 3
+#define csr_gain_curr_adj_lsb 7
+#define csr_major_mode_dbyte_lsb 4
+#define csr_dfe_ctrl_lsb 2
+#define csr_ext_vref_range_lsb 1
+#define csr_sel_analog_vref_lsb 0
+#define csr_malertsync_bypass_lsb 0
+#define csr_ck_dis_val_lsb 2
+#define csr_ddr2tmode_lsb 1
+#define csr_dis_dyn_adr_tri_lsb 0
+#define csr_dbyte_disable_lsb 2
+#define csr_power_down_rcvr_lsb 0
+#define csr_power_down_rcvr_dqs_lsb 9
+#define csr_rx_pad_standby_en_lsb 10
+#define csr_rx_pad_standby_en_mask 0x400
+#define csr_x4tg_lsb 0
+#define csr_reset_to_micro_mask 0x8
+#define csr_protect_mem_reset_mask 0x2
+#define csr_stall_to_micro_mask 0x1
+#define uct_write_prot_shadow_mask 0x1
+#define csr_acsm_par_mode_mask 0x4000
+#define csr_acsm_cke_enb_lsb 0
+#define csr_dfiphyupd_threshold_lsb 8
+#define csr_dfiphyupd_threshold_msb 11
+#define csr_dfiphyupd_threshold_mask 0xf00
+#define csr_dfi_rd_destm0_lsb 0
+#define csr_dfi_rd_destm1_lsb 2
+#define csr_dfi_rd_destm2_lsb 4
+#define csr_dfi_rd_destm3_lsb 6
+#define csr_dfi_wr_destm0_lsb 0
+#define csr_dfi_wr_destm1_lsb 2
+#define csr_dfi_wr_destm2_lsb 4
+#define csr_dfi_wr_destm3_lsb 6
+#define csr_acsm_2t_mode_mask 0x40
+#define csr_cal_misc2_err_dis 13
+#define csr_cal_offset_pdc_lsb 6
+#define csr_cal_offset_pdc_msb 9
+#define csr_cal_offset_pdc_mask 0xe0
+#define csr_cal_drv_pdth_mask 0x3c0
+
+
+struct impedance_mapping {
+ int ohm;
+ int code;
+};
+
+#endif
diff --git a/drivers/nxp/ddr/phy-gen2/ddr4fw.h b/drivers/nxp/ddr/phy-gen2/ddr4fw.h
new file mode 100644
index 0000000000..f17f2e716b
--- /dev/null
+++ b/drivers/nxp/ddr/phy-gen2/ddr4fw.h
@@ -0,0 +1,2897 @@
+/*
+ * Copyright 2021 NXP
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef DDR4FW
+#define DDR4FW
+
+#define PHY_GEN2_MAX_IMAGE_SIZE 32768
+#define PHY_GEN2_IMEM_ADDR 0x50000
+#define PHY_GEN2_DMEM_ADDR 0x54000
+
+struct ddr4u1d {
+ uint8_t reserved00;
+ uint8_t msg_misc;
+ uint16_t pmu_revision;
+ uint8_t pstate;
+ uint8_t pll_bypass_en;
+ uint16_t dramfreq;
+ uint8_t dfi_freq_ratio;
+ uint8_t bpznres_val;
+ uint8_t phy_odt_impedance;
+ uint8_t phy_drv_impedance;
+ uint8_t phy_vref;
+ uint8_t dram_type;
+ uint8_t disabled_dbyte;
+ uint8_t enabled_dqs;
+ uint8_t cs_present;
+ uint8_t cs_present_d0;
+ uint8_t cs_present_d1;
+ uint8_t addr_mirror;
+ uint8_t cs_test_fail;
+ uint8_t phy_cfg;
+ uint16_t sequence_ctrl;
+ uint8_t hdt_ctrl;
+ uint8_t reserved19[0x1B - 0x19];
+ uint8_t share2dvref_result;
+ uint8_t reserved1c[0x22 - 0x1c];
+ uint16_t phy_config_override;
+ uint8_t dfimrlmargin;
+ int8_t cdd_rr_3_2;
+ int8_t cdd_rr_3_1;
+ int8_t cdd_rr_3_0;
+ int8_t cdd_rr_2_3;
+ int8_t cdd_rr_2_1;
+ int8_t cdd_rr_2_0;
+ int8_t cdd_rr_1_3;
+ int8_t cdd_rr_1_2;
+ int8_t cdd_rr_1_0;
+ int8_t cdd_rr_0_3;
+ int8_t cdd_rr_0_2;
+ int8_t cdd_rr_0_1;
+ int8_t cdd_ww_3_2;
+ int8_t cdd_ww_3_1;
+ int8_t cdd_ww_3_0;
+ int8_t cdd_ww_2_3;
+ int8_t cdd_ww_2_1;
+ int8_t cdd_ww_2_0;
+ int8_t cdd_ww_1_3;
+ int8_t cdd_ww_1_2;
+ int8_t cdd_ww_1_0;
+ int8_t cdd_ww_0_3;
+ int8_t cdd_ww_0_2;
+ int8_t cdd_ww_0_1;
+ int8_t cdd_rw_3_3;
+ int8_t cdd_rw_3_2;
+ int8_t cdd_rw_3_1;
+ int8_t cdd_rw_3_0;
+ int8_t cdd_rw_2_3;
+ int8_t cdd_rw_2_2;
+ int8_t cdd_rw_2_1;
+ int8_t cdd_rw_2_0;
+ int8_t cdd_rw_1_3;
+ int8_t cdd_rw_1_2;
+ int8_t cdd_rw_1_1;
+ int8_t cdd_rw_1_0;
+ int8_t cdd_rw_0_3;
+ int8_t cdd_rw_0_2;
+ int8_t cdd_rw_0_1;
+ int8_t cdd_rw_0_0;
+ int8_t cdd_wr_3_3;
+ int8_t cdd_wr_3_2;
+ int8_t cdd_wr_3_1;
+ int8_t cdd_wr_3_0;
+ int8_t cdd_wr_2_3;
+ int8_t cdd_wr_2_2;
+ int8_t cdd_wr_2_1;
+ int8_t cdd_wr_2_0;
+ int8_t cdd_wr_1_3;
+ int8_t cdd_wr_1_2;
+ int8_t cdd_wr_1_1;
+ int8_t cdd_wr_1_0;
+ int8_t cdd_wr_0_3;
+ int8_t cdd_wr_0_2;
+ int8_t cdd_wr_0_1;
+ int8_t cdd_wr_0_0;
+ uint8_t reserved5d;
+ uint16_t mr0;
+ uint16_t mr1;
+ uint16_t mr2;
+ uint16_t mr3;
+ uint16_t mr4;
+ uint16_t mr5;
+ uint16_t mr6;
+ uint8_t x16present;
+ uint8_t cs_setup_gddec;
+ uint16_t rtt_nom_wr_park0;
+ uint16_t rtt_nom_wr_park1;
+ uint16_t rtt_nom_wr_park2;
+ uint16_t rtt_nom_wr_park3;
+ uint16_t rtt_nom_wr_park4;
+ uint16_t rtt_nom_wr_park5;
+ uint16_t rtt_nom_wr_park6;
+ uint16_t rtt_nom_wr_park7;
+ uint8_t acsm_odt_ctrl0;
+ uint8_t acsm_odt_ctrl1;
+ uint8_t acsm_odt_ctrl2;
+ uint8_t acsm_odt_ctrl3;
+ uint8_t acsm_odt_ctrl4;
+ uint8_t acsm_odt_ctrl5;
+ uint8_t acsm_odt_ctrl6;
+ uint8_t acsm_odt_ctrl7;
+ uint8_t vref_dq_r0nib0;
+ uint8_t vref_dq_r0nib1;
+ uint8_t vref_dq_r0nib2;
+ uint8_t vref_dq_r0nib3;
+ uint8_t vref_dq_r0nib4;
+ uint8_t vref_dq_r0nib5;
+ uint8_t vref_dq_r0nib6;
+ uint8_t vref_dq_r0nib7;
+ uint8_t vref_dq_r0nib8;
+ uint8_t vref_dq_r0nib9;
+ uint8_t vref_dq_r0nib10;
+ uint8_t vref_dq_r0nib11;
+ uint8_t vref_dq_r0nib12;
+ uint8_t vref_dq_r0nib13;
+ uint8_t vref_dq_r0nib14;
+ uint8_t vref_dq_r0nib15;
+ uint8_t vref_dq_r0nib16;
+ uint8_t vref_dq_r0nib17;
+ uint8_t vref_dq_r0nib18;
+ uint8_t vref_dq_r0nib19;
+ uint8_t vref_dq_r1nib0;
+ uint8_t vref_dq_r1nib1;
+ uint8_t vref_dq_r1nib2;
+ uint8_t vref_dq_r1nib3;
+ uint8_t vref_dq_r1nib4;
+ uint8_t vref_dq_r1nib5;
+ uint8_t vref_dq_r1nib6;
+ uint8_t vref_dq_r1nib7;
+ uint8_t vref_dq_r1nib8;
+ uint8_t vref_dq_r1nib9;
+ uint8_t vref_dq_r1nib10;
+ uint8_t vref_dq_r1nib11;
+ uint8_t vref_dq_r1nib12;
+ uint8_t vref_dq_r1nib13;
+ uint8_t vref_dq_r1nib14;
+ uint8_t vref_dq_r1nib15;
+ uint8_t vref_dq_r1nib16;
+ uint8_t vref_dq_r1nib17;
+ uint8_t vref_dq_r1nib18;
+ uint8_t vref_dq_r1nib19;
+ uint8_t vref_dq_r2nib0;
+ uint8_t vref_dq_r2nib1;
+ uint8_t vref_dq_r2nib2;
+ uint8_t vref_dq_r2nib3;
+ uint8_t vref_dq_r2nib4;
+ uint8_t vref_dq_r2nib5;
+ uint8_t vref_dq_r2nib6;
+ uint8_t vref_dq_r2nib7;
+ uint8_t vref_dq_r2nib8;
+ uint8_t vref_dq_r2nib9;
+ uint8_t vref_dq_r2nib10;
+ uint8_t vref_dq_r2nib11;
+ uint8_t vref_dq_r2nib12;
+ uint8_t vref_dq_r2nib13;
+ uint8_t vref_dq_r2nib14;
+ uint8_t vref_dq_r2nib15;
+ uint8_t vref_dq_r2nib16;
+ uint8_t vref_dq_r2nib17;
+ uint8_t vref_dq_r2nib18;
+ uint8_t vref_dq_r2nib19;
+ uint8_t vref_dq_r3nib0;
+ uint8_t vref_dq_r3nib1;
+ uint8_t vref_dq_r3nib2;
+ uint8_t vref_dq_r3nib3;
+ uint8_t vref_dq_r3nib4;
+ uint8_t vref_dq_r3nib5;
+ uint8_t vref_dq_r3nib6;
+ uint8_t vref_dq_r3nib7;
+ uint8_t vref_dq_r3nib8;
+ uint8_t vref_dq_r3nib9;
+ uint8_t vref_dq_r3nib10;
+ uint8_t vref_dq_r3nib11;
+ uint8_t vref_dq_r3nib12;
+ uint8_t vref_dq_r3nib13;
+ uint8_t vref_dq_r3nib14;
+ uint8_t vref_dq_r3nib15;
+ uint8_t vref_dq_r3nib16;
+ uint8_t vref_dq_r3nib17;
+ uint8_t vref_dq_r3nib18;
+ uint8_t vref_dq_r3nib19;
+ uint8_t reserved_d6[0x3f6 - 0xd6];
+ uint16_t alt_cas_l;
+ uint8_t alt_wcas_l;
+ uint8_t d4misc;
+} __packed;
+
+struct ddr4u2d {
+ uint8_t reserved00;
+ uint8_t msg_misc;
+ uint16_t pmu_revision;
+ uint8_t pstate;
+ uint8_t pll_bypass_en;
+ uint16_t dramfreq;
+ uint8_t dfi_freq_ratio;
+ uint8_t bpznres_val;
+ uint8_t phy_odt_impedance;
+ uint8_t phy_drv_impedance;
+ uint8_t phy_vref;
+ uint8_t dram_type;
+ uint8_t disabled_dbyte;
+ uint8_t enabled_dqs;
+ uint8_t cs_present;
+ uint8_t cs_present_d0;
+ uint8_t cs_present_d1;
+ uint8_t addr_mirror;
+ uint8_t cs_test_fail;
+ uint8_t phy_cfg;
+ uint16_t sequence_ctrl;
+ uint8_t hdt_ctrl;
+ uint8_t rx2d_train_opt;
+ uint8_t tx2d_train_opt;
+ uint8_t share2dvref_result;
+ uint8_t delay_weight2d;
+ uint8_t voltage_weight2d;
+ uint8_t reserved1e[0x22 - 0x1e];
+ uint16_t phy_config_override;
+ uint8_t dfimrlmargin;
+ uint8_t r0_rx_clk_dly_margin;
+ uint8_t r0_vref_dac_margin;
+ uint8_t r0_tx_dq_dly_margin;
+ uint8_t r0_device_vref_margin;
+ uint8_t reserved29[0x33 - 0x29];
+ uint8_t r1_rx_clk_dly_margin;
+ uint8_t r1_vref_dac_margin;
+ uint8_t r1_tx_dq_dly_margin;
+ uint8_t r1_device_vref_margin;
+ uint8_t reserved37[0x41 - 0x37];
+ uint8_t r2_rx_clk_dly_margin;
+ uint8_t r2_vref_dac_margin;
+ uint8_t r2_tx_dq_dly_margin;
+ uint8_t r2_device_vref_margin;
+ uint8_t reserved45[0x4f - 0x45];
+ uint8_t r3_rx_clk_dly_margin;
+ uint8_t r3_vref_dac_margin;
+ uint8_t r3_tx_dq_dly_margin;
+ uint8_t r3_device_vref_margin;
+ uint8_t reserved53[0x5e - 0x53];
+ uint16_t mr0;
+ uint16_t mr1;
+ uint16_t mr2;
+ uint16_t mr3;
+ uint16_t mr4;
+ uint16_t mr5;
+ uint16_t mr6;
+ uint8_t x16present;
+ uint8_t cs_setup_gddec;
+ uint16_t rtt_nom_wr_park0;
+ uint16_t rtt_nom_wr_park1;
+ uint16_t rtt_nom_wr_park2;
+ uint16_t rtt_nom_wr_park3;
+ uint16_t rtt_nom_wr_park4;
+ uint16_t rtt_nom_wr_park5;
+ uint16_t rtt_nom_wr_park6;
+ uint16_t rtt_nom_wr_park7;
+ uint8_t acsm_odt_ctrl0;
+ uint8_t acsm_odt_ctrl1;
+ uint8_t acsm_odt_ctrl2;
+ uint8_t acsm_odt_ctrl3;
+ uint8_t acsm_odt_ctrl4;
+ uint8_t acsm_odt_ctrl5;
+ uint8_t acsm_odt_ctrl6;
+ uint8_t acsm_odt_ctrl7;
+ uint8_t vref_dq_r0nib0;
+ uint8_t vref_dq_r0nib1;
+ uint8_t vref_dq_r0nib2;
+ uint8_t vref_dq_r0nib3;
+ uint8_t vref_dq_r0nib4;
+ uint8_t vref_dq_r0nib5;
+ uint8_t vref_dq_r0nib6;
+ uint8_t vref_dq_r0nib7;
+ uint8_t vref_dq_r0nib8;
+ uint8_t vref_dq_r0nib9;
+ uint8_t vref_dq_r0nib10;
+ uint8_t vref_dq_r0nib11;
+ uint8_t vref_dq_r0nib12;
+ uint8_t vref_dq_r0nib13;
+ uint8_t vref_dq_r0nib14;
+ uint8_t vref_dq_r0nib15;
+ uint8_t vref_dq_r0nib16;
+ uint8_t vref_dq_r0nib17;
+ uint8_t vref_dq_r0nib18;
+ uint8_t vref_dq_r0nib19;
+ uint8_t vref_dq_r1nib0;
+ uint8_t vref_dq_r1nib1;
+ uint8_t vref_dq_r1nib2;
+ uint8_t vref_dq_r1nib3;
+ uint8_t vref_dq_r1nib4;
+ uint8_t vref_dq_r1nib5;
+ uint8_t vref_dq_r1nib6;
+ uint8_t vref_dq_r1nib7;
+ uint8_t vref_dq_r1nib8;
+ uint8_t vref_dq_r1nib9;
+ uint8_t vref_dq_r1nib10;
+ uint8_t vref_dq_r1nib11;
+ uint8_t vref_dq_r1nib12;
+ uint8_t vref_dq_r1nib13;
+ uint8_t vref_dq_r1nib14;
+ uint8_t vref_dq_r1nib15;
+ uint8_t vref_dq_r1nib16;
+ uint8_t vref_dq_r1nib17;
+ uint8_t vref_dq_r1nib18;
+ uint8_t vref_dq_r1nib19;
+ uint8_t vref_dq_r2nib0;
+ uint8_t vref_dq_r2nib1;
+ uint8_t vref_dq_r2nib2;
+ uint8_t vref_dq_r2nib3;
+ uint8_t vref_dq_r2nib4;
+ uint8_t vref_dq_r2nib5;
+ uint8_t vref_dq_r2nib6;
+ uint8_t vref_dq_r2nib7;
+ uint8_t vref_dq_r2nib8;
+ uint8_t vref_dq_r2nib9;
+ uint8_t vref_dq_r2nib10;
+ uint8_t vref_dq_r2nib11;
+ uint8_t vref_dq_r2nib12;
+ uint8_t vref_dq_r2nib13;
+ uint8_t vref_dq_r2nib14;
+ uint8_t vref_dq_r2nib15;
+ uint8_t vref_dq_r2nib16;
+ uint8_t vref_dq_r2nib17;
+ uint8_t vref_dq_r2nib18;
+ uint8_t vref_dq_r2nib19;
+ uint8_t vref_dq_r3nib0;
+ uint8_t vref_dq_r3nib1;
+ uint8_t vref_dq_r3nib2;
+ uint8_t vref_dq_r3nib3;
+ uint8_t vref_dq_r3nib4;
+ uint8_t vref_dq_r3nib5;
+ uint8_t vref_dq_r3nib6;
+ uint8_t vref_dq_r3nib7;
+ uint8_t vref_dq_r3nib8;
+ uint8_t vref_dq_r3nib9;
+ uint8_t vref_dq_r3nib10;
+ uint8_t vref_dq_r3nib11;
+ uint8_t vref_dq_r3nib12;
+ uint8_t vref_dq_r3nib13;
+ uint8_t vref_dq_r3nib14;
+ uint8_t vref_dq_r3nib15;
+ uint8_t vref_dq_r3nib16;
+ uint8_t vref_dq_r3nib17;
+ uint8_t vref_dq_r3nib18;
+ uint8_t vref_dq_r3nib19;
+ uint8_t reserved_d6[0x3f6 - 0xd6];
+ uint16_t alt_cas_l;
+ uint8_t alt_wcas_l;
+ uint8_t d4misc;
+} __packed;
+
+struct ddr4r1d {
+ uint8_t reserved00;
+ uint8_t msg_misc;
+ uint16_t pmu_revision;
+ uint8_t pstate;
+ uint8_t pll_bypass_en;
+ uint16_t dramfreq;
+ uint8_t dfi_freq_ratio;
+ uint8_t bpznres_val;
+ uint8_t phy_odt_impedance;
+ uint8_t phy_drv_impedance;
+ uint8_t phy_vref;
+ uint8_t dram_type;
+ uint8_t disabled_dbyte;
+ uint8_t enabled_dqs;
+ uint8_t cs_present;
+ uint8_t cs_present_d0;
+ uint8_t cs_present_d1;
+ uint8_t addr_mirror;
+ uint8_t cs_test_fail;
+ uint8_t phy_cfg;
+ uint16_t sequence_ctrl;
+ uint8_t hdt_ctrl;
+ uint8_t reserved19[0x22 - 0x19];
+ uint16_t phy_config_override;
+ uint8_t dfimrlmargin;
+ int8_t cdd_rr_3_2;
+ int8_t cdd_rr_3_1;
+ int8_t cdd_rr_3_0;
+ int8_t cdd_rr_2_3;
+ int8_t cdd_rr_2_1;
+ int8_t cdd_rr_2_0;
+ int8_t cdd_rr_1_3;
+ int8_t cdd_rr_1_2;
+ int8_t cdd_rr_1_0;
+ int8_t cdd_rr_0_3;
+ int8_t cdd_rr_0_2;
+ int8_t cdd_rr_0_1;
+ int8_t cdd_ww_3_2;
+ int8_t cdd_ww_3_1;
+ int8_t cdd_ww_3_0;
+ int8_t cdd_ww_2_3;
+ int8_t cdd_ww_2_1;
+ int8_t cdd_ww_2_0;
+ int8_t cdd_ww_1_3;
+ int8_t cdd_ww_1_2;
+ int8_t cdd_ww_1_0;
+ int8_t cdd_ww_0_3;
+ int8_t cdd_ww_0_2;
+ int8_t cdd_ww_0_1;
+ int8_t cdd_rw_3_3;
+ int8_t cdd_rw_3_2;
+ int8_t cdd_rw_3_1;
+ int8_t cdd_rw_3_0;
+ int8_t cdd_rw_2_3;
+ int8_t cdd_rw_2_2;
+ int8_t cdd_rw_2_1;
+ int8_t cdd_rw_2_0;
+ int8_t cdd_rw_1_3;
+ int8_t cdd_rw_1_2;
+ int8_t cdd_rw_1_1;
+ int8_t cdd_rw_1_0;
+ int8_t cdd_rw_0_3;
+ int8_t cdd_rw_0_2;
+ int8_t cdd_rw_0_1;
+ int8_t cdd_rw_0_0;
+ int8_t cdd_wr_3_3;
+ int8_t cdd_wr_3_2;
+ int8_t cdd_wr_3_1;
+ int8_t cdd_wr_3_0;
+ int8_t cdd_wr_2_3;
+ int8_t cdd_wr_2_2;
+ int8_t cdd_wr_2_1;
+ int8_t cdd_wr_2_0;
+ int8_t cdd_wr_1_3;
+ int8_t cdd_wr_1_2;
+ int8_t cdd_wr_1_1;
+ int8_t cdd_wr_1_0;
+ int8_t cdd_wr_0_3;
+ int8_t cdd_wr_0_2;
+ int8_t cdd_wr_0_1;
+ int8_t cdd_wr_0_0;
+ uint8_t reserved5d;
+ uint16_t mr0;
+ uint16_t mr1;
+ uint16_t mr2;
+ uint16_t mr3;
+ uint16_t mr4;
+ uint16_t mr5;
+ uint16_t mr6;
+ uint8_t x16present;
+ uint8_t cs_setup_gddec;
+ uint16_t rtt_nom_wr_park0;
+ uint16_t rtt_nom_wr_park1;
+ uint16_t rtt_nom_wr_park2;
+ uint16_t rtt_nom_wr_park3;
+ uint16_t rtt_nom_wr_park4;
+ uint16_t rtt_nom_wr_park5;
+ uint16_t rtt_nom_wr_park6;
+ uint16_t rtt_nom_wr_park7;
+ uint8_t acsm_odt_ctrl0;
+ uint8_t acsm_odt_ctrl1;
+ uint8_t acsm_odt_ctrl2;
+ uint8_t acsm_odt_ctrl3;
+ uint8_t acsm_odt_ctrl4;
+ uint8_t acsm_odt_ctrl5;
+ uint8_t acsm_odt_ctrl6;
+ uint8_t acsm_odt_ctrl7;
+ uint8_t vref_dq_r0nib0;
+ uint8_t vref_dq_r0nib1;
+ uint8_t vref_dq_r0nib2;
+ uint8_t vref_dq_r0nib3;
+ uint8_t vref_dq_r0nib4;
+ uint8_t vref_dq_r0nib5;
+ uint8_t vref_dq_r0nib6;
+ uint8_t vref_dq_r0nib7;
+ uint8_t vref_dq_r0nib8;
+ uint8_t vref_dq_r0nib9;
+ uint8_t vref_dq_r0nib10;
+ uint8_t vref_dq_r0nib11;
+ uint8_t vref_dq_r0nib12;
+ uint8_t vref_dq_r0nib13;
+ uint8_t vref_dq_r0nib14;
+ uint8_t vref_dq_r0nib15;
+ uint8_t vref_dq_r0nib16;
+ uint8_t vref_dq_r0nib17;
+ uint8_t vref_dq_r0nib18;
+ uint8_t vref_dq_r0nib19;
+ uint8_t vref_dq_r1nib0;
+ uint8_t vref_dq_r1nib1;
+ uint8_t vref_dq_r1nib2;
+ uint8_t vref_dq_r1nib3;
+ uint8_t vref_dq_r1nib4;
+ uint8_t vref_dq_r1nib5;
+ uint8_t vref_dq_r1nib6;
+ uint8_t vref_dq_r1nib7;
+ uint8_t vref_dq_r1nib8;
+ uint8_t vref_dq_r1nib9;
+ uint8_t vref_dq_r1nib10;
+ uint8_t vref_dq_r1nib11;
+ uint8_t vref_dq_r1nib12;
+ uint8_t vref_dq_r1nib13;
+ uint8_t vref_dq_r1nib14;
+ uint8_t vref_dq_r1nib15;
+ uint8_t vref_dq_r1nib16;
+ uint8_t vref_dq_r1nib17;
+ uint8_t vref_dq_r1nib18;
+ uint8_t vref_dq_r1nib19;
+ uint8_t vref_dq_r2nib0;
+ uint8_t vref_dq_r2nib1;
+ uint8_t vref_dq_r2nib2;
+ uint8_t vref_dq_r2nib3;
+ uint8_t vref_dq_r2nib4;
+ uint8_t vref_dq_r2nib5;
+ uint8_t vref_dq_r2nib6;
+ uint8_t vref_dq_r2nib7;
+ uint8_t vref_dq_r2nib8;
+ uint8_t vref_dq_r2nib9;
+ uint8_t vref_dq_r2nib10;
+ uint8_t vref_dq_r2nib11;
+ uint8_t vref_dq_r2nib12;
+ uint8_t vref_dq_r2nib13;
+ uint8_t vref_dq_r2nib14;
+ uint8_t vref_dq_r2nib15;
+ uint8_t vref_dq_r2nib16;
+ uint8_t vref_dq_r2nib17;
+ uint8_t vref_dq_r2nib18;
+ uint8_t vref_dq_r2nib19;
+ uint8_t vref_dq_r3nib0;
+ uint8_t vref_dq_r3nib1;
+ uint8_t vref_dq_r3nib2;
+ uint8_t vref_dq_r3nib3;
+ uint8_t vref_dq_r3nib4;
+ uint8_t vref_dq_r3nib5;
+ uint8_t vref_dq_r3nib6;
+ uint8_t vref_dq_r3nib7;
+ uint8_t vref_dq_r3nib8;
+ uint8_t vref_dq_r3nib9;
+ uint8_t vref_dq_r3nib10;
+ uint8_t vref_dq_r3nib11;
+ uint8_t vref_dq_r3nib12;
+ uint8_t vref_dq_r3nib13;
+ uint8_t vref_dq_r3nib14;
+ uint8_t vref_dq_r3nib15;
+ uint8_t vref_dq_r3nib16;
+ uint8_t vref_dq_r3nib17;
+ uint8_t vref_dq_r3nib18;
+ uint8_t vref_dq_r3nib19;
+ uint8_t f0rc00_d0;
+ uint8_t f0rc01_d0;
+ uint8_t f0rc02_d0;
+ uint8_t f0rc03_d0;
+ uint8_t f0rc04_d0;
+ uint8_t f0rc05_d0;
+ uint8_t f0rc06_d0;
+ uint8_t f0rc07_d0;
+ uint8_t f0rc08_d0;
+ uint8_t f0rc09_d0;
+ uint8_t f0rc0a_d0;
+ uint8_t f0rc0b_d0;
+ uint8_t f0rc0c_d0;
+ uint8_t f0rc0d_d0;
+ uint8_t f0rc0e_d0;
+ uint8_t f0rc0f_d0;
+ uint8_t f0rc1x_d0;
+ uint8_t f0rc2x_d0;
+ uint8_t f0rc3x_d0;
+ uint8_t f0rc4x_d0;
+ uint8_t f0rc5x_d0;
+ uint8_t f0rc6x_d0;
+ uint8_t f0rc7x_d0;
+ uint8_t f0rc8x_d0;
+ uint8_t f0rc9x_d0;
+ uint8_t f0rcax_d0;
+ uint8_t f0rcbx_d0;
+ uint8_t f1rc00_d0;
+ uint8_t f1rc01_d0;
+ uint8_t f1rc02_d0;
+ uint8_t f1rc03_d0;
+ uint8_t f1rc04_d0;
+ uint8_t f1rc05_d0;
+ uint8_t f1rc06_d0;
+ uint8_t f1rc07_d0;
+ uint8_t f1rc08_d0;
+ uint8_t f1rc09_d0;
+ uint8_t f1rc0a_d0;
+ uint8_t f1rc0b_d0;
+ uint8_t f1rc0c_d0;
+ uint8_t f1rc0d_d0;
+ uint8_t f1rc0e_d0;
+ uint8_t f1rc0f_d0;
+ uint8_t f1rc1x_d0;
+ uint8_t f1rc2x_d0;
+ uint8_t f1rc3x_d0;
+ uint8_t f1rc4x_d0;
+ uint8_t f1rc5x_d0;
+ uint8_t f1rc6x_d0;
+ uint8_t f1rc7x_d0;
+ uint8_t f1rc8x_d0;
+ uint8_t f1rc9x_d0;
+ uint8_t f1rcax_d0;
+ uint8_t f1rcbx_d0;
+ uint8_t f0rc00_d1;
+ uint8_t f0rc01_d1;
+ uint8_t f0rc02_d1;
+ uint8_t f0rc03_d1;
+ uint8_t f0rc04_d1;
+ uint8_t f0rc05_d1;
+ uint8_t f0rc06_d1;
+ uint8_t f0rc07_d1;
+ uint8_t f0rc08_d1;
+ uint8_t f0rc09_d1;
+ uint8_t f0rc0a_d1;
+ uint8_t f0rc0b_d1;
+ uint8_t f0rc0c_d1;
+ uint8_t f0rc0d_d1;
+ uint8_t f0rc0e_d1;
+ uint8_t f0rc0f_d1;
+ uint8_t f0rc1x_d1;
+ uint8_t f0rc2x_d1;
+ uint8_t f0rc3x_d1;
+ uint8_t f0rc4x_d1;
+ uint8_t f0rc5x_d1;
+ uint8_t f0rc6x_d1;
+ uint8_t f0rc7x_d1;
+ uint8_t f0rc8x_d1;
+ uint8_t f0rc9x_d1;
+ uint8_t f0rcax_d1;
+ uint8_t f0rcbx_d1;
+ uint8_t f1rc00_d1;
+ uint8_t f1rc01_d1;
+ uint8_t f1rc02_d1;
+ uint8_t f1rc03_d1;
+ uint8_t f1rc04_d1;
+ uint8_t f1rc05_d1;
+ uint8_t f1rc06_d1;
+ uint8_t f1rc07_d1;
+ uint8_t f1rc08_d1;
+ uint8_t f1rc09_d1;
+ uint8_t f1rc0a_d1;
+ uint8_t f1rc0b_d1;
+ uint8_t f1rc0c_d1;
+ uint8_t f1rc0d_d1;
+ uint8_t f1rc0e_d1;
+ uint8_t f1rc0f_d1;
+ uint8_t f1rc1x_d1;
+ uint8_t f1rc2x_d1;
+ uint8_t f1rc3x_d1;
+ uint8_t f1rc4x_d1;
+ uint8_t f1rc5x_d1;
+ uint8_t f1rc6x_d1;
+ uint8_t f1rc7x_d1;
+ uint8_t f1rc8x_d1;
+ uint8_t f1rc9x_d1;
+ uint8_t f1rcax_d1;
+ uint8_t f1rcbx_d1;
+ uint8_t reserved142[0x3f6 - 0x142];
+ uint16_t alt_cas_l;
+ uint8_t alt_wcas_l;
+ uint8_t d4misc;
+} __packed;
+
+struct ddr4r2d {
+ uint8_t reserved00;
+ uint8_t msg_misc;
+ uint16_t pmu_revision;
+ uint8_t pstate;
+ uint8_t pll_bypass_en;
+ uint16_t dramfreq;
+ uint8_t dfi_freq_ratio;
+ uint8_t bpznres_val;
+ uint8_t phy_odt_impedance;
+ uint8_t phy_drv_impedance;
+ uint8_t phy_vref;
+ uint8_t dram_type;
+ uint8_t disabled_dbyte;
+ uint8_t enabled_dqs;
+ uint8_t cs_present;
+ uint8_t cs_present_d0;
+ uint8_t cs_present_d1;
+ uint8_t addr_mirror;
+ uint8_t cs_test_fail;
+ uint8_t phy_cfg;
+ uint16_t sequence_ctrl;
+ uint8_t hdt_ctrl;
+ uint8_t rx2d_train_opt;
+ uint8_t tx2d_train_opt;
+ uint8_t share2dvref_result;
+ uint8_t delay_weight2d;
+ uint8_t voltage_weight2d;
+ uint8_t reserved1e[0x22-0x1e];
+ uint16_t phy_config_override;
+ uint8_t dfimrlmargin;
+ uint8_t r0_rx_clk_dly_margin;
+ uint8_t r0_vref_dac_margin;
+ uint8_t r0_tx_dq_dly_margin;
+ uint8_t r0_device_vref_margin;
+ uint8_t reserved29[0x33-0x29];
+ uint8_t r1_rx_clk_dly_margin;
+ uint8_t r1_vref_dac_margin;
+ uint8_t r1_tx_dq_dly_margin;
+ uint8_t r1_device_vref_margin;
+ uint8_t reserved37[0x41-0x37];
+ uint8_t r2_rx_clk_dly_margin;
+ uint8_t r2_vref_dac_margin;
+ uint8_t r2_tx_dq_dly_margin;
+ uint8_t r2_device_vref_margin;
+ uint8_t reserved45[0x4f - 0x45];
+ uint8_t r3_rx_clk_dly_margin;
+ uint8_t r3_vref_dac_margin;
+ uint8_t r3_tx_dq_dly_margin;
+ uint8_t r3_device_vref_margin;
+ uint8_t reserved53[0x5e - 0x53];
+ uint16_t mr0;
+ uint16_t mr1;
+ uint16_t mr2;
+ uint16_t mr3;
+ uint16_t mr4;
+ uint16_t mr5;
+ uint16_t mr6;
+ uint8_t x16present;
+ uint8_t cs_setup_gddec;
+ uint16_t rtt_nom_wr_park0;
+ uint16_t rtt_nom_wr_park1;
+ uint16_t rtt_nom_wr_park2;
+ uint16_t rtt_nom_wr_park3;
+ uint16_t rtt_nom_wr_park4;
+ uint16_t rtt_nom_wr_park5;
+ uint16_t rtt_nom_wr_park6;
+ uint16_t rtt_nom_wr_park7;
+ uint8_t acsm_odt_ctrl0;
+ uint8_t acsm_odt_ctrl1;
+ uint8_t acsm_odt_ctrl2;
+ uint8_t acsm_odt_ctrl3;
+ uint8_t acsm_odt_ctrl4;
+ uint8_t acsm_odt_ctrl5;
+ uint8_t acsm_odt_ctrl6;
+ uint8_t acsm_odt_ctrl7;
+ uint8_t vref_dq_r0nib0;
+ uint8_t vref_dq_r0nib1;
+ uint8_t vref_dq_r0nib2;
+ uint8_t vref_dq_r0nib3;
+ uint8_t vref_dq_r0nib4;
+ uint8_t vref_dq_r0nib5;
+ uint8_t vref_dq_r0nib6;
+ uint8_t vref_dq_r0nib7;
+ uint8_t vref_dq_r0nib8;
+ uint8_t vref_dq_r0nib9;
+ uint8_t vref_dq_r0nib10;
+ uint8_t vref_dq_r0nib11;
+ uint8_t vref_dq_r0nib12;
+ uint8_t vref_dq_r0nib13;
+ uint8_t vref_dq_r0nib14;
+ uint8_t vref_dq_r0nib15;
+ uint8_t vref_dq_r0nib16;
+ uint8_t vref_dq_r0nib17;
+ uint8_t vref_dq_r0nib18;
+ uint8_t vref_dq_r0nib19;
+ uint8_t vref_dq_r1nib0;
+ uint8_t vref_dq_r1nib1;
+ uint8_t vref_dq_r1nib2;
+ uint8_t vref_dq_r1nib3;
+ uint8_t vref_dq_r1nib4;
+ uint8_t vref_dq_r1nib5;
+ uint8_t vref_dq_r1nib6;
+ uint8_t vref_dq_r1nib7;
+ uint8_t vref_dq_r1nib8;
+ uint8_t vref_dq_r1nib9;
+ uint8_t vref_dq_r1nib10;
+ uint8_t vref_dq_r1nib11;
+ uint8_t vref_dq_r1nib12;
+ uint8_t vref_dq_r1nib13;
+ uint8_t vref_dq_r1nib14;
+ uint8_t vref_dq_r1nib15;
+ uint8_t vref_dq_r1nib16;
+ uint8_t vref_dq_r1nib17;
+ uint8_t vref_dq_r1nib18;
+ uint8_t vref_dq_r1nib19;
+ uint8_t vref_dq_r2nib0;
+ uint8_t vref_dq_r2nib1;
+ uint8_t vref_dq_r2nib2;
+ uint8_t vref_dq_r2nib3;
+ uint8_t vref_dq_r2nib4;
+ uint8_t vref_dq_r2nib5;
+ uint8_t vref_dq_r2nib6;
+ uint8_t vref_dq_r2nib7;
+ uint8_t vref_dq_r2nib8;
+ uint8_t vref_dq_r2nib9;
+ uint8_t vref_dq_r2nib10;
+ uint8_t vref_dq_r2nib11;
+ uint8_t vref_dq_r2nib12;
+ uint8_t vref_dq_r2nib13;
+ uint8_t vref_dq_r2nib14;
+ uint8_t vref_dq_r2nib15;
+ uint8_t vref_dq_r2nib16;
+ uint8_t vref_dq_r2nib17;
+ uint8_t vref_dq_r2nib18;
+ uint8_t vref_dq_r2nib19;
+ uint8_t vref_dq_r3nib0;
+ uint8_t vref_dq_r3nib1;
+ uint8_t vref_dq_r3nib2;
+ uint8_t vref_dq_r3nib3;
+ uint8_t vref_dq_r3nib4;
+ uint8_t vref_dq_r3nib5;
+ uint8_t vref_dq_r3nib6;
+ uint8_t vref_dq_r3nib7;
+ uint8_t vref_dq_r3nib8;
+ uint8_t vref_dq_r3nib9;
+ uint8_t vref_dq_r3nib10;
+ uint8_t vref_dq_r3nib11;
+ uint8_t vref_dq_r3nib12;
+ uint8_t vref_dq_r3nib13;
+ uint8_t vref_dq_r3nib14;
+ uint8_t vref_dq_r3nib15;
+ uint8_t vref_dq_r3nib16;
+ uint8_t vref_dq_r3nib17;
+ uint8_t vref_dq_r3nib18;
+ uint8_t vref_dq_r3nib19;
+ uint8_t f0rc00_d0;
+ uint8_t f0rc01_d0;
+ uint8_t f0rc02_d0;
+ uint8_t f0rc03_d0;
+ uint8_t f0rc04_d0;
+ uint8_t f0rc05_d0;
+ uint8_t f0rc06_d0;
+ uint8_t f0rc07_d0;
+ uint8_t f0rc08_d0;
+ uint8_t f0rc09_d0;
+ uint8_t f0rc0a_d0;
+ uint8_t f0rc0b_d0;
+ uint8_t f0rc0c_d0;
+ uint8_t f0rc0d_d0;
+ uint8_t f0rc0e_d0;
+ uint8_t f0rc0f_d0;
+ uint8_t f0rc1x_d0;
+ uint8_t f0rc2x_d0;
+ uint8_t f0rc3x_d0;
+ uint8_t f0rc4x_d0;
+ uint8_t f0rc5x_d0;
+ uint8_t f0rc6x_d0;
+ uint8_t f0rc7x_d0;
+ uint8_t f0rc8x_d0;
+ uint8_t f0rc9x_d0;
+ uint8_t f0rcax_d0;
+ uint8_t f0rcbx_d0;
+ uint8_t f1rc00_d0;
+ uint8_t f1rc01_d0;
+ uint8_t f1rc02_d0;
+ uint8_t f1rc03_d0;
+ uint8_t f1rc04_d0;
+ uint8_t f1rc05_d0;
+ uint8_t f1rc06_d0;
+ uint8_t f1rc07_d0;
+ uint8_t f1rc08_d0;
+ uint8_t f1rc09_d0;
+ uint8_t f1rc0a_d0;
+ uint8_t f1rc0b_d0;
+ uint8_t f1rc0c_d0;
+ uint8_t f1rc0d_d0;
+ uint8_t f1rc0e_d0;
+ uint8_t f1rc0f_d0;
+ uint8_t f1rc1x_d0;
+ uint8_t f1rc2x_d0;
+ uint8_t f1rc3x_d0;
+ uint8_t f1rc4x_d0;
+ uint8_t f1rc5x_d0;
+ uint8_t f1rc6x_d0;
+ uint8_t f1rc7x_d0;
+ uint8_t f1rc8x_d0;
+ uint8_t f1rc9x_d0;
+ uint8_t f1rcax_d0;
+ uint8_t f1rcbx_d0;
+ uint8_t f0rc00_d1;
+ uint8_t f0rc01_d1;
+ uint8_t f0rc02_d1;
+ uint8_t f0rc03_d1;
+ uint8_t f0rc04_d1;
+ uint8_t f0rc05_d1;
+ uint8_t f0rc06_d1;
+ uint8_t f0rc07_d1;
+ uint8_t f0rc08_d1;
+ uint8_t f0rc09_d1;
+ uint8_t f0rc0a_d1;
+ uint8_t f0rc0b_d1;
+ uint8_t f0rc0c_d1;
+ uint8_t f0rc0d_d1;
+ uint8_t f0rc0e_d1;
+ uint8_t f0rc0f_d1;
+ uint8_t f0rc1x_d1;
+ uint8_t f0rc2x_d1;
+ uint8_t f0rc3x_d1;
+ uint8_t f0rc4x_d1;
+ uint8_t f0rc5x_d1;
+ uint8_t f0rc6x_d1;
+ uint8_t f0rc7x_d1;
+ uint8_t f0rc8x_d1;
+ uint8_t f0rc9x_d1;
+ uint8_t f0rcax_d1;
+ uint8_t f0rcbx_d1;
+ uint8_t f1rc00_d1;
+ uint8_t f1rc01_d1;
+ uint8_t f1rc02_d1;
+ uint8_t f1rc03_d1;
+ uint8_t f1rc04_d1;
+ uint8_t f1rc05_d1;
+ uint8_t f1rc06_d1;
+ uint8_t f1rc07_d1;
+ uint8_t f1rc08_d1;
+ uint8_t f1rc09_d1;
+ uint8_t f1rc0a_d1;
+ uint8_t f1rc0b_d1;
+ uint8_t f1rc0c_d1;
+ uint8_t f1rc0d_d1;
+ uint8_t f1rc0e_d1;
+ uint8_t f1rc0f_d1;
+ uint8_t f1rc1x_d1;
+ uint8_t f1rc2x_d1;
+ uint8_t f1rc3x_d1;
+ uint8_t f1rc4x_d1;
+ uint8_t f1rc5x_d1;
+ uint8_t f1rc6x_d1;
+ uint8_t f1rc7x_d1;
+ uint8_t f1rc8x_d1;
+ uint8_t f1rc9x_d1;
+ uint8_t f1rcax_d1;
+ uint8_t f1rcbx_d1;
+ uint8_t reserved142[0x3f6 - 0x142];
+ uint16_t alt_cas_l;
+ uint8_t alt_wcas_l;
+ uint8_t d4misc;
+} __packed;
+
+struct ddr4lr1d {
+ uint8_t reserved00;
+ uint8_t msg_misc;
+ uint16_t pmu_revision;
+ uint8_t pstate;
+ uint8_t pll_bypass_en;
+ uint16_t dramfreq;
+ uint8_t dfi_freq_ratio;
+ uint8_t bpznres_val;
+ uint8_t phy_odt_impedance;
+ uint8_t phy_drv_impedance;
+ uint8_t phy_vref;
+ uint8_t dram_type;
+ uint8_t disabled_dbyte;
+ uint8_t enabled_dqs;
+ uint8_t cs_present;
+ uint8_t cs_present_d0;
+ uint8_t cs_present_d1;
+ uint8_t addr_mirror;
+ uint8_t cs_test_fail;
+ uint8_t phy_cfg;
+ uint16_t sequence_ctrl;
+ uint8_t hdt_ctrl;
+ uint8_t reserved19[0x22 - 0x19];
+ uint16_t phy_config_override;
+ uint8_t dfimrlmargin;
+ int8_t cdd_rr_3_2;
+ int8_t cdd_rr_3_1;
+ int8_t cdd_rr_3_0;
+ int8_t cdd_rr_2_3;
+ int8_t cdd_rr_2_1;
+ int8_t cdd_rr_2_0;
+ int8_t cdd_rr_1_3;
+ int8_t cdd_rr_1_2;
+ int8_t cdd_rr_1_0;
+ int8_t cdd_rr_0_3;
+ int8_t cdd_rr_0_2;
+ int8_t cdd_rr_0_1;
+ int8_t cdd_ww_3_2;
+ int8_t cdd_ww_3_1;
+ int8_t cdd_ww_3_0;
+ int8_t cdd_ww_2_3;
+ int8_t cdd_ww_2_1;
+ int8_t cdd_ww_2_0;
+ int8_t cdd_ww_1_3;
+ int8_t cdd_ww_1_2;
+ int8_t cdd_ww_1_0;
+ int8_t cdd_ww_0_3;
+ int8_t cdd_ww_0_2;
+ int8_t cdd_ww_0_1;
+ int8_t cdd_rw_3_3;
+ int8_t cdd_rw_3_2;
+ int8_t cdd_rw_3_1;
+ int8_t cdd_rw_3_0;
+ int8_t cdd_rw_2_3;
+ int8_t cdd_rw_2_2;
+ int8_t cdd_rw_2_1;
+ int8_t cdd_rw_2_0;
+ int8_t cdd_rw_1_3;
+ int8_t cdd_rw_1_2;
+ int8_t cdd_rw_1_1;
+ int8_t cdd_rw_1_0;
+ int8_t cdd_rw_0_3;
+ int8_t cdd_rw_0_2;
+ int8_t cdd_rw_0_1;
+ int8_t cdd_rw_0_0;
+ int8_t cdd_wr_3_3;
+ int8_t cdd_wr_3_2;
+ int8_t cdd_wr_3_1;
+ int8_t cdd_wr_3_0;
+ int8_t cdd_wr_2_3;
+ int8_t cdd_wr_2_2;
+ int8_t cdd_wr_2_1;
+ int8_t cdd_wr_2_0;
+ int8_t cdd_wr_1_3;
+ int8_t cdd_wr_1_2;
+ int8_t cdd_wr_1_1;
+ int8_t cdd_wr_1_0;
+ int8_t cdd_wr_0_3;
+ int8_t cdd_wr_0_2;
+ int8_t cdd_wr_0_1;
+ int8_t cdd_wr_0_0;
+ uint8_t reserved5d;
+ uint16_t mr0;
+ uint16_t mr1;
+ uint16_t mr2;
+ uint16_t mr3;
+ uint16_t mr4;
+ uint16_t mr5;
+ uint16_t mr6;
+ uint8_t x16present;
+ uint8_t cs_setup_gddec;
+ uint16_t rtt_nom_wr_park0;
+ uint16_t rtt_nom_wr_park1;
+ uint16_t rtt_nom_wr_park2;
+ uint16_t rtt_nom_wr_park3;
+ uint16_t rtt_nom_wr_park4;
+ uint16_t rtt_nom_wr_park5;
+ uint16_t rtt_nom_wr_park6;
+ uint16_t rtt_nom_wr_park7;
+ uint8_t acsm_odt_ctrl0;
+ uint8_t acsm_odt_ctrl1;
+ uint8_t acsm_odt_ctrl2;
+ uint8_t acsm_odt_ctrl3;
+ uint8_t acsm_odt_ctrl4;
+ uint8_t acsm_odt_ctrl5;
+ uint8_t acsm_odt_ctrl6;
+ uint8_t acsm_odt_ctrl7;
+ uint8_t vref_dq_r0nib0;
+ uint8_t vref_dq_r0nib1;
+ uint8_t vref_dq_r0nib2;
+ uint8_t vref_dq_r0nib3;
+ uint8_t vref_dq_r0nib4;
+ uint8_t vref_dq_r0nib5;
+ uint8_t vref_dq_r0nib6;
+ uint8_t vref_dq_r0nib7;
+ uint8_t vref_dq_r0nib8;
+ uint8_t vref_dq_r0nib9;
+ uint8_t vref_dq_r0nib10;
+ uint8_t vref_dq_r0nib11;
+ uint8_t vref_dq_r0nib12;
+ uint8_t vref_dq_r0nib13;
+ uint8_t vref_dq_r0nib14;
+ uint8_t vref_dq_r0nib15;
+ uint8_t vref_dq_r0nib16;
+ uint8_t vref_dq_r0nib17;
+ uint8_t vref_dq_r0nib18;
+ uint8_t vref_dq_r0nib19;
+ uint8_t vref_dq_r1nib0;
+ uint8_t vref_dq_r1nib1;
+ uint8_t vref_dq_r1nib2;
+ uint8_t vref_dq_r1nib3;
+ uint8_t vref_dq_r1nib4;
+ uint8_t vref_dq_r1nib5;
+ uint8_t vref_dq_r1nib6;
+ uint8_t vref_dq_r1nib7;
+ uint8_t vref_dq_r1nib8;
+ uint8_t vref_dq_r1nib9;
+ uint8_t vref_dq_r1nib10;
+ uint8_t vref_dq_r1nib11;
+ uint8_t vref_dq_r1nib12;
+ uint8_t vref_dq_r1nib13;
+ uint8_t vref_dq_r1nib14;
+ uint8_t vref_dq_r1nib15;
+ uint8_t vref_dq_r1nib16;
+ uint8_t vref_dq_r1nib17;
+ uint8_t vref_dq_r1nib18;
+ uint8_t vref_dq_r1nib19;
+ uint8_t vref_dq_r2nib0;
+ uint8_t vref_dq_r2nib1;
+ uint8_t vref_dq_r2nib2;
+ uint8_t vref_dq_r2nib3;
+ uint8_t vref_dq_r2nib4;
+ uint8_t vref_dq_r2nib5;
+ uint8_t vref_dq_r2nib6;
+ uint8_t vref_dq_r2nib7;
+ uint8_t vref_dq_r2nib8;
+ uint8_t vref_dq_r2nib9;
+ uint8_t vref_dq_r2nib10;
+ uint8_t vref_dq_r2nib11;
+ uint8_t vref_dq_r2nib12;
+ uint8_t vref_dq_r2nib13;
+ uint8_t vref_dq_r2nib14;
+ uint8_t vref_dq_r2nib15;
+ uint8_t vref_dq_r2nib16;
+ uint8_t vref_dq_r2nib17;
+ uint8_t vref_dq_r2nib18;
+ uint8_t vref_dq_r2nib19;
+ uint8_t vref_dq_r3nib0;
+ uint8_t vref_dq_r3nib1;
+ uint8_t vref_dq_r3nib2;
+ uint8_t vref_dq_r3nib3;
+ uint8_t vref_dq_r3nib4;
+ uint8_t vref_dq_r3nib5;
+ uint8_t vref_dq_r3nib6;
+ uint8_t vref_dq_r3nib7;
+ uint8_t vref_dq_r3nib8;
+ uint8_t vref_dq_r3nib9;
+ uint8_t vref_dq_r3nib10;
+ uint8_t vref_dq_r3nib11;
+ uint8_t vref_dq_r3nib12;
+ uint8_t vref_dq_r3nib13;
+ uint8_t vref_dq_r3nib14;
+ uint8_t vref_dq_r3nib15;
+ uint8_t vref_dq_r3nib16;
+ uint8_t vref_dq_r3nib17;
+ uint8_t vref_dq_r3nib18;
+ uint8_t vref_dq_r3nib19;
+ uint8_t f0rc00_d0;
+ uint8_t f0rc01_d0;
+ uint8_t f0rc02_d0;
+ uint8_t f0rc03_d0;
+ uint8_t f0rc04_d0;
+ uint8_t f0rc05_d0;
+ uint8_t f0rc06_d0;
+ uint8_t f0rc07_d0;
+ uint8_t f0rc08_d0;
+ uint8_t f0rc09_d0;
+ uint8_t f0rc0a_d0;
+ uint8_t f0rc0b_d0;
+ uint8_t f0rc0c_d0;
+ uint8_t f0rc0d_d0;
+ uint8_t f0rc0e_d0;
+ uint8_t f0rc0f_d0;
+ uint8_t f0rc1x_d0;
+ uint8_t f0rc2x_d0;
+ uint8_t f0rc3x_d0;
+ uint8_t f0rc4x_d0;
+ uint8_t f0rc5x_d0;
+ uint8_t f0rc6x_d0;
+ uint8_t f0rc7x_d0;
+ uint8_t f0rc8x_d0;
+ uint8_t f0rc9x_d0;
+ uint8_t f0rcax_d0;
+ uint8_t f0rcbx_d0;
+ uint8_t f1rc00_d0;
+ uint8_t f1rc01_d0;
+ uint8_t f1rc02_d0;
+ uint8_t f1rc03_d0;
+ uint8_t f1rc04_d0;
+ uint8_t f1rc05_d0;
+ uint8_t f1rc06_d0;
+ uint8_t f1rc07_d0;
+ uint8_t f1rc08_d0;
+ uint8_t f1rc09_d0;
+ uint8_t f1rc0a_d0;
+ uint8_t f1rc0b_d0;
+ uint8_t f1rc0c_d0;
+ uint8_t f1rc0d_d0;
+ uint8_t f1rc0e_d0;
+ uint8_t f1rc0f_d0;
+ uint8_t f1rc1x_d0;
+ uint8_t f1rc2x_d0;
+ uint8_t f1rc3x_d0;
+ uint8_t f1rc4x_d0;
+ uint8_t f1rc5x_d0;
+ uint8_t f1rc6x_d0;
+ uint8_t f1rc7x_d0;
+ uint8_t f1rc8x_d0;
+ uint8_t f1rc9x_d0;
+ uint8_t f1rcax_d0;
+ uint8_t f1rcbx_d0;
+ uint8_t f0rc00_d1;
+ uint8_t f0rc01_d1;
+ uint8_t f0rc02_d1;
+ uint8_t f0rc03_d1;
+ uint8_t f0rc04_d1;
+ uint8_t f0rc05_d1;
+ uint8_t f0rc06_d1;
+ uint8_t f0rc07_d1;
+ uint8_t f0rc08_d1;
+ uint8_t f0rc09_d1;
+ uint8_t f0rc0a_d1;
+ uint8_t f0rc0b_d1;
+ uint8_t f0rc0c_d1;
+ uint8_t f0rc0d_d1;
+ uint8_t f0rc0e_d1;
+ uint8_t f0rc0f_d1;
+ uint8_t f0rc1x_d1;
+ uint8_t f0rc2x_d1;
+ uint8_t f0rc3x_d1;
+ uint8_t f0rc4x_d1;
+ uint8_t f0rc5x_d1;
+ uint8_t f0rc6x_d1;
+ uint8_t f0rc7x_d1;
+ uint8_t f0rc8x_d1;
+ uint8_t f0rc9x_d1;
+ uint8_t f0rcax_d1;
+ uint8_t f0rcbx_d1;
+ uint8_t f1rc00_d1;
+ uint8_t f1rc01_d1;
+ uint8_t f1rc02_d1;
+ uint8_t f1rc03_d1;
+ uint8_t f1rc04_d1;
+ uint8_t f1rc05_d1;
+ uint8_t f1rc06_d1;
+ uint8_t f1rc07_d1;
+ uint8_t f1rc08_d1;
+ uint8_t f1rc09_d1;
+ uint8_t f1rc0a_d1;
+ uint8_t f1rc0b_d1;
+ uint8_t f1rc0c_d1;
+ uint8_t f1rc0d_d1;
+ uint8_t f1rc0e_d1;
+ uint8_t f1rc0f_d1;
+ uint8_t f1rc1x_d1;
+ uint8_t f1rc2x_d1;
+ uint8_t f1rc3x_d1;
+ uint8_t f1rc4x_d1;
+ uint8_t f1rc5x_d1;
+ uint8_t f1rc6x_d1;
+ uint8_t f1rc7x_d1;
+ uint8_t f1rc8x_d1;
+ uint8_t f1rc9x_d1;
+ uint8_t f1rcax_d1;
+ uint8_t f1rcbx_d1;
+ uint8_t bc00_d0;
+ uint8_t bc01_d0;
+ uint8_t bc02_d0;
+ uint8_t bc03_d0;
+ uint8_t bc04_d0;
+ uint8_t bc05_d0;
+ uint8_t bc06_d0;
+ uint8_t bc07_d0;
+ uint8_t bc08_d0;
+ uint8_t bc09_d0;
+ uint8_t bc0a_d0;
+ uint8_t bc0b_d0;
+ uint8_t bc0c_d0;
+ uint8_t bc0d_d0;
+ uint8_t bc0e_d0;
+ uint8_t f0bc6x_d0;
+ uint8_t f0bccx_d0;
+ uint8_t f0bcdx_d0;
+ uint8_t f0bcex_d0;
+ uint8_t f0bcfx_d0;
+ uint8_t f1bccx_d0;
+ uint8_t f1bcdx_d0;
+ uint8_t f1bcex_d0;
+ uint8_t f1bcfx_d0;
+ uint8_t f0bc2x_b0_d0;
+ uint8_t f0bc3x_b0_d0;
+ uint8_t f0bc4x_b0_d0;
+ uint8_t f0bc5x_b0_d0;
+ uint8_t f0bc8x_b0_d0;
+ uint8_t f0bc9x_b0_d0;
+ uint8_t f0bcax_b0_d0;
+ uint8_t f0bcbx_b0_d0;
+ uint8_t f1bc2x_b0_d0;
+ uint8_t f1bc3x_b0_d0;
+ uint8_t f1bc4x_b0_d0;
+ uint8_t f1bc5x_b0_d0;
+ uint8_t f1bc8x_b0_d0;
+ uint8_t f1bc9x_b0_d0;
+ uint8_t f1bcax_b0_d0;
+ uint8_t f1bcbx_b0_d0;
+ uint8_t f2bc2x_b0_d0;
+ uint8_t f2bc3x_b0_d0;
+ uint8_t f2bc4x_b0_d0;
+ uint8_t f2bc5x_b0_d0;
+ uint8_t f2bc8x_b0_d0;
+ uint8_t f2bc9x_b0_d0;
+ uint8_t f2bcax_b0_d0;
+ uint8_t f2bcbx_b0_d0;
+ uint8_t f3bc2x_b0_d0;
+ uint8_t f3bc3x_b0_d0;
+ uint8_t f3bc4x_b0_d0;
+ uint8_t f3bc5x_b0_d0;
+ uint8_t f3bc8x_b0_d0;
+ uint8_t f3bc9x_b0_d0;
+ uint8_t f3bcax_b0_d0;
+ uint8_t f3bcbx_b0_d0;
+ uint8_t f0bc2x_b1_d0;
+ uint8_t f0bc3x_b1_d0;
+ uint8_t f0bc4x_b1_d0;
+ uint8_t f0bc5x_b1_d0;
+ uint8_t f0bc8x_b1_d0;
+ uint8_t f0bc9x_b1_d0;
+ uint8_t f0bcax_b1_d0;
+ uint8_t f0bcbx_b1_d0;
+ uint8_t f1bc2x_b1_d0;
+ uint8_t f1bc3x_b1_d0;
+ uint8_t f1bc4x_b1_d0;
+ uint8_t f1bc5x_b1_d0;
+ uint8_t f1bc8x_b1_d0;
+ uint8_t f1bc9x_b1_d0;
+ uint8_t f1bcax_b1_d0;
+ uint8_t f1bcbx_b1_d0;
+ uint8_t f2bc2x_b1_d0;
+ uint8_t f2bc3x_b1_d0;
+ uint8_t f2bc4x_b1_d0;
+ uint8_t f2bc5x_b1_d0;
+ uint8_t f2bc8x_b1_d0;
+ uint8_t f2bc9x_b1_d0;
+ uint8_t f2bcax_b1_d0;
+ uint8_t f2bcbx_b1_d0;
+ uint8_t f3bc2x_b1_d0;
+ uint8_t f3bc3x_b1_d0;
+ uint8_t f3bc4x_b1_d0;
+ uint8_t f3bc5x_b1_d0;
+ uint8_t f3bc8x_b1_d0;
+ uint8_t f3bc9x_b1_d0;
+ uint8_t f3bcax_b1_d0;
+ uint8_t f3bcbx_b1_d0;
+ uint8_t f0bc2x_b2_d0;
+ uint8_t f0bc3x_b2_d0;
+ uint8_t f0bc4x_b2_d0;
+ uint8_t f0bc5x_b2_d0;
+ uint8_t f0bc8x_b2_d0;
+ uint8_t f0bc9x_b2_d0;
+ uint8_t f0bcax_b2_d0;
+ uint8_t f0bcbx_b2_d0;
+ uint8_t f1bc2x_b2_d0;
+ uint8_t f1bc3x_b2_d0;
+ uint8_t f1bc4x_b2_d0;
+ uint8_t f1bc5x_b2_d0;
+ uint8_t f1bc8x_b2_d0;
+ uint8_t f1bc9x_b2_d0;
+ uint8_t f1bcax_b2_d0;
+ uint8_t f1bcbx_b2_d0;
+ uint8_t f2bc2x_b2_d0;
+ uint8_t f2bc3x_b2_d0;
+ uint8_t f2bc4x_b2_d0;
+ uint8_t f2bc5x_b2_d0;
+ uint8_t f2bc8x_b2_d0;
+ uint8_t f2bc9x_b2_d0;
+ uint8_t f2bcax_b2_d0;
+ uint8_t f2bcbx_b2_d0;
+ uint8_t f3bc2x_b2_d0;
+ uint8_t f3bc3x_b2_d0;
+ uint8_t f3bc4x_b2_d0;
+ uint8_t f3bc5x_b2_d0;
+ uint8_t f3bc8x_b2_d0;
+ uint8_t f3bc9x_b2_d0;
+ uint8_t f3bcax_b2_d0;
+ uint8_t f3bcbx_b2_d0;
+ uint8_t f0bc2x_b3_d0;
+ uint8_t f0bc3x_b3_d0;
+ uint8_t f0bc4x_b3_d0;
+ uint8_t f0bc5x_b3_d0;
+ uint8_t f0bc8x_b3_d0;
+ uint8_t f0bc9x_b3_d0;
+ uint8_t f0bcax_b3_d0;
+ uint8_t f0bcbx_b3_d0;
+ uint8_t f1bc2x_b3_d0;
+ uint8_t f1bc3x_b3_d0;
+ uint8_t f1bc4x_b3_d0;
+ uint8_t f1bc5x_b3_d0;
+ uint8_t f1bc8x_b3_d0;
+ uint8_t f1bc9x_b3_d0;
+ uint8_t f1bcax_b3_d0;
+ uint8_t f1bcbx_b3_d0;
+ uint8_t f2bc2x_b3_d0;
+ uint8_t f2bc3x_b3_d0;
+ uint8_t f2bc4x_b3_d0;
+ uint8_t f2bc5x_b3_d0;
+ uint8_t f2bc8x_b3_d0;
+ uint8_t f2bc9x_b3_d0;
+ uint8_t f2bcax_b3_d0;
+ uint8_t f2bcbx_b3_d0;
+ uint8_t f3bc2x_b3_d0;
+ uint8_t f3bc3x_b3_d0;
+ uint8_t f3bc4x_b3_d0;
+ uint8_t f3bc5x_b3_d0;
+ uint8_t f3bc8x_b3_d0;
+ uint8_t f3bc9x_b3_d0;
+ uint8_t f3bcax_b3_d0;
+ uint8_t f3bcbx_b3_d0;
+ uint8_t f0bc2x_b4_d0;
+ uint8_t f0bc3x_b4_d0;
+ uint8_t f0bc4x_b4_d0;
+ uint8_t f0bc5x_b4_d0;
+ uint8_t f0bc8x_b4_d0;
+ uint8_t f0bc9x_b4_d0;
+ uint8_t f0bcax_b4_d0;
+ uint8_t f0bcbx_b4_d0;
+ uint8_t f1bc2x_b4_d0;
+ uint8_t f1bc3x_b4_d0;
+ uint8_t f1bc4x_b4_d0;
+ uint8_t f1bc5x_b4_d0;
+ uint8_t f1bc8x_b4_d0;
+ uint8_t f1bc9x_b4_d0;
+ uint8_t f1bcax_b4_d0;
+ uint8_t f1bcbx_b4_d0;
+ uint8_t f2bc2x_b4_d0;
+ uint8_t f2bc3x_b4_d0;
+ uint8_t f2bc4x_b4_d0;
+ uint8_t f2bc5x_b4_d0;
+ uint8_t f2bc8x_b4_d0;
+ uint8_t f2bc9x_b4_d0;
+ uint8_t f2bcax_b4_d0;
+ uint8_t f2bcbx_b4_d0;
+ uint8_t f3bc2x_b4_d0;
+ uint8_t f3bc3x_b4_d0;
+ uint8_t f3bc4x_b4_d0;
+ uint8_t f3bc5x_b4_d0;
+ uint8_t f3bc8x_b4_d0;
+ uint8_t f3bc9x_b4_d0;
+ uint8_t f3bcax_b4_d0;
+ uint8_t f3bcbx_b4_d0;
+ uint8_t f0bc2x_b5_d0;
+ uint8_t f0bc3x_b5_d0;
+ uint8_t f0bc4x_b5_d0;
+ uint8_t f0bc5x_b5_d0;
+ uint8_t f0bc8x_b5_d0;
+ uint8_t f0bc9x_b5_d0;
+ uint8_t f0bcax_b5_d0;
+ uint8_t f0bcbx_b5_d0;
+ uint8_t f1bc2x_b5_d0;
+ uint8_t f1bc3x_b5_d0;
+ uint8_t f1bc4x_b5_d0;
+ uint8_t f1bc5x_b5_d0;
+ uint8_t f1bc8x_b5_d0;
+ uint8_t f1bc9x_b5_d0;
+ uint8_t f1bcax_b5_d0;
+ uint8_t f1bcbx_b5_d0;
+ uint8_t f2bc2x_b5_d0;
+ uint8_t f2bc3x_b5_d0;
+ uint8_t f2bc4x_b5_d0;
+ uint8_t f2bc5x_b5_d0;
+ uint8_t f2bc8x_b5_d0;
+ uint8_t f2bc9x_b5_d0;
+ uint8_t f2bcax_b5_d0;
+ uint8_t f2bcbx_b5_d0;
+ uint8_t f3bc2x_b5_d0;
+ uint8_t f3bc3x_b5_d0;
+ uint8_t f3bc4x_b5_d0;
+ uint8_t f3bc5x_b5_d0;
+ uint8_t f3bc8x_b5_d0;
+ uint8_t f3bc9x_b5_d0;
+ uint8_t f3bcax_b5_d0;
+ uint8_t f3bcbx_b5_d0;
+ uint8_t f0bc2x_b6_d0;
+ uint8_t f0bc3x_b6_d0;
+ uint8_t f0bc4x_b6_d0;
+ uint8_t f0bc5x_b6_d0;
+ uint8_t f0bc8x_b6_d0;
+ uint8_t f0bc9x_b6_d0;
+ uint8_t f0bcax_b6_d0;
+ uint8_t f0bcbx_b6_d0;
+ uint8_t f1bc2x_b6_d0;
+ uint8_t f1bc3x_b6_d0;
+ uint8_t f1bc4x_b6_d0;
+ uint8_t f1bc5x_b6_d0;
+ uint8_t f1bc8x_b6_d0;
+ uint8_t f1bc9x_b6_d0;
+ uint8_t f1bcax_b6_d0;
+ uint8_t f1bcbx_b6_d0;
+ uint8_t f2bc2x_b6_d0;
+ uint8_t f2bc3x_b6_d0;
+ uint8_t f2bc4x_b6_d0;
+ uint8_t f2bc5x_b6_d0;
+ uint8_t f2bc8x_b6_d0;
+ uint8_t f2bc9x_b6_d0;
+ uint8_t f2bcax_b6_d0;
+ uint8_t f2bcbx_b6_d0;
+ uint8_t f3bc2x_b6_d0;
+ uint8_t f3bc3x_b6_d0;
+ uint8_t f3bc4x_b6_d0;
+ uint8_t f3bc5x_b6_d0;
+ uint8_t f3bc8x_b6_d0;
+ uint8_t f3bc9x_b6_d0;
+ uint8_t f3bcax_b6_d0;
+ uint8_t f3bcbx_b6_d0;
+ uint8_t f0bc2x_b7_d0;
+ uint8_t f0bc3x_b7_d0;
+ uint8_t f0bc4x_b7_d0;
+ uint8_t f0bc5x_b7_d0;
+ uint8_t f0bc8x_b7_d0;
+ uint8_t f0bc9x_b7_d0;
+ uint8_t f0bcax_b7_d0;
+ uint8_t f0bcbx_b7_d0;
+ uint8_t f1bc2x_b7_d0;
+ uint8_t f1bc3x_b7_d0;
+ uint8_t f1bc4x_b7_d0;
+ uint8_t f1bc5x_b7_d0;
+ uint8_t f1bc8x_b7_d0;
+ uint8_t f1bc9x_b7_d0;
+ uint8_t f1bcax_b7_d0;
+ uint8_t f1bcbx_b7_d0;
+ uint8_t f2bc2x_b7_d0;
+ uint8_t f2bc3x_b7_d0;
+ uint8_t f2bc4x_b7_d0;
+ uint8_t f2bc5x_b7_d0;
+ uint8_t f2bc8x_b7_d0;
+ uint8_t f2bc9x_b7_d0;
+ uint8_t f2bcax_b7_d0;
+ uint8_t f2bcbx_b7_d0;
+ uint8_t f3bc2x_b7_d0;
+ uint8_t f3bc3x_b7_d0;
+ uint8_t f3bc4x_b7_d0;
+ uint8_t f3bc5x_b7_d0;
+ uint8_t f3bc8x_b7_d0;
+ uint8_t f3bc9x_b7_d0;
+ uint8_t f3bcax_b7_d0;
+ uint8_t f3bcbx_b7_d0;
+ uint8_t f0bc2x_b8_d0;
+ uint8_t f0bc3x_b8_d0;
+ uint8_t f0bc4x_b8_d0;
+ uint8_t f0bc5x_b8_d0;
+ uint8_t f0bc8x_b8_d0;
+ uint8_t f0bc9x_b8_d0;
+ uint8_t f0bcax_b8_d0;
+ uint8_t f0bcbx_b8_d0;
+ uint8_t f1bc2x_b8_d0;
+ uint8_t f1bc3x_b8_d0;
+ uint8_t f1bc4x_b8_d0;
+ uint8_t f1bc5x_b8_d0;
+ uint8_t f1bc8x_b8_d0;
+ uint8_t f1bc9x_b8_d0;
+ uint8_t f1bcax_b8_d0;
+ uint8_t f1bcbx_b8_d0;
+ uint8_t f2bc2x_b8_d0;
+ uint8_t f2bc3x_b8_d0;
+ uint8_t f2bc4x_b8_d0;
+ uint8_t f2bc5x_b8_d0;
+ uint8_t f2bc8x_b8_d0;
+ uint8_t f2bc9x_b8_d0;
+ uint8_t f2bcax_b8_d0;
+ uint8_t f2bcbx_b8_d0;
+ uint8_t f3bc2x_b8_d0;
+ uint8_t f3bc3x_b8_d0;
+ uint8_t f3bc4x_b8_d0;
+ uint8_t f3bc5x_b8_d0;
+ uint8_t f3bc8x_b8_d0;
+ uint8_t f3bc9x_b8_d0;
+ uint8_t f3bcax_b8_d0;
+ uint8_t f3bcbx_b8_d0;
+ uint8_t f5bc5x_d0;
+ uint8_t f5bc6x_d0;
+ uint8_t f4bc8x_d0;
+ uint8_t f4bc9x_d0;
+ uint8_t f4bcax_d0;
+ uint8_t f4bcbx_d0;
+ uint8_t f4bccx_d0;
+ uint8_t f4bcdx_d0;
+ uint8_t f4bcex_d0;
+ uint8_t f4bcfx_d0;
+ uint8_t f5bc8x_d0;
+ uint8_t f5bc9x_d0;
+ uint8_t f5bcax_d0;
+ uint8_t f5bcbx_d0;
+ uint8_t f5bccx_d0;
+ uint8_t f5bcdx_d0;
+ uint8_t f5bcex_d0;
+ uint8_t f5bcfx_d0;
+ uint8_t f6bc8x_d0;
+ uint8_t f6bc9x_d0;
+ uint8_t f6bcax_d0;
+ uint8_t f6bcbx_d0;
+ uint8_t f6bccx_d0;
+ uint8_t f6bcdx_d0;
+ uint8_t f6bcex_d0;
+ uint8_t f6bcfx_d0;
+ uint8_t f7bc8x_d0;
+ uint8_t f7bc9x_d0;
+ uint8_t f7bcax_d0;
+ uint8_t f7bcbx_d0;
+ uint8_t f7bccx_d0;
+ uint8_t f7bcdx_d0;
+ uint8_t f7bcex_d0;
+ uint8_t f7bcfx_d0;
+ uint8_t bc00_d1;
+ uint8_t bc01_d1;
+ uint8_t bc02_d1;
+ uint8_t bc03_d1;
+ uint8_t bc04_d1;
+ uint8_t bc05_d1;
+ uint8_t bc06_d1;
+ uint8_t bc07_d1;
+ uint8_t bc08_d1;
+ uint8_t bc09_d1;
+ uint8_t bc0a_d1;
+ uint8_t bc0b_d1;
+ uint8_t bc0c_d1;
+ uint8_t bc0d_d1;
+ uint8_t bc0e_d1;
+ uint8_t f0bc6x_d1;
+ uint8_t f0bccx_d1;
+ uint8_t f0bcdx_d1;
+ uint8_t f0bcex_d1;
+ uint8_t f0bcfx_d1;
+ uint8_t f1bccx_d1;
+ uint8_t f1bcdx_d1;
+ uint8_t f1bcex_d1;
+ uint8_t f1bcfx_d1;
+ uint8_t f0bc2x_b0_d1;
+ uint8_t f0bc3x_b0_d1;
+ uint8_t f0bc4x_b0_d1;
+ uint8_t f0bc5x_b0_d1;
+ uint8_t f0bc8x_b0_d1;
+ uint8_t f0bc9x_b0_d1;
+ uint8_t f0bcax_b0_d1;
+ uint8_t f0bcbx_b0_d1;
+ uint8_t f1bc2x_b0_d1;
+ uint8_t f1bc3x_b0_d1;
+ uint8_t f1bc4x_b0_d1;
+ uint8_t f1bc5x_b0_d1;
+ uint8_t f1bc8x_b0_d1;
+ uint8_t f1bc9x_b0_d1;
+ uint8_t f1bcax_b0_d1;
+ uint8_t f1bcbx_b0_d1;
+ uint8_t f2bc2x_b0_d1;
+ uint8_t f2bc3x_b0_d1;
+ uint8_t f2bc4x_b0_d1;
+ uint8_t f2bc5x_b0_d1;
+ uint8_t f2bc8x_b0_d1;
+ uint8_t f2bc9x_b0_d1;
+ uint8_t f2bcax_b0_d1;
+ uint8_t f2bcbx_b0_d1;
+ uint8_t f3bc2x_b0_d1;
+ uint8_t f3bc3x_b0_d1;
+ uint8_t f3bc4x_b0_d1;
+ uint8_t f3bc5x_b0_d1;
+ uint8_t f3bc8x_b0_d1;
+ uint8_t f3bc9x_b0_d1;
+ uint8_t f3bcax_b0_d1;
+ uint8_t f3bcbx_b0_d1;
+ uint8_t f0bc2x_b1_d1;
+ uint8_t f0bc3x_b1_d1;
+ uint8_t f0bc4x_b1_d1;
+ uint8_t f0bc5x_b1_d1;
+ uint8_t f0bc8x_b1_d1;
+ uint8_t f0bc9x_b1_d1;
+ uint8_t f0bcax_b1_d1;
+ uint8_t f0bcbx_b1_d1;
+ uint8_t f1bc2x_b1_d1;
+ uint8_t f1bc3x_b1_d1;
+ uint8_t f1bc4x_b1_d1;
+ uint8_t f1bc5x_b1_d1;
+ uint8_t f1bc8x_b1_d1;
+ uint8_t f1bc9x_b1_d1;
+ uint8_t f1bcax_b1_d1;
+ uint8_t f1bcbx_b1_d1;
+ uint8_t f2bc2x_b1_d1;
+ uint8_t f2bc3x_b1_d1;
+ uint8_t f2bc4x_b1_d1;
+ uint8_t f2bc5x_b1_d1;
+ uint8_t f2bc8x_b1_d1;
+ uint8_t f2bc9x_b1_d1;
+ uint8_t f2bcax_b1_d1;
+ uint8_t f2bcbx_b1_d1;
+ uint8_t f3bc2x_b1_d1;
+ uint8_t f3bc3x_b1_d1;
+ uint8_t f3bc4x_b1_d1;
+ uint8_t f3bc5x_b1_d1;
+ uint8_t f3bc8x_b1_d1;
+ uint8_t f3bc9x_b1_d1;
+ uint8_t f3bcax_b1_d1;
+ uint8_t f3bcbx_b1_d1;
+ uint8_t f0bc2x_b2_d1;
+ uint8_t f0bc3x_b2_d1;
+ uint8_t f0bc4x_b2_d1;
+ uint8_t f0bc5x_b2_d1;
+ uint8_t f0bc8x_b2_d1;
+ uint8_t f0bc9x_b2_d1;
+ uint8_t f0bcax_b2_d1;
+ uint8_t f0bcbx_b2_d1;
+ uint8_t f1bc2x_b2_d1;
+ uint8_t f1bc3x_b2_d1;
+ uint8_t f1bc4x_b2_d1;
+ uint8_t f1bc5x_b2_d1;
+ uint8_t f1bc8x_b2_d1;
+ uint8_t f1bc9x_b2_d1;
+ uint8_t f1bcax_b2_d1;
+ uint8_t f1bcbx_b2_d1;
+ uint8_t f2bc2x_b2_d1;
+ uint8_t f2bc3x_b2_d1;
+ uint8_t f2bc4x_b2_d1;
+ uint8_t f2bc5x_b2_d1;
+ uint8_t f2bc8x_b2_d1;
+ uint8_t f2bc9x_b2_d1;
+ uint8_t f2bcax_b2_d1;
+ uint8_t f2bcbx_b2_d1;
+ uint8_t f3bc2x_b2_d1;
+ uint8_t f3bc3x_b2_d1;
+ uint8_t f3bc4x_b2_d1;
+ uint8_t f3bc5x_b2_d1;
+ uint8_t f3bc8x_b2_d1;
+ uint8_t f3bc9x_b2_d1;
+ uint8_t f3bcax_b2_d1;
+ uint8_t f3bcbx_b2_d1;
+ uint8_t f0bc2x_b3_d1;
+ uint8_t f0bc3x_b3_d1;
+ uint8_t f0bc4x_b3_d1;
+ uint8_t f0bc5x_b3_d1;
+ uint8_t f0bc8x_b3_d1;
+ uint8_t f0bc9x_b3_d1;
+ uint8_t f0bcax_b3_d1;
+ uint8_t f0bcbx_b3_d1;
+ uint8_t f1bc2x_b3_d1;
+ uint8_t f1bc3x_b3_d1;
+ uint8_t f1bc4x_b3_d1;
+ uint8_t f1bc5x_b3_d1;
+ uint8_t f1bc8x_b3_d1;
+ uint8_t f1bc9x_b3_d1;
+ uint8_t f1bcax_b3_d1;
+ uint8_t f1bcbx_b3_d1;
+ uint8_t f2bc2x_b3_d1;
+ uint8_t f2bc3x_b3_d1;
+ uint8_t f2bc4x_b3_d1;
+ uint8_t f2bc5x_b3_d1;
+ uint8_t f2bc8x_b3_d1;
+ uint8_t f2bc9x_b3_d1;
+ uint8_t f2bcax_b3_d1;
+ uint8_t f2bcbx_b3_d1;
+ uint8_t f3bc2x_b3_d1;
+ uint8_t f3bc3x_b3_d1;
+ uint8_t f3bc4x_b3_d1;
+ uint8_t f3bc5x_b3_d1;
+ uint8_t f3bc8x_b3_d1;
+ uint8_t f3bc9x_b3_d1;
+ uint8_t f3bcax_b3_d1;
+ uint8_t f3bcbx_b3_d1;
+ uint8_t f0bc2x_b4_d1;
+ uint8_t f0bc3x_b4_d1;
+ uint8_t f0bc4x_b4_d1;
+ uint8_t f0bc5x_b4_d1;
+ uint8_t f0bc8x_b4_d1;
+ uint8_t f0bc9x_b4_d1;
+ uint8_t f0bcax_b4_d1;
+ uint8_t f0bcbx_b4_d1;
+ uint8_t f1bc2x_b4_d1;
+ uint8_t f1bc3x_b4_d1;
+ uint8_t f1bc4x_b4_d1;
+ uint8_t f1bc5x_b4_d1;
+ uint8_t f1bc8x_b4_d1;
+ uint8_t f1bc9x_b4_d1;
+ uint8_t f1bcax_b4_d1;
+ uint8_t f1bcbx_b4_d1;
+ uint8_t f2bc2x_b4_d1;
+ uint8_t f2bc3x_b4_d1;
+ uint8_t f2bc4x_b4_d1;
+ uint8_t f2bc5x_b4_d1;
+ uint8_t f2bc8x_b4_d1;
+ uint8_t f2bc9x_b4_d1;
+ uint8_t f2bcax_b4_d1;
+ uint8_t f2bcbx_b4_d1;
+ uint8_t f3bc2x_b4_d1;
+ uint8_t f3bc3x_b4_d1;
+ uint8_t f3bc4x_b4_d1;
+ uint8_t f3bc5x_b4_d1;
+ uint8_t f3bc8x_b4_d1;
+ uint8_t f3bc9x_b4_d1;
+ uint8_t f3bcax_b4_d1;
+ uint8_t f3bcbx_b4_d1;
+ uint8_t f0bc2x_b5_d1;
+ uint8_t f0bc3x_b5_d1;
+ uint8_t f0bc4x_b5_d1;
+ uint8_t f0bc5x_b5_d1;
+ uint8_t f0bc8x_b5_d1;
+ uint8_t f0bc9x_b5_d1;
+ uint8_t f0bcax_b5_d1;
+ uint8_t f0bcbx_b5_d1;
+ uint8_t f1bc2x_b5_d1;
+ uint8_t f1bc3x_b5_d1;
+ uint8_t f1bc4x_b5_d1;
+ uint8_t f1bc5x_b5_d1;
+ uint8_t f1bc8x_b5_d1;
+ uint8_t f1bc9x_b5_d1;
+ uint8_t f1bcax_b5_d1;
+ uint8_t f1bcbx_b5_d1;
+ uint8_t f2bc2x_b5_d1;
+ uint8_t f2bc3x_b5_d1;
+ uint8_t f2bc4x_b5_d1;
+ uint8_t f2bc5x_b5_d1;
+ uint8_t f2bc8x_b5_d1;
+ uint8_t f2bc9x_b5_d1;
+ uint8_t f2bcax_b5_d1;
+ uint8_t f2bcbx_b5_d1;
+ uint8_t f3bc2x_b5_d1;
+ uint8_t f3bc3x_b5_d1;
+ uint8_t f3bc4x_b5_d1;
+ uint8_t f3bc5x_b5_d1;
+ uint8_t f3bc8x_b5_d1;
+ uint8_t f3bc9x_b5_d1;
+ uint8_t f3bcax_b5_d1;
+ uint8_t f3bcbx_b5_d1;
+ uint8_t f0bc2x_b6_d1;
+ uint8_t f0bc3x_b6_d1;
+ uint8_t f0bc4x_b6_d1;
+ uint8_t f0bc5x_b6_d1;
+ uint8_t f0bc8x_b6_d1;
+ uint8_t f0bc9x_b6_d1;
+ uint8_t f0bcax_b6_d1;
+ uint8_t f0bcbx_b6_d1;
+ uint8_t f1bc2x_b6_d1;
+ uint8_t f1bc3x_b6_d1;
+ uint8_t f1bc4x_b6_d1;
+ uint8_t f1bc5x_b6_d1;
+ uint8_t f1bc8x_b6_d1;
+ uint8_t f1bc9x_b6_d1;
+ uint8_t f1bcax_b6_d1;
+ uint8_t f1bcbx_b6_d1;
+ uint8_t f2bc2x_b6_d1;
+ uint8_t f2bc3x_b6_d1;
+ uint8_t f2bc4x_b6_d1;
+ uint8_t f2bc5x_b6_d1;
+ uint8_t f2bc8x_b6_d1;
+ uint8_t f2bc9x_b6_d1;
+ uint8_t f2bcax_b6_d1;
+ uint8_t f2bcbx_b6_d1;
+ uint8_t f3bc2x_b6_d1;
+ uint8_t f3bc3x_b6_d1;
+ uint8_t f3bc4x_b6_d1;
+ uint8_t f3bc5x_b6_d1;
+ uint8_t f3bc8x_b6_d1;
+ uint8_t f3bc9x_b6_d1;
+ uint8_t f3bcax_b6_d1;
+ uint8_t f3bcbx_b6_d1;
+ uint8_t f0bc2x_b7_d1;
+ uint8_t f0bc3x_b7_d1;
+ uint8_t f0bc4x_b7_d1;
+ uint8_t f0bc5x_b7_d1;
+ uint8_t f0bc8x_b7_d1;
+ uint8_t f0bc9x_b7_d1;
+ uint8_t f0bcax_b7_d1;
+ uint8_t f0bcbx_b7_d1;
+ uint8_t f1bc2x_b7_d1;
+ uint8_t f1bc3x_b7_d1;
+ uint8_t f1bc4x_b7_d1;
+ uint8_t f1bc5x_b7_d1;
+ uint8_t f1bc8x_b7_d1;
+ uint8_t f1bc9x_b7_d1;
+ uint8_t f1bcax_b7_d1;
+ uint8_t f1bcbx_b7_d1;
+ uint8_t f2bc2x_b7_d1;
+ uint8_t f2bc3x_b7_d1;
+ uint8_t f2bc4x_b7_d1;
+ uint8_t f2bc5x_b7_d1;
+ uint8_t f2bc8x_b7_d1;
+ uint8_t f2bc9x_b7_d1;
+ uint8_t f2bcax_b7_d1;
+ uint8_t f2bcbx_b7_d1;
+ uint8_t f3bc2x_b7_d1;
+ uint8_t f3bc3x_b7_d1;
+ uint8_t f3bc4x_b7_d1;
+ uint8_t f3bc5x_b7_d1;
+ uint8_t f3bc8x_b7_d1;
+ uint8_t f3bc9x_b7_d1;
+ uint8_t f3bcax_b7_d1;
+ uint8_t f3bcbx_b7_d1;
+ uint8_t f0bc2x_b8_d1;
+ uint8_t f0bc3x_b8_d1;
+ uint8_t f0bc4x_b8_d1;
+ uint8_t f0bc5x_b8_d1;
+ uint8_t f0bc8x_b8_d1;
+ uint8_t f0bc9x_b8_d1;
+ uint8_t f0bcax_b8_d1;
+ uint8_t f0bcbx_b8_d1;
+ uint8_t f1bc2x_b8_d1;
+ uint8_t f1bc3x_b8_d1;
+ uint8_t f1bc4x_b8_d1;
+ uint8_t f1bc5x_b8_d1;
+ uint8_t f1bc8x_b8_d1;
+ uint8_t f1bc9x_b8_d1;
+ uint8_t f1bcax_b8_d1;
+ uint8_t f1bcbx_b8_d1;
+ uint8_t f2bc2x_b8_d1;
+ uint8_t f2bc3x_b8_d1;
+ uint8_t f2bc4x_b8_d1;
+ uint8_t f2bc5x_b8_d1;
+ uint8_t f2bc8x_b8_d1;
+ uint8_t f2bc9x_b8_d1;
+ uint8_t f2bcax_b8_d1;
+ uint8_t f2bcbx_b8_d1;
+ uint8_t f3bc2x_b8_d1;
+ uint8_t f3bc3x_b8_d1;
+ uint8_t f3bc4x_b8_d1;
+ uint8_t f3bc5x_b8_d1;
+ uint8_t f3bc8x_b8_d1;
+ uint8_t f3bc9x_b8_d1;
+ uint8_t f3bcax_b8_d1;
+ uint8_t f3bcbx_b8_d1;
+ uint8_t f5bc5x_d1;
+ uint8_t f5bc6x_d1;
+ uint8_t f4bc8x_d1;
+ uint8_t f4bc9x_d1;
+ uint8_t f4bcax_d1;
+ uint8_t f4bcbx_d1;
+ uint8_t f4bccx_d1;
+ uint8_t f4bcdx_d1;
+ uint8_t f4bcex_d1;
+ uint8_t f4bcfx_d1;
+ uint8_t f5bc8x_d1;
+ uint8_t f5bc9x_d1;
+ uint8_t f5bcax_d1;
+ uint8_t f5bcbx_d1;
+ uint8_t f5bccx_d1;
+ uint8_t f5bcdx_d1;
+ uint8_t f5bcex_d1;
+ uint8_t f5bcfx_d1;
+ uint8_t f6bc8x_d1;
+ uint8_t f6bc9x_d1;
+ uint8_t f6bcax_d1;
+ uint8_t f6bcbx_d1;
+ uint8_t f6bccx_d1;
+ uint8_t f6bcdx_d1;
+ uint8_t f6bcex_d1;
+ uint8_t f6bcfx_d1;
+ uint8_t f7bc8x_d1;
+ uint8_t f7bc9x_d1;
+ uint8_t f7bcax_d1;
+ uint8_t f7bcbx_d1;
+ uint8_t f7bccx_d1;
+ uint8_t f7bcdx_d1;
+ uint8_t f7bcex_d1;
+ uint8_t f7bcfx_d1;
+ uint16_t alt_cas_l;
+ uint8_t alt_wcas_l;
+ uint8_t d4misc;
+} __packed;
+
+struct ddr4lr2d {
+ uint8_t reserved00;
+ uint8_t msg_misc;
+ uint16_t pmu_revision;
+ uint8_t pstate;
+ uint8_t pll_bypass_en;
+ uint16_t dramfreq;
+ uint8_t dfi_freq_ratio;
+ uint8_t bpznres_val;
+ uint8_t phy_odt_impedance;
+ uint8_t phy_drv_impedance;
+ uint8_t phy_vref;
+ uint8_t dram_type;
+ uint8_t disabled_dbyte;
+ uint8_t enabled_dqs;
+ uint8_t cs_present;
+ uint8_t cs_present_d0;
+ uint8_t cs_present_d1;
+ uint8_t addr_mirror;
+ uint8_t cs_test_fail;
+ uint8_t phy_cfg;
+ uint16_t sequence_ctrl;
+ uint8_t hdt_ctrl;
+ uint8_t rx2d_train_opt;
+ uint8_t tx2d_train_opt;
+ uint8_t share2dvref_result;
+ uint8_t delay_weight2d;
+ uint8_t voltage_weight2d;
+ uint8_t reserved1e[0x22 - 0x1e];
+ uint16_t phy_config_override;
+ uint8_t dfimrlmargin;
+ uint8_t r0_rx_clk_dly_margin;
+ uint8_t r0_vref_dac_margin;
+ uint8_t r0_tx_dq_dly_margin;
+ uint8_t r0_device_vref_margin;
+ uint8_t reserved29[0x33 - 0x29];
+ uint8_t r1_rx_clk_dly_margin;
+ uint8_t r1_vref_dac_margin;
+ uint8_t r1_tx_dq_dly_margin;
+ uint8_t r1_device_vref_margin;
+ uint8_t reserved37[0x41 - 0x37];
+ uint8_t r2_rx_clk_dly_margin;
+ uint8_t r2_vref_dac_margin;
+ uint8_t r2_tx_dq_dly_margin;
+ uint8_t r2_device_vref_margin;
+ uint8_t reserved45[0x4f - 0x45];
+ uint8_t r3_rx_clk_dly_margin;
+ uint8_t r3_vref_dac_margin;
+ uint8_t r3_tx_dq_dly_margin;
+ uint8_t r3_device_vref_margin;
+ uint8_t reserved53[0x5e - 0x53];
+ uint16_t mr0;
+ uint16_t mr1;
+ uint16_t mr2;
+ uint16_t mr3;
+ uint16_t mr4;
+ uint16_t mr5;
+ uint16_t mr6;
+ uint8_t x16present;
+ uint8_t cs_setup_gddec;
+ uint16_t rtt_nom_wr_park0;
+ uint16_t rtt_nom_wr_park1;
+ uint16_t rtt_nom_wr_park2;
+ uint16_t rtt_nom_wr_park3;
+ uint16_t rtt_nom_wr_park4;
+ uint16_t rtt_nom_wr_park5;
+ uint16_t rtt_nom_wr_park6;
+ uint16_t rtt_nom_wr_park7;
+ uint8_t acsm_odt_ctrl0;
+ uint8_t acsm_odt_ctrl1;
+ uint8_t acsm_odt_ctrl2;
+ uint8_t acsm_odt_ctrl3;
+ uint8_t acsm_odt_ctrl4;
+ uint8_t acsm_odt_ctrl5;
+ uint8_t acsm_odt_ctrl6;
+ uint8_t acsm_odt_ctrl7;
+ uint8_t vref_dq_r0nib0;
+ uint8_t vref_dq_r0nib1;
+ uint8_t vref_dq_r0nib2;
+ uint8_t vref_dq_r0nib3;
+ uint8_t vref_dq_r0nib4;
+ uint8_t vref_dq_r0nib5;
+ uint8_t vref_dq_r0nib6;
+ uint8_t vref_dq_r0nib7;
+ uint8_t vref_dq_r0nib8;
+ uint8_t vref_dq_r0nib9;
+ uint8_t vref_dq_r0nib10;
+ uint8_t vref_dq_r0nib11;
+ uint8_t vref_dq_r0nib12;
+ uint8_t vref_dq_r0nib13;
+ uint8_t vref_dq_r0nib14;
+ uint8_t vref_dq_r0nib15;
+ uint8_t vref_dq_r0nib16;
+ uint8_t vref_dq_r0nib17;
+ uint8_t vref_dq_r0nib18;
+ uint8_t vref_dq_r0nib19;
+ uint8_t vref_dq_r1nib0;
+ uint8_t vref_dq_r1nib1;
+ uint8_t vref_dq_r1nib2;
+ uint8_t vref_dq_r1nib3;
+ uint8_t vref_dq_r1nib4;
+ uint8_t vref_dq_r1nib5;
+ uint8_t vref_dq_r1nib6;
+ uint8_t vref_dq_r1nib7;
+ uint8_t vref_dq_r1nib8;
+ uint8_t vref_dq_r1nib9;
+ uint8_t vref_dq_r1nib10;
+ uint8_t vref_dq_r1nib11;
+ uint8_t vref_dq_r1nib12;
+ uint8_t vref_dq_r1nib13;
+ uint8_t vref_dq_r1nib14;
+ uint8_t vref_dq_r1nib15;
+ uint8_t vref_dq_r1nib16;
+ uint8_t vref_dq_r1nib17;
+ uint8_t vref_dq_r1nib18;
+ uint8_t vref_dq_r1nib19;
+ uint8_t vref_dq_r2nib0;
+ uint8_t vref_dq_r2nib1;
+ uint8_t vref_dq_r2nib2;
+ uint8_t vref_dq_r2nib3;
+ uint8_t vref_dq_r2nib4;
+ uint8_t vref_dq_r2nib5;
+ uint8_t vref_dq_r2nib6;
+ uint8_t vref_dq_r2nib7;
+ uint8_t vref_dq_r2nib8;
+ uint8_t vref_dq_r2nib9;
+ uint8_t vref_dq_r2nib10;
+ uint8_t vref_dq_r2nib11;
+ uint8_t vref_dq_r2nib12;
+ uint8_t vref_dq_r2nib13;
+ uint8_t vref_dq_r2nib14;
+ uint8_t vref_dq_r2nib15;
+ uint8_t vref_dq_r2nib16;
+ uint8_t vref_dq_r2nib17;
+ uint8_t vref_dq_r2nib18;
+ uint8_t vref_dq_r2nib19;
+ uint8_t vref_dq_r3nib0;
+ uint8_t vref_dq_r3nib1;
+ uint8_t vref_dq_r3nib2;
+ uint8_t vref_dq_r3nib3;
+ uint8_t vref_dq_r3nib4;
+ uint8_t vref_dq_r3nib5;
+ uint8_t vref_dq_r3nib6;
+ uint8_t vref_dq_r3nib7;
+ uint8_t vref_dq_r3nib8;
+ uint8_t vref_dq_r3nib9;
+ uint8_t vref_dq_r3nib10;
+ uint8_t vref_dq_r3nib11;
+ uint8_t vref_dq_r3nib12;
+ uint8_t vref_dq_r3nib13;
+ uint8_t vref_dq_r3nib14;
+ uint8_t vref_dq_r3nib15;
+ uint8_t vref_dq_r3nib16;
+ uint8_t vref_dq_r3nib17;
+ uint8_t vref_dq_r3nib18;
+ uint8_t vref_dq_r3nib19;
+ uint8_t f0rc00_d0;
+ uint8_t f0rc01_d0;
+ uint8_t f0rc02_d0;
+ uint8_t f0rc03_d0;
+ uint8_t f0rc04_d0;
+ uint8_t f0rc05_d0;
+ uint8_t f0rc06_d0;
+ uint8_t f0rc07_d0;
+ uint8_t f0rc08_d0;
+ uint8_t f0rc09_d0;
+ uint8_t f0rc0a_d0;
+ uint8_t f0rc0b_d0;
+ uint8_t f0rc0c_d0;
+ uint8_t f0rc0d_d0;
+ uint8_t f0rc0e_d0;
+ uint8_t f0rc0f_d0;
+ uint8_t f0rc1x_d0;
+ uint8_t f0rc2x_d0;
+ uint8_t f0rc3x_d0;
+ uint8_t f0rc4x_d0;
+ uint8_t f0rc5x_d0;
+ uint8_t f0rc6x_d0;
+ uint8_t f0rc7x_d0;
+ uint8_t f0rc8x_d0;
+ uint8_t f0rc9x_d0;
+ uint8_t f0rcax_d0;
+ uint8_t f0rcbx_d0;
+ uint8_t f1rc00_d0;
+ uint8_t f1rc01_d0;
+ uint8_t f1rc02_d0;
+ uint8_t f1rc03_d0;
+ uint8_t f1rc04_d0;
+ uint8_t f1rc05_d0;
+ uint8_t f1rc06_d0;
+ uint8_t f1rc07_d0;
+ uint8_t f1rc08_d0;
+ uint8_t f1rc09_d0;
+ uint8_t f1rc0a_d0;
+ uint8_t f1rc0b_d0;
+ uint8_t f1rc0c_d0;
+ uint8_t f1rc0d_d0;
+ uint8_t f1rc0e_d0;
+ uint8_t f1rc0f_d0;
+ uint8_t f1rc1x_d0;
+ uint8_t f1rc2x_d0;
+ uint8_t f1rc3x_d0;
+ uint8_t f1rc4x_d0;
+ uint8_t f1rc5x_d0;
+ uint8_t f1rc6x_d0;
+ uint8_t f1rc7x_d0;
+ uint8_t f1rc8x_d0;
+ uint8_t f1rc9x_d0;
+ uint8_t f1rcax_d0;
+ uint8_t f1rcbx_d0;
+ uint8_t f0rc00_d1;
+ uint8_t f0rc01_d1;
+ uint8_t f0rc02_d1;
+ uint8_t f0rc03_d1;
+ uint8_t f0rc04_d1;
+ uint8_t f0rc05_d1;
+ uint8_t f0rc06_d1;
+ uint8_t f0rc07_d1;
+ uint8_t f0rc08_d1;
+ uint8_t f0rc09_d1;
+ uint8_t f0rc0a_d1;
+ uint8_t f0rc0b_d1;
+ uint8_t f0rc0c_d1;
+ uint8_t f0rc0d_d1;
+ uint8_t f0rc0e_d1;
+ uint8_t f0rc0f_d1;
+ uint8_t f0rc1x_d1;
+ uint8_t f0rc2x_d1;
+ uint8_t f0rc3x_d1;
+ uint8_t f0rc4x_d1;
+ uint8_t f0rc5x_d1;
+ uint8_t f0rc6x_d1;
+ uint8_t f0rc7x_d1;
+ uint8_t f0rc8x_d1;
+ uint8_t f0rc9x_d1;
+ uint8_t f0rcax_d1;
+ uint8_t f0rcbx_d1;
+ uint8_t f1rc00_d1;
+ uint8_t f1rc01_d1;
+ uint8_t f1rc02_d1;
+ uint8_t f1rc03_d1;
+ uint8_t f1rc04_d1;
+ uint8_t f1rc05_d1;
+ uint8_t f1rc06_d1;
+ uint8_t f1rc07_d1;
+ uint8_t f1rc08_d1;
+ uint8_t f1rc09_d1;
+ uint8_t f1rc0a_d1;
+ uint8_t f1rc0b_d1;
+ uint8_t f1rc0c_d1;
+ uint8_t f1rc0d_d1;
+ uint8_t f1rc0e_d1;
+ uint8_t f1rc0f_d1;
+ uint8_t f1rc1x_d1;
+ uint8_t f1rc2x_d1;
+ uint8_t f1rc3x_d1;
+ uint8_t f1rc4x_d1;
+ uint8_t f1rc5x_d1;
+ uint8_t f1rc6x_d1;
+ uint8_t f1rc7x_d1;
+ uint8_t f1rc8x_d1;
+ uint8_t f1rc9x_d1;
+ uint8_t f1rcax_d1;
+ uint8_t f1rcbx_d1;
+ uint8_t bc00_d0;
+ uint8_t bc01_d0;
+ uint8_t bc02_d0;
+ uint8_t bc03_d0;
+ uint8_t bc04_d0;
+ uint8_t bc05_d0;
+ uint8_t bc06_d0;
+ uint8_t bc07_d0;
+ uint8_t bc08_d0;
+ uint8_t bc09_d0;
+ uint8_t bc0a_d0;
+ uint8_t bc0b_d0;
+ uint8_t bc0c_d0;
+ uint8_t bc0d_d0;
+ uint8_t bc0e_d0;
+ uint8_t f0bc6x_d0;
+ uint8_t f0bccx_d0;
+ uint8_t f0bcdx_d0;
+ uint8_t f0bcex_d0;
+ uint8_t f0bcfx_d0;
+ uint8_t f1bccx_d0;
+ uint8_t f1bcdx_d0;
+ uint8_t f1bcex_d0;
+ uint8_t f1bcfx_d0;
+ uint8_t f0bc2x_b0_d0;
+ uint8_t f0bc3x_b0_d0;
+ uint8_t f0bc4x_b0_d0;
+ uint8_t f0bc5x_b0_d0;
+ uint8_t f0bc8x_b0_d0;
+ uint8_t f0bc9x_b0_d0;
+ uint8_t f0bcax_b0_d0;
+ uint8_t f0bcbx_b0_d0;
+ uint8_t f1bc2x_b0_d0;
+ uint8_t f1bc3x_b0_d0;
+ uint8_t f1bc4x_b0_d0;
+ uint8_t f1bc5x_b0_d0;
+ uint8_t f1bc8x_b0_d0;
+ uint8_t f1bc9x_b0_d0;
+ uint8_t f1bcax_b0_d0;
+ uint8_t f1bcbx_b0_d0;
+ uint8_t f2bc2x_b0_d0;
+ uint8_t f2bc3x_b0_d0;
+ uint8_t f2bc4x_b0_d0;
+ uint8_t f2bc5x_b0_d0;
+ uint8_t f2bc8x_b0_d0;
+ uint8_t f2bc9x_b0_d0;
+ uint8_t f2bcax_b0_d0;
+ uint8_t f2bcbx_b0_d0;
+ uint8_t f3bc2x_b0_d0;
+ uint8_t f3bc3x_b0_d0;
+ uint8_t f3bc4x_b0_d0;
+ uint8_t f3bc5x_b0_d0;
+ uint8_t f3bc8x_b0_d0;
+ uint8_t f3bc9x_b0_d0;
+ uint8_t f3bcax_b0_d0;
+ uint8_t f3bcbx_b0_d0;
+ uint8_t f0bc2x_b1_d0;
+ uint8_t f0bc3x_b1_d0;
+ uint8_t f0bc4x_b1_d0;
+ uint8_t f0bc5x_b1_d0;
+ uint8_t f0bc8x_b1_d0;
+ uint8_t f0bc9x_b1_d0;
+ uint8_t f0bcax_b1_d0;
+ uint8_t f0bcbx_b1_d0;
+ uint8_t f1bc2x_b1_d0;
+ uint8_t f1bc3x_b1_d0;
+ uint8_t f1bc4x_b1_d0;
+ uint8_t f1bc5x_b1_d0;
+ uint8_t f1bc8x_b1_d0;
+ uint8_t f1bc9x_b1_d0;
+ uint8_t f1bcax_b1_d0;
+ uint8_t f1bcbx_b1_d0;
+ uint8_t f2bc2x_b1_d0;
+ uint8_t f2bc3x_b1_d0;
+ uint8_t f2bc4x_b1_d0;
+ uint8_t f2bc5x_b1_d0;
+ uint8_t f2bc8x_b1_d0;
+ uint8_t f2bc9x_b1_d0;
+ uint8_t f2bcax_b1_d0;
+ uint8_t f2bcbx_b1_d0;
+ uint8_t f3bc2x_b1_d0;
+ uint8_t f3bc3x_b1_d0;
+ uint8_t f3bc4x_b1_d0;
+ uint8_t f3bc5x_b1_d0;
+ uint8_t f3bc8x_b1_d0;
+ uint8_t f3bc9x_b1_d0;
+ uint8_t f3bcax_b1_d0;
+ uint8_t f3bcbx_b1_d0;
+ uint8_t f0bc2x_b2_d0;
+ uint8_t f0bc3x_b2_d0;
+ uint8_t f0bc4x_b2_d0;
+ uint8_t f0bc5x_b2_d0;
+ uint8_t f0bc8x_b2_d0;
+ uint8_t f0bc9x_b2_d0;
+ uint8_t f0bcax_b2_d0;
+ uint8_t f0bcbx_b2_d0;
+ uint8_t f1bc2x_b2_d0;
+ uint8_t f1bc3x_b2_d0;
+ uint8_t f1bc4x_b2_d0;
+ uint8_t f1bc5x_b2_d0;
+ uint8_t f1bc8x_b2_d0;
+ uint8_t f1bc9x_b2_d0;
+ uint8_t f1bcax_b2_d0;
+ uint8_t f1bcbx_b2_d0;
+ uint8_t f2bc2x_b2_d0;
+ uint8_t f2bc3x_b2_d0;
+ uint8_t f2bc4x_b2_d0;
+ uint8_t f2bc5x_b2_d0;
+ uint8_t f2bc8x_b2_d0;
+ uint8_t f2bc9x_b2_d0;
+ uint8_t f2bcax_b2_d0;
+ uint8_t f2bcbx_b2_d0;
+ uint8_t f3bc2x_b2_d0;
+ uint8_t f3bc3x_b2_d0;
+ uint8_t f3bc4x_b2_d0;
+ uint8_t f3bc5x_b2_d0;
+ uint8_t f3bc8x_b2_d0;
+ uint8_t f3bc9x_b2_d0;
+ uint8_t f3bcax_b2_d0;
+ uint8_t f3bcbx_b2_d0;
+ uint8_t f0bc2x_b3_d0;
+ uint8_t f0bc3x_b3_d0;
+ uint8_t f0bc4x_b3_d0;
+ uint8_t f0bc5x_b3_d0;
+ uint8_t f0bc8x_b3_d0;
+ uint8_t f0bc9x_b3_d0;
+ uint8_t f0bcax_b3_d0;
+ uint8_t f0bcbx_b3_d0;
+ uint8_t f1bc2x_b3_d0;
+ uint8_t f1bc3x_b3_d0;
+ uint8_t f1bc4x_b3_d0;
+ uint8_t f1bc5x_b3_d0;
+ uint8_t f1bc8x_b3_d0;
+ uint8_t f1bc9x_b3_d0;
+ uint8_t f1bcax_b3_d0;
+ uint8_t f1bcbx_b3_d0;
+ uint8_t f2bc2x_b3_d0;
+ uint8_t f2bc3x_b3_d0;
+ uint8_t f2bc4x_b3_d0;
+ uint8_t f2bc5x_b3_d0;
+ uint8_t f2bc8x_b3_d0;
+ uint8_t f2bc9x_b3_d0;
+ uint8_t f2bcax_b3_d0;
+ uint8_t f2bcbx_b3_d0;
+ uint8_t f3bc2x_b3_d0;
+ uint8_t f3bc3x_b3_d0;
+ uint8_t f3bc4x_b3_d0;
+ uint8_t f3bc5x_b3_d0;
+ uint8_t f3bc8x_b3_d0;
+ uint8_t f3bc9x_b3_d0;
+ uint8_t f3bcax_b3_d0;
+ uint8_t f3bcbx_b3_d0;
+ uint8_t f0bc2x_b4_d0;
+ uint8_t f0bc3x_b4_d0;
+ uint8_t f0bc4x_b4_d0;
+ uint8_t f0bc5x_b4_d0;
+ uint8_t f0bc8x_b4_d0;
+ uint8_t f0bc9x_b4_d0;
+ uint8_t f0bcax_b4_d0;
+ uint8_t f0bcbx_b4_d0;
+ uint8_t f1bc2x_b4_d0;
+ uint8_t f1bc3x_b4_d0;
+ uint8_t f1bc4x_b4_d0;
+ uint8_t f1bc5x_b4_d0;
+ uint8_t f1bc8x_b4_d0;
+ uint8_t f1bc9x_b4_d0;
+ uint8_t f1bcax_b4_d0;
+ uint8_t f1bcbx_b4_d0;
+ uint8_t f2bc2x_b4_d0;
+ uint8_t f2bc3x_b4_d0;
+ uint8_t f2bc4x_b4_d0;
+ uint8_t f2bc5x_b4_d0;
+ uint8_t f2bc8x_b4_d0;
+ uint8_t f2bc9x_b4_d0;
+ uint8_t f2bcax_b4_d0;
+ uint8_t f2bcbx_b4_d0;
+ uint8_t f3bc2x_b4_d0;
+ uint8_t f3bc3x_b4_d0;
+ uint8_t f3bc4x_b4_d0;
+ uint8_t f3bc5x_b4_d0;
+ uint8_t f3bc8x_b4_d0;
+ uint8_t f3bc9x_b4_d0;
+ uint8_t f3bcax_b4_d0;
+ uint8_t f3bcbx_b4_d0;
+ uint8_t f0bc2x_b5_d0;
+ uint8_t f0bc3x_b5_d0;
+ uint8_t f0bc4x_b5_d0;
+ uint8_t f0bc5x_b5_d0;
+ uint8_t f0bc8x_b5_d0;
+ uint8_t f0bc9x_b5_d0;
+ uint8_t f0bcax_b5_d0;
+ uint8_t f0bcbx_b5_d0;
+ uint8_t f1bc2x_b5_d0;
+ uint8_t f1bc3x_b5_d0;
+ uint8_t f1bc4x_b5_d0;
+ uint8_t f1bc5x_b5_d0;
+ uint8_t f1bc8x_b5_d0;
+ uint8_t f1bc9x_b5_d0;
+ uint8_t f1bcax_b5_d0;
+ uint8_t f1bcbx_b5_d0;
+ uint8_t f2bc2x_b5_d0;
+ uint8_t f2bc3x_b5_d0;
+ uint8_t f2bc4x_b5_d0;
+ uint8_t f2bc5x_b5_d0;
+ uint8_t f2bc8x_b5_d0;
+ uint8_t f2bc9x_b5_d0;
+ uint8_t f2bcax_b5_d0;
+ uint8_t f2bcbx_b5_d0;
+ uint8_t f3bc2x_b5_d0;
+ uint8_t f3bc3x_b5_d0;
+ uint8_t f3bc4x_b5_d0;
+ uint8_t f3bc5x_b5_d0;
+ uint8_t f3bc8x_b5_d0;
+ uint8_t f3bc9x_b5_d0;
+ uint8_t f3bcax_b5_d0;
+ uint8_t f3bcbx_b5_d0;
+ uint8_t f0bc2x_b6_d0;
+ uint8_t f0bc3x_b6_d0;
+ uint8_t f0bc4x_b6_d0;
+ uint8_t f0bc5x_b6_d0;
+ uint8_t f0bc8x_b6_d0;
+ uint8_t f0bc9x_b6_d0;
+ uint8_t f0bcax_b6_d0;
+ uint8_t f0bcbx_b6_d0;
+ uint8_t f1bc2x_b6_d0;
+ uint8_t f1bc3x_b6_d0;
+ uint8_t f1bc4x_b6_d0;
+ uint8_t f1bc5x_b6_d0;
+ uint8_t f1bc8x_b6_d0;
+ uint8_t f1bc9x_b6_d0;
+ uint8_t f1bcax_b6_d0;
+ uint8_t f1bcbx_b6_d0;
+ uint8_t f2bc2x_b6_d0;
+ uint8_t f2bc3x_b6_d0;
+ uint8_t f2bc4x_b6_d0;
+ uint8_t f2bc5x_b6_d0;
+ uint8_t f2bc8x_b6_d0;
+ uint8_t f2bc9x_b6_d0;
+ uint8_t f2bcax_b6_d0;
+ uint8_t f2bcbx_b6_d0;
+ uint8_t f3bc2x_b6_d0;
+ uint8_t f3bc3x_b6_d0;
+ uint8_t f3bc4x_b6_d0;
+ uint8_t f3bc5x_b6_d0;
+ uint8_t f3bc8x_b6_d0;
+ uint8_t f3bc9x_b6_d0;
+ uint8_t f3bcax_b6_d0;
+ uint8_t f3bcbx_b6_d0;
+ uint8_t f0bc2x_b7_d0;
+ uint8_t f0bc3x_b7_d0;
+ uint8_t f0bc4x_b7_d0;
+ uint8_t f0bc5x_b7_d0;
+ uint8_t f0bc8x_b7_d0;
+ uint8_t f0bc9x_b7_d0;
+ uint8_t f0bcax_b7_d0;
+ uint8_t f0bcbx_b7_d0;
+ uint8_t f1bc2x_b7_d0;
+ uint8_t f1bc3x_b7_d0;
+ uint8_t f1bc4x_b7_d0;
+ uint8_t f1bc5x_b7_d0;
+ uint8_t f1bc8x_b7_d0;
+ uint8_t f1bc9x_b7_d0;
+ uint8_t f1bcax_b7_d0;
+ uint8_t f1bcbx_b7_d0;
+ uint8_t f2bc2x_b7_d0;
+ uint8_t f2bc3x_b7_d0;
+ uint8_t f2bc4x_b7_d0;
+ uint8_t f2bc5x_b7_d0;
+ uint8_t f2bc8x_b7_d0;
+ uint8_t f2bc9x_b7_d0;
+ uint8_t f2bcax_b7_d0;
+ uint8_t f2bcbx_b7_d0;
+ uint8_t f3bc2x_b7_d0;
+ uint8_t f3bc3x_b7_d0;
+ uint8_t f3bc4x_b7_d0;
+ uint8_t f3bc5x_b7_d0;
+ uint8_t f3bc8x_b7_d0;
+ uint8_t f3bc9x_b7_d0;
+ uint8_t f3bcax_b7_d0;
+ uint8_t f3bcbx_b7_d0;
+ uint8_t f0bc2x_b8_d0;
+ uint8_t f0bc3x_b8_d0;
+ uint8_t f0bc4x_b8_d0;
+ uint8_t f0bc5x_b8_d0;
+ uint8_t f0bc8x_b8_d0;
+ uint8_t f0bc9x_b8_d0;
+ uint8_t f0bcax_b8_d0;
+ uint8_t f0bcbx_b8_d0;
+ uint8_t f1bc2x_b8_d0;
+ uint8_t f1bc3x_b8_d0;
+ uint8_t f1bc4x_b8_d0;
+ uint8_t f1bc5x_b8_d0;
+ uint8_t f1bc8x_b8_d0;
+ uint8_t f1bc9x_b8_d0;
+ uint8_t f1bcax_b8_d0;
+ uint8_t f1bcbx_b8_d0;
+ uint8_t f2bc2x_b8_d0;
+ uint8_t f2bc3x_b8_d0;
+ uint8_t f2bc4x_b8_d0;
+ uint8_t f2bc5x_b8_d0;
+ uint8_t f2bc8x_b8_d0;
+ uint8_t f2bc9x_b8_d0;
+ uint8_t f2bcax_b8_d0;
+ uint8_t f2bcbx_b8_d0;
+ uint8_t f3bc2x_b8_d0;
+ uint8_t f3bc3x_b8_d0;
+ uint8_t f3bc4x_b8_d0;
+ uint8_t f3bc5x_b8_d0;
+ uint8_t f3bc8x_b8_d0;
+ uint8_t f3bc9x_b8_d0;
+ uint8_t f3bcax_b8_d0;
+ uint8_t f3bcbx_b8_d0;
+ uint8_t f5bc5x_d0;
+ uint8_t f5bc6x_d0;
+ uint8_t f4bc8x_d0;
+ uint8_t f4bc9x_d0;
+ uint8_t f4bcax_d0;
+ uint8_t f4bcbx_d0;
+ uint8_t f4bccx_d0;
+ uint8_t f4bcdx_d0;
+ uint8_t f4bcex_d0;
+ uint8_t f4bcfx_d0;
+ uint8_t f5bc8x_d0;
+ uint8_t f5bc9x_d0;
+ uint8_t f5bcax_d0;
+ uint8_t f5bcbx_d0;
+ uint8_t f5bccx_d0;
+ uint8_t f5bcdx_d0;
+ uint8_t f5bcex_d0;
+ uint8_t f5bcfx_d0;
+ uint8_t f6bc8x_d0;
+ uint8_t f6bc9x_d0;
+ uint8_t f6bcax_d0;
+ uint8_t f6bcbx_d0;
+ uint8_t f6bccx_d0;
+ uint8_t f6bcdx_d0;
+ uint8_t f6bcex_d0;
+ uint8_t f6bcfx_d0;
+ uint8_t f7bc8x_d0;
+ uint8_t f7bc9x_d0;
+ uint8_t f7bcax_d0;
+ uint8_t f7bcbx_d0;
+ uint8_t f7bccx_d0;
+ uint8_t f7bcdx_d0;
+ uint8_t f7bcex_d0;
+ uint8_t f7bcfx_d0;
+ uint8_t bc00_d1;
+ uint8_t bc01_d1;
+ uint8_t bc02_d1;
+ uint8_t bc03_d1;
+ uint8_t bc04_d1;
+ uint8_t bc05_d1;
+ uint8_t bc06_d1;
+ uint8_t bc07_d1;
+ uint8_t bc08_d1;
+ uint8_t bc09_d1;
+ uint8_t bc0a_d1;
+ uint8_t bc0b_d1;
+ uint8_t bc0c_d1;
+ uint8_t bc0d_d1;
+ uint8_t bc0e_d1;
+ uint8_t f0bc6x_d1;
+ uint8_t f0bccx_d1;
+ uint8_t f0bcdx_d1;
+ uint8_t f0bcex_d1;
+ uint8_t f0bcfx_d1;
+ uint8_t f1bccx_d1;
+ uint8_t f1bcdx_d1;
+ uint8_t f1bcex_d1;
+ uint8_t f1bcfx_d1;
+ uint8_t f0bc2x_b0_d1;
+ uint8_t f0bc3x_b0_d1;
+ uint8_t f0bc4x_b0_d1;
+ uint8_t f0bc5x_b0_d1;
+ uint8_t f0bc8x_b0_d1;
+ uint8_t f0bc9x_b0_d1;
+ uint8_t f0bcax_b0_d1;
+ uint8_t f0bcbx_b0_d1;
+ uint8_t f1bc2x_b0_d1;
+ uint8_t f1bc3x_b0_d1;
+ uint8_t f1bc4x_b0_d1;
+ uint8_t f1bc5x_b0_d1;
+ uint8_t f1bc8x_b0_d1;
+ uint8_t f1bc9x_b0_d1;
+ uint8_t f1bcax_b0_d1;
+ uint8_t f1bcbx_b0_d1;
+ uint8_t f2bc2x_b0_d1;
+ uint8_t f2bc3x_b0_d1;
+ uint8_t f2bc4x_b0_d1;
+ uint8_t f2bc5x_b0_d1;
+ uint8_t f2bc8x_b0_d1;
+ uint8_t f2bc9x_b0_d1;
+ uint8_t f2bcax_b0_d1;
+ uint8_t f2bcbx_b0_d1;
+ uint8_t f3bc2x_b0_d1;
+ uint8_t f3bc3x_b0_d1;
+ uint8_t f3bc4x_b0_d1;
+ uint8_t f3bc5x_b0_d1;
+ uint8_t f3bc8x_b0_d1;
+ uint8_t f3bc9x_b0_d1;
+ uint8_t f3bcax_b0_d1;
+ uint8_t f3bcbx_b0_d1;
+ uint8_t f0bc2x_b1_d1;
+ uint8_t f0bc3x_b1_d1;
+ uint8_t f0bc4x_b1_d1;
+ uint8_t f0bc5x_b1_d1;
+ uint8_t f0bc8x_b1_d1;
+ uint8_t f0bc9x_b1_d1;
+ uint8_t f0bcax_b1_d1;
+ uint8_t f0bcbx_b1_d1;
+ uint8_t f1bc2x_b1_d1;
+ uint8_t f1bc3x_b1_d1;
+ uint8_t f1bc4x_b1_d1;
+ uint8_t f1bc5x_b1_d1;
+ uint8_t f1bc8x_b1_d1;
+ uint8_t f1bc9x_b1_d1;
+ uint8_t f1bcax_b1_d1;
+ uint8_t f1bcbx_b1_d1;
+ uint8_t f2bc2x_b1_d1;
+ uint8_t f2bc3x_b1_d1;
+ uint8_t f2bc4x_b1_d1;
+ uint8_t f2bc5x_b1_d1;
+ uint8_t f2bc8x_b1_d1;
+ uint8_t f2bc9x_b1_d1;
+ uint8_t f2bcax_b1_d1;
+ uint8_t f2bcbx_b1_d1;
+ uint8_t f3bc2x_b1_d1;
+ uint8_t f3bc3x_b1_d1;
+ uint8_t f3bc4x_b1_d1;
+ uint8_t f3bc5x_b1_d1;
+ uint8_t f3bc8x_b1_d1;
+ uint8_t f3bc9x_b1_d1;
+ uint8_t f3bcax_b1_d1;
+ uint8_t f3bcbx_b1_d1;
+ uint8_t f0bc2x_b2_d1;
+ uint8_t f0bc3x_b2_d1;
+ uint8_t f0bc4x_b2_d1;
+ uint8_t f0bc5x_b2_d1;
+ uint8_t f0bc8x_b2_d1;
+ uint8_t f0bc9x_b2_d1;
+ uint8_t f0bcax_b2_d1;
+ uint8_t f0bcbx_b2_d1;
+ uint8_t f1bc2x_b2_d1;
+ uint8_t f1bc3x_b2_d1;
+ uint8_t f1bc4x_b2_d1;
+ uint8_t f1bc5x_b2_d1;
+ uint8_t f1bc8x_b2_d1;
+ uint8_t f1bc9x_b2_d1;
+ uint8_t f1bcax_b2_d1;
+ uint8_t f1bcbx_b2_d1;
+ uint8_t f2bc2x_b2_d1;
+ uint8_t f2bc3x_b2_d1;
+ uint8_t f2bc4x_b2_d1;
+ uint8_t f2bc5x_b2_d1;
+ uint8_t f2bc8x_b2_d1;
+ uint8_t f2bc9x_b2_d1;
+ uint8_t f2bcax_b2_d1;
+ uint8_t f2bcbx_b2_d1;
+ uint8_t f3bc2x_b2_d1;
+ uint8_t f3bc3x_b2_d1;
+ uint8_t f3bc4x_b2_d1;
+ uint8_t f3bc5x_b2_d1;
+ uint8_t f3bc8x_b2_d1;
+ uint8_t f3bc9x_b2_d1;
+ uint8_t f3bcax_b2_d1;
+ uint8_t f3bcbx_b2_d1;
+ uint8_t f0bc2x_b3_d1;
+ uint8_t f0bc3x_b3_d1;
+ uint8_t f0bc4x_b3_d1;
+ uint8_t f0bc5x_b3_d1;
+ uint8_t f0bc8x_b3_d1;
+ uint8_t f0bc9x_b3_d1;
+ uint8_t f0bcax_b3_d1;
+ uint8_t f0bcbx_b3_d1;
+ uint8_t f1bc2x_b3_d1;
+ uint8_t f1bc3x_b3_d1;
+ uint8_t f1bc4x_b3_d1;
+ uint8_t f1bc5x_b3_d1;
+ uint8_t f1bc8x_b3_d1;
+ uint8_t f1bc9x_b3_d1;
+ uint8_t f1bcax_b3_d1;
+ uint8_t f1bcbx_b3_d1;
+ uint8_t f2bc2x_b3_d1;
+ uint8_t f2bc3x_b3_d1;
+ uint8_t f2bc4x_b3_d1;
+ uint8_t f2bc5x_b3_d1;
+ uint8_t f2bc8x_b3_d1;
+ uint8_t f2bc9x_b3_d1;
+ uint8_t f2bcax_b3_d1;
+ uint8_t f2bcbx_b3_d1;
+ uint8_t f3bc2x_b3_d1;
+ uint8_t f3bc3x_b3_d1;
+ uint8_t f3bc4x_b3_d1;
+ uint8_t f3bc5x_b3_d1;
+ uint8_t f3bc8x_b3_d1;
+ uint8_t f3bc9x_b3_d1;
+ uint8_t f3bcax_b3_d1;
+ uint8_t f3bcbx_b3_d1;
+ uint8_t f0bc2x_b4_d1;
+ uint8_t f0bc3x_b4_d1;
+ uint8_t f0bc4x_b4_d1;
+ uint8_t f0bc5x_b4_d1;
+ uint8_t f0bc8x_b4_d1;
+ uint8_t f0bc9x_b4_d1;
+ uint8_t f0bcax_b4_d1;
+ uint8_t f0bcbx_b4_d1;
+ uint8_t f1bc2x_b4_d1;
+ uint8_t f1bc3x_b4_d1;
+ uint8_t f1bc4x_b4_d1;
+ uint8_t f1bc5x_b4_d1;
+ uint8_t f1bc8x_b4_d1;
+ uint8_t f1bc9x_b4_d1;
+ uint8_t f1bcax_b4_d1;
+ uint8_t f1bcbx_b4_d1;
+ uint8_t f2bc2x_b4_d1;
+ uint8_t f2bc3x_b4_d1;
+ uint8_t f2bc4x_b4_d1;
+ uint8_t f2bc5x_b4_d1;
+ uint8_t f2bc8x_b4_d1;
+ uint8_t f2bc9x_b4_d1;
+ uint8_t f2bcax_b4_d1;
+ uint8_t f2bcbx_b4_d1;
+ uint8_t f3bc2x_b4_d1;
+ uint8_t f3bc3x_b4_d1;
+ uint8_t f3bc4x_b4_d1;
+ uint8_t f3bc5x_b4_d1;
+ uint8_t f3bc8x_b4_d1;
+ uint8_t f3bc9x_b4_d1;
+ uint8_t f3bcax_b4_d1;
+ uint8_t f3bcbx_b4_d1;
+ uint8_t f0bc2x_b5_d1;
+ uint8_t f0bc3x_b5_d1;
+ uint8_t f0bc4x_b5_d1;
+ uint8_t f0bc5x_b5_d1;
+ uint8_t f0bc8x_b5_d1;
+ uint8_t f0bc9x_b5_d1;
+ uint8_t f0bcax_b5_d1;
+ uint8_t f0bcbx_b5_d1;
+ uint8_t f1bc2x_b5_d1;
+ uint8_t f1bc3x_b5_d1;
+ uint8_t f1bc4x_b5_d1;
+ uint8_t f1bc5x_b5_d1;
+ uint8_t f1bc8x_b5_d1;
+ uint8_t f1bc9x_b5_d1;
+ uint8_t f1bcax_b5_d1;
+ uint8_t f1bcbx_b5_d1;
+ uint8_t f2bc2x_b5_d1;
+ uint8_t f2bc3x_b5_d1;
+ uint8_t f2bc4x_b5_d1;
+ uint8_t f2bc5x_b5_d1;
+ uint8_t f2bc8x_b5_d1;
+ uint8_t f2bc9x_b5_d1;
+ uint8_t f2bcax_b5_d1;
+ uint8_t f2bcbx_b5_d1;
+ uint8_t f3bc2x_b5_d1;
+ uint8_t f3bc3x_b5_d1;
+ uint8_t f3bc4x_b5_d1;
+ uint8_t f3bc5x_b5_d1;
+ uint8_t f3bc8x_b5_d1;
+ uint8_t f3bc9x_b5_d1;
+ uint8_t f3bcax_b5_d1;
+ uint8_t f3bcbx_b5_d1;
+ uint8_t f0bc2x_b6_d1;
+ uint8_t f0bc3x_b6_d1;
+ uint8_t f0bc4x_b6_d1;
+ uint8_t f0bc5x_b6_d1;
+ uint8_t f0bc8x_b6_d1;
+ uint8_t f0bc9x_b6_d1;
+ uint8_t f0bcax_b6_d1;
+ uint8_t f0bcbx_b6_d1;
+ uint8_t f1bc2x_b6_d1;
+ uint8_t f1bc3x_b6_d1;
+ uint8_t f1bc4x_b6_d1;
+ uint8_t f1bc5x_b6_d1;
+ uint8_t f1bc8x_b6_d1;
+ uint8_t f1bc9x_b6_d1;
+ uint8_t f1bcax_b6_d1;
+ uint8_t f1bcbx_b6_d1;
+ uint8_t f2bc2x_b6_d1;
+ uint8_t f2bc3x_b6_d1;
+ uint8_t f2bc4x_b6_d1;
+ uint8_t f2bc5x_b6_d1;
+ uint8_t f2bc8x_b6_d1;
+ uint8_t f2bc9x_b6_d1;
+ uint8_t f2bcax_b6_d1;
+ uint8_t f2bcbx_b6_d1;
+ uint8_t f3bc2x_b6_d1;
+ uint8_t f3bc3x_b6_d1;
+ uint8_t f3bc4x_b6_d1;
+ uint8_t f3bc5x_b6_d1;
+ uint8_t f3bc8x_b6_d1;
+ uint8_t f3bc9x_b6_d1;
+ uint8_t f3bcax_b6_d1;
+ uint8_t f3bcbx_b6_d1;
+ uint8_t f0bc2x_b7_d1;
+ uint8_t f0bc3x_b7_d1;
+ uint8_t f0bc4x_b7_d1;
+ uint8_t f0bc5x_b7_d1;
+ uint8_t f0bc8x_b7_d1;
+ uint8_t f0bc9x_b7_d1;
+ uint8_t f0bcax_b7_d1;
+ uint8_t f0bcbx_b7_d1;
+ uint8_t f1bc2x_b7_d1;
+ uint8_t f1bc3x_b7_d1;
+ uint8_t f1bc4x_b7_d1;
+ uint8_t f1bc5x_b7_d1;
+ uint8_t f1bc8x_b7_d1;
+ uint8_t f1bc9x_b7_d1;
+ uint8_t f1bcax_b7_d1;
+ uint8_t f1bcbx_b7_d1;
+ uint8_t f2bc2x_b7_d1;
+ uint8_t f2bc3x_b7_d1;
+ uint8_t f2bc4x_b7_d1;
+ uint8_t f2bc5x_b7_d1;
+ uint8_t f2bc8x_b7_d1;
+ uint8_t f2bc9x_b7_d1;
+ uint8_t f2bcax_b7_d1;
+ uint8_t f2bcbx_b7_d1;
+ uint8_t f3bc2x_b7_d1;
+ uint8_t f3bc3x_b7_d1;
+ uint8_t f3bc4x_b7_d1;
+ uint8_t f3bc5x_b7_d1;
+ uint8_t f3bc8x_b7_d1;
+ uint8_t f3bc9x_b7_d1;
+ uint8_t f3bcax_b7_d1;
+ uint8_t f3bcbx_b7_d1;
+ uint8_t f0bc2x_b8_d1;
+ uint8_t f0bc3x_b8_d1;
+ uint8_t f0bc4x_b8_d1;
+ uint8_t f0bc5x_b8_d1;
+ uint8_t f0bc8x_b8_d1;
+ uint8_t f0bc9x_b8_d1;
+ uint8_t f0bcax_b8_d1;
+ uint8_t f0bcbx_b8_d1;
+ uint8_t f1bc2x_b8_d1;
+ uint8_t f1bc3x_b8_d1;
+ uint8_t f1bc4x_b8_d1;
+ uint8_t f1bc5x_b8_d1;
+ uint8_t f1bc8x_b8_d1;
+ uint8_t f1bc9x_b8_d1;
+ uint8_t f1bcax_b8_d1;
+ uint8_t f1bcbx_b8_d1;
+ uint8_t f2bc2x_b8_d1;
+ uint8_t f2bc3x_b8_d1;
+ uint8_t f2bc4x_b8_d1;
+ uint8_t f2bc5x_b8_d1;
+ uint8_t f2bc8x_b8_d1;
+ uint8_t f2bc9x_b8_d1;
+ uint8_t f2bcax_b8_d1;
+ uint8_t f2bcbx_b8_d1;
+ uint8_t f3bc2x_b8_d1;
+ uint8_t f3bc3x_b8_d1;
+ uint8_t f3bc4x_b8_d1;
+ uint8_t f3bc5x_b8_d1;
+ uint8_t f3bc8x_b8_d1;
+ uint8_t f3bc9x_b8_d1;
+ uint8_t f3bcax_b8_d1;
+ uint8_t f3bcbx_b8_d1;
+ uint8_t f5bc5x_d1;
+ uint8_t f5bc6x_d1;
+ uint8_t f4bc8x_d1;
+ uint8_t f4bc9x_d1;
+ uint8_t f4bcax_d1;
+ uint8_t f4bcbx_d1;
+ uint8_t f4bccx_d1;
+ uint8_t f4bcdx_d1;
+ uint8_t f4bcex_d1;
+ uint8_t f4bcfx_d1;
+ uint8_t f5bc8x_d1;
+ uint8_t f5bc9x_d1;
+ uint8_t f5bcax_d1;
+ uint8_t f5bcbx_d1;
+ uint8_t f5bccx_d1;
+ uint8_t f5bcdx_d1;
+ uint8_t f5bcex_d1;
+ uint8_t f5bcfx_d1;
+ uint8_t f6bc8x_d1;
+ uint8_t f6bc9x_d1;
+ uint8_t f6bcax_d1;
+ uint8_t f6bcbx_d1;
+ uint8_t f6bccx_d1;
+ uint8_t f6bcdx_d1;
+ uint8_t f6bcex_d1;
+ uint8_t f6bcfx_d1;
+ uint8_t f7bc8x_d1;
+ uint8_t f7bc9x_d1;
+ uint8_t f7bcax_d1;
+ uint8_t f7bcbx_d1;
+ uint8_t f7bccx_d1;
+ uint8_t f7bcdx_d1;
+ uint8_t f7bcex_d1;
+ uint8_t f7bcfx_d1;
+ uint16_t alt_cas_l;
+ uint8_t alt_wcas_l;
+ uint8_t d4misc;
+} __packed;
+#endif
diff --git a/drivers/nxp/ddr/phy-gen2/ddrphy.mk b/drivers/nxp/ddr/phy-gen2/ddrphy.mk
new file mode 100644
index 0000000000..ba5c774273
--- /dev/null
+++ b/drivers/nxp/ddr/phy-gen2/ddrphy.mk
@@ -0,0 +1,20 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#-----------------------------------------------------------------------------
+
+# SNPS ddr phy driver files
+
+DDR_PHY_C =
+DDR_PHY_H =
+
+$(DDR_PHY_C): $(DDR_PHY_H) $(COMMON_HDRS) src
+ @cp -r "$(DDR_PHY_PATH)/$@" "$(SRC_DIR)/$@"
+
+$(DDR_PHY_H): src
+ @cp -r "$(DDR_PHY_PATH)/$@" "$(SRC_DIR)/$@"
+
+#------------------------------------------------
diff --git a/drivers/nxp/ddr/phy-gen2/input.h b/drivers/nxp/ddr/phy-gen2/input.h
new file mode 100644
index 0000000000..dbcd1ae6d9
--- /dev/null
+++ b/drivers/nxp/ddr/phy-gen2/input.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2021 NXP
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+enum dram_types {
+ DDR4,
+ DDR3,
+ LPDDR4,
+ LPDDR3,
+ LPDDR2,
+ DDR5,
+};
+
+enum dimm_types {
+ UDIMM,
+ SODIMM,
+ RDIMM,
+ LRDIMM,
+ NODIMM,
+};
+
+struct input_basic {
+ enum dram_types dram_type;
+ enum dimm_types dimm_type;
+ int lp4x_mode; /* 0x1 = lpddr4x mode, when dram_type is lpddr4
+ */
+ /* not used for protocols other than lpddr4 */
+ int num_dbyte; /* number of dbytes physically instantiated */
+ int num_active_dbyte_dfi0; /* number of active dbytes to be
+ * controlled by dfi0
+ */
+ int num_active_dbyte_dfi1; /* number of active dbytes to be
+ * controlled by dfi1. Not used for
+ * protocols other than lpddr3 and
+ * lpddr4
+ */
+ int num_anib; /* number of anibs physically instantiated */
+ int num_rank_dfi0; /* number of ranks in dfi0 channel */
+ int num_rank_dfi1; /* number of ranks in dfi1 channel */
+ int dram_data_width; /* 4,8,16 or 32 depending on protocol and dram
+ * type
+ */
+ int num_pstates;
+ int frequency; /* memclk frequency in mhz -- round up */
+ int pll_bypass; /* pll bypass enable */
+ int dfi_freq_ratio; /* selected dfi frequency ratio */
+ int dfi1exists; /* whether they phy config has dfi1 channel */
+ int train2d;
+ int hard_macro_ver;
+ int read_dbienable;
+ int dfi_mode; /* no longer used */
+};
+
+struct input_advanced {
+ int d4rx_preamble_length;
+ int d4tx_preamble_length;
+ int ext_cal_res_val; /* external pull-down resistor */
+ int is2ttiming;
+ int odtimpedance;
+ int tx_impedance;
+ int atx_impedance;
+ int mem_alert_en;
+ int mem_alert_puimp;
+ int mem_alert_vref_level;
+ int mem_alert_sync_bypass;
+ int dis_dyn_adr_tri;
+ int phy_mstr_train_interval;
+ int phy_mstr_max_req_to_ack;
+ int wdqsext;
+ int cal_interval;
+ int cal_once;
+ int dram_byte_swap;
+ int rx_en_back_off;
+ int train_sequence_ctrl;
+ int phy_gen2_umctl_opt;
+ int phy_gen2_umctl_f0rc5x;
+ int tx_slew_rise_dq;
+ int tx_slew_fall_dq;
+ int tx_slew_rise_ac;
+ int tx_slew_fall_ac;
+ int enable_high_clk_skew_fix;
+ int disable_unused_addr_lns;
+ int phy_init_sequence_num;
+ int cs_mode; /* rdimm */
+ int cast_cs_to_cid; /* rdimm */
+};
+
+struct input {
+ struct input_basic basic;
+ struct input_advanced adv;
+ unsigned int mr[7];
+ unsigned int cs_d0;
+ unsigned int cs_d1;
+ unsigned int mirror;
+ unsigned int odt[4];
+ unsigned int rcw[16];
+ unsigned int rcw3x;
+ unsigned int vref;
+};
+
+#endif
diff --git a/drivers/nxp/ddr/phy-gen2/messages.h b/drivers/nxp/ddr/phy-gen2/messages.h
new file mode 100644
index 0000000000..7dec7df55f
--- /dev/null
+++ b/drivers/nxp/ddr/phy-gen2/messages.h
@@ -0,0 +1,2909 @@
+/*
+ * Copyright 2021 NXP
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+#ifdef DEBUG
+struct phy_msg {
+ uint32_t index;
+ const char *msg;
+};
+
+const static struct phy_msg messages_1d[] = {
+ {0x00000001,
+ "PMU1:prbsGenCtl:%x\n"
+ },
+ {0x00010000,
+ "PMU1: loading 2D acsm sequence\n"
+ },
+ {0x00020000,
+ "PMU1: loading 1D acsm sequence\n"
+ },
+ {0x00030002,
+ "PMU3: %d memclocks @ %d to get half of 300ns\n"
+ },
+ {0x00040000,
+ "PMU: Error: User requested MPR read pattern for read DQS training in DDR3 Mode\n"
+ },
+ {0x00050000,
+ "PMU3: Running 1D search for left eye edge\n"
+ },
+ {0x00060001,
+ "PMU1: In Phase Left Edge Search cs %d\n"
+ },
+ {0x00070001,
+ "PMU1: Out of Phase Left Edge Search cs %d\n"
+ },
+ {0x00080000,
+ "PMU3: Running 1D search for right eye edge\n"
+ },
+ {0x00090001,
+ "PMU1: In Phase Right Edge Search cs %d\n"
+ },
+ {0x000a0001,
+ "PMU1: Out of Phase Right Edge Search cs %d\n"
+ },
+ {0x000b0001,
+ "PMU1: mxRdLat training pstate %d\n"
+ },
+ {0x000c0001,
+ "PMU1: mxRdLat search for cs %d\n"
+ },
+ {0x000d0001,
+ "PMU0: MaxRdLat non consistent DtsmLoThldXingInd 0x%03x\n"
+ },
+ {0x000e0003,
+ "PMU4: CS %d Dbyte %d worked with DFIMRL = %d DFICLKs\n"
+ },
+ {0x000f0004,
+ "PMU3: MaxRdLat Read Lane err mask for csn %d, DFIMRL %2d DFIClks, dbyte %d = 0x%03x\n"
+ },
+ {0x00100003,
+ "PMU3: MaxRdLat Read Lane err mask for csn %d DFIMRL %2d, All dbytes = 0x%03x\n"
+ },
+ {0x00110001,
+ "PMU: Error: CS%d failed to find a DFIMRL setting that worked for all bytes during MaxRdLat training\n"
+ },
+ {0x00120002,
+ "PMU3: Smallest passing DFIMRL for all dbytes in CS%d = %d DFIClks\n"
+ },
+ {0x00130000,
+ "PMU: Error: No passing DFIMRL value found for any chip select during MaxRdLat training\n"
+ },
+ {0x00140003,
+ "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n"
+ },
+ {0x00150006,
+ "PMU10: Adjusting rxclkdly db %d nib %d from %d+%d=%d->%d\n"
+ },
+ {0x00160000,
+ "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n"
+ },
+ {0x00170005,
+ "PMU4: DB %d Lane %d: %3d %3d -> %3d\n"
+ },
+ {0x00180002,
+ "PMU2: TXDQ delayLeft[%2d] = %3d (DISCONNECTED)\n"
+ },
+ {0x00190004,
+ "PMU2: TXDQ delayLeft[%2d] = %3d oopScaled = %3d selectOop %d\n"
+ },
+ {0x001a0002,
+ "PMU2: TXDQ delayRight[%2d] = %3d (DISCONNECTED)\n"
+ },
+ {0x001b0004,
+ "PMU2: TXDQ delayRight[%2d] = %3d oopScaled = %3d selectOop %d\n"
+ },
+ {0x001c0003,
+ "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n"
+ },
+ {0x001d0000,
+ "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n"
+ },
+ {0x001e0002,
+ "PMU4: DB %d Lane %d: (DISCONNECTED)\n"
+ },
+ {0x001f0005,
+ "PMU4: DB %d Lane %d: %3d %3d -> %3d\n"
+ },
+ {0x00200002,
+ "PMU3: Running 1D search csn %d for DM Right/NotLeft(%d) eye edge\n"
+ },
+ {0x00210002,
+ "PMU3: WrDq DM byte%2d with Errcnt %d\n"
+ },
+ {0x00220002,
+ "PMU3: WrDq DM byte%2d avgDly 0x%04x\n"
+ },
+ {0x00230002,
+ "PMU1: WrDq DM byte%2d with Errcnt %d\n"
+ },
+ {0x00240001,
+ "PMU: Error: Dbyte %d txDqDly DM training did not start inside the eye\n"
+ },
+ {0x00250000,
+ "PMU4: DM TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n"
+ },
+ {0x00260002,
+ "PMU4: DB %d Lane %d: (DISCONNECTED)\n"
+ },
+ {0x00270005,
+ "PMU4: DB %d Lane %d: %3d %3d -> %3d\n"
+ },
+ {0x00280003,
+ "PMU: Error: Dbyte %d lane %d txDqDly DM passing region is too small (width = %d)\n"
+ },
+ {0x00290004,
+ "PMU3: Errcnt for MRD/MWD search nib %2d delay = (%d, 0x%02x) = %d\n"
+ },
+ {0x002a0000,
+ "PMU3: Precharge all open banks\n"
+ },
+ {0x002b0002,
+ "PMU: Error: Dbyte %d nibble %d found mutliple working coarse delay setting for MRD/MWD\n"
+ },
+ {0x002c0000,
+ "PMU4: MRD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n"
+ },
+ {0x002d0000,
+ "PMU4: MWD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n"
+ },
+ {0x002e0004,
+ "PMU10: Warning: DB %d nibble %d has multiple working coarse delays, %d and %d, choosing the smaller delay\n"
+ },
+ {0x002f0003,
+ "PMU: Error: Dbyte %d nibble %d MRD/MWD passing region is too small (width = %d)\n"
+ },
+ {0x00300006,
+ "PMU4: DB %d nibble %d: %3d, %3d %3d -> %3d\n"
+ },
+ {0x00310002,
+ "PMU1: Start MRD/nMWD %d for csn %d\n"
+ },
+ {0x00320002,
+ "PMU2: RXDQS delayLeft[%2d] = %3d (DISCONNECTED)\n"
+ },
+ {0x00330006,
+ "PMU2: RXDQS delayLeft[%2d] = %3d delayOop[%2d] = %3d OopScaled %4d, selectOop %d\n"
+ },
+ {0x00340002,
+ "PMU2: RXDQS delayRight[%2d] = %3d (DISCONNECTED)\n"
+ },
+ {0x00350006,
+ "PMU2: RXDQS delayRight[%2d] = %3d delayOop[%2d] = %4d OopScaled %4d, selectOop %d\n"
+ },
+ {0x00360000,
+ "PMU4: RxClkDly Passing Regions (EyeLeft EyeRight -> EyeCenter)\n"
+ },
+ {0x00370002,
+ "PMU4: DB %d nibble %d: (DISCONNECTED)\n"
+ },
+ {0x00380005,
+ "PMU4: DB %d nibble %d: %3d %3d -> %3d\n"
+ },
+ {0x00390003,
+ "PMU: Error: Dbyte %d nibble %d rxClkDly passing region is too small (width = %d)\n"
+ },
+ {0x003a0002,
+ "PMU0: goodbar = %d for RDWR_BLEN %d\n"
+ },
+ {0x003b0001,
+ "PMU3: RxClkDly = %d\n"
+ },
+ {0x003c0005,
+ "PMU0: db %d l %d absLane %d -> bottom %d top %d\n"
+ },
+ {0x003d0009,
+ "PMU3: BYTE %d - %3d %3d %3d %3d %3d %3d %3d %3d\n"
+ },
+ {0x003e0002,
+ "PMU: Error: dbyte %d lane %d's per-lane vrefDAC's had no passing region\n"
+ },
+ {0x003f0004,
+ "PMU0: db%d l%d - %d %d\n"
+ },
+ {0x00400002,
+ "PMU0: goodbar = %d for RDWR_BLEN %d\n"
+ },
+ {0x00410004,
+ "PMU3: db%d l%d saw %d issues at rxClkDly %d\n"
+ },
+ {0x00420003,
+ "PMU3: db%d l%d first saw a pass->fail edge at rxClkDly %d\n"
+ },
+ {0x00430002,
+ "PMU3: lane %d PBD = %d\n"
+ },
+ {0x00440003,
+ "PMU3: db%d l%d first saw a DBI pass->fail edge at rxClkDly %d\n"
+ },
+ {0x00450003,
+ "PMU2: db%d l%d already passed rxPBD = %d\n"
+ },
+ {0x00460003,
+ "PMU0: db%d l%d, PBD = %d\n"
+ },
+ {0x00470002,
+ "PMU: Error: dbyte %d lane %d failed read deskew\n"
+ },
+ {0x00480003,
+ "PMU0: db%d l%d, inc PBD = %d\n"
+ },
+ {0x00490003,
+ "PMU1: Running lane deskew on pstate %d csn %d rdDBIEn %d\n"
+ },
+ {0x004a0000,
+ "PMU: Error: Read deskew training has been requested, but csrMajorModeDbyte[2] is set\n"
+ },
+ {0x004b0002,
+ "PMU1: AcsmCsMapCtrl%02d 0x%04x\n"
+ },
+ {0x004c0002,
+ "PMU1: AcsmCsMapCtrl%02d 0x%04x\n"
+ },
+ {0x004d0001,
+ "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3U Type\n"
+ },
+ {0x004e0001,
+ "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3R Type\n"
+ },
+ {0x004f0001,
+ "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4U Type\n"
+ },
+ {0x00500001,
+ "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4R Type\n"
+ },
+ {0x00510001,
+ "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4LR Type\n"
+ },
+ {0x00520000,
+ "PMU: Error: Both 2t timing mode and ddr4 geardown mode specified in the messageblock's PhyCfg and MR3 fields. Only one can be enabled\n"
+ },
+ {0x00530003,
+ "PMU10: PHY TOTALS - NUM_DBYTES %d NUM_NIBBLES %d NUM_ANIBS %d\n"
+ },
+ {0x00540006,
+ "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR3\n"
+ },
+ {0x00550006,
+ "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR4\n"
+ },
+ {0x00560008,
+ "PMU10: CS=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, 2T=%d, MMISC=%d AddrMirror=%d DRAMFreq=%dMT DramType=%d\n"
+ },
+ {0x00570004,
+ "PMU10: Pstate%d MR0=0x%04x MR1=0x%04x MR2=0x%04x\n"
+ },
+ {0x00580008,
+ "PMU10: Pstate%d MRS MR0=0x%04x MR1=0x%04x MR2=0x%04x MR3=0x%04x MR4=0x%04x MR5=0x%04x MR6=0x%04x\n"
+ },
+ {0x00590005,
+ "PMU10: Pstate%d MRS MR1_A0=0x%04x MR2_A0=0x%04x MR3_A0=0x%04x MR11_A0=0x%04x\n"
+ },
+ {0x005a0000,
+ "PMU10: UseBroadcastMR set. All ranks and channels use MRXX_A0 for MR settings.\n"
+ },
+ {0x005b0005,
+ "PMU10: Pstate%d MRS MR01_A0=0x%02x MR02_A0=0x%02x MR03_A0=0x%02x MR11_A0=0x%02x\n"
+ },
+ {0x005c0005,
+ "PMU10: Pstate%d MRS MR12_A0=0x%02x MR13_A0=0x%02x MR14_A0=0x%02x MR22_A0=0x%02x\n"
+ },
+ {0x005d0005,
+ "PMU10: Pstate%d MRS MR01_A1=0x%02x MR02_A1=0x%02x MR03_A1=0x%02x MR11_A1=0x%02x\n"
+ },
+ {0x005e0005,
+ "PMU10: Pstate%d MRS MR12_A1=0x%02x MR13_A1=0x%02x MR14_A1=0x%02x MR22_A1=0x%02x\n"
+ },
+ {0x005f0005,
+ "PMU10: Pstate%d MRS MR01_B0=0x%02x MR02_B0=0x%02x MR03_B0=0x%02x MR11_B0=0x%02x\n"
+ },
+ {0x00600005,
+ "PMU10: Pstate%d MRS MR12_B0=0x%02x MR13_B0=0x%02x MR14_B0=0x%02x MR22_B0=0x%02x\n"
+ },
+ {0x00610005,
+ "PMU10: Pstate%d MRS MR01_B1=0x%02x MR02_B1=0x%02x MR03_B1=0x%02x MR11_B1=0x%02x\n"
+ },
+ {0x00620005,
+ "PMU10: Pstate%d MRS MR12_B1=0x%02x MR13_B1=0x%02x MR14_B1=0x%02x MR22_B1=0x%02x\n"
+ },
+ {0x00630002,
+ "PMU1: AcsmOdtCtrl%02d 0x%02x\n"
+ },
+ {0x00640002,
+ "PMU1: AcsmCsMapCtrl%02d 0x%04x\n"
+ },
+ {0x00650002,
+ "PMU1: AcsmCsMapCtrl%02d 0x%04x\n"
+ },
+ {0x00660000,
+ "PMU1: HwtCAMode set\n"
+ },
+ {0x00670001,
+ "PMU3: DDR4 infinite preamble enter/exit mode %d\n"
+ },
+ {0x00680002,
+ "PMU1: In rxenb_train() csn=%d pstate=%d\n"
+ },
+ {0x00690000,
+ "PMU3: Finding DQS falling edge\n"
+ },
+ {0x006a0000,
+ "PMU3: Searching for DDR3/LPDDR3/LPDDR4 read preamble\n"
+ },
+ {0x006b0009,
+ "PMU3: dtsm fails Even Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n"
+ },
+ {0x006c0009,
+ "PMU3: dtsm fails Odd Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n"
+ },
+ {0x006d0002,
+ "PMU3: Preamble search pass=%d anyfail=%d\n"
+ },
+ {0x006e0000,
+ "PMU: Error: RxEn training preamble not found\n"
+ },
+ {0x006f0000,
+ "PMU3: Found DQS pre-amble\n"
+ },
+ {0x00700001,
+ "PMU: Error: Dbyte %d couldn't find the rising edge of DQS during RxEn Training\n"
+ },
+ {0x00710000,
+ "PMU3: RxEn aligning to first rising edge of burst\n"
+ },
+ {0x00720001,
+ "PMU3: Decreasing RxEn delay by %d fine step to allow full capture of reads\n"
+ },
+ {0x00730001,
+ "PMU3: MREP Delay = %d\n"
+ },
+ {0x00740003,
+ "PMU3: Errcnt for MREP nib %2d delay = %2d is %d\n"
+ },
+ {0x00750002,
+ "PMU3: MREP nibble %d sampled a 1 at data buffer delay %d\n"
+ },
+ {0x00760002,
+ "PMU3: MREP nibble %d saw a 0 to 1 transition at data buffer delay %d\n"
+ },
+ {0x00770000,
+ "PMU2: MREP did not find a 0 to 1 transition for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n"
+ },
+ {0x00780002,
+ "PMU2: Rising edge found in alias window, setting rxDly for nibble %d = %d\n"
+ },
+ {0x00790002,
+ "PMU: Error: Failed MREP for nib %d with %d one\n"
+ },
+ {0x007a0003,
+ "PMU2: Rising edge not found in alias window with %d one, leaving rxDly for nibble %d = %d\n"
+ },
+ {0x007b0002,
+ "PMU3: Training DIMM %d CSn %d\n"
+ },
+ {0x007c0001,
+ "PMU3: exitCAtrain_lp3 cs 0x%x\n"
+ },
+ {0x007d0001,
+ "PMU3: enterCAtrain_lp3 cs 0x%x\n"
+ },
+ {0x007e0001,
+ "PMU3: CAtrain_switchmsb_lp3 cs 0x%x\n"
+ },
+ {0x007f0001,
+ "PMU3: CATrain_rdwr_lp3 looking for pattern %x\n"
+ },
+ {0x00800000,
+ "PMU3: exitCAtrain_lp4\n"
+ },
+ {0x00810001,
+ "PMU3: DEBUG enterCAtrain_lp4 1: cs 0x%x\n"
+ },
+ {0x00820001,
+ "PMU3: DEBUG enterCAtrain_lp4 3: Put dbyte %d in async mode\n"
+ },
+ {0x00830000,
+ "PMU3: DEBUG enterCAtrain_lp4 5: Send MR13 to turn on CA training\n"
+ },
+ {0x00840003,
+ "PMU3: DEBUG enterCAtrain_lp4 7: idx = %d vref = %x mr12 = %x\n"
+ },
+ {0x00850001,
+ "PMU3: CATrain_rdwr_lp4 looking for pattern %x\n"
+ },
+ {0x00860004,
+ "PMU3: Phase %d CAreadbackA db:%d %x xo:%x\n"
+ },
+ {0x00870005,
+ "PMU3: DEBUG lp4SetCatrVref 1: cs=%d chan=%d mr12=%x vref=%d.%d%%\n"
+ },
+ {0x00880003,
+ "PMU3: DEBUG lp4SetCatrVref 3: mr12 = %x send vref= %x to db=%d\n"
+ },
+ {0x00890000,
+ "PMU10:Optimizing vref\n"
+ },
+ {0x008a0004,
+ "PMU4:mr12:%2x cs:%d chan %d r:%4x\n"
+ },
+ {0x008b0005,
+ "PMU3: i:%2d bstr:%2d bsto:%2d st:%d r:%d\n"
+ },
+ {0x008c0002,
+ "Failed to find sufficient CA Vref Passing Region for CS %d ch. %d\n"
+ },
+ {0x008d0005,
+ "PMU3:Found %d.%d%% MR12:%x for cs:%d chan %d\n"
+ },
+ {0x008e0002,
+ "PMU3:Calculated %d for AtxImpedence from acx %d.\n"
+ },
+ {0x008f0000,
+ "PMU3:CA Odt impedence ==0. Use default vref.\n"
+ },
+ {0x00900003,
+ "PMU3:Calculated %d.%d%% for Vref MR12=0x%x.\n"
+ },
+ {0x00910000,
+ "PMU3: CAtrain_lp\n"
+ },
+ {0x00920000,
+ "PMU3: CAtrain Begins.\n"
+ },
+ {0x00930001,
+ "PMU3: CAtrain_lp testing dly %d\n"
+ },
+ {0x00940001,
+ "PMU5: CA bitmap dump for cs %x\n"
+ },
+ {0x00950001,
+ "PMU5: CAA%d "
+ },
+ {0x00960001, "%02x"
+ },
+ {0x00970000, "\n"
+ },
+ {0x00980001,
+ "PMU5: CAB%d "
+ },
+ {0x00990001, "%02x"
+ },
+ {0x009a0000, "\n"
+ },
+ {0x009b0003,
+ "PMU3: anibi=%d, anibichan[anibi]=%d ,chan=%d\n"
+ },
+ {0x009c0001, "%02x"
+ },
+ {0x009d0001, "\nPMU3:Raw CA setting :%x"
+ },
+ {0x009e0002, "\nPMU3:ATxDly setting:%x margin:%d\n"
+ },
+ {0x009f0002, "\nPMU3:InvClk ATxDly setting:%x margin:%d\n"
+ },
+ {0x00a00000, "\nPMU3:No Range found!\n"
+ },
+ {0x00a10003,
+ "PMU3: 2 anibi=%d, anibichan[anibi]=%d ,chan=%d"
+ },
+ {0x00a20002, "\nPMU3: no neg clock => CA setting anib=%d, :%d\n"
+ },
+ {0x00a30001,
+ "PMU3:Normal margin:%d\n"
+ },
+ {0x00a40001,
+ "PMU3:Inverted margin:%d\n"
+ },
+ {0x00a50000,
+ "PMU3:Using Inverted clock\n"
+ },
+ {0x00a60000,
+ "PMU3:Using normal clk\n"
+ },
+ {0x00a70003,
+ "PMU3: 3 anibi=%d, anibichan[anibi]=%d ,chan=%d\n"
+ },
+ {0x00a80002,
+ "PMU3: Setting ATxDly for anib %x to %x\n"
+ },
+ {0x00a90000,
+ "PMU: Error: CA Training Failed.\n"
+ },
+ {0x00aa0000,
+ "PMU1: Writing MRs\n"
+ },
+ {0x00ab0000,
+ "PMU4:Using MR12 values from 1D CA VREF training.\n"
+ },
+ {0x00ac0000,
+ "PMU3:Writing all MRs to fsp 1\n"
+ },
+ {0x00ad0000,
+ "PMU10:Lp4Quickboot mode.\n"
+ },
+ {0x00ae0000,
+ "PMU3: Writing MRs\n"
+ },
+ {0x00af0001,
+ "PMU10: Setting boot clock divider to %d\n"
+ },
+ {0x00b00000,
+ "PMU3: Resetting DRAM\n"
+ },
+ {0x00b10000,
+ "PMU3: setup for RCD initalization\n"
+ },
+ {0x00b20000,
+ "PMU3: pmu_exit_SR from dev_init()\n"
+ },
+ {0x00b30000,
+ "PMU3: initializing RCD\n"
+ },
+ {0x00b40000,
+ "PMU10: **** Executing 2D Image ****\n"
+ },
+ {0x00b50001,
+ "PMU10: **** Start DDR4 Training. PMU Firmware Revision 0x%04x ****\n"
+ },
+ {0x00b60001,
+ "PMU10: **** Start DDR3 Training. PMU Firmware Revision 0x%04x ****\n"
+ },
+ {0x00b70001,
+ "PMU10: **** Start LPDDR3 Training. PMU Firmware Revision 0x%04x ****\n"
+ },
+ {0x00b80001,
+ "PMU10: **** Start LPDDR4 Training. PMU Firmware Revision 0x%04x ****\n"
+ },
+ {0x00b90000,
+ "PMU: Error: Mismatched internal revision between DCCM and ICCM images\n"
+ },
+ {0x00ba0001,
+ "PMU10: **** Testchip %d Specific Firmware ****\n"
+ },
+ {0x00bb0000,
+ "PMU1: LRDIMM with EncodedCS mode, one DIMM\n"
+ },
+ {0x00bc0000,
+ "PMU1: LRDIMM with EncodedCS mode, two DIMMs\n"
+ },
+ {0x00bd0000,
+ "PMU1: RDIMM with EncodedCS mode, one DIMM\n"
+ },
+ {0x00be0000,
+ "PMU2: Starting LRDIMM MREP training for all ranks\n"
+ },
+ {0x00bf0000,
+ "PMU199: LRDIMM MREP training for all ranks completed\n"
+ },
+ {0x00c00000,
+ "PMU2: Starting LRDIMM DWL training for all ranks\n"
+ },
+ {0x00c10000,
+ "PMU199: LRDIMM DWL training for all ranks completed\n"
+ },
+ {0x00c20000,
+ "PMU2: Starting LRDIMM MRD training for all ranks\n"
+ },
+ {0x00c30000,
+ "PMU199: LRDIMM MRD training for all ranks completed\n"
+ },
+ {0x00c40000,
+ "PMU2: Starting RXEN training for all ranks\n"
+ },
+ {0x00c50000,
+ "PMU2: Starting write leveling fine delay training for all ranks\n"
+ },
+ {0x00c60000,
+ "PMU2: Starting LRDIMM MWD training for all ranks\n"
+ },
+ {0x00c70000,
+ "PMU199: LRDIMM MWD training for all ranks completed\n"
+ },
+ {0x00c80000,
+ "PMU2: Starting write leveling fine delay training for all ranks\n"
+ },
+ {0x00c90000,
+ "PMU2: Starting read deskew training\n"
+ },
+ {0x00ca0000,
+ "PMU2: Starting SI friendly 1d RdDqs training for all ranks\n"
+ },
+ {0x00cb0000,
+ "PMU2: Starting write leveling coarse delay training for all ranks\n"
+ },
+ {0x00cc0000,
+ "PMU2: Starting 1d WrDq training for all ranks\n"
+ },
+ {0x00cd0000,
+ "PMU2: Running DQS2DQ Oscillator for all ranks\n"
+ },
+ {0x00ce0000,
+ "PMU2: Starting again read deskew training but with PRBS\n"
+ },
+ {0x00cf0000,
+ "PMU2: Starting 1d RdDqs training for all ranks\n"
+ },
+ {0x00d00000,
+ "PMU2: Starting again 1d WrDq training for all ranks\n"
+ },
+ {0x00d10000,
+ "PMU2: Starting MaxRdLat training\n"
+ },
+ {0x00d20000,
+ "PMU2: Starting 2d WrDq training for all ranks\n"
+ },
+ {0x00d30000,
+ "PMU2: Starting 2d RdDqs training for all ranks\n"
+ },